228 lines
9.5 KiB
C#
228 lines
9.5 KiB
C#
using System;
|
||
|
||
namespace MosswartMassacre
|
||
{
|
||
/// <summary>
|
||
/// Provides helper methods to control VTank from within your plugin.
|
||
/// </summary>
|
||
public static class VtankControl
|
||
{
|
||
/// <summary>
|
||
/// Sends a chat command to VTank to switch its current meta-state.
|
||
/// </summary>
|
||
/// <param name="state">
|
||
/// The name of the VTank meta-state to activate.
|
||
/// </param>
|
||
/// <returns>Always returns 1 on sending the command.</returns>
|
||
public static double VtSetMetaState(string state)
|
||
{
|
||
// Dispatch a local chat command that VTank will interpret.
|
||
PluginCore.Decal_DispatchOnChatCommand($"/vt setmetastate {state}");
|
||
return 1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Queries VTank for its currently active meta-state.
|
||
/// </summary>
|
||
/// <returns>
|
||
/// The name of the current meta-state, or empty string if VTank isn’t initialized.
|
||
/// </returns>
|
||
public static string VtGetMetaState()
|
||
{
|
||
// Instance.CurrentMetaState is typed as object, so cast it:
|
||
return (vTank.Instance.CurrentMetaState as string) ?? string.Empty;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Attempts to set a VTank configuration value by name.
|
||
/// </summary>
|
||
/// <param name="setting">
|
||
/// The VTank setting key (e.g. “EnableCombat”, “RingDistance”).
|
||
/// </param>
|
||
/// <param name="value">
|
||
/// The string or numeric value to assign. Numeric strings will be parsed.
|
||
/// </param>
|
||
/// <returns>
|
||
/// 1 if the setting was applied or possibly applied; 0 on known failure.
|
||
/// </returns>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Reads back a VTank configuration value as a string.
|
||
/// </summary>
|
||
/// <param name="setting">The name of the setting to read.</param>
|
||
/// <returns>
|
||
/// The raw string form of the setting, or empty string if undefined.
|
||
/// </returns>
|
||
public static string VtGetSetting(string setting)
|
||
{
|
||
var val = vTank.Instance.GetSetting(setting);
|
||
return (val as string) ?? string.Empty;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Checks whether the VTank macro engine is currently enabled.
|
||
/// </summary>
|
||
/// <returns>
|
||
/// <c>true</c> if macros are active; otherwise <c>false</c>.
|
||
/// </returns>
|
||
public static bool VtMacroEnabled()
|
||
{
|
||
return vTank.Instance.MacroEnabled;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Advances VTank to the next waypoint in the current navigation route.
|
||
/// </summary>
|
||
/// <returns>
|
||
/// 1 if the waypoint was advanced successfully; 0 on failure.
|
||
/// </returns>
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|