Decompiled source of AutoAttack v0.1.0

plugins\AutoAttack.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AutoAttack")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AutoAttack")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
namespace AutoAttack;

[BepInPlugin("orax.AutoAttack", "AutoAttack", "0.1.0")]
public class AutoAttack : BaseUnityPlugin
{
	public const string PluginGuid = "orax.AutoAttack";

	public const string PluginName = "AutoAttack";

	public const string PluginVersion = "0.1.0";

	public static ConfigEntry<bool> Enabled;

	public static ConfigEntry<KeyboardShortcut> ToggleKey;

	public static ConfigEntry<string> GamepadToggleButtons;

	public static ConfigEntry<bool> CancelOnWeaponChange;

	public static ConfigEntry<bool> ShowOnScreenMessage;

	public static ConfigEntry<MessageType> ScreenMessagePosition;

	public static ConfigEntry<string> MessageOn;

	public static ConfigEntry<string> MessageOff;

	public static ConfigEntry<string> MessageCancelled;

	public static ConfigEntry<string> MessageWeaponChanged;

	internal static AutoAttack Instance;

	private static ManualLogSource _log;

	private Harmony _harmony;

	private static string[] _gamepadChord = new string[0];

	private static string _gamepadChordRaw;

	private static bool _gamepadChordHeldLastFrame;

	private static bool _gamepadChordValidated;

	internal static void LogStatic(string message)
	{
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogInfo((object)message);
		}
	}

	private void Awake()
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Expected O, but got Unknown
		Instance = this;
		_log = ((BaseUnityPlugin)this).Logger;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch for the mod. When disabled, continuous attack is forced off and the game behaves exactly as vanilla (no toggle key, no pause/cancel buttons, no jump or weapon-swap adjustments).");
		ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keyboard", "Toggle auto-attack key", new KeyboardShortcut((KeyCode)324, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Keyboard key combination that starts/stops continuous attacking (equivalent to holding down the attack button). Written as Unity KeyCode names - first the key to press, then the modifiers held with it, separated by + or , (default Mouse1 + LeftAlt). Names are case-sensitive (Mouse1, not mouse1), and the combination only fires while no other keyboard key is held (mouse buttons don't count). Mouse buttons: Mouse0 (left) to Mouse6. Full list of key names: https://docs.unity3d.com/6000.0/Documentation/ScriptReference/KeyCode.html");
		CancelOnWeaponChange = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Cancel on weapon change", true, "Cancel continuous attack if the equipped weapon changes while it is active (swapping to another weapon, unequipping, or the weapon being destroyed).");
		ShowOnScreenMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Show on screen message", true, "Show a short on-screen message when continuous attack turns on, off, or gets cancelled.");
		ScreenMessagePosition = ((BaseUnityPlugin)this).Config.Bind<MessageType>("HUD", "Screen message position", (MessageType)1, "Position of the screen message.");
		MessageOn = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Turned on", "Continuous attack: ON", "Text shown when the toggle turns on. Leave empty to hide this message.");
		MessageOff = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Turned off", "Continuous attack: OFF", "Text shown when the toggle turns off. Leave empty to hide this message.");
		MessageCancelled = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Cancelled", "Continuous attack: cancelled", "Text shown when a cancel button stops continuous attack. Leave empty to hide this message.");
		MessageWeaponChanged = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Cancelled (weapon changed)", "Continuous attack: cancelled (weapon changed)", "Text shown when continuous attack stops because the equipped weapon changed (only when \"Cancel on weapon change\" is enabled). Leave empty to hide this message.");
		_harmony = new Harmony("orax.AutoAttack");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"AutoAttack 0.1.0 loaded.");
	}

	private void Update()
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		if (DynamicButtonConfig.CancelEntries.Count == 0)
		{
			DynamicButtonConfig.Generate(((BaseUnityPlugin)this).Config);
		}
		bool flag = GamepadToggleDown();
		if (!Enabled.Value)
		{
			AutoAttackState.Reset();
			return;
		}
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			AutoAttackState.Reset();
			return;
		}
		AutoAttackState.Paused = DynamicButtonConfig.AnyHeld(DynamicButtonConfig.PauseEntries);
		bool flag2 = false;
		if (!Minimap.InTextInput())
		{
			KeyboardShortcut value = ToggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() || flag)
			{
				bool flag3 = AutoAttackState.Toggle();
				ShowMessage(flag3 ? MessageOn.Value : MessageOff.Value);
				flag2 = true;
			}
		}
		if (!flag2 && AutoAttackState.Active && DynamicButtonConfig.AnyDown(DynamicButtonConfig.CancelEntries))
		{
			AutoAttackState.Reset();
			ShowMessage(MessageCancelled.Value);
		}
		if (!flag2 && AutoAttackState.Active && CancelOnWeaponChange.Value && ((Humanoid)Player.m_localPlayer).GetCurrentWeapon() != AutoAttackState.ActiveWeapon)
		{
			AutoAttackState.Reset();
			ShowMessage(MessageWeaponChanged.Value);
		}
	}

	internal void ShowMessage(string text)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		if (!string.IsNullOrEmpty(text) && ShowOnScreenMessage.Value && (Object)(object)MessageHud.instance != (Object)null)
		{
			MessageHud.instance.ShowMessage(ScreenMessagePosition.Value, text, 0, (Sprite)null, false, true);
		}
	}

	private bool GamepadToggleDown()
	{
		if (GamepadToggleButtons == null)
		{
			return false;
		}
		string value = GamepadToggleButtons.Value;
		if (!string.Equals(value, _gamepadChordRaw, StringComparison.Ordinal))
		{
			_gamepadChordRaw = value;
			_gamepadChord = (from part in (value ?? string.Empty).Split(new char[2] { ',', '+' }, StringSplitOptions.RemoveEmptyEntries)
				select part.Trim() into part
				where part.Length > 0
				select part).ToArray();
			_gamepadChordHeldLastFrame = false;
			_gamepadChordValidated = false;
		}
		bool flag = _gamepadChord.Length != 0;
		int num = 0;
		while (flag && num < _gamepadChord.Length)
		{
			flag = ZInput.GetButton(_gamepadChord[num]);
			num++;
		}
		bool result = flag && !_gamepadChordHeldLastFrame;
		_gamepadChordHeldLastFrame = flag;
		if (!_gamepadChordValidated && DynamicButtonConfig.CancelEntries.Count > 0)
		{
			_gamepadChordValidated = true;
			string[] gamepadChord = _gamepadChord;
			foreach (string text in gamepadChord)
			{
				if (!DynamicButtonConfig.IsRegisteredButton(text))
				{
					LogStatic("Gamepad toggle: ZInput has no button named \"" + text + "\" - it can never complete the combo. Check [Gamepad] Toggle auto-attack buttons.");
				}
			}
		}
		return result;
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}
internal static class DynamicButtonConfig
{
	public static readonly Dictionary<string, ConfigEntry<bool>> CancelEntries = new Dictionary<string, ConfigEntry<bool>>();

	public static readonly Dictionary<string, ConfigEntry<bool>> PauseEntries = new Dictionary<string, ConfigEntry<bool>>();

	private static readonly FieldRef<ZInput, Dictionary<string, ButtonDef>> ButtonsRef = AccessTools.FieldRefAccess<ZInput, Dictionary<string, ButtonDef>>("m_buttons");

	public static bool IsRegisteredButton(string name)
	{
		ZInput instance = ZInput.instance;
		if (instance != null)
		{
			return ButtonsRef.Invoke(instance).ContainsKey(name);
		}
		return false;
	}

	public static void Generate(ConfigFile config)
	{
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Invalid comparison between Unknown and I4
		if (CancelEntries.Count > 0)
		{
			return;
		}
		ZInput instance = ZInput.instance;
		if (instance == null)
		{
			return;
		}
		List<ButtonDef> list = ButtonsRef.Invoke(instance).Values.Where((ButtonDef b) => b.Rebindable || (int)b.Source == 180).OrderBy<ButtonDef, string>((ButtonDef b) => b.Name, StringComparer.OrdinalIgnoreCase).ToList();
		if (AutoAttack.GamepadToggleButtons == null)
		{
			AutoAttack.GamepadToggleButtons = config.Bind<string>("Gamepad", "Toggle auto-attack buttons", "JoyLBumper, JoyRBumper", BuildGamepadChordDescription(list));
		}
		foreach (ButtonDef item in list)
		{
			string name = item.Name;
			bool flag = (int)item.Source == 180;
			string text = DescribeButton(instance, name);
			string text2 = (flag ? "Gamepad cancel buttons" : "Keyboard cancel buttons");
			string text3 = (flag ? "Gamepad pause buttons" : "Keyboard pause buttons");
			bool flag3;
			if (flag)
			{
				bool flag2;
				switch (name)
				{
				case "JoyAttack":
				case "JoySecondaryAttack":
				case "JoyBlock":
				case "JoyUse":
				case "JoyCrouch":
				case "JoySit":
					flag2 = true;
					break;
				default:
					flag2 = false;
					break;
				}
				flag3 = flag2;
			}
			else
			{
				bool flag2;
				switch (name)
				{
				case "Attack":
				case "Crouch":
				case "Sit":
				case "Use":
				case "SecondaryAttack":
				case "Block":
				case "AltDodge":
				case "AutoRun":
					flag2 = true;
					break;
				default:
					flag2 = false;
					break;
				}
				flag3 = flag2;
			}
			bool flag4 = flag3;
			CancelEntries[name] = config.Bind<bool>(text2, name, flag4, flag ? ("Pressing " + text + " fully cancels continuous attack. Raw name \"" + name + "\", also usable in [Gamepad] Toggle auto-attack buttons.") : ("Pressing " + text + " fully cancels continuous attack."));
			if (name == "Attack" || name == "JoyAttack")
			{
				continue;
			}
			if (flag)
			{
				bool flag2;
				switch (name)
				{
				case "JoyLStickDown":
				case "JoyLStickLeft":
				case "JoySecondaryAttack":
				case "JoyJump":
				case "JoyBlock":
				case "JoyLStickUp":
				case "JoyLStickRight":
					flag2 = true;
					break;
				default:
					flag2 = false;
					break;
				}
				flag3 = flag2;
			}
			else
			{
				bool flag2;
				switch (name)
				{
				case "Jump":
				case "Left":
				case "Block":
				case "Right":
				case "SecondaryAttack":
				case "Forward":
				case "Backward":
					flag2 = true;
					break;
				default:
					flag2 = false;
					break;
				}
				flag3 = flag2;
			}
			bool flag5 = flag3;
			PauseEntries[name] = config.Bind<bool>(text3, name, flag5, flag ? ("Holding " + text + " temporarily pauses continuous attack; it resumes automatically on release. Raw name \"" + name + "\", also usable in [Gamepad] Toggle auto-attack buttons.") : ("Holding " + text + " temporarily pauses continuous attack; it resumes automatically on release."));
		}
		AutoAttack.LogStatic($"Generated {CancelEntries.Count} cancel / {PauseEntries.Count} pause button entries from ZInput (keyboard + gamepad).");
	}

	private static string BuildGamepadChordDescription(List<ButtonDef> buttons)
	{
		string[] array = (from b in buttons
			where (int)b.Source == 180
			select b.Name).ToArray();
		string text = "Gamepad buttons that must all be held together to start/stop continuous attacking, as comma or plus separated ZInput button names (default JoyLBumper, JoyRBumper = L1 + R1). The combo fires on the press that completes it, like the keyboard combination. Leave empty to disable the gamepad toggle.\n";
		if (array.Length == 0)
		{
			return text;
		}
		return text + "\nAll button names available in this game, generated from ZInput at startup (controller layout: " + ((object)Unsafe.As<InputLayout, InputLayout>(ref ZInput.InputLayout)/*cast due to .constrained prefix*/).ToString() + "; restart the game after changing the layout). Each name is also listed with its in-game label and current binding under [Gamepad cancel buttons]:\n" + WrapNameList(array);
	}

	private static string WrapNameList(string[] names)
	{
		List<string> list = new List<string>();
		string text = null;
		int num = 0;
		foreach (string text2 in names)
		{
			int num2 = text2.Length + ((text != null) ? 2 : 0);
			if (text != null && num + num2 > 100)
			{
				list.Add(text);
				text = null;
				num = 0;
				num2 = text2.Length;
			}
			text = ((text == null) ? text2 : (text + ", " + text2));
			num += num2;
		}
		if (text != null)
		{
			list.Add(text);
		}
		return string.Join("\n", list);
	}

	private static string DescribeButton(ZInput instance, string name)
	{
		string text = null;
		try
		{
			if (Localization.instance != null)
			{
				text = Localization.instance.Localize("$settings_" + name.ToLower());
			}
		}
		catch (Exception ex)
		{
			AutoAttack.LogStatic("Could not localize button \"" + name + "\": " + ex.Message);
		}
		string text2 = null;
		try
		{
			text2 = instance.GetBoundKeyString(name, true);
			if (!string.IsNullOrEmpty(text2) && Localization.instance != null)
			{
				text2 = Localization.instance.Localize(text2);
			}
		}
		catch (Exception ex2)
		{
			AutoAttack.LogStatic("Could not read bound key for \"" + name + "\": " + ex2.Message);
		}
		bool flag = !string.IsNullOrEmpty(text) && text != name;
		bool flag2 = !string.IsNullOrEmpty(text2);
		if (flag && flag2)
		{
			return "\"" + name + "\" (" + text + ", currently bound to: " + text2 + ")";
		}
		if (flag)
		{
			return "\"" + name + "\" (" + text + ")";
		}
		if (flag2)
		{
			return "\"" + name + "\" (currently bound to: " + text2 + ")";
		}
		return "\"" + name + "\"";
	}

	public static bool AnyDown(Dictionary<string, ConfigEntry<bool>> entries)
	{
		foreach (KeyValuePair<string, ConfigEntry<bool>> entry in entries)
		{
			if (entry.Value.Value && ZInput.GetButtonDown(entry.Key))
			{
				return true;
			}
		}
		return false;
	}

	public static bool AnyHeld(Dictionary<string, ConfigEntry<bool>> entries)
	{
		foreach (KeyValuePair<string, ConfigEntry<bool>> entry in entries)
		{
			if (entry.Value.Value && ZInput.GetButton(entry.Key))
			{
				return true;
			}
		}
		return false;
	}
}
[HarmonyPatch(typeof(ZInput), "Initialize")]
internal static class ZInput_Initialize_GenerateButtonConfig
{
	private static void Postfix()
	{
		if ((Object)(object)AutoAttack.Instance != (Object)null)
		{
			DynamicButtonConfig.Generate(((BaseUnityPlugin)AutoAttack.Instance).Config);
		}
	}
}
internal static class AutoAttackState
{
	public static bool Active { get; private set; }

	public static bool Paused { get; set; }

	public static ItemData ActiveWeapon { get; private set; }

	public static bool Toggle()
	{
		Active = !Active;
		Paused = false;
		object activeWeapon;
		if (!Active)
		{
			activeWeapon = null;
		}
		else
		{
			Player localPlayer = Player.m_localPlayer;
			activeWeapon = ((localPlayer != null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null);
		}
		ActiveWeapon = (ItemData)activeWeapon;
		return Active;
	}

	public static void Reset()
	{
		Active = false;
		Paused = false;
		ActiveWeapon = null;
	}
}
[HarmonyPatch(typeof(ZInput), "GetButton", new Type[] { typeof(string) })]
internal static class ZInput_GetButton_ForceAttackHold
{
	private static readonly FieldRef<Humanoid, float> AttackDrawTimeRef = AccessTools.FieldRefAccess<Humanoid, float>("m_attackDrawTime");

	private static void Postfix(string name, ref bool __result)
	{
		if (!__result && AutoAttackState.Active && !AutoAttackState.Paused && !(name != "Attack") && !ReloadPending() && !BowDrawStuck() && !BowFullyDrawn())
		{
			__result = true;
		}
	}

	private static bool BowDrawStuck()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon();
		if (currentWeapon == null || !currentWeapon.m_shared.m_attack.m_bowDraw)
		{
			return false;
		}
		return AttackDrawTimeRef.Invoke((Humanoid)(object)localPlayer) < 0f;
	}

	private static bool ReloadPending()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon();
		if (currentWeapon != null && currentWeapon.m_shared.m_attack.m_requiresReload)
		{
			return !((Humanoid)localPlayer).IsWeaponLoaded();
		}
		return false;
	}

	private static bool BowFullyDrawn()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon();
		if (currentWeapon == null || !currentWeapon.m_shared.m_attack.m_bowDraw)
		{
			return false;
		}
		if (((Character)localPlayer).InAttack())
		{
			return false;
		}
		return ((Humanoid)localPlayer).GetAttackDrawPercentage() >= 1f;
	}
}
[HarmonyPatch(typeof(Character), "Jump", new Type[] { typeof(bool) })]
internal static class Character_Jump_AllowWhileAutoAttack
{
	private static void Prefix(Character __instance, ref bool force)
	{
		if (!force && AutoAttackState.Active && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && (ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")))
		{
			force = true;
		}
	}
}
internal static class EquipDuringAutoAttack
{
	private static readonly MethodInfo BlocksEquipMethod = AccessTools.Method(typeof(EquipDuringAutoAttack), "BlocksEquip", (Type[])null, (Type[])null);

	private static readonly MethodInfo BlocksQueuedActionMethod = AccessTools.Method(typeof(EquipDuringAutoAttack), "BlocksQueuedAction", (Type[])null, (Type[])null);

	private static readonly FieldRef<Player, List<MinorActionData>> ActionQueueRef = AccessTools.FieldRefAccess<Player, List<MinorActionData>>("m_actionQueue");

	private static bool BypassEnabled(Humanoid self)
	{
		if (AutoAttackState.Active)
		{
			return (Object)(object)self == (Object)(object)Player.m_localPlayer;
		}
		return false;
	}

	public static bool BlocksEquip(Humanoid self)
	{
		if (!BypassEnabled(self))
		{
			return ((Character)self).InAttack();
		}
		return false;
	}

	public static bool BlocksQueuedAction(Humanoid self)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_0035: Invalid comparison between Unknown and I4
		if (BypassEnabled(self))
		{
			List<MinorActionData> list = ActionQueueRef.Invoke((Player)self);
			if (list.Count > 0)
			{
				ActionType type = list[0].m_type;
				if ((int)type == 0 || (int)type == 1)
				{
					return false;
				}
			}
		}
		return ((Character)self).InAttack();
	}

	public static IEnumerable<CodeInstruction> TranspileBlocksEquip(IEnumerable<CodeInstruction> instructions)
	{
		return ReplaceInAttackCall(instructions, BlocksEquipMethod);
	}

	public static IEnumerable<CodeInstruction> TranspileBlocksQueuedAction(IEnumerable<CodeInstruction> instructions)
	{
		return ReplaceInAttackCall(instructions, BlocksQueuedActionMethod);
	}

	private static IEnumerable<CodeInstruction> ReplaceInAttackCall(IEnumerable<CodeInstruction> instructions, MethodInfo replacement)
	{
		foreach (CodeInstruction instruction in instructions)
		{
			if ((instruction.opcode == OpCodes.Callvirt || instruction.opcode == OpCodes.Call) && instruction.operand is MethodInfo { Name: "InAttack" })
			{
				instruction.opcode = OpCodes.Call;
				instruction.operand = replacement;
			}
			yield return instruction;
		}
	}
}
[HarmonyPatch(typeof(Player), "ToggleEquipped")]
internal static class Player_ToggleEquipped_AllowSwapDuringAutoAttack
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		return EquipDuringAutoAttack.TranspileBlocksEquip(instructions);
	}
}
[HarmonyPatch(typeof(Humanoid), "EquipItem")]
internal static class Humanoid_EquipItem_AllowSwapDuringAutoAttack
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		return EquipDuringAutoAttack.TranspileBlocksEquip(instructions);
	}
}
[HarmonyPatch(typeof(Player), "UpdateActionQueue")]
internal static class Player_UpdateActionQueue_AllowQueuedSwapDuringAutoAttack
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		return EquipDuringAutoAttack.TranspileBlocksQueuedAction(instructions);
	}
}
[HarmonyPatch(typeof(Player), "Update")]
internal static class Player_Update_AllowHideDuringAutoAttack
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		return EquipDuringAutoAttack.TranspileBlocksEquip(instructions);
	}
}
[HarmonyPatch(typeof(Player), "OnDeath")]
internal static class Player_OnDeath_ResetAutoAttack
{
	private static void Postfix(Player __instance)
	{
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
		{
			AutoAttackState.Reset();
		}
	}
}