Decompiled source of SalvoMacro v1.2.1

BepInEx/plugins/SalvoMacro.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon.Math;
using Pigeon.Movement;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Interactions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Sparroh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1")]
[assembly: AssemblyProduct("SalvoMacro")]
[assembly: AssemblyTitle("SalvoMacro")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public static class ConfigManager
{
	public enum ActivationMode
	{
		None,
		Toggle,
		Always
	}

	private const float DebounceSeconds = 0.25f;

	private static ConfigFile config;

	private static ManualLogSource logger;

	private static FileSystemWatcher configWatcher;

	private static volatile bool reloadPending;

	private static float lastReloadTime;

	public static ConfigEntry<ActivationMode> SalvoMode { get; private set; }

	public static ConfigEntry<bool> UseZeroLockRelease { get; private set; }

	public static ConfigEntry<bool> SuppressSalvoModelAlways { get; private set; }

	public static void Initialize(ConfigFile configFile, ManualLogSource log)
	{
		config = configFile;
		logger = log;
		SalvoMode = config.Bind<ActivationMode>("General", "Salvo Activation Mode", ActivationMode.Toggle, "None: default manual firing. Toggle: Slot3 toggles auto-fire on/off. Always: auto-fire whenever charged.");
		UseZeroLockRelease = config.Bind<bool>("General", "Use Zero Lock Release", true, "When true (recommended), auto-fire uses vanilla zero-lock release (crosshair point + spread). When false, instantly fills target locks via FindSalvoTarget before firing.");
		SuppressSalvoModelAlways = config.Bind<bool>("General", "Suppress Salvo Model", false, "Always hide the 3D salvo launcher model to save screen space (including manual aim). Auto-fire never shows the model regardless.");
		SalvoMode.SettingChanged += OnSalvoModeChanged;
		try
		{
			SetupFileWatcher();
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Error setting up config file watcher: " + ex.Message));
		}
	}

	public static void Tick()
	{
		if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f)
		{
			return;
		}
		reloadPending = false;
		lastReloadTime = Time.unscaledTime;
		try
		{
			config.Reload();
			WingsuitPatches.ResetToggle();
			logger.LogInfo((object)"Config reloaded from disk.");
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Error reloading config: " + ex.Message));
		}
	}

	public static void Dispose()
	{
		if (SalvoMode != null)
		{
			SalvoMode.SettingChanged -= OnSalvoModeChanged;
		}
		if (configWatcher != null)
		{
			configWatcher.EnableRaisingEvents = false;
			configWatcher.Changed -= OnConfigFileChanged;
			configWatcher.Created -= OnConfigFileChanged;
			configWatcher.Renamed -= OnConfigFileChanged;
			configWatcher.Dispose();
			configWatcher = null;
		}
	}

	private static void SetupFileWatcher()
	{
		configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.salvomacro.cfg");
		configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
		configWatcher.Changed += OnConfigFileChanged;
		configWatcher.Created += OnConfigFileChanged;
		configWatcher.Renamed += OnConfigFileChanged;
		configWatcher.EnableRaisingEvents = true;
	}

	private static void OnConfigFileChanged(object sender, FileSystemEventArgs e)
	{
		reloadPending = true;
	}

	private static void OnSalvoModeChanged(object sender, EventArgs e)
	{
		WingsuitPatches.ResetToggle();
	}
}
[BepInPlugin("sparroh.salvomacro", "SalvoMacro", "1.2.1")]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class SalvoMacroPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.salvomacro";

	public const string PluginName = "SalvoMacro";

	public const string PluginVersion = "1.2.1";

	internal static ManualLogSource Logger;

	private Harmony harmony;

	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		Logger = ((BaseUnityPlugin)this).Logger;
		ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Logger);
		harmony = new Harmony("sparroh.salvomacro");
		try
		{
			WingsuitPatches.InitializeAccess();
			harmony.PatchAll(typeof(WingsuitPatches));
			Logger.LogInfo((object)"Harmony patches applied.");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error applying patches: " + ex.Message));
		}
		Logger.LogInfo((object)"SalvoMacro v1.2.1 loaded successfully.");
	}

	private void Update()
	{
		ConfigManager.Tick();
	}

	private void OnDestroy()
	{
		ConfigManager.Dispose();
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}
}
[HarmonyPatch(typeof(Wingsuit))]
public static class WingsuitPatches
{
	public static bool salvoAutoEnabled;

	private static FieldInfo isSalvoActiveField;

	private static FieldInfo salvoLockOrFireTimeField;

	private static FieldInfo salvoModelField;

	private static FieldInfo salvoAnimationTimeField;

	private static PropertyInfo maxSalvoLocksProperty;

	private static MethodInfo addExtraHealingRocketMethod;

	private static MethodInfo findSalvoTargetMethod;

	private static bool accessReady;

	public static void InitializeAccess()
	{
		isSalvoActiveField = AccessTools.Field(typeof(Wingsuit), "isSalvoActive");
		salvoLockOrFireTimeField = AccessTools.Field(typeof(Wingsuit), "salvoLockOrFireTime");
		salvoModelField = AccessTools.Field(typeof(Wingsuit), "salvoModel");
		salvoAnimationTimeField = AccessTools.Field(typeof(Wingsuit), "salvoAnimationTime");
		maxSalvoLocksProperty = AccessTools.Property(typeof(Wingsuit), "MaxSalvoLocks");
		addExtraHealingRocketMethod = AccessTools.Method(typeof(Wingsuit), "AddExtraHealingRocket", (Type[])null, (Type[])null);
		findSalvoTargetMethod = AccessTools.Method(typeof(Wingsuit), "FindSalvoTarget", (Type[])null, (Type[])null);
		accessReady = isSalvoActiveField != null && salvoLockOrFireTimeField != null && maxSalvoLocksProperty != null;
		if (!accessReady)
		{
			SalvoMacroPlugin.Logger.LogError((object)"Failed to resolve one or more Wingsuit members for SalvoMacro.");
		}
	}

	public static void ResetToggle()
	{
		salvoAutoEnabled = false;
	}

	private static bool IsAutoFireActive()
	{
		return ConfigManager.SalvoMode.Value switch
		{
			ConfigManager.ActivationMode.Always => true, 
			ConfigManager.ActivationMode.Toggle => salvoAutoEnabled, 
			_ => false, 
		};
	}

	[HarmonyPatch("OnSalvoPressed")]
	[HarmonyPrefix]
	private static bool OnSalvoPressedPrefix(CallbackContext context)
	{
		if (ConfigManager.SalvoMode.Value != ConfigManager.ActivationMode.Toggle)
		{
			return true;
		}
		if (((CallbackContext)(ref context)).interaction is TapInteraction)
		{
			return true;
		}
		salvoAutoEnabled = !salvoAutoEnabled;
		SalvoMacroPlugin.Logger.LogDebug((object)("Salvo auto-fire " + (salvoAutoEnabled ? "enabled" : "disabled")));
		return false;
	}

	[HarmonyPatch("FixedUpdate")]
	[HarmonyPostfix]
	private static void FixedUpdatePostfix(Wingsuit __instance)
	{
		if (!accessReady || !((NetworkBehaviour)__instance).IsOwner || !IsAutoFireActive())
		{
			return;
		}
		try
		{
			TryAutoFire(__instance);
		}
		catch (Exception ex)
		{
			SalvoMacroPlugin.Logger.LogError((object)("Error in salvo auto-fire: " + ex));
		}
	}

	[HarmonyPatch("Update")]
	[HarmonyPostfix]
	private static void UpdatePostfix(Wingsuit __instance)
	{
		if (!ConfigManager.SuppressSalvoModelAlways.Value || !((NetworkBehaviour)__instance).IsOwner)
		{
			return;
		}
		try
		{
			SuppressSalvoModel(__instance);
		}
		catch (Exception ex)
		{
			SalvoMacroPlugin.Logger.LogError((object)("Error suppressing salvo model: " + ex.Message));
		}
	}

	[HarmonyPatch("OnSalvoPressed")]
	[HarmonyPostfix]
	private static void OnSalvoPressedPostfix(Wingsuit __instance)
	{
		if (!ConfigManager.SuppressSalvoModelAlways.Value || !((NetworkBehaviour)__instance).IsOwner)
		{
			return;
		}
		try
		{
			SuppressSalvoModel(__instance);
		}
		catch (Exception ex)
		{
			SalvoMacroPlugin.Logger.LogError((object)("Error suppressing salvo model on press: " + ex.Message));
		}
	}

	private static void SuppressSalvoModel(Wingsuit wingsuit)
	{
		if (!(salvoModelField == null))
		{
			object? value = salvoModelField.GetValue(wingsuit);
			Transform val = (Transform)((value is Transform) ? value : null);
			if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
			{
				((Component)val).gameObject.SetActive(false);
			}
			if (salvoAnimationTimeField != null)
			{
				salvoAnimationTimeField.SetValue(wingsuit, 0f);
			}
		}
	}

	private static void TryAutoFire(Wingsuit wingsuit)
	{
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		if ((bool)isSalvoActiveField.GetValue(wingsuit))
		{
			return;
		}
		List<ITarget> salvoLocks = wingsuit.SalvoLocks;
		List<Vector3> salvoLockPositions = wingsuit.SalvoLockPositions;
		if (salvoLocks == null || salvoLockPositions == null || salvoLocks.Count > 0)
		{
			return;
		}
		Cooldown rocketSalvoCooldown = wingsuit.RocketSalvoCooldown;
		if (rocketSalvoCooldown == null || !((CooldownData)(ref rocketSalvoCooldown.data)).IsCharged)
		{
			return;
		}
		int num = (int)maxSalvoLocksProperty.GetValue(wingsuit);
		if (num > 0)
		{
			ref WingsuitData data = ref wingsuit.Data;
			salvoLocks.Clear();
			salvoLockPositions.Clear();
			salvoLockOrFireTimeField.SetValue(wingsuit, -99f);
			if (ConfigManager.UseZeroLockRelease.Value)
			{
				BuildZeroLockRelease(wingsuit, salvoLocks, salvoLockPositions, num, ref data);
			}
			else
			{
				BuildInstantTargetLocks(wingsuit, salvoLocks, num);
			}
			if (salvoLocks.Count == 0)
			{
				BuildZeroLockRelease(wingsuit, salvoLocks, salvoLockPositions, num, ref data);
			}
			if (UpgradeFlagsExtensions.IsEnabled(wingsuit.UpgradeFlags, (WingsuitUpgradeFlags)16) && addExtraHealingRocketMethod != null)
			{
				addExtraHealingRocketMethod.Invoke(wingsuit, null);
			}
			((CooldownData)(ref rocketSalvoCooldown.data)).UseCharge();
			if (data.fuelAddedOnSalvoFire > 0f)
			{
				float num2 = Mathf.LerpUnclamped(1f, 0.13f, Mathf.InverseLerp(2f, 20f, (float)rocketSalvoCooldown.MaxCharges));
				wingsuit.AddCharge(data.fuelAddedOnSalvoFire * num2);
			}
		}
	}

	private static void BuildZeroLockRelease(Wingsuit wingsuit, List<ITarget> locks, List<Vector3> lockPositions, int maxLocks, ref WingsuitData data)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		RaycastHit val2 = default(RaycastHit);
		Vector3 val = ((!IBullet.RaycastForBullet(PlayerLook.Position, PlayerLook.Forward, data.maxSalvoLockDistance, 10241, 0f, ref val2)) ? (PlayerLook.Position + PlayerLook.Forward * data.maxSalvoLockDistance) : ((RaycastHit)(ref val2)).point);
		for (int i = 0; i < maxLocks; i++)
		{
			locks.Add(null);
			lockPositions.Add(val + ((Random)(ref data.salvoSpread.spreadRandom)).InsideUnitSphere() * 4f);
		}
	}

	private static void BuildInstantTargetLocks(Wingsuit wingsuit, List<ITarget> locks, int maxLocks)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		if (findSalvoTargetMethod == null)
		{
			return;
		}
		for (int i = 0; i < maxLocks; i++)
		{
			if (!(bool)findSalvoTargetMethod.Invoke(wingsuit, null))
			{
				break;
			}
			salvoLockOrFireTimeField.SetValue(wingsuit, -99f);
		}
		if (locks.Count > 0 && locks.Count < maxLocks && !UpgradeFlagsExtensions.IsEnabled(wingsuit.UpgradeFlags, (WingsuitUpgradeFlags)8))
		{
			List<Vector3> salvoLockPositions = wingsuit.SalvoLockPositions;
			int index = locks.Count - 1;
			for (int j = locks.Count; j < maxLocks; j++)
			{
				locks.Add(locks[index]);
				salvoLockPositions.Add(salvoLockPositions[index]);
			}
		}
	}
}
namespace SalvoMacro
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "SalvoMacro";

		public const string PLUGIN_NAME = "SalvoMacro";

		public const string PLUGIN_VERSION = "1.2.1";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}