Decompiled source of Magical v1.0.3

Magical.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Magical")]
[assembly: AssemblyDescription("Magical")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Crystal")]
[assembly: AssemblyProduct("Magical")]
[assembly: AssemblyCopyright("Copyright © 2023 Crystal Ferrai")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1414a5c1-1a42-448f-8f27-000b965fcb46")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.3.0")]
namespace Magical;

[BepInPlugin("dev.crystal.magical", "Magical", "1.0.3.0")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class MagicalPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Player))]
	private static class Player_Tracking_Patches
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void Awake_Prefix(Player __instance)
		{
			SetPlayerValues(__instance);
			sPlayers.Add(__instance);
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroy_Prefix(Player __instance)
		{
			sPlayers.Remove(__instance);
		}
	}

	[HarmonyPatch(typeof(Player))]
	private static class Player_Patches
	{
		private enum TranspilerState
		{
			Searching,
			Checking,
			Replacing,
			Searching2,
			Checking2,
			Replacing2,
			Finishing
		}

		[CompilerGenerated]
		private sealed class <GetTotalFoodValue_Transpiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private TranspilerState <state>5__2;

			private IEnumerator<CodeInstruction> <>7__wrap2;

			private CodeInstruction <instruction>5__4;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetTotalFoodValue_Transpiler>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 3u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap2 = null;
				<instruction>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<state>5__2 = TranspilerState.Searching;
						<>7__wrap2 = instructions.GetEnumerator();
						<>1__state = -3;
						goto IL_015d;
					case 1:
						<>1__state = -3;
						goto IL_0156;
					case 2:
						<>1__state = -3;
						<>2__current = <instruction>5__4;
						<>1__state = 3;
						return true;
					case 3:
						<>1__state = -3;
						<state>5__2 = TranspilerState.Finishing;
						goto IL_0156;
					case 4:
						{
							<>1__state = -3;
							goto IL_0156;
						}
						IL_015d:
						if (<>7__wrap2.MoveNext())
						{
							<instruction>5__4 = <>7__wrap2.Current;
							switch (<state>5__2)
							{
							case TranspilerState.Searching:
								if (<instruction>5__4.opcode == OpCodes.Ldc_R4 && (float)<instruction>5__4.operand == 0f)
								{
									<state>5__2 = TranspilerState.Replacing;
									break;
								}
								<>2__current = <instruction>5__4;
								<>1__state = 1;
								return true;
							case TranspilerState.Replacing:
								<>2__current = new CodeInstruction(OpCodes.Ldc_R4, (object)BaseEitr.Value);
								<>1__state = 2;
								return true;
							case TranspilerState.Finishing:
								<>2__current = <instruction>5__4;
								<>1__state = 4;
								return true;
							}
							goto IL_0156;
						}
						<>m__Finally1();
						<>7__wrap2 = null;
						return false;
						IL_0156:
						<instruction>5__4 = null;
						goto IL_015d;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap2 != null)
				{
					<>7__wrap2.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<GetTotalFoodValue_Transpiler>d__2 <GetTotalFoodValue_Transpiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetTotalFoodValue_Transpiler>d__ = this;
				}
				else
				{
					<GetTotalFoodValue_Transpiler>d__ = new <GetTotalFoodValue_Transpiler>d__2(0);
				}
				<GetTotalFoodValue_Transpiler>d__.instructions = <>3__instructions;
				return <GetTotalFoodValue_Transpiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <UpdateFood_Transpiler>d__1 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private TranspilerState <state>5__2;

			private CodeInstruction <previousInstruction>5__3;

			private IEnumerator<CodeInstruction> <>7__wrap3;

			private CodeInstruction <instruction>5__5;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <UpdateFood_Transpiler>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 10u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<previousInstruction>5__3 = null;
				<>7__wrap3 = null;
				<instruction>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0199: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Expected O, but got Unknown
				//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f2: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<state>5__2 = TranspilerState.Searching;
						<previousInstruction>5__3 = null;
						<>7__wrap3 = instructions.GetEnumerator();
						<>1__state = -3;
						goto IL_037b;
					case 1:
						<>1__state = -3;
						goto IL_0374;
					case 2:
						<>1__state = -3;
						<state>5__2 = TranspilerState.Searching;
						goto IL_0374;
					case 3:
						<>1__state = -3;
						<>2__current = <instruction>5__5;
						<>1__state = 4;
						return true;
					case 4:
						<>1__state = -3;
						<state>5__2 = TranspilerState.Searching2;
						goto IL_0374;
					case 5:
						<>1__state = -3;
						goto IL_0374;
					case 6:
						<>1__state = -3;
						<>2__current = <instruction>5__5;
						<>1__state = 7;
						return true;
					case 7:
						<>1__state = -3;
						<state>5__2 = TranspilerState.Searching2;
						goto IL_0374;
					case 8:
						<>1__state = -3;
						<>2__current = <previousInstruction>5__3;
						<>1__state = 9;
						return true;
					case 9:
						<>1__state = -3;
						<>2__current = <instruction>5__5;
						<>1__state = 10;
						return true;
					case 10:
						<>1__state = -3;
						<state>5__2 = TranspilerState.Finishing;
						goto IL_0374;
					case 11:
						{
							<>1__state = -3;
							goto IL_0374;
						}
						IL_037b:
						if (<>7__wrap3.MoveNext())
						{
							<instruction>5__5 = <>7__wrap3.Current;
							switch (<state>5__2)
							{
							case TranspilerState.Searching:
								if (<instruction>5__5.opcode == OpCodes.Ldfld && ((FieldInfo)<instruction>5__5.operand).Name.Equals("m_foodRegenTimer"))
								{
									<state>5__2 = TranspilerState.Checking;
								}
								<>2__current = <instruction>5__5;
								<>1__state = 1;
								return true;
							case TranspilerState.Checking:
								if (<instruction>5__5.opcode == OpCodes.Ldc_R4 && (float)<instruction>5__5.operand == 10f)
								{
									<state>5__2 = TranspilerState.Replacing;
									break;
								}
								<>2__current = <instruction>5__5;
								<>1__state = 2;
								return true;
							case TranspilerState.Replacing:
								<>2__current = new CodeInstruction(OpCodes.Ldc_R4, (object)HealthRegenTickRate.Value);
								<>1__state = 3;
								return true;
							case TranspilerState.Searching2:
								if (<instruction>5__5.opcode == OpCodes.Ldc_R4 && (float)<instruction>5__5.operand == 0f)
								{
									<previousInstruction>5__3 = <instruction>5__5;
									<state>5__2 = TranspilerState.Checking2;
									break;
								}
								<>2__current = <instruction>5__5;
								<>1__state = 5;
								return true;
							case TranspilerState.Checking2:
								if (<instruction>5__5.opcode == OpCodes.Stloc_S)
								{
									<previousInstruction>5__3 = <instruction>5__5;
									<state>5__2 = TranspilerState.Replacing2;
									break;
								}
								<>2__current = <previousInstruction>5__3;
								<>1__state = 6;
								return true;
							case TranspilerState.Replacing2:
								<>2__current = new CodeInstruction(OpCodes.Ldc_R4, (object)BaseHealthRegen.Value);
								<>1__state = 8;
								return true;
							case TranspilerState.Finishing:
								<>2__current = <instruction>5__5;
								<>1__state = 11;
								return true;
							}
							goto IL_0374;
						}
						<>m__Finally1();
						<>7__wrap3 = null;
						return false;
						IL_0374:
						<instruction>5__5 = null;
						goto IL_037b;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap3 != null)
				{
					<>7__wrap3.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<UpdateFood_Transpiler>d__1 <UpdateFood_Transpiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<UpdateFood_Transpiler>d__ = this;
				}
				else
				{
					<UpdateFood_Transpiler>d__ = new <UpdateFood_Transpiler>d__1(0);
				}
				<UpdateFood_Transpiler>d__.instructions = <>3__instructions;
				return <UpdateFood_Transpiler>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		[IteratorStateMachine(typeof(<UpdateFood_Transpiler>d__1))]
		[HarmonyPatch("UpdateFood")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> UpdateFood_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <UpdateFood_Transpiler>d__1(-2)
			{
				<>3__instructions = instructions
			};
		}

		[IteratorStateMachine(typeof(<GetTotalFoodValue_Transpiler>d__2))]
		[HarmonyPatch("GetTotalFoodValue")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> GetTotalFoodValue_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetTotalFoodValue_Transpiler>d__2(-2)
			{
				<>3__instructions = instructions
			};
		}
	}

	[HarmonyPatch(typeof(Attack))]
	private static class Attack_Patches
	{
		private enum TranspilerState
		{
			Searching,
			Replacing,
			Finishing
		}

		[CompilerGenerated]
		private sealed class <ReplaceSkillModifier>d__4 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private float newModifier;

			public float <>3__newModifier;

			private TranspilerState <state>5__2;

			private IEnumerator<CodeInstruction> <>7__wrap2;

			private CodeInstruction <instruction>5__4;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ReplaceSkillModifier>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 3u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap2 = null;
				<instruction>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<state>5__2 = TranspilerState.Searching;
						<>7__wrap2 = instructions.GetEnumerator();
						<>1__state = -3;
						goto IL_015d;
					case 1:
						<>1__state = -3;
						goto IL_0156;
					case 2:
						<>1__state = -3;
						<>2__current = <instruction>5__4;
						<>1__state = 3;
						return true;
					case 3:
						<>1__state = -3;
						<state>5__2 = TranspilerState.Finishing;
						goto IL_0156;
					case 4:
						{
							<>1__state = -3;
							goto IL_0156;
						}
						IL_015d:
						if (<>7__wrap2.MoveNext())
						{
							<instruction>5__4 = <>7__wrap2.Current;
							switch (<state>5__2)
							{
							case TranspilerState.Searching:
								if (<instruction>5__4.opcode == OpCodes.Ldc_R4 && (float)<instruction>5__4.operand == 0.33f)
								{
									<state>5__2 = TranspilerState.Replacing;
									break;
								}
								<>2__current = <instruction>5__4;
								<>1__state = 1;
								return true;
							case TranspilerState.Replacing:
								<>2__current = new CodeInstruction(OpCodes.Ldc_R4, (object)newModifier);
								<>1__state = 2;
								return true;
							case TranspilerState.Finishing:
								<>2__current = <instruction>5__4;
								<>1__state = 4;
								return true;
							}
							goto IL_0156;
						}
						<>m__Finally1();
						<>7__wrap2 = null;
						return false;
						IL_0156:
						<instruction>5__4 = null;
						goto IL_015d;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap2 != null)
				{
					<>7__wrap2.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<ReplaceSkillModifier>d__4 <ReplaceSkillModifier>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<ReplaceSkillModifier>d__ = this;
				}
				else
				{
					<ReplaceSkillModifier>d__ = new <ReplaceSkillModifier>d__4(0);
				}
				<ReplaceSkillModifier>d__.instructions = <>3__instructions;
				<ReplaceSkillModifier>d__.newModifier = <>3__newModifier;
				return <ReplaceSkillModifier>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		[HarmonyPatch("GetAttackStamina")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> GetAttackStamina_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return ReplaceSkillModifier(instructions, SkillStaminaReduction.Value);
		}

		[HarmonyPatch("GetAttackEitr")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> GetAttackEitr_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return ReplaceSkillModifier(instructions, SkillEitrReduction.Value);
		}

		[HarmonyPatch("GetAttackHealth")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> GetAttackHealth_Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			return ReplaceSkillModifier(instructions, SkillHealthReduction.Value);
		}

		[IteratorStateMachine(typeof(<ReplaceSkillModifier>d__4))]
		private static IEnumerable<CodeInstruction> ReplaceSkillModifier(IEnumerable<CodeInstruction> instructions, float newModifier)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ReplaceSkillModifier>d__4(-2)
			{
				<>3__instructions = instructions,
				<>3__newModifier = newModifier
			};
		}
	}

	public const string ModId = "dev.crystal.magical";

	public static ConfigEntry<float> BaseStamina;

	public static ConfigEntry<float> BaseEitr;

	public static ConfigEntry<float> BaseHealth;

	public static ConfigEntry<float> BaseStaminaRegen;

	public static ConfigEntry<float> BaseEitrRegen;

	public static ConfigEntry<float> BaseHealthRegen;

	public static ConfigEntry<float> StaminaRegenDelay;

	public static ConfigEntry<float> EitrRegenDelay;

	public static ConfigEntry<float> HealthRegenTickRate;

	public static ConfigEntry<float> SkillStaminaReduction;

	public static ConfigEntry<float> SkillEitrReduction;

	public static ConfigEntry<float> SkillHealthReduction;

	private static Harmony sPlayerTrackingHarmony;

	private static Harmony sPlayerHarmony;

	private static Harmony sAttackHarmony;

	private static List<Player> sPlayers;

	static MagicalPlugin()
	{
		sPlayers = new List<Player>();
	}

	private void Awake()
	{
		//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c7: Expected O, but got Unknown
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d6: Expected O, but got Unknown
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Expected O, but got Unknown
		BaseStamina = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "BaseStamina", 50f, "Maximum stamina before any food modifiers are applied. Game default 50.");
		BaseStamina.SettingChanged += PlayerVariable_SettingChanged;
		BaseEitr = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "BaseEitr", 0f, "Maximum eitr before any food modifiers are applied. Game default 0.");
		BaseEitr.SettingChanged += PlayerConstant_SettingChanged;
		BaseHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "BaseHealth", 25f, "Maximum health before any food modifiers are applied. Game default 25.");
		BaseHealth.SettingChanged += PlayerVariable_SettingChanged;
		BaseStaminaRegen = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "BaseStaminaRegen", 6f, "The base rate of stamina regen per second, before any modifiers are applied. Game default 6.");
		BaseStaminaRegen.SettingChanged += PlayerVariable_SettingChanged;
		BaseEitrRegen = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "BaseEitrRegen", 2f, "The base rate of eitr regen per second, before any modifiers are applied. Game default 2.");
		BaseEitrRegen.SettingChanged += PlayerVariable_SettingChanged;
		BaseHealthRegen = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "BaseHealthRegen", 0f, "The base rate of health regen per health regen tick, before any modifiers are applied. Game default 0.");
		BaseHealthRegen.SettingChanged += PlayerConstant_SettingChanged;
		StaminaRegenDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "StaminaRegenDelay", 1f, "The number of seconds after using stamina before it starts to regenerate. Game default 1.");
		StaminaRegenDelay.SettingChanged += PlayerVariable_SettingChanged;
		EitrRegenDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "EitrRegenDelay", 1f, "The number of seconds after using eitr before it starts to regenerate. Game default 1.");
		EitrRegenDelay.SettingChanged += PlayerVariable_SettingChanged;
		HealthRegenTickRate = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "HealthRegenTickRate", 10f, "The number of seconds between ticks of health regeneration. Game default 10.");
		HealthRegenTickRate.SettingChanged += PlayerConstant_SettingChanged;
		SkillStaminaReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillStaminaReduction", 0.33f, "Stamina cost reduction multiplier for actions based on player skill. Value represents reduction with 100 skill and will scale down at lower skill levels. Game default 0.33.");
		SkillStaminaReduction.SettingChanged += Attack_SettingChanged;
		SkillEitrReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillEitrReduction", 0.33f, "Eitr cost reduction multiplier for actions based on player skill. Value represents reduction with 100 skill and will scale down at lower skill levels. Game default 0.33.");
		SkillEitrReduction.SettingChanged += Attack_SettingChanged;
		SkillHealthReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillHealthReduction", 0.33f, "Health cost reduction multiplier for actions based on player skill. Value represents reduction with 100 skill and will scale down at lower skill levels. Game default 0.33.");
		SkillHealthReduction.SettingChanged += Attack_SettingChanged;
		sPlayerTrackingHarmony = new Harmony("dev.crystal.magical_Player_Tracking");
		sPlayerHarmony = new Harmony("dev.crystal.magical_Player");
		sAttackHarmony = new Harmony("dev.crystal.magical_Attack");
		ClampConfig();
		sPlayerTrackingHarmony.PatchAll(typeof(Player_Tracking_Patches));
		sPlayerHarmony.PatchAll(typeof(Player_Patches));
		sAttackHarmony.PatchAll(typeof(Attack_Patches));
	}

	private void OnDestroy()
	{
		sPlayerTrackingHarmony.UnpatchSelf();
		sPlayerHarmony.UnpatchSelf();
		sAttackHarmony.UnpatchSelf();
		sPlayers.Clear();
	}

	private static void ClampConfig()
	{
		if (BaseStamina.Value < 0f)
		{
			BaseStamina.Value = 0f;
		}
		if (BaseStamina.Value > 1000f)
		{
			BaseStamina.Value = 1000f;
		}
		if (BaseEitr.Value < 0f)
		{
			BaseEitr.Value = 0f;
		}
		if (BaseEitr.Value > 1000f)
		{
			BaseEitr.Value = 1000f;
		}
		if (BaseHealth.Value < 0f)
		{
			BaseHealth.Value = 0f;
		}
		if (BaseHealth.Value > 1000f)
		{
			BaseHealth.Value = 1000f;
		}
		if (BaseStaminaRegen.Value < 0.1f)
		{
			BaseStaminaRegen.Value = 0.1f;
		}
		if (BaseStaminaRegen.Value > 1000f)
		{
			BaseStaminaRegen.Value = 1000f;
		}
		if (BaseEitrRegen.Value < 0.1f)
		{
			BaseEitrRegen.Value = 0.1f;
		}
		if (BaseEitrRegen.Value > 1000f)
		{
			BaseEitrRegen.Value = 1000f;
		}
		if (BaseHealthRegen.Value < 0f)
		{
			BaseHealthRegen.Value = 0f;
		}
		if (BaseHealthRegen.Value > 1000f)
		{
			BaseHealthRegen.Value = 1000f;
		}
		if (StaminaRegenDelay.Value < 0.1f)
		{
			StaminaRegenDelay.Value = 0.1f;
		}
		if (StaminaRegenDelay.Value > 3600f)
		{
			StaminaRegenDelay.Value = 3600f;
		}
		if (EitrRegenDelay.Value < 0.1f)
		{
			EitrRegenDelay.Value = 0.1f;
		}
		if (EitrRegenDelay.Value > 3600f)
		{
			EitrRegenDelay.Value = 3600f;
		}
		if (HealthRegenTickRate.Value < 0.1f)
		{
			HealthRegenTickRate.Value = 0.1f;
		}
		if (HealthRegenTickRate.Value > 3600f)
		{
			HealthRegenTickRate.Value = 3600f;
		}
		if (SkillStaminaReduction.Value < 0f)
		{
			SkillStaminaReduction.Value = 0f;
		}
		if (SkillStaminaReduction.Value > 1f)
		{
			SkillStaminaReduction.Value = 1f;
		}
		if (SkillEitrReduction.Value < 0f)
		{
			SkillEitrReduction.Value = 0f;
		}
		if (SkillEitrReduction.Value > 1f)
		{
			SkillEitrReduction.Value = 1f;
		}
		if (SkillHealthReduction.Value < 0f)
		{
			SkillHealthReduction.Value = 0f;
		}
		if (SkillHealthReduction.Value > 1f)
		{
			SkillHealthReduction.Value = 1f;
		}
	}

	private void PlayerVariable_SettingChanged(object sender, EventArgs e)
	{
		ClampConfig();
		foreach (Player sPlayer in sPlayers)
		{
			SetPlayerValues(sPlayer);
		}
	}

	private void Attack_SettingChanged(object sender, EventArgs e)
	{
		ClampConfig();
		sAttackHarmony.UnpatchSelf();
		sAttackHarmony.PatchAll(typeof(Attack_Patches));
	}

	private void PlayerConstant_SettingChanged(object sender, EventArgs e)
	{
		ClampConfig();
		sPlayerHarmony.UnpatchSelf();
		sPlayerHarmony.PatchAll(typeof(Player_Patches));
	}

	private static void SetPlayerValues(Player player)
	{
		player.m_baseStamina = BaseStamina.Value;
		player.m_baseHP = BaseHealth.Value;
		player.m_staminaRegen = BaseStaminaRegen.Value;
		player.m_eiterRegen = BaseEitrRegen.Value;
		player.m_staminaRegenDelay = StaminaRegenDelay.Value;
		player.m_eitrRegenDelay = EitrRegenDelay.Value;
	}
}