diff --git a/MosswartMassacre/PluginCore.cs b/MosswartMassacre/PluginCore.cs
index 68ee088..8987794 100644
--- a/MosswartMassacre/PluginCore.cs
+++ b/MosswartMassacre/PluginCore.cs
@@ -1301,6 +1301,15 @@ namespace MosswartMassacre
WriteToChat("Failed to advance VTank waypoint. Is VTank running?");
}, "Advance VTank to next waypoint");
+ _commandRouter.Register("prevwp", args =>
+ {
+ double result = VtankControl.VtPreviousWaypoint();
+ if (result == 1)
+ WriteToChat("Moved VTank back to previous waypoint.");
+ else
+ WriteToChat("Failed to move VTank waypoint back. Is VTank running?");
+ }, "Move VTank back to previous waypoint");
+
_commandRouter.Register("setchest", args =>
{
if (args.Length < 2)
diff --git a/MosswartMassacre/VtankControl.cs b/MosswartMassacre/VtankControl.cs
index 4bee425..f5f427d 100644
--- a/MosswartMassacre/VtankControl.cs
+++ b/MosswartMassacre/VtankControl.cs
@@ -224,5 +224,114 @@ namespace MosswartMassacre
return 0;
}
}
+
+ ///
+ /// Moves VTank back to the previous waypoint in the current navigation route.
+ ///
+ ///
+ /// 1 if the waypoint was moved back successfully; 0 on failure.
+ ///
+ public static double VtPreviousWaypoint()
+ {
+ try
+ {
+ var externalInterface = vTank.Instance;
+
+ // Basic validation
+ if (externalInterface.NavNumPoints == 0)
+ {
+ return 0; // No waypoints
+ }
+
+ int currentWaypoint = externalInterface.NavCurrent;
+
+ // Check if we can go back
+ if (currentWaypoint <= 0)
+ {
+ return 0; // Already at first waypoint
+ }
+
+ // Check navigation type
+ var navType = (int)externalInterface.NavType;
+ if (navType == 2 || navType == 4) // Target or Once
+ {
+ return 0;
+ }
+
+ var interfaceType = externalInterface.GetType();
+ var assembly = interfaceType.Assembly;
+ var pluginCoreType = assembly.GetType("uTank2.PluginCore");
+
+ if (pluginCoreType != null)
+ {
+ var pcField = pluginCoreType.GetField("PC", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+
+ if (pcField != null)
+ {
+ var pluginCoreInstance = pcField.GetValue(null);
+
+ if (pluginCoreInstance != null)
+ {
+ // VTank's previous-waypoint button handler is 'j' — the exact
+ // mirror of the advance handler 'i' (decrements dz.o.l, clamps
+ // at 0, refreshes nav state via m()).
+ Type[] parameterTypes = new Type[] { typeof(object), assembly.GetType("MetaViewWrappers.MVControlEventArgs") };
+ var previousMethod = pluginCoreType.GetMethod("j",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
+ null, parameterTypes, null);
+
+ if (previousMethod != null)
+ {
+ previousMethod.Invoke(pluginCoreInstance, new object[] { null, null });
+ return 1;
+ }
+ }
+ }
+
+ // Fallback: decrement the current-waypoint field dz.o.l directly
+ var dzField = pluginCoreType.GetField("dz", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+
+ if (dzField != null)
+ {
+ var dzObject = dzField.GetValue(null);
+
+ if (dzObject != null)
+ {
+ var dzType = dzObject.GetType();
+ var oField = dzType.GetField("o", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+
+ if (oField != null)
+ {
+ var oObject = oField.GetValue(dzObject);
+ if (oObject != null)
+ {
+ var oType = oObject.GetType();
+ var lField = oType.GetField("l", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+
+ if (lField != null)
+ {
+ int current = (int)lField.GetValue(oObject);
+ current--;
+ if (current < 0)
+ {
+ current = 0;
+ }
+ lField.SetValue(oObject, current);
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+ }
+ catch (System.Exception ex)
+ {
+ PluginCore.WriteToChat("VTank previous-waypoint error: " + ex.Message);
+ return 0;
+ }
+ }
}
}
diff --git a/MosswartMassacre/bin/Release/MosswartMassacre.dll b/MosswartMassacre/bin/Release/MosswartMassacre.dll
index c01e9a9..1823df0 100644
Binary files a/MosswartMassacre/bin/Release/MosswartMassacre.dll and b/MosswartMassacre/bin/Release/MosswartMassacre.dll differ