Decompiled source of EasyFall v0.1.0

EasyFall.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using EasyFall.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[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("EasyFall")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EasyFall")]
[assembly: AssemblyTitle("EasyFall")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace EasyFall
{
	public class ModMenu : MonoBehaviour
	{
		private bool _visible;

		private Rect _windowRect = new Rect(10f, 10f, 340f, 580f);

		private bool _isResizing;

		private Vector2 _scrollPos;

		public bool InstantWaveSpawn;

		public bool AutoStartNextWave;

		public float PlayerUnitHpMultiplier = 1f;

		public float PlayerUnitDamageMultiplier = 1f;

		public float PlayerUnitAttackSpeedMultiplier = 1f;

		public float PlayerUnitMoveSpeedMultiplier = 1f;

		public float PlayerMoveSpeedMultiplier = 1f;

		public float PlayerHpMultiplier = 1f;

		public float PlayerDamageMultiplier = 1f;

		public float PlayerAttackSpeedMultiplier = 1f;

		public bool PlayerRandomTarget;

		public float TowerHpMultiplier = 1f;

		public float TowerDamageMultiplier = 1f;

		public float TowerAttackSpeedMultiplier = 1f;

		public int CoinsToSpawn;

		private string _playerHpText = "1";

		private string _playerDmgText = "1";

		private string _playerAtkSpdText = "1";

		private string _playerMoveSpdText = "1";

		private string _playerCharMoveSpdText = "1";

		private string _playerCharHpText = "1";

		private string _playerCharDmgText = "1";

		private string _playerCharAtkSpdText = "1";

		private string _towerHpText = "1";

		private string _towerDmgText = "1";

		private string _towerAtkSpdText = "1";

		private string _coinsText = "0";

		private float _prevPlayerHp = 1f;

		private float _prevPlayerDmg = 1f;

		private float _prevPlayerAtkSpd = 1f;

		private float _prevPlayerMoveSpd = 1f;

		private float _prevPlayerCharMoveSpd = 1f;

		private float _prevPlayerCharHp = 1f;

		private float _prevPlayerCharDmg = 1f;

		private float _prevPlayerCharAtkSpd = 1f;

		private static GUIStyle _richStyle;

		public bool PlayerStatsChanged { get; private set; }

		public bool PlayerCharStatsChanged { get; private set; }

		public bool SpawnCoinsRequested { get; set; }

		public static ModMenu Instance { get; private set; }

		private static GUIStyle RichStyle
		{
			get
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Expected O, but got Unknown
				object obj = _richStyle;
				if (obj == null)
				{
					GUIStyle val = new GUIStyle(GUI.skin.label)
					{
						richText = true
					};
					_richStyle = val;
					obj = (object)val;
				}
				return (GUIStyle)obj;
			}
		}

		private void Awake()
		{
			Instance = this;
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)286))
			{
				_visible = !_visible;
			}
			PlayerStatsChanged = false;
			if (PlayerUnitHpMultiplier != _prevPlayerHp || PlayerUnitDamageMultiplier != _prevPlayerDmg || PlayerUnitAttackSpeedMultiplier != _prevPlayerAtkSpd || PlayerUnitMoveSpeedMultiplier != _prevPlayerMoveSpd)
			{
				PlayerStatsChanged = true;
				_prevPlayerHp = PlayerUnitHpMultiplier;
				_prevPlayerDmg = PlayerUnitDamageMultiplier;
				_prevPlayerAtkSpd = PlayerUnitAttackSpeedMultiplier;
				_prevPlayerMoveSpd = PlayerUnitMoveSpeedMultiplier;
			}
			PlayerCharStatsChanged = false;
			if (PlayerMoveSpeedMultiplier != _prevPlayerCharMoveSpd || PlayerHpMultiplier != _prevPlayerCharHp || PlayerDamageMultiplier != _prevPlayerCharDmg || PlayerAttackSpeedMultiplier != _prevPlayerCharAtkSpd)
			{
				PlayerCharStatsChanged = true;
				_prevPlayerCharMoveSpd = PlayerMoveSpeedMultiplier;
				_prevPlayerCharHp = PlayerHpMultiplier;
				_prevPlayerCharDmg = PlayerDamageMultiplier;
				_prevPlayerCharAtkSpd = PlayerAttackSpeedMultiplier;
			}
		}

		private void OnGUI()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_002b: 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)
			if (_visible)
			{
				_windowRect = GUILayout.Window(948201, _windowRect, new WindowFunction(DrawWindow), "EasyFall", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawWindow(int id)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0415: Unknown result type (might be due to invalid IL or missing references)
			if (GUI.Button(new Rect(((Rect)(ref _windowRect)).width - 22f, 2f, 20f, 20f), "X"))
			{
				_visible = false;
			}
			_scrollPos = GUILayout.BeginScrollView(_scrollPos, Array.Empty<GUILayoutOption>());
			GUILayout.Label("<b>Wave Spawning</b>", RichStyle, Array.Empty<GUILayoutOption>());
			InstantWaveSpawn = GUILayout.Toggle(InstantWaveSpawn, " Spawn all enemies instantly", Array.Empty<GUILayoutOption>());
			AutoStartNextWave = GUILayout.Toggle(AutoStartNextWave, " Auto start next wave", Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			GUILayout.Label("<b>Player Character</b>", RichStyle, Array.Empty<GUILayoutOption>());
			DrawMultiplierField("HP:", ref _playerCharHpText, ref PlayerHpMultiplier);
			DrawMultiplierField("Damage:", ref _playerCharDmgText, ref PlayerDamageMultiplier);
			DrawMultiplierField("Attack Speed:", ref _playerCharAtkSpdText, ref PlayerAttackSpeedMultiplier);
			DrawMultiplierField("Move Speed:", ref _playerCharMoveSpdText, ref PlayerMoveSpeedMultiplier);
			PlayerRandomTarget = GUILayout.Toggle(PlayerRandomTarget, " Random target each attack", Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Reset Player Character Stats", Array.Empty<GUILayoutOption>()))
			{
				PlayerHpMultiplier = 1f;
				_playerCharHpText = "1";
				PlayerDamageMultiplier = 1f;
				_playerCharDmgText = "1";
				PlayerAttackSpeedMultiplier = 1f;
				_playerCharAtkSpdText = "1";
				PlayerMoveSpeedMultiplier = 1f;
				_playerCharMoveSpdText = "1";
				PlayerRandomTarget = false;
			}
			GUILayout.Space(10f);
			GUILayout.Label("<b>Player Unit Stats</b>", RichStyle, Array.Empty<GUILayoutOption>());
			DrawMultiplierField("HP:", ref _playerHpText, ref PlayerUnitHpMultiplier);
			DrawMultiplierField("Damage:", ref _playerDmgText, ref PlayerUnitDamageMultiplier);
			DrawMultiplierField("Attack Speed:", ref _playerAtkSpdText, ref PlayerUnitAttackSpeedMultiplier);
			DrawMultiplierField("Move Speed:", ref _playerMoveSpdText, ref PlayerUnitMoveSpeedMultiplier);
			if (GUILayout.Button("Reset Player Unit Stats", Array.Empty<GUILayoutOption>()))
			{
				PlayerUnitHpMultiplier = 1f;
				_playerHpText = "1";
				PlayerUnitDamageMultiplier = 1f;
				_playerDmgText = "1";
				PlayerUnitAttackSpeedMultiplier = 1f;
				_playerAtkSpdText = "1";
				PlayerUnitMoveSpeedMultiplier = 1f;
				_playerMoveSpdText = "1";
			}
			GUILayout.Space(10f);
			GUILayout.Label("<b>Tower Stats</b>", RichStyle, Array.Empty<GUILayoutOption>());
			DrawMultiplierField("HP:", ref _towerHpText, ref TowerHpMultiplier);
			DrawMultiplierField("Damage:", ref _towerDmgText, ref TowerDamageMultiplier);
			DrawMultiplierField("Attack Speed:", ref _towerAtkSpdText, ref TowerAttackSpeedMultiplier);
			if (GUILayout.Button("Reset Tower Stats", Array.Empty<GUILayoutOption>()))
			{
				TowerHpMultiplier = 1f;
				_towerHpText = "1";
				TowerDamageMultiplier = 1f;
				_towerDmgText = "1";
				TowerAttackSpeedMultiplier = 1f;
				_towerAtkSpdText = "1";
			}
			GUILayout.Space(10f);
			GUILayout.Label("<b>Coins</b>", RichStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Amount:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			_coinsText = GUILayout.TextField(_coinsText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			if (int.TryParse(_coinsText, out var result))
			{
				CoinsToSpawn = Mathf.Max(0, result);
			}
			if (GUILayout.Button("Spawn", Array.Empty<GUILayoutOption>()))
			{
				SpawnCoinsRequested = true;
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			GUILayout.Label("<i>Drag title to move · Drag corner to resize · F5 to toggle</i>", RichStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndScrollView();
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, 20f));
			HandleResize();
		}

		private void DrawMultiplierField(string label, ref string text, ref float value)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			text = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.Label("x", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(14f) });
			if (float.TryParse(text, out var result) && result > 0f)
			{
				value = result;
			}
			GUILayout.EndHorizontal();
		}

		private void HandleResize()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Invalid comparison between Unknown and I4
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref _windowRect)).width - 16f, ((Rect)(ref _windowRect)).height - 16f, 16f, 16f);
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(1f, 1f, 1f, 0.3f), 0f, 0f);
			Event current = Event.current;
			if ((int)current.type == 0 && ((Rect)(ref val)).Contains(current.mousePosition))
			{
				_isResizing = true;
			}
			if (_isResizing)
			{
				((Rect)(ref _windowRect)).width = Mathf.Max(280f, current.mousePosition.x + 4f);
				((Rect)(ref _windowRect)).height = Mathf.Max(300f, current.mousePosition.y + 4f);
			}
			if ((int)current.type == 1)
			{
				_isResizing = false;
			}
		}
	}
	[BepInPlugin("com.easyfall", "EasyFall", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.easyfall";

		public const string PluginName = "EasyFall";

		public const string PluginVersion = "0.1.0";

		internal static ManualLogSource Logger;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			((Component)this).gameObject.AddComponent<ModMenu>();
			Logger.LogInfo((object)"EasyFall v0.1.0 loaded!");
			_harmony = new Harmony("com.easyfall");
			_harmony.PatchAll();
			Logger.LogInfo((object)"All patches applied.");
		}

		private void Update()
		{
			if (!((Object)(object)ModMenu.Instance == (Object)null))
			{
				if (ModMenu.Instance.PlayerStatsChanged)
				{
					PlayerUnitHpPatch.ReapplyAll();
					PlayerUnitAutoAttackPatch.ReapplyAll();
					PlayerUnitMoveSpeedPatch.ReapplyAll();
				}
				if (ModMenu.Instance.PlayerCharStatsChanged)
				{
					PlayerCharacterMoveSpeedPatch.ReapplyIfNeeded();
					PlayerCharacterHpPatch.ReapplyIfNeeded();
					PlayerCharacterAttackPatch.ReapplyIfNeeded();
					PlayerCharacterDamagePatch.ReapplyIfNeeded();
				}
				TowerHpPatch.ApplyToAllTowers();
				TowerAutoAttackPatch.ApplyToAllTowers();
				if (ModMenu.Instance.SpawnCoinsRequested)
				{
					ModMenu.Instance.SpawnCoinsRequested = false;
					SpawnCoins(ModMenu.Instance.CoinsToSpawn);
				}
			}
		}

		private void SpawnCoins(int amount)
		{
			if (amount > 0)
			{
				if ((Object)(object)PlayerInteraction.instance == (Object)null)
				{
					Logger.LogWarning((object)"Cannot spawn coins: no PlayerInteraction instance.");
					return;
				}
				PlayerInteraction.instance.AddCoin(amount);
				Logger.LogInfo((object)$"Spawned {amount} coins.");
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace EasyFall.Patches
{
	[HarmonyPatch(typeof(Spawn), "Update")]
	public static class SpawnUpdatePatch
	{
		private static bool Prefix(Spawn __instance)
		{
			if ((Object)(object)ModMenu.Instance == (Object)null || !ModMenu.Instance.InstantWaveSpawn)
			{
				return true;
			}
			__instance.delay = 0f;
			__instance.interval = 0f;
			__instance.waitBeforeNextSpawn = 0f;
			return true;
		}
	}
	[HarmonyPatch(typeof(EnemySpawner), "Update")]
	public static class EnemySpawnerUpdatePatch
	{
		private static readonly FieldRef<EnemySpawner, int> PauseSpawningRef = AccessTools.FieldRefAccess<EnemySpawner, int>("pauseSpawningAtEnemyCount");

		private static readonly FieldRef<EnemySpawner, int> WavenumberRef = AccessTools.FieldRefAccess<EnemySpawner, int>("wavenumber");

		private static void Prefix(EnemySpawner __instance)
		{
			if (!((Object)(object)ModMenu.Instance == (Object)null) && ModMenu.Instance.InstantWaveSpawn)
			{
				PauseSpawningRef.Invoke(__instance) = int.MaxValue;
			}
		}

		private static void Postfix(EnemySpawner __instance)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ModMenu.Instance == (Object)null) && ModMenu.Instance.AutoStartNextWave && !__instance.SpawningInProgress && !__instance.MatchOver)
			{
				DayNightCycle instance = DayNightCycle.Instance;
				if (!((Object)(object)instance == (Object)null) && (int)instance.CurrentTimestate == 0 && __instance.NumberOfEnemiesOnTheMap <= 0 && WavenumberRef.Invoke(__instance) > 0)
				{
					instance.SwitchToNight();
				}
			}
		}
	}
	[HarmonyPatch(typeof(ManualAttack), "FindAttackTarget")]
	public static class PlayerRandomTargetPatch
	{
		private static readonly List<TaggedObject> InRange = new List<TaggedObject>();

		private static void Postfix(ManualAttack __instance, ref TaggedObject __result)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ModMenu.Instance == (Object)null || !ModMenu.Instance.PlayerRandomTarget || (Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			IReadOnlyList<TaggedObject> enemyUnits = TagManager.instance.EnemyUnits;
			if (enemyUnits == null || enemyUnits.Count == 0)
			{
				return;
			}
			float num = (((Object)(object)__instance.weapon != (Object)null) ? __instance.weapon.maximumChaseRange : 0f);
			if (num <= 0f)
			{
				return;
			}
			float num2 = num * num;
			Vector3 position = ((Component)__instance).transform.position;
			InRange.Clear();
			for (int i = 0; i < enemyUnits.Count; i++)
			{
				TaggedObject val = enemyUnits[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Hp hp = val.Hp;
				if (!((Object)(object)hp == (Object)null) && hp.Alive)
				{
					Vector3 val2 = ((Component)val).transform.position - position;
					if (((Vector3)(ref val2)).sqrMagnitude <= num2)
					{
						InRange.Add(val);
					}
				}
			}
			if (InRange.Count != 0)
			{
				__result = InRange[Random.Range(0, InRange.Count)];
			}
		}
	}
	internal static class HpFieldAccess
	{
		public static readonly FieldRef<Hp, float> HpValue = AccessTools.FieldRefAccess<Hp, float>("hp");

		public static void SetMaxHpSilent(Hp hp, float newMax)
		{
			float maxHp = hp.maxHp;
			float num = HpValue.Invoke(hp);
			float num2 = ((maxHp > 0f) ? (num / maxHp) : 1f);
			hp.maxHp = newMax;
			HpValue.Invoke(hp) = newMax * num2;
		}

		public static void ScaleHpSilent(Hp hp, float mult, HashSet<Hp> scaled)
		{
			float num;
			if (scaled.Contains(hp))
			{
				num = hp.HpOriginal;
			}
			else
			{
				num = (hp.HpOriginal = hp.HpOriginal);
				scaled.Add(hp);
			}
			SetMaxHpSilent(hp, num * mult);
		}
	}
	[HarmonyPatch(typeof(Hp), "Start")]
	public static class HpStartPatch
	{
		private static void Postfix(Hp __instance)
		{
			if ((Object)(object)ModMenu.Instance == (Object)null)
			{
				return;
			}
			ModMenu instance = ModMenu.Instance;
			if (instance.PlayerUnitHpMultiplier == 1f && instance.PlayerHpMultiplier == 1f && instance.PlayerDamageMultiplier == 1f && instance.TowerHpMultiplier == 1f)
			{
				return;
			}
			TaggedObject taggedObj = __instance.TaggedObj;
			if ((Object)(object)taggedObj == (Object)null)
			{
				return;
			}
			List<ETag> tags = taggedObj.Tags;
			if (instance.PlayerUnitHpMultiplier != 1f && tags.Contains((ETag)7))
			{
				PlayerUnitHpPatch.TryApply(__instance);
			}
			if (tags.Contains((ETag)2))
			{
				if (instance.PlayerHpMultiplier != 1f)
				{
					PlayerCharacterHpPatch.TryApply(__instance);
				}
				if (instance.PlayerDamageMultiplier != 1f)
				{
					PlayerCharacterDamagePatch.Apply(__instance);
				}
			}
			if (instance.TowerHpMultiplier != 1f && tags.Contains((ETag)24))
			{
				TowerHpPatch.TryApply(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(AutoAttack), "Start")]
	public static class AutoAttackStartPatch
	{
		private static void Postfix(AutoAttack __instance)
		{
			if ((Object)(object)ModMenu.Instance == (Object)null)
			{
				return;
			}
			ModMenu instance = ModMenu.Instance;
			if (instance.PlayerUnitAttackSpeedMultiplier == 1f && instance.PlayerUnitDamageMultiplier == 1f && instance.TowerAttackSpeedMultiplier == 1f && instance.TowerDamageMultiplier == 1f)
			{
				return;
			}
			TaggedObject component = ((Component)__instance).GetComponent<TaggedObject>();
			if (!((Object)(object)component == (Object)null))
			{
				List<ETag> tags = component.Tags;
				if ((instance.PlayerUnitAttackSpeedMultiplier != 1f || instance.PlayerUnitDamageMultiplier != 1f) && tags.Contains((ETag)7))
				{
					PlayerUnitAutoAttackPatch.TryApply(__instance);
				}
				if ((instance.TowerAttackSpeedMultiplier != 1f || instance.TowerDamageMultiplier != 1f) && tags.Contains((ETag)24))
				{
					TowerAutoAttackPatch.TryApply(__instance);
				}
			}
		}
	}
	public static class PlayerUnitHpPatch
	{
		private static readonly HashSet<Hp> Scaled = new HashSet<Hp>();

		public static void TryApply(Hp hp)
		{
			float playerUnitHpMultiplier = ModMenu.Instance.PlayerUnitHpMultiplier;
			if (playerUnitHpMultiplier != 1f || Scaled.Contains(hp))
			{
				HpFieldAccess.ScaleHpSilent(hp, playerUnitHpMultiplier, Scaled);
			}
		}

		public static void ReapplyAll()
		{
			if ((Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			IReadOnlyList<TaggedObject> playerUnits = TagManager.instance.PlayerUnits;
			for (int i = 0; i < playerUnits.Count; i++)
			{
				Hp component = ((Component)playerUnits[i]).GetComponent<Hp>();
				if ((Object)(object)component != (Object)null)
				{
					TryApply(component);
				}
			}
		}
	}
	public static class PlayerUnitAutoAttackPatch
	{
		private static readonly Dictionary<AutoAttack, float> OriginalCooldowns = new Dictionary<AutoAttack, float>();

		public static void TryApply(AutoAttack atk)
		{
			if (!OriginalCooldowns.ContainsKey(atk))
			{
				OriginalCooldowns[atk] = atk.cooldownDuration;
			}
			float num = OriginalCooldowns[atk];
			atk.cooldownDuration = num / ModMenu.Instance.PlayerUnitAttackSpeedMultiplier;
			atk.DamageMultiplyer = ModMenu.Instance.PlayerUnitDamageMultiplier;
		}

		public static void ReapplyAll()
		{
			if ((Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			IReadOnlyList<TaggedObject> playerUnits = TagManager.instance.PlayerUnits;
			for (int i = 0; i < playerUnits.Count; i++)
			{
				AutoAttack[] components = ((Component)playerUnits[i]).GetComponents<AutoAttack>();
				for (int j = 0; j < components.Length; j++)
				{
					TryApply(components[j]);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PathfindMovementPlayerunit), "Start")]
	public static class PlayerUnitMoveSpeedPatch
	{
		private static readonly Dictionary<PathfindMovementPlayerunit, float> OriginalSpeeds = new Dictionary<PathfindMovementPlayerunit, float>();

		private static void Postfix(PathfindMovementPlayerunit __instance)
		{
			if (!((Object)(object)ModMenu.Instance == (Object)null) && ModMenu.Instance.PlayerUnitMoveSpeedMultiplier != 1f)
			{
				TryApply(__instance);
			}
		}

		public static void TryApply(PathfindMovementPlayerunit mov)
		{
			if (!OriginalSpeeds.ContainsKey(mov))
			{
				OriginalSpeeds[mov] = mov.movementSpeed;
			}
			mov.movementSpeed = OriginalSpeeds[mov] * ModMenu.Instance.PlayerUnitMoveSpeedMultiplier;
		}

		public static void ReapplyAll()
		{
			if ((Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			IReadOnlyList<TaggedObject> playerUnits = TagManager.instance.PlayerUnits;
			for (int i = 0; i < playerUnits.Count; i++)
			{
				PathfindMovementPlayerunit component = ((Component)playerUnits[i]).GetComponent<PathfindMovementPlayerunit>();
				if ((Object)(object)component != (Object)null)
				{
					TryApply(component);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "Start")]
	public static class PlayerCharacterMoveSpeedPatch
	{
		private static readonly Dictionary<PlayerMovement, float[]> OriginalSpeeds = new Dictionary<PlayerMovement, float[]>();

		private static void Postfix(PlayerMovement __instance)
		{
			if (!((Object)(object)ModMenu.Instance == (Object)null) && ModMenu.Instance.PlayerMoveSpeedMultiplier != 1f)
			{
				StoreAndApply(__instance);
			}
		}

		public static void StoreAndApply(PlayerMovement pm)
		{
			if (!OriginalSpeeds.ContainsKey(pm))
			{
				OriginalSpeeds[pm] = new float[4] { pm.speed, pm.sprintSpeed, pm.speedDuringDay, pm.sprintSpeedDuringDay };
			}
			float[] array = OriginalSpeeds[pm];
			float playerMoveSpeedMultiplier = ModMenu.Instance.PlayerMoveSpeedMultiplier;
			pm.speed = array[0] * playerMoveSpeedMultiplier;
			pm.sprintSpeed = array[1] * playerMoveSpeedMultiplier;
			pm.speedDuringDay = array[2] * playerMoveSpeedMultiplier;
			pm.sprintSpeedDuringDay = array[3] * playerMoveSpeedMultiplier;
		}

		public static void ReapplyIfNeeded()
		{
			if (!((Object)(object)PlayerMovement.instance == (Object)null))
			{
				StoreAndApply(PlayerMovement.instance);
			}
		}
	}
	public static class PlayerCharacterHpPatch
	{
		private static readonly Dictionary<Hp, float> OriginalMaxHp = new Dictionary<Hp, float>();

		public static void TryApply(Hp hp)
		{
			float playerHpMultiplier = ModMenu.Instance.PlayerHpMultiplier;
			if (playerHpMultiplier != 1f || OriginalMaxHp.ContainsKey(hp))
			{
				if (!OriginalMaxHp.ContainsKey(hp))
				{
					OriginalMaxHp[hp] = hp.HpOriginal;
				}
				HpFieldAccess.SetMaxHpSilent(hp, OriginalMaxHp[hp] * playerHpMultiplier);
			}
		}

		public static void ReapplyIfNeeded()
		{
			if ((Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			IReadOnlyList<TaggedObject> players = TagManager.instance.Players;
			for (int i = 0; i < players.Count; i++)
			{
				Hp component = ((Component)players[i]).GetComponent<Hp>();
				if ((Object)(object)component != (Object)null)
				{
					TryApply(component);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ManualAttack), "Start")]
	public static class PlayerCharacterAttackPatch
	{
		private static readonly Dictionary<ManualAttack, float> OriginalCooldowns = new Dictionary<ManualAttack, float>();

		private static void Postfix(ManualAttack __instance)
		{
			if (!((Object)(object)ModMenu.Instance == (Object)null) && ModMenu.Instance.PlayerAttackSpeedMultiplier != 1f)
			{
				TryApply(__instance);
			}
		}

		public static void TryApply(ManualAttack atk)
		{
			if (!OriginalCooldowns.ContainsKey(atk))
			{
				OriginalCooldowns[atk] = atk.cooldownTime;
			}
			float num = OriginalCooldowns[atk];
			atk.cooldownTime = num / ModMenu.Instance.PlayerAttackSpeedMultiplier;
		}

		public static void ReapplyIfNeeded()
		{
			if (!((Object)(object)PlayerInteraction.instance == (Object)null))
			{
				ManualAttack manualAttack = PlayerInteraction.instance.ManualAttack;
				if ((Object)(object)manualAttack != (Object)null)
				{
					TryApply(manualAttack);
				}
				ManualAttack autoAttack = PlayerInteraction.instance.AutoAttack;
				if ((Object)(object)autoAttack != (Object)null)
				{
					TryApply(autoAttack);
				}
			}
		}
	}
	public static class PlayerCharacterDamagePatch
	{
		public static void Apply(Hp hp)
		{
			if (ModMenu.Instance.PlayerDamageMultiplier != 1f)
			{
				hp.DamageMultiplyer = ModMenu.Instance.PlayerDamageMultiplier;
			}
		}

		public static void ReapplyIfNeeded()
		{
			if ((Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			IReadOnlyList<TaggedObject> players = TagManager.instance.Players;
			for (int i = 0; i < players.Count; i++)
			{
				Hp component = ((Component)players[i]).GetComponent<Hp>();
				if ((Object)(object)component != (Object)null)
				{
					component.DamageMultiplyer = ModMenu.Instance.PlayerDamageMultiplier;
				}
			}
		}
	}
	public static class TowerHpPatch
	{
		private static readonly HashSet<Hp> Scaled = new HashSet<Hp>();

		private static readonly HashSet<Hp> Applied = new HashSet<Hp>();

		private static float _lastMult = 1f;

		public static void TryApply(Hp hp)
		{
			float towerHpMultiplier = ModMenu.Instance.TowerHpMultiplier;
			if (towerHpMultiplier != 1f || Scaled.Contains(hp))
			{
				HpFieldAccess.ScaleHpSilent(hp, towerHpMultiplier, Scaled);
				Applied.Add(hp);
			}
		}

		public static void ApplyToAllTowers()
		{
			if ((Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			float towerHpMultiplier = ModMenu.Instance.TowerHpMultiplier;
			bool flag = towerHpMultiplier != _lastMult;
			if (towerHpMultiplier == 1f && !flag)
			{
				return;
			}
			_lastMult = towerHpMultiplier;
			List<TaggedObject> list = TagManager.instance.FindAllTaggedObjectsWithTagDirect_UseWithCare((ETag)24);
			if (list == null)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				Hp component = ((Component)list[i]).GetComponent<Hp>();
				if (!((Object)(object)component == (Object)null) && (flag || !Applied.Contains(component)))
				{
					TryApply(component);
				}
			}
		}
	}
	public static class TowerAutoAttackPatch
	{
		private static readonly Dictionary<AutoAttack, float> OriginalCooldowns = new Dictionary<AutoAttack, float>();

		private static readonly HashSet<AutoAttack> Applied = new HashSet<AutoAttack>();

		private static float _lastDmgMult = 1f;

		private static float _lastAtkSpdMult = 1f;

		public static void TryApply(AutoAttack atk)
		{
			if (!OriginalCooldowns.ContainsKey(atk))
			{
				OriginalCooldowns[atk] = atk.cooldownDuration;
			}
			float num = OriginalCooldowns[atk];
			atk.cooldownDuration = num / ModMenu.Instance.TowerAttackSpeedMultiplier;
			atk.DamageMultiplyer = ModMenu.Instance.TowerDamageMultiplier;
			Applied.Add(atk);
		}

		public static void ApplyToAllTowers()
		{
			if ((Object)(object)TagManager.instance == (Object)null)
			{
				return;
			}
			float towerDamageMultiplier = ModMenu.Instance.TowerDamageMultiplier;
			float towerAttackSpeedMultiplier = ModMenu.Instance.TowerAttackSpeedMultiplier;
			bool flag = towerDamageMultiplier != _lastDmgMult || towerAttackSpeedMultiplier != _lastAtkSpdMult;
			if (towerDamageMultiplier == 1f && towerAttackSpeedMultiplier == 1f && !flag)
			{
				return;
			}
			_lastDmgMult = towerDamageMultiplier;
			_lastAtkSpdMult = towerAttackSpeedMultiplier;
			List<TaggedObject> list = TagManager.instance.FindAllTaggedObjectsWithTagDirect_UseWithCare((ETag)24);
			if (list == null)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				AutoAttack[] components = ((Component)list[i]).GetComponents<AutoAttack>();
				foreach (AutoAttack val in components)
				{
					if (flag || !Applied.Contains(val))
					{
						TryApply(val);
					}
				}
			}
		}
	}
}