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