using System;
namespace MosswartMassacre
{
///
/// Provides helper methods to control VTank from within your plugin.
///
public static class VtankControl
{
///
/// Sends a chat command to VTank to switch its current meta-state.
///
///
/// The name of the VTank meta-state to activate.
///
/// Always returns 1 on sending the command.
public static double VtSetMetaState(string state)
{
// Dispatch a local chat command that VTank will interpret.
PluginCore.Decal_DispatchOnChatCommand($"/vt setmetastate {state}");
return 1;
}
///
/// Queries VTank for its currently active meta-state.
///
///
/// The name of the current meta-state, or empty string if VTank isn’t initialized.
///
public static string VtGetMetaState()
{
// Instance.CurrentMetaState is typed as object, so cast it:
return (vTank.Instance.CurrentMetaState as string) ?? string.Empty;
}
///
/// Attempts to set a VTank configuration value by name.
///
///
/// The VTank setting key (e.g. “EnableCombat”, “RingDistance”).
///
///
/// The string or numeric value to assign. Numeric strings will be parsed.
///
///
/// 1 if the setting was applied or possibly applied; 0 on known failure.
///
public static double VtSetSetting(string setting, string value)
{
try
{
var settingType = vTank.Instance.GetSettingType(setting);
if (settingType == typeof(string))
{
vTank.Instance.SetSetting(setting, value);
}
else if (double.TryParse(value, out double number))
{
if (settingType == typeof(bool))
vTank.Instance.SetSetting(setting, number == 1);
else if (settingType == typeof(double))
vTank.Instance.SetSetting(setting, number);
else if (settingType == typeof(int))
vTank.Instance.SetSetting(setting, Convert.ToInt32(number));
else if (settingType == typeof(float))
vTank.Instance.SetSetting(setting, Convert.ToSingle(number));
}
else
{
// Value wasn’t parseable—report failure
return 0;
}
}
catch
{
// Swallow any errors and signal failure
return 0;
}
return 1;
}
///
/// Reads back a VTank configuration value as a string.
///
/// The name of the setting to read.
///
/// The raw string form of the setting, or empty string if undefined.
///
public static string VtGetSetting(string setting)
{
var val = vTank.Instance.GetSetting(setting);
return (val as string) ?? string.Empty;
}
///
/// Checks whether the VTank macro engine is currently enabled.
///
///
/// true if macros are active; otherwise false.
///
public static bool VtMacroEnabled()
{
return vTank.Instance.MacroEnabled;
}
///
/// Advances VTank to the next waypoint in the current navigation route.
///
///
/// 1 if the waypoint was advanced successfully; 0 on failure.
///
public static double VtAdvanceWaypoint()
{
try
{
var externalInterface = vTank.Instance;
// Basic validation
if (externalInterface.NavNumPoints == 0)
{
return 0; // No waypoints
}
int currentWaypoint = externalInterface.NavCurrent;
int totalWaypoints = externalInterface.NavNumPoints;
// Check if we can advance
if (currentWaypoint >= totalWaypoints - 1)
{
return 0; // Already at last waypoint
}
// Check navigation type
var navType = (int)externalInterface.NavType;
if (navType == 2 || navType == 4) // Target or Once
{
return 0;
}
// Access the cExternalInterfaceTrustedRelay and get the PC (PluginCore) reference
// From decompiled code: external interface uses PC.NavCurrent which references dz.o.l
var interfaceType = externalInterface.GetType();
// Look for any way to get to the PluginCore instance
// The interface should have access to PC or some way to reach it
// Try to get the underlying assembly and find the PC static field
var assembly = interfaceType.Assembly;
var pluginCoreType = assembly.GetType("uTank2.PluginCore");
if (pluginCoreType != null)
{
// Get the static PC field
var pcField = pluginCoreType.GetField("PC", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
if (pcField != null)
{
var pluginCoreInstance = pcField.GetValue(null);
if (pluginCoreInstance != null)
{
// Try to call the advance method 'i' on the PluginCore instance
// Need to specify parameter types to avoid "Ambiguous match found"
Type[] parameterTypes = new Type[] { typeof(object), assembly.GetType("MetaViewWrappers.MVControlEventArgs") };
var advanceMethod = pluginCoreType.GetMethod("i",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
null, parameterTypes, null);
if (advanceMethod != null)
{
// Call with parameters matching: i(object A_0, MVControlEventArgs A_1)
advanceMethod.Invoke(pluginCoreInstance, new object[] { null, null });
return 1;
}
}
}
// Fallback: try to access dz static field 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)
{
// Navigate the dz.o.l path
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)
{
// Get current value and increment it
int current = (int)lField.GetValue(oObject);
current++;
if (current >= totalWaypoints)
{
current = totalWaypoints - 1;
}
lField.SetValue(oObject, current);
return 1;
}
}
}
}
}
}
return 0;
}
catch (System.Exception ex)
{
PluginCore.WriteToChat("VTank advance error: " + ex.Message);
return 0;
}
}
}
}