Decompiled source of coopPlus v1.1.3

AOEHealingFix.dll

Decompiled a week 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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AOEHealingFix")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AOEHealingFix")]
[assembly: AssemblyTitle("AOEHealingFix")]
[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 AOEHealingFix
{
	[BepInPlugin("jill920.aoefix", "AOE Healing Fix", "1.0.0")]
	public class AOEHealingFixPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.aoefix";

		public const string MOD_NAME = "AOE Healing Fix";

		public const string MOD_VERSION = "1.0.0";

		public static AOEHealingFixPlugin Instance;

		public static ManualLogSource Logger;

		private void Awake()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			try
			{
				Harmony val = new Harmony("jill920.aoefix");
				val.PatchAll(Assembly.GetExecutingAssembly());
				Logger.LogInfo((object)"[AOE Healing Fix 1.0.0] Loaded successfully!");
				Logger.LogInfo((object)"  AOE healing now works on carried/downed players");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Harmony patch failed: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(AOE), "Explode")]
	internal static class AOE_Explode_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(AOE __instance)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Expected I4, but got Unknown
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Expected I4, but got Unknown
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Expected I4, but got Unknown
			AOEHealingFixPlugin.Logger.LogInfo((object)("[AOE DEBUG] Explode() called on " + ((Object)__instance).name));
			AOEHealingFixPlugin.Logger.LogInfo((object)$"[AOE DEBUG]   statusAmount: {__instance.statusAmount}, statusType: {__instance.statusType}");
			AOEHealingFixPlugin.Logger.LogInfo((object)$"[AOE DEBUG]   range: {__instance.range}, hasAffliction: {__instance.hasAffliction}");
			if (!(__instance.statusAmount < 0f))
			{
				AOEHealingFixPlugin.Logger.LogInfo((object)"[AOE DEBUG] Not a healing AOE (statusAmount >= 0), letting original handle");
				return true;
			}
			AOEHealingFixPlugin.Logger.LogInfo((object)$"[AOE DEBUG] HEALING AOE DETECTED! statusAmount: {__instance.statusAmount}");
			float statusAmount = __instance.statusAmount;
			STATUSTYPE statusType = __instance.statusType;
			STATUSTYPE[] addtlStatus = __instance.addtlStatus;
			bool hasAffliction = __instance.hasAffliction;
			Affliction affliction = __instance.affliction;
			__instance.statusAmount = 0f;
			__instance.hasAffliction = false;
			__instance.affliction = null;
			__instance.Explode();
			__instance.statusAmount = statusAmount;
			__instance.hasAffliction = hasAffliction;
			__instance.affliction = affliction;
			if (!PhotonNetwork.IsMasterClient)
			{
				AOEHealingFixPlugin.Logger.LogInfo((object)"[AOE DEBUG] Skipping healing application - not MasterClient");
				return false;
			}
			AOEHealingFixPlugin.Logger.LogInfo((object)"[AOE DEBUG] MasterClient: Processing healing...");
			float num = Mathf.Abs(statusAmount);
			Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, __instance.range, LayerMask.op_Implicit(HelperFunctions.GetMask(__instance.mask)));
			List<Character> list = new List<Character>();
			AOEHealingFixPlugin.Logger.LogInfo((object)$"[AOE DEBUG] Found {array.Length} colliders in range");
			Collider[] array2 = array;
			Character item = default(Character);
			Character val2 = default(Character);
			foreach (Collider val in array2)
			{
				if (CharacterRagdoll.TryGetCharacterFromCollider(val, ref item) && !list.Contains(item))
				{
					list.Add(item);
				}
				if (CharacterRagdoll.TryGetCharacterFromCollider(val, ref val2) && (Object)(object)val2.data.carriedPlayer != (Object)null && !list.Contains(val2.data.carriedPlayer))
				{
					list.Add(val2.data.carriedPlayer);
					AOEHealingFixPlugin.Logger.LogInfo((object)("[AOE DEBUG] Found carried player " + val2.data.carriedPlayer.characterName + " via carrier " + val2.characterName));
				}
			}
			foreach (Character item2 in list)
			{
				float num2 = Vector3.Distance(((Component)__instance).transform.position, item2.Center);
				if (num2 > __instance.range)
				{
					continue;
				}
				float num3 = Mathf.Pow(1f - num2 / __instance.range, __instance.factorPow);
				if (num3 < __instance.minFactor)
				{
					continue;
				}
				if (__instance.requireLineOfSigh)
				{
					RaycastHit val3 = HelperFunctions.LineCheck(((Component)__instance).transform.position, item2.Center, (LayerType)1, 0f, (QueryTriggerInteraction)1);
					if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val3)).transform))
					{
						continue;
					}
				}
				float num4 = num * num3;
				AOEHealingFixPlugin.Logger.LogInfo((object)$"[AOE DEBUG] Healing {item2.characterName} for {num4:F4} (factor: {num3:F4}) | IsCarried: {item2.data.isCarried}");
				HealingReceiver component = ((Component)item2).GetComponent<HealingReceiver>();
				if ((Object)(object)component != (Object)null)
				{
					((MonoBehaviourPun)component).photonView.RPC("RPC_ApplyHealing", ((MonoBehaviourPun)component).photonView.Owner, new object[2]
					{
						(int)statusType,
						num4
					});
					if (addtlStatus != null)
					{
						STATUSTYPE[] array3 = addtlStatus;
						foreach (STATUSTYPE val4 in array3)
						{
							((MonoBehaviourPun)component).photonView.RPC("RPC_ApplyHealing", ((MonoBehaviourPun)component).photonView.Owner, new object[2]
							{
								(int)val4,
								num4
							});
						}
					}
					if (hasAffliction && affliction != null)
					{
						((MonoBehaviourPun)component).photonView.RPC("RPC_ApplyAffliction", ((MonoBehaviourPun)component).photonView.Owner, new object[1] { (int)affliction.GetAfflictionType() });
					}
				}
				else
				{
					AOEHealingFixPlugin.Logger.LogError((object)("[AOE DEBUG] No HealingReceiver on " + item2.characterName + "! Make sure Character_Awake_Patch is running."));
				}
			}
			AOEHealingFixPlugin.Logger.LogInfo((object)$"[AOE DEBUG] Healing applied to {list.Count} characters");
			return false;
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class Character_Awake_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<HealingReceiver>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<HealingReceiver>();
				AOEHealingFixPlugin.Logger.LogInfo((object)("Added HealingReceiver to " + __instance.characterName));
			}
		}
	}
	public class HealingReceiver : MonoBehaviourPun
	{
		private Character character;

		private void Awake()
		{
			character = ((Component)this).GetComponent<Character>();
		}

		[PunRPC]
		public void RPC_ApplyHealing(int statusTypeInt, float amount)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if (!((MonoBehaviourPun)this).photonView.IsMine)
			{
				ManualLogSource logger = AOEHealingFixPlugin.Logger;
				Character obj = character;
				logger.LogInfo((object)("[HEAL] Skipped " + ((obj != null) ? obj.characterName : null) + " - not owner"));
			}
			else if (!((Object)(object)character == (Object)null) && !(amount <= 0f))
			{
				STATUSTYPE val = (STATUSTYPE)statusTypeInt;
				float currentStatus = character.refs.afflictions.GetCurrentStatus(val);
				character.refs.afflictions.SubtractStatus(val, amount, true, false);
				float currentStatus2 = character.refs.afflictions.GetCurrentStatus(val);
				AOEHealingFixPlugin.Logger.LogInfo((object)($"[HEAL] {character.characterName} healed: {val} " + $"{currentStatus:F3} → {currentStatus2:F3} (-{amount:F3}) | IsCarried: {character.data.isCarried} | " + "Carrier: " + (((Object)(object)character.data.carrier != (Object)null) ? character.data.carrier.characterName : "none")));
			}
		}

		[PunRPC]
		public void RPC_ApplyAffliction(int afflictionTypeInt)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (((MonoBehaviourPun)this).photonView.IsMine && !((Object)(object)character == (Object)null))
			{
				AfflictionType val = (AfflictionType)afflictionTypeInt;
				Affliction val2 = Affliction.CreateBlankAffliction(val);
				if (val2 != null)
				{
					character.refs.afflictions.AddAffliction(val2, true);
				}
			}
		}
	}
}

BetterFriendJump.dll

Decompiled a week ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace BetterFriendJump
{
	[HarmonyPatch(typeof(CharacterMovement), "JumpRpc")]
	public static class PatchJumpRpc
	{
		private const float FRIEND_JUMP_FORCE = 2050f;

		[HarmonyPostfix]
		private static void Postfix(CharacterMovement __instance, bool isPalJump)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (!isPalJump)
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			foreach (Bodypart part in component.refs.ragdoll.partList)
			{
				part.AddForce(Vector3.up * 2050f, (ForceMode)5);
			}
		}
	}
	[BepInPlugin("jill920.BetterFriendJump", "BetterFriendJump", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.BetterFriendJump";

		public const string MOD_NAME = "BetterFriendJump";

		public const string MOD_VERSION = "1.0.1";

		public static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "jill920.BetterFriendJump");
			Log.LogInfo((object)"[BetterFriendJump 1.0.1] Loaded! Friend jump force: 2000");
		}
	}
}

BetterFriendPull.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
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 Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterFriendPull")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+4d83d2fcd8cc02921a02fe7ced1336060af8c951")]
[assembly: AssemblyProduct("BetterFriendPull")]
[assembly: AssemblyTitle("BetterFriendPull")]
[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 BetterFriendPull
{
	[HarmonyPatch(typeof(CharacterGrabbing), "Reach")]
	public static class PatchReachRange
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)list[i].operand, 4f))
				{
					Debug.Log((object)$"[BetterFriendPull] Replacing 4f range with {Plugin.PullRange.Value}f");
					list[i] = new CodeInstruction(OpCodes.Ldc_R4, (object)Plugin.PullRange.Value);
				}
				if (list[i].opcode == OpCodes.Ldc_R4 && Mathf.Approximately((float)list[i].operand, 60f))
				{
					Debug.Log((object)$"[BetterFriendPull] Replacing 60f angle with {Plugin.PullAngle.Value}f");
					list[i] = new CodeInstruction(OpCodes.Ldc_R4, (object)Plugin.PullAngle.Value);
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(CharacterGrabbing), "TargetCanBeHelped")]
	public static class PatchVerticalLimit
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				if (!(list[i].opcode == OpCodes.Ldc_R4) || !Mathf.Approximately((float)list[i].operand, 1f))
				{
					continue;
				}
				bool flag = false;
				for (int j = Mathf.Max(0, i - 8); j < i; j++)
				{
					if (list[j].opcode == OpCodes.Callvirt && list[j].operand.ToString().Contains("get_isClimbing"))
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					Debug.Log((object)$"[BetterFriendPull] Replacing vertical limit 1f with {Plugin.PullVerticalLimit.Value}f");
					list[i] = new CodeInstruction(OpCodes.Ldc_R4, (object)Plugin.PullVerticalLimit.Value);
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(Character), "DragTowards")]
	public static class PatchPullForce
	{
		[HarmonyPrefix]
		private static void Prefix(Character __instance, Vector3 target, ref float force)
		{
			if (!Mathf.Approximately(Plugin.PullForceMultiplier.Value, 1f))
			{
				force *= Plugin.PullForceMultiplier.Value;
				if (Plugin.PullForceMultiplier.Value != 1f)
				{
					Debug.Log((object)$"[BetterFriendPull] Pull force multiplied: {force / Plugin.PullForceMultiplier.Value:F0} → {force:F0}");
				}
			}
		}
	}
	public static class StaminaFreezeManager
	{
		private static HashSet<Character> _protectedChars = new HashSet<Character>();

		private static Dictionary<Character, float> _protectUntil = new Dictionary<Character, float>();

		public static void ProtectCharacter(Character c)
		{
			if (Plugin.EnableStaminaFreeze.Value)
			{
				_protectedChars.Add(c);
				_protectUntil[c] = Time.time + Plugin.StaminaFreezeCooldown.Value;
			}
		}

		public static bool IsProtected(Character c)
		{
			if (!Plugin.EnableStaminaFreeze.Value)
			{
				return false;
			}
			float time = Time.time;
			List<Character> list = new List<Character>();
			foreach (KeyValuePair<Character, float> item in _protectUntil)
			{
				if (time > item.Value)
				{
					list.Add(item.Key);
				}
			}
			foreach (Character item2 in list)
			{
				_protectedChars.Remove(item2);
				_protectUntil.Remove(item2);
			}
			return _protectedChars.Contains(c);
		}
	}
	[HarmonyPatch(typeof(Character), "DragTowards")]
	public static class PatchTrackPullSimple
	{
		[HarmonyPrefix]
		private static void Prefix(Character __instance)
		{
			StaminaFreezeManager.ProtectCharacter(__instance);
			if (((MonoBehaviourPun)__instance).photonView.IsMine && Plugin.EnableStaminaFreeze.Value)
			{
				Debug.Log((object)("[BetterFriendPull] Stamina frozen for " + __instance.characterName));
			}
		}
	}
	[HarmonyPatch(typeof(Character), "UseStamina")]
	public static class PatchBlockStamina
	{
		[HarmonyPrefix]
		private static bool Prefix(Character __instance)
		{
			if (StaminaFreezeManager.IsProtected(__instance))
			{
				return false;
			}
			return true;
		}
	}
	[BepInPlugin("jill920.BetterFriendPull", "BetterFriendPull", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Log;

		public static ConfigEntry<float> PullRange;

		public static ConfigEntry<float> PullAngle;

		public static ConfigEntry<float> PullVerticalLimit;

		public static ConfigEntry<float> PullForceMultiplier;

		public static ConfigEntry<bool> EnableStaminaFreeze;

		public static ConfigEntry<float> StaminaFreezeCooldown;

		public static HashSet<Character> PullProtectedCharacters = new HashSet<Character>();

		public static Dictionary<Character, float> PullProtectionEndTime = new Dictionary<Character, float>();

		private void Awake()
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			PullRange = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Pull Range", 6f, "Max distance to detect climbing friends (vanilla: 4)");
			PullAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Pull Angle", 60f, "Cone angle in degrees (vanilla: 60)");
			PullVerticalLimit = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Vertical Pull Limit", 1f, "Max height difference to pull (vanilla: 1)");
			PullForceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Pull Force Multiplier", 1f, "Multiply pull force (vanilla: 1)");
			EnableStaminaFreeze = ((BaseUnityPlugin)this).Config.Bind<bool>("Stamina", "Enable Stamina Freeze", true, "Prevent stamina drain while being pulled");
			StaminaFreezeCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Stamina", "Stamina Freeze Cooldown", 0.8f, "Seconds after pull ends to keep stamina frozen (prevents instant drain)");
			Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
			val.PatchAll();
			Log.LogInfo((object)$"BetterFriendPull loaded. Range: {PullRange.Value}m, Stamina Freeze: {EnableStaminaFreeze.Value}, Cooldown: {StaminaFreezeCooldown.Value}s");
		}

		private void Update()
		{
			float time = Time.time;
			List<Character> list = new List<Character>();
			foreach (KeyValuePair<Character, float> item in PullProtectionEndTime)
			{
				if (time > item.Value)
				{
					list.Add(item.Key);
				}
			}
			foreach (Character item2 in list)
			{
				PullProtectedCharacters.Remove(item2);
				PullProtectionEndTime.Remove(item2);
				if ((Object)(object)item2 != (Object)null && ((MonoBehaviourPun)item2).photonView.IsMine)
				{
					Log.LogDebug((object)("Stamina freeze expired for " + item2.characterName));
				}
			}
			if (!Application.isFocused || (Object)(object)Character.localCharacter == (Object)null || (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305)))
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)273))
			{
				ConfigEntry<float> pullRange = PullRange;
				pullRange.Value += 0.5f;
				Log.LogInfo((object)$"↑ Pull Range increased to {PullRange.Value}m");
			}
			if (Input.GetKeyDown((KeyCode)274))
			{
				ConfigEntry<float> pullRange2 = PullRange;
				pullRange2.Value -= 0.5f;
				Log.LogInfo((object)$"↓ Pull Range decreased to {PullRange.Value}m");
			}
			if (Input.GetKeyDown((KeyCode)275))
			{
				ConfigEntry<float> pullAngle = PullAngle;
				pullAngle.Value += 5f;
				Log.LogInfo((object)$"→ Pull Angle increased to {PullAngle.Value}°");
			}
			if (Input.GetKeyDown((KeyCode)276))
			{
				ConfigEntry<float> pullAngle2 = PullAngle;
				pullAngle2.Value -= 5f;
				Log.LogInfo((object)$"← Pull Angle decreased to {PullAngle.Value}°");
			}
			if (Input.GetKeyDown((KeyCode)280))
			{
				ConfigEntry<float> pullVerticalLimit = PullVerticalLimit;
				pullVerticalLimit.Value += 0.5f;
				Log.LogInfo((object)$"PgUp Vertical Limit increased to {PullVerticalLimit.Value}m");
			}
			if (Input.GetKeyDown((KeyCode)281))
			{
				ConfigEntry<float> pullVerticalLimit2 = PullVerticalLimit;
				pullVerticalLimit2.Value -= 0.5f;
				Log.LogInfo((object)$"PgDn Vertical Limit decreased to {PullVerticalLimit.Value}m");
			}
			if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
			{
				if (Input.GetKeyDown((KeyCode)273))
				{
					ConfigEntry<float> pullForceMultiplier = PullForceMultiplier;
					pullForceMultiplier.Value += 0.25f;
					Log.LogInfo((object)$"↑ Pull Force increased to {PullForceMultiplier.Value}x");
				}
				if (Input.GetKeyDown((KeyCode)274))
				{
					ConfigEntry<float> pullForceMultiplier2 = PullForceMultiplier;
					pullForceMultiplier2.Value -= 0.25f;
					Log.LogInfo((object)$"↓ Pull Force decreased to {PullForceMultiplier.Value}x");
				}
			}
			if (Input.GetKeyDown((KeyCode)115))
			{
				EnableStaminaFreeze.Value = !EnableStaminaFreeze.Value;
				Log.LogInfo((object)("Stamina Freeze: " + (EnableStaminaFreeze.Value ? "ENABLED" : "DISABLED")));
			}
		}
	}
}

BlowgunEnhanced.dll

Decompiled a week ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BlowgunEnhanced")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e2fc2576a986539ed321b56e932194c0a5465ff8")]
[assembly: AssemblyProduct("BlowgunEnhanced")]
[assembly: AssemblyTitle("BlowgunEnhanced")]
[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 BlowgunEnhanced
{
	[BepInPlugin("jill920.blowgunenhanced", "Blowgun Enhanced", "1.0.0")]
	public class BlowgunEnhancedPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.blowgunenhanced";

		public const string MOD_NAME = "Blowgun Enhanced";

		public const string MOD_VERSION = "1.0.0";

		public static BlowgunEnhancedPlugin Instance;

		public static ManualLogSource Logger;

		public static bool IsDizzinessModInstalled;

		public static bool IsFatigueModInstalled;

		public static bool debugMode;

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableLogs", false, "Enable debug logging").Value;
			CheckForInstalledMods();
			try
			{
				Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "jill920.blowgunenhanced");
				Logger.LogInfo((object)"[Blowgun Enhanced 1.0.0] Loaded successfully!");
				Logger.LogInfo((object)$"  Dizziness Mod detected (initial): {IsDizzinessModInstalled}");
				Logger.LogInfo((object)$"  Fatigue Mod detected (initial): {IsFatigueModInstalled}");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to load: " + ex.Message));
			}
		}

		private void CheckForInstalledMods()
		{
			IsDizzinessModInstalled = false;
			IsFatigueModInstalled = false;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						IsDizzinessModInstalled = true;
					}
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						IsFatigueModInstalled = true;
					}
				}
				catch
				{
				}
			}
		}
	}
}
namespace BlowgunEnhanced.Patches
{
	[HarmonyPatch(typeof(Action_RaycastDart), "RPC_DartImpact")]
	internal static class Action_RaycastDart_Patch
	{
		private static bool _fatigueCheckDone;

		private static bool _fatigueAvailable;

		private static bool _dizzinessCheckDone;

		private static bool _dizzinessAvailable;

		private static bool IsFatigueModPresent()
		{
			if (_fatigueCheckDone)
			{
				return _fatigueAvailable;
			}
			_fatigueCheckDone = true;
			if (BlowgunEnhancedPlugin.IsFatigueModInstalled)
			{
				_fatigueAvailable = true;
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						_fatigueAvailable = true;
						BlowgunEnhancedPlugin.IsFatigueModInstalled = true;
						BlowgunEnhancedPlugin.Logger.LogInfo((object)"Blowgun: Fatigue Mod detected at runtime!");
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsDizzinessModPresent()
		{
			if (_dizzinessCheckDone)
			{
				return _dizzinessAvailable;
			}
			_dizzinessCheckDone = true;
			if (BlowgunEnhancedPlugin.IsDizzinessModInstalled)
			{
				_dizzinessAvailable = true;
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						_dizzinessAvailable = true;
						BlowgunEnhancedPlugin.IsDizzinessModInstalled = true;
						BlowgunEnhancedPlugin.Logger.LogInfo((object)"Blowgun: Dizziness Mod detected at runtime!");
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		[HarmonyPostfix]
		private static void Postfix(int characterID, Vector3 origin, Vector3 endpoint)
		{
			if (characterID == -1)
			{
				return;
			}
			try
			{
				PhotonView photonView = PhotonNetwork.GetPhotonView(characterID);
				if ((Object)(object)photonView == (Object)null)
				{
					return;
				}
				Character component = ((Component)photonView).GetComponent<Character>();
				if ((Object)(object)component == (Object)null || !component.IsLocal)
				{
					return;
				}
				bool flag = IsDizzinessModPresent();
				bool flag2 = IsFatigueModPresent();
				if (flag || flag2)
				{
					if (flag)
					{
						ClearDizziness(component);
					}
					if (flag2)
					{
						ClearFatigue(component);
					}
					if (BlowgunEnhancedPlugin.debugMode)
					{
						BlowgunEnhancedPlugin.Logger.LogInfo((object)("Blowgun: Cleared Dizziness/Fatigue for " + component.characterName));
					}
				}
			}
			catch (Exception ex)
			{
				BlowgunEnhancedPlugin.Logger.LogWarning((object)("Failed to process blowgun hit: " + ex.Message));
			}
		}

		private static void ClearDizziness(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (field == null)
				{
					return;
				}
				float num = (float)field.GetValue(component);
				if (num > 0.01f)
				{
					field.SetValue(component, 0f);
					if (BlowgunEnhancedPlugin.debugMode)
					{
						BlowgunEnhancedPlugin.Logger.LogInfo((object)$"Blowgun: Cleared Dizziness: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				BlowgunEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Dizziness: " + ex.Message));
			}
		}

		private static void ClearFatigue(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					field.SetValue(component, 0f);
					if (BlowgunEnhancedPlugin.debugMode && num > 0.01f)
					{
						BlowgunEnhancedPlugin.Logger.LogInfo((object)$"Blowgun: Cleared Fatigue: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				BlowgunEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Fatigue: " + ex.Message));
			}
		}
	}
}

CursedSkullEnhanced.dll

Decompiled a week ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CursedSkullEnhanced")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0a4f7b16fa778ffc5cd0ca73c4eecf8a56cf834e")]
[assembly: AssemblyProduct("CursedSkullEnhanced")]
[assembly: AssemblyTitle("CursedSkullEnhanced")]
[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 CursedSkullEnhanced
{
	[BepInPlugin("jill920.cursedskullenhanced", "Cursed Skull Enhanced", "1.0.0")]
	public class CursedSkullEnhancedPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.cursedskullenhanced";

		public const string MOD_NAME = "Cursed Skull Enhanced";

		public const string MOD_VERSION = "1.0.0";

		public static CursedSkullEnhancedPlugin Instance;

		public static ManualLogSource Logger;

		public static bool IsDizzinessModInstalled;

		public static bool IsFatigueModInstalled;

		public static bool debugMode;

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableLogs", false, "Enable debug logging").Value;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "jill920.cursedskullenhanced");
			CheckForInstalledMods();
			Logger.LogInfo((object)"[Cursed Skull Enhanced 1.0.0] Loaded successfully!");
			Logger.LogInfo((object)$"  Dizziness Mod detected: {IsDizzinessModInstalled}");
			Logger.LogInfo((object)$"  Fatigue Mod detected: {IsFatigueModInstalled}");
		}

		private void CheckForInstalledMods()
		{
			IsDizzinessModInstalled = false;
			IsFatigueModInstalled = false;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						IsDizzinessModInstalled = true;
					}
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						IsFatigueModInstalled = true;
					}
				}
				catch
				{
				}
			}
		}
	}
}
namespace CursedSkullEnhanced.Patches
{
	[HarmonyPatch(typeof(Action_ApplyMassAffliction), "TryAddAfflictionToLocalCharacter")]
	internal static class Action_ApplyMassAffliction_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Action_ApplyMassAffliction __instance)
		{
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)localCharacter == (Object)null) && ((Action_ApplyAffliction)__instance).affliction is Affliction_ClearAllStatus)
			{
				ClearDizzinessAndFatigue(localCharacter);
				if (CursedSkullEnhancedPlugin.debugMode)
				{
					CursedSkullEnhancedPlugin.Logger.LogInfo((object)("Cursed Skull: Cleared Dizziness/Fatigue for " + localCharacter.characterName));
				}
			}
		}

		private static void ClearDizzinessAndFatigue(Character character)
		{
			if (IsDizzinessModPresent())
			{
				ClearDizziness(character);
			}
			if (IsFatigueModPresent())
			{
				ClearFatigue(character);
			}
		}

		private static bool IsDizzinessModPresent()
		{
			if (CursedSkullEnhancedPlugin.IsDizzinessModInstalled)
			{
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						CursedSkullEnhancedPlugin.IsDizzinessModInstalled = true;
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsFatigueModPresent()
		{
			if (CursedSkullEnhancedPlugin.IsFatigueModInstalled)
			{
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						CursedSkullEnhancedPlugin.IsFatigueModInstalled = true;
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static void ClearDizziness(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (field == null)
				{
					return;
				}
				float num = (float)field.GetValue(component);
				if (num > 0.01f)
				{
					field.SetValue(component, 0f);
					if (CursedSkullEnhancedPlugin.debugMode)
					{
						CursedSkullEnhancedPlugin.Logger.LogInfo((object)$"Cleared Dizziness: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				CursedSkullEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Dizziness: " + ex.Message));
			}
		}

		private static void ClearFatigue(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					field.SetValue(component, 0f);
					if (CursedSkullEnhancedPlugin.debugMode && num > 0.01f)
					{
						CursedSkullEnhancedPlugin.Logger.LogInfo((object)$"Cleared Fatigue: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				CursedSkullEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Fatigue: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(ItemCooking), "RPC_CookingExplode")]
	internal static class ItemCooking_Explode_Patch
	{
		private const float CURSED_SKULL_RADIUS = 900f;

		private const int CURSED_SKULL_ITEM_ID = 25;

		[HarmonyPrefix]
		private static void Prefix(ItemCooking __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			Item item = ((ItemComponent)__instance).item;
			if ((Object)(object)item == (Object)null || item.itemID != 25)
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (!((Object)(object)allCharacter == (Object)null))
				{
					float num = Vector3.Distance(position, allCharacter.Center);
					if (!(num > 900f))
					{
						ClearDizzinessAndFatigue(allCharacter);
					}
				}
			}
			CursedSkullEnhancedPlugin.Logger.LogInfo((object)$"Cursed Skull explosion: Cleared Dizziness/Fatigue for players within {900f} units");
		}

		private static void ClearDizzinessAndFatigue(Character character)
		{
			if (CursedSkullEnhancedPlugin.IsDizzinessModInstalled)
			{
				ClearDizziness(character);
			}
			if (CursedSkullEnhancedPlugin.IsFatigueModInstalled)
			{
				ClearFatigue(character);
			}
		}

		private static void ClearDizziness(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (field == null)
				{
					return;
				}
				float num = (float)field.GetValue(component);
				if (num > 0.01f)
				{
					field.SetValue(component, 0f);
					if (CursedSkullEnhancedPlugin.debugMode)
					{
						CursedSkullEnhancedPlugin.Logger.LogInfo((object)$"Cleared Dizziness for {character.characterName}: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				CursedSkullEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Dizziness: " + ex.Message));
			}
		}

		private static bool IsFatigueModPresent()
		{
			if (CursedSkullEnhancedPlugin.IsFatigueModInstalled)
			{
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						CursedSkullEnhancedPlugin.IsFatigueModInstalled = true;
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static void ClearFatigue(Character character)
		{
			if (!IsFatigueModPresent())
			{
				return;
			}
			try
			{
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					field.SetValue(component, 0f);
					if (CursedSkullEnhancedPlugin.debugMode)
					{
						CursedSkullEnhancedPlugin.Logger.LogInfo((object)("Cleared Fatigue for " + character.characterName));
					}
				}
			}
			catch (Exception ex)
			{
				CursedSkullEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Fatigue: " + ex.Message));
			}
		}
	}
}

DizzinessMod.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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 Peak.Afflictions;
using Photon.Pun;
using UnityEngine;
using UnityEngine.UI;
using Zorro.Core;
using Zorro.Core.CLI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 DizzinessMod
{
	[HarmonyPatch(typeof(Action_ModifyStatus), "RunAction")]
	internal static class Action_ModifyStatus_Patch
	{
		private static readonly HashSet<ushort> healingItemIDs = new HashSet<ushort> { 24 };

		private static FieldInfo itemField;

		private static FieldInfo characterField;

		private static PropertyInfo characterProperty;

		[HarmonyPostfix]
		private static void Postfix(Action_ModifyStatus __instance)
		{
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			if (itemField == null)
			{
				itemField = typeof(ItemActionBase).GetField("item", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			object? obj = itemField?.GetValue(__instance);
			Item val = (Item)((obj is Item) ? obj : null);
			if ((Object)(object)val == (Object)null || __instance.changeAmount >= 0f || !healingItemIDs.Contains(val.itemID))
			{
				return;
			}
			if (characterProperty == null)
			{
				characterProperty = typeof(ItemActionBase).GetProperty("character", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			Character val2 = null;
			if (characterProperty != null)
			{
				object? value = characterProperty.GetValue(__instance);
				val2 = (Character)((value is Character) ? value : null);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				if (characterField == null)
				{
					characterField = typeof(ItemActionBase).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				object? obj2 = characterField?.GetValue(__instance);
				val2 = (Character)((obj2 is Character) ? obj2 : null);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				DizzinessPlugin.Logger.LogWarning((object)$"Target character is null for item {((Object)val).name} (ID:{val.itemID})");
				return;
			}
			DizzinessPlugin.Logger.LogInfo((object)$"Healing item used - Item: {((Object)val).name} (ID:{val.itemID}), Target: {val2.characterName}, Status: {__instance.statusType}, Amount: {__instance.changeAmount}");
			if (val2.IsLocal)
			{
				if (val2.data.isSkeleton && !val2.data.dead && !val2.data.fullyPassedOut)
				{
					DizzinessPlugin.Logger.LogInfo((object)"Skipping dizziness reduction - target is a living skeleton");
					return;
				}
				DizzinessTracker component = ((Component)val2).GetComponent<DizzinessTracker>();
				if ((Object)(object)component != (Object)null)
				{
					float num = Mathf.Abs(__instance.changeAmount) * 0.1f;
					float dizzinessValue = component.dizzinessValue;
					component.dizzinessValue = Mathf.Max(0f, component.dizzinessValue - num);
					DizzinessPlugin.Logger.LogInfo((object)$"Reduced dizziness by {num:F3} (from {dizzinessValue:F3} to {component.dizzinessValue:F3})");
				}
				else
				{
					DizzinessPlugin.Logger.LogWarning((object)("No DizzinessTracker found on " + val2.characterName));
				}
			}
			else
			{
				DizzinessPlugin.Logger.LogInfo((object)("Skipping dizziness reduction - target is not local player: " + val2.characterName));
			}
		}
	}
	[HarmonyPatch(typeof(CharacterData), "set_isSkeleton")]
	internal static class CharacterData_SetSkeleton_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(CharacterData __instance, bool value)
		{
			if (!value)
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			Component component2 = ((Component)component).GetComponent("DizzinessMod.DizzinessTracker");
			if ((Object)(object)component2 != (Object)null)
			{
				FieldInfo field = ((object)component2).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (field != null)
				{
					field.SetValue(component2, 0f);
					DizzinessPlugin.Logger.LogInfo((object)"Cleared dizziness on skeleton transformation");
				}
			}
		}
	}
	[HarmonyPatch(typeof(BarAffliction), "ChangeAffliction")]
	internal static class BarAffliction_ChangeAffliction_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(BarAffliction __instance, StaminaBar bar)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (((Object)((Component)__instance).gameObject).name != "DizzinessCustomBar")
			{
				return true;
			}
			Character observedCharacter = Character.observedCharacter;
			if ((Object)observedCharacter == (Object)null)
			{
				return false;
			}
			DizzinessTracker component = ((Component)observedCharacter).GetComponent<DizzinessTracker>();
			if ((Object)component == (Object)null)
			{
				return false;
			}
			float dizzinessValue = component.dizzinessValue;
			__instance.size = bar.fullBar.sizeDelta.x * dizzinessValue;
			if (dizzinessValue > 0.01f)
			{
				if (__instance.size < bar.minAfflictionWidth)
				{
					__instance.size = bar.minAfflictionWidth;
				}
				((Component)__instance).gameObject.SetActive(true);
			}
			else
			{
				((Component)__instance).gameObject.SetActive(false);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(CharacterMovement), "CameraLook")]
	internal static class CameraDizzinessPatch
	{
		private static float swayPhase;

		private static float lurchTimer;

		[HarmonyPrefix]
		private static void Prefix(CharacterMovement __instance)
		{
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			DizzinessTracker component2 = ((Component)component).GetComponent<DizzinessTracker>();
			if ((Object)(object)component2 == (Object)null)
			{
				return;
			}
			float dizzinessValue = component2.dizzinessValue;
			if (dizzinessValue <= 0.05f)
			{
				return;
			}
			float num = Mathf.Clamp01((dizzinessValue - 0.05f) / 0.95f);
			if ((Object)(object)component.input != (Object)null && dizzinessValue > 0.15f)
			{
				float num2 = Mathf.Clamp01((dizzinessValue - 0.15f) / 0.85f);
				float num3 = Mathf.Sin(Time.time * 1.2f) * 90f * num2;
				num3 += Mathf.Sin(Time.time * 0.6f) * 45f * num2;
				float num4 = num3 * (MathF.PI / 180f);
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(component.input.lookInput.x * Mathf.Cos(num4) - component.input.lookInput.y * Mathf.Sin(num4), component.input.lookInput.x * Mathf.Sin(num4) + component.input.lookInput.y * Mathf.Cos(num4));
				float num5 = num2 * 0.8f;
				val += new Vector2((Mathf.PerlinNoise(Time.time * 4f, 0f) - 0.5f) * 2f * num5, (Mathf.PerlinNoise(Time.time * 3f, 1000f) - 0.5f) * 2f * num5);
				component.input.lookInput = val;
			}
			float num6 = 0.8f + dizzinessValue * 0.8f;
			swayPhase += Time.deltaTime * num6;
			float num7 = Mathf.Sin(swayPhase) * num * 60f;
			float num8 = Mathf.Cos(swayPhase * 0.8f) * num * 30f;
			float num9 = Mathf.Sin(swayPhase * 0.5f) * num * 20f;
			lurchTimer += Time.deltaTime;
			if (dizzinessValue > 0.4f && lurchTimer > 3f)
			{
				float num10 = (dizzinessValue - 0.4f) / 0.6f;
				if (Random.value < num10 * 0.4f)
				{
					float num11 = Random.Range(-35f, 35f) * num10;
					float num12 = Random.Range(-20f, 20f) * num10;
					num7 += num11;
					num8 += num12;
					lurchTimer = 0f;
					if (DizzinessPlugin.debugMode.Value)
					{
						DizzinessPlugin.Logger.LogInfo((object)$"Camera lurch! Yaw:{num11:F0}, Pitch:{num12:F0}");
					}
				}
			}
			float num13 = num;
			num7 += (Mathf.PerlinNoise(Time.time * 1.5f, 0f) - 0.5f) * 8f * num13;
			num8 += (Mathf.PerlinNoise(Time.time * 1.2f, 1000f) - 0.5f) * 5f * num13;
			component.data.lookValues.x += num7 * Time.deltaTime * 3f;
			component.data.lookValues.y += num8 * Time.deltaTime * 3f;
			component.data.lookValues.y = Mathf.Clamp(component.data.lookValues.y, -85f, 85f);
			if (dizzinessValue > 0.3f)
			{
				float num14 = Mathf.Clamp01((dizzinessValue - 0.3f) / 0.7f);
				float num15 = num14 * 0.4f;
				CharacterInput input = component.input;
				input.movementInput += new Vector2((Mathf.PerlinNoise(Time.time * 2f, 0f) - 0.5f) * 2f * num15, (Mathf.PerlinNoise(Time.time * 1.5f, 1000f) - 0.5f) * 2f * num15);
				component.input.movementInput = Vector2.ClampMagnitude(component.input.movementInput, 1f);
			}
		}
	}
	[HarmonyPatch(typeof(CharacterAfflictions))]
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class CharacterAfflictions_statusSum_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(CharacterAfflictions __instance, ref float __result)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			if (!((Object)__instance.character == (Object)null))
			{
				DizzinessTracker component = ((Component)__instance.character).GetComponent<DizzinessTracker>();
				if (!((Object)component == (Object)null) && !((Object)__instance.character.data == (Object)null))
				{
					__result += component.dizzinessValue;
				}
			}
		}
	}
	public static class CharacterFallHelper
	{
		private static MethodInfo _fallMethod;

		public static void TriggerFall(Character character, float seconds, float screenShake = 0f)
		{
			if ((Object)(object)character == (Object)null || !character.IsLocal)
			{
				return;
			}
			if (_fallMethod == null)
			{
				_fallMethod = typeof(Character).GetMethod("Fall", BindingFlags.Instance | BindingFlags.NonPublic);
				if (_fallMethod == null)
				{
					DizzinessPlugin.Logger.LogError((object)"Could not find Character.Fall method!");
					return;
				}
			}
			_fallMethod.Invoke(character, new object[2] { seconds, screenShake });
			if (DizzinessPlugin.debugMode.Value)
			{
				DizzinessPlugin.Logger.LogInfo((object)$"Stumble triggered! Duration: {seconds:F2}s, Dizziness: {GetDizzinessValue(character):F2}");
			}
		}

		public static void TriggerScreenShake(float amount, float duration = 0.2f, float scale = 15f)
		{
			if (!((Object)(object)GamefeelHandler.instance == (Object)null))
			{
				GamefeelHandler.instance.AddPerlinShake(amount, duration, scale);
			}
		}

		private static float GetDizzinessValue(Character character)
		{
			DizzinessTracker component = ((Component)character).GetComponent<DizzinessTracker>();
			return ((Object)(object)component != (Object)null) ? component.dizzinessValue : 0f;
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class Character_Awake_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<DizzinessTracker>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<DizzinessTracker>();
			}
			if ((Object)(object)((Component)__instance).GetComponent<DizzinessRpcReceiver>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<DizzinessRpcReceiver>();
			}
			if ((Object)(object)((Component)__instance).GetComponent<DizzinessControlModifier>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<DizzinessControlModifier>();
			}
		}
	}
	[HarmonyPatch(typeof(Character), "CheckJump")]
	internal static class Character_CheckJump_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance, ref bool __result)
		{
			if (!__result)
			{
				return;
			}
			DizzinessTracker component = ((Component)__instance).GetComponent<DizzinessTracker>();
			if (!((Object)(object)component == (Object)null))
			{
				float dizzinessValue = component.dizzinessValue;
				if (dizzinessValue > 0.7f)
				{
					__result = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "HasMeaningfulTempStatuses")]
	internal static class Character_HasMeaningfulTempStatuses_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance, ref bool __result)
		{
			DizzinessTracker component = ((Component)__instance).GetComponent<DizzinessTracker>();
			if (!((Object)(object)component == (Object)null) && !__result && component.dizzinessValue > 0.05f)
			{
				__result = true;
			}
		}
	}
	public static class DizzinessBarInjector
	{
		public static BarAffliction injectedBar;

		private static bool injectionFailed;

		public static void TryInjectBar()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Invalid comparison between Unknown and I4
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Expected O, but got Unknown
			//IL_0201: Expected O, but got Unknown
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)injectedBar != (Object)null || injectionFailed)
			{
				return;
			}
			try
			{
				if ((Object)GUIManager.instance == (Object)null)
				{
					return;
				}
				StaminaBar bar = GUIManager.instance.bar;
				if ((Object)bar == (Object)null || bar.afflictions == null || bar.afflictions.Length == 0)
				{
					return;
				}
				BarAffliction val = null;
				BarAffliction[] afflictions = bar.afflictions;
				BarAffliction[] array = afflictions;
				foreach (BarAffliction val2 in array)
				{
					if (!((Object)val2 == (Object)null) && (int)val2.afflictionType == 4)
					{
						val = val2;
						break;
					}
				}
				if ((Object)val == (Object)null)
				{
					DizzinessPlugin.Logger.LogWarning((object)"Crab template bar not found in StaminaBar.afflictions");
					injectionFailed = true;
					return;
				}
				GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent);
				((Object)val3).name = "DizzinessCustomBar";
				BarAffliction component = val3.GetComponent<BarAffliction>();
				if ((Object)component == (Object)null)
				{
					DizzinessPlugin.Logger.LogError((object)"Cloned GameObject has no BarAffliction component");
					Object.Destroy((Object)val3);
					injectionFailed = true;
					return;
				}
				if ((Object)DizzinessPlugin.DizzinessIconSprite != (Object)null && (Object)component.icon != (Object)null)
				{
					component.icon.sprite = DizzinessPlugin.DizzinessIconSprite;
					((Graphic)component.icon).color = Color.white;
				}
				Image[] componentsInChildren = ((Component)component).GetComponentsInChildren<Image>(true);
				Image[] array2 = componentsInChildren;
				foreach (Image val4 in array2)
				{
					if (!((Object)component.icon != (Object)null) || !((Object)val4 == (Object)component.icon))
					{
						Color dizzinessColor = DizzinessPlugin.DizzinessColor;
						dizzinessColor.a = ((Graphic)val4).color.a;
						((Graphic)val4).color = dizzinessColor;
					}
				}
				component.size = 0f;
				val3.SetActive(false);
				FieldInfo field = typeof(StaminaBar).GetField("afflictions", BindingFlags.Instance | BindingFlags.Public);
				if (field == null)
				{
					DizzinessPlugin.Logger.LogError((object)"StaminaBar.afflictions field not found");
					Object.Destroy((Object)val3);
					injectionFailed = true;
					return;
				}
				BarAffliction[] array3 = (BarAffliction[])field.GetValue(bar);
				BarAffliction[] array4 = (BarAffliction[])(object)new BarAffliction[array3.Length + 1];
				Array.Copy(array3, array4, array3.Length);
				array4[array3.Length] = component;
				field.SetValue(bar, array4);
				injectedBar = component;
				DizzinessPlugin.Logger.LogInfo((object)$"Independent bar injected. New array size: {array4.Length}");
			}
			catch (Exception arg)
			{
				DizzinessPlugin.Logger.LogError((object)$"Bar injection failed: {arg}");
				injectionFailed = true;
			}
		}
	}
	public class DizzinessControlModifier : MonoBehaviour
	{
		private Character character;

		private DizzinessTracker tracker;

		private float originalMovementModifier;

		[Header("Control Loss Settings")]
		public AnimationCurve controlReductionCurve = AnimationCurve.EaseInOut(0f, 1f, 1f, 0.3f);

		[Header("Thresholds")]
		[Range(0f, 1f)]
		public float wobbleStartThreshold = 0.15f;

		[Range(0f, 1f)]
		public float collapseThreshold = 1f;

		[Range(0f, 1f)]
		public float maxMovementReduction = 0.7f;

		private void Awake()
		{
			character = ((Component)this).GetComponent<Character>();
			tracker = ((Component)this).GetComponent<DizzinessTracker>();
			if ((Object)(object)character != (Object)null && (Object)(object)character.refs.movement != (Object)null)
			{
				originalMovementModifier = character.refs.movement.movementModifier;
			}
		}

		private void Update()
		{
			if (!((Object)(object)character == (Object)null) && !((Object)(object)tracker == (Object)null) && character.IsLocal)
			{
				float dizzinessValue = tracker.dizzinessValue;
				float num = RemapDizzinessToCurve(dizzinessValue);
				float num2 = controlReductionCurve.Evaluate(num);
				character.data.ragdollControlClamp = Mathf.Clamp01(num2);
				float num3 = 1f;
				if (dizzinessValue > wobbleStartThreshold)
				{
					float num4 = Mathf.Clamp01((dizzinessValue - wobbleStartThreshold) / (collapseThreshold - wobbleStartThreshold));
					num3 = Mathf.Lerp(1f, maxMovementReduction, num4);
				}
				character.refs.movement.movementModifier = originalMovementModifier * num3;
			}
		}

		private float RemapDizzinessToCurve(float dizziness)
		{
			if (dizziness <= wobbleStartThreshold)
			{
				return 0f;
			}
			if (dizziness >= collapseThreshold)
			{
				return 1f;
			}
			float num = (dizziness - wobbleStartThreshold) / (collapseThreshold - wobbleStartThreshold);
			return Mathf.Clamp01(num);
		}
	}
	[HarmonyPatch(typeof(CharacterMovement), "GetMovementForce")]
	internal static class CharacterMovement_GetMovementForce_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(CharacterMovement __instance, ref float __result)
		{
		}
	}
	[HarmonyPatch(typeof(CharacterInput), "Sample")]
	internal static class CharacterInput_Sample_Patch
	{
		private static Vector2 lastMovementInput;

		private static float lastInputTime;

		[HarmonyPrefix]
		private static void Prefix(CharacterInput __instance, bool playerMovementActive)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if (!playerMovementActive)
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			DizzinessTracker component2 = ((Component)component).GetComponent<DizzinessTracker>();
			if ((Object)(object)component2 == (Object)null)
			{
				return;
			}
			float dizzinessValue = component2.dizzinessValue;
			if (!(dizzinessValue <= 0.1f))
			{
				float num = Mathf.Lerp(0f, 4f, dizzinessValue);
				if (Time.time - lastInputTime > num)
				{
					lastMovementInput = __instance.movementInput;
					lastInputTime = Time.time;
				}
				else
				{
					__instance.movementInput = lastMovementInput;
				}
				if (dizzinessValue > 0.2f)
				{
					float num2 = Mathf.Lerp(0f, 0.3f, (dizzinessValue - 0.2f) / 0.8f);
					__instance.movementInput += new Vector2(Random.Range(0f - num2, num2), Random.Range(0f - num2, num2));
					__instance.movementInput = Vector2.ClampMagnitude(__instance.movementInput, 1f);
				}
			}
		}
	}
	public static class DizzinessDebugCommands
	{
		[ConsoleCommand]
		public static void ListAllItemsWithIDs()
		{
			try
			{
				ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance;
				if (instance?.itemLookup == null)
				{
					DizzinessPlugin.Logger.LogError((object)"ItemDatabase not found!");
					return;
				}
				DizzinessPlugin.Logger.LogInfo((object)$"=== ITEM DATABASE ({instance.itemLookup.Count} items) ===");
				foreach (KeyValuePair<ushort, Item> item in instance.itemLookup.OrderBy((KeyValuePair<ushort, Item> x) => ((Object)x.Value).name))
				{
					DizzinessPlugin.Logger.LogInfo((object)$"ID: {item.Key} | Name: {((Object)item.Value).name}");
				}
				DizzinessPlugin.Logger.LogInfo((object)$"=== END OF ITEM DATABASE ({instance.itemLookup.Count} items) ===");
			}
			catch (Exception ex)
			{
				DizzinessPlugin.Logger.LogError((object)("ListAllItemsWithIDs failed: " + ex.Message));
			}
		}

		public static void TestDizzinessReduction()
		{
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				DizzinessPlugin.Logger.LogError((object)"No local character!");
				return;
			}
			DizzinessTracker component = ((Component)localCharacter).GetComponent<DizzinessTracker>();
			if ((Object)(object)component == (Object)null)
			{
				DizzinessPlugin.Logger.LogError((object)"No DizzinessTracker!");
				return;
			}
			float dizzinessValue = component.dizzinessValue;
			component.dizzinessValue = Mathf.Max(0f, component.dizzinessValue - 0.5f);
			DizzinessPlugin.Logger.LogInfo((object)$"Test: Reduced dizziness from {dizzinessValue:F3} to {component.dizzinessValue:F3}");
		}
	}
	[BepInPlugin("com.tambistudios.dizziness", "Dizziness Mod", "1.2.0")]
	public class DizzinessPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "com.tambistudios.dizziness";

		public const string MOD_NAME = "Dizziness Mod";

		public const string MOD_VERSION = "1.2.0";

		public static DizzinessPlugin Instance;

		public static ManualLogSource Logger;

		public static ConfigEntry<bool> debugMode;

		public const float SPEED_THRESHOLD = 7f;

		public const float DIZZINESS_GAIN_BASE = 0.0012f;

		public const float RECOVERY_PER_SEC = 0.035f;

		public const float REST_REQUIRED = 8f;

		public const float SUSTAINED_VELOCITY_DELAY = 0.25f;

		public const float DIZZINESS_REDUCTION_MULTIPLIER = 0.1f;

		public const float MAX_DIZZINESS_GAIN_PER_SECOND = 0.35f;

		public static readonly Color DizzinessColor = new Color(0.25f, 0.88f, 0.82f, 1f);

		public static Sprite DizzinessIconSprite;

		public const string CUSTOM_BAR_NAME = "DizzinessCustomBar";

		private void Awake()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugKeys", false, "Enables F5 (teleport 100m up), F7 (set dizziness 100%) and on-screen debug HUD.");
			LoadIconSprite();
			try
			{
				new Harmony("com.tambistudios.dizziness").PatchAll();
				Logger.LogInfo((object)"[Dizziness From Speed 1.2.0] Loaded.");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Harmony patch failed: {arg}");
			}
		}

		private static void LoadIconSprite()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DizzinessMod.Assets.dizziness_icon.png");
				if (stream == null)
				{
					Logger.LogWarning((object)"Embedded icon not found in resources!");
					return;
				}
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)1;
				if (ImageConversion.LoadImage(val, memoryStream.ToArray()))
				{
					DizzinessIconSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
					Logger.LogInfo((object)$"Icon loaded: {((Texture)val).width}x{((Texture)val).height}");
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"LoadIconSprite failed: {arg}");
			}
		}

		public static float GetEtcDamageMultiplier()
		{
			try
			{
				return Ascents.etcDamageMultiplier;
			}
			catch
			{
				return 1f;
			}
		}

		public static bool IsDizzinessDisabled()
		{
			return GetEtcDamageMultiplier() <= 0.001f;
		}

		public static float GetGainMultiplier()
		{
			float etcDamageMultiplier = GetEtcDamageMultiplier();
			if (etcDamageMultiplier <= 0.001f)
			{
				return 0f;
			}
			if (etcDamageMultiplier <= 0.6f)
			{
				return 1f;
			}
			if (etcDamageMultiplier <= 1.5f)
			{
				return 3f;
			}
			return 5f;
		}

		private void Update()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if ((Object)localCharacter != (Object)null && (Object)((Component)localCharacter).GetComponent<DizzinessTracker>() == (Object)null)
			{
				((Component)localCharacter).gameObject.AddComponent<DizzinessTracker>();
				if ((Object)((Component)localCharacter).GetComponent<DizzinessRpcReceiver>() == (Object)null)
				{
					((Component)localCharacter).gameObject.AddComponent<DizzinessRpcReceiver>();
				}
				Logger.LogInfo((object)"DizzinessTracker attached (fallback).");
			}
			DizzinessBarInjector.TryInjectBar();
			if (!debugMode.Value || !((Object)localCharacter != (Object)null))
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)286))
			{
				Rigidbody playerRigidbody = DizzinessTracker.GetPlayerRigidbody(localCharacter);
				if ((Object)playerRigidbody != (Object)null)
				{
					Transform transform = ((Component)playerRigidbody).transform;
					transform.position += Vector3.up * 100f;
					Logger.LogInfo((object)"[F5] Teleported +100m up.");
				}
			}
			if (Input.GetKeyDown((KeyCode)288))
			{
				DizzinessTracker component = ((Component)localCharacter).GetComponent<DizzinessTracker>();
				if ((Object)component != (Object)null)
				{
					component.dizzinessValue = 1f;
					Logger.LogInfo((object)"[F7] Forced dizziness = 1.0");
				}
			}
		}

		private void OnGUI()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			if (!debugMode.Value)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)localCharacter == (Object)null)
			{
				return;
			}
			DizzinessTracker component = ((Component)localCharacter).GetComponent<DizzinessTracker>();
			if (!((Object)component == (Object)null))
			{
				GUIStyle val = new GUIStyle();
				val.fontSize = 18;
				val.normal.textColor = Color.white;
				float num = 0f;
				Rigidbody playerRigidbody = DizzinessTracker.GetPlayerRigidbody(localCharacter);
				if ((Object)playerRigidbody != (Object)null)
				{
					Vector3 linearVelocity = playerRigidbody.linearVelocity;
					num = ((Vector3)(ref linearVelocity)).magnitude;
				}
				float etcDamageMultiplier = GetEtcDamageMultiplier();
				float gainMultiplier = GetGainMultiplier();
				string text = (IsDizzinessDisabled() ? "DISABLED" : $"x{gainMultiplier:F0}");
				float statusSum = localCharacter.refs.afflictions.statusSum;
				float maxStamina = localCharacter.GetMaxStamina();
				float currentStamina = localCharacter.data.currentStamina;
				GUI.Label(new Rect(20f, 100f, 700f, 30f), $"Speed: {num:F1}   Dizziness: {component.dizzinessValue:F3}   etcMult: {etcDamageMultiplier:F2} ({text})", val);
				GUI.Label(new Rect(20f, 122f, 700f, 30f), $"Ground: {component.isGrounded}   Climb: {component.isClimbing}   Resting: {component.IsResting}   RestTimer: {component.restTimer:F2}/{6f}", val);
				GUI.Label(new Rect(20f, 144f, 700f, 30f), $"FullyOut: {localCharacter.data.fullyPassedOut}   Sum: {statusSum:F2}   MaxStam: {maxStamina:F2}   CurStam: {currentStamina:F2}", val);
				GUI.Label(new Rect(20f, 166f, 700f, 30f), "CustomBar: " + (((Object)DizzinessBarInjector.injectedBar != (Object)null) ? "OK" : "missing"), val);
			}
		}
	}
	public class DizzinessRpcReceiver : MonoBehaviourPun
	{
		[PunRPC]
		public void Dizziness_RPC_Sync(float value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			DizzinessTracker component = ((Component)this).GetComponent<DizzinessTracker>();
			if ((Object)component != (Object)null && !component.character.IsLocal)
			{
				component.dizzinessValue = Mathf.Clamp01(value);
			}
		}
	}
	public class DizzinessTracker : MonoBehaviour
	{
		private float sustainedVelocityTimer;

		private float lastHighVelocityTime;

		public Character character;

		public float dizzinessValue;

		public float restTimer;

		public bool isGrounded;

		public bool isClimbing;

		private bool wasFullyPassedOut;

		private float lastSyncSent;

		private const float SYNC_INTERVAL = 0.2f;

		private Rigidbody _cachedRb;

		private static FieldInfo _groundedField;

		private static bool _groundedFieldSearched;

		private static FieldInfo[] _climbingFields;

		private static bool _climbingFieldsSearched;

		private float _lastStumbleTime;

		private float _stumbleCooldown = 2f;

		public bool IsResting
		{
			get
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Expected O, but got Unknown
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				if (isClimbing)
				{
					return false;
				}
				Rigidbody playerRigidbody = GetPlayerRigidbody(character);
				if ((Object)playerRigidbody == (Object)null)
				{
					return false;
				}
				Vector3 linearVelocity = playerRigidbody.linearVelocity;
				return ((Vector3)(ref linearVelocity)).magnitude < 7f;
			}
		}

		private void CheckForStumble(float dizziness)
		{
			if (dizziness < 0.25f || Time.time - _lastStumbleTime < _stumbleCooldown)
			{
				return;
			}
			float num = dizziness - 0.25f;
			float num2 = Mathf.Pow(num / 0.75f, 1.5f) * 0.15f;
			float num3 = num2 * Time.deltaTime * 60f;
			if (Random.value < num3)
			{
				float num4 = Mathf.Lerp(0.15f, 0.6f, (dizziness - 0.25f) / 0.75f);
				num4 *= Random.Range(0.8f, 1.2f);
				CharacterFallHelper.TriggerFall(character, num4);
				_lastStumbleTime = Time.time;
				if (DizzinessPlugin.debugMode.Value)
				{
					DizzinessPlugin.Logger.LogInfo((object)$"STUMBLE! Duration: {num4:F2}s, Dizziness: {dizziness:F2}");
				}
			}
		}

		public static Rigidbody GetPlayerRigidbody(Character c)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			if ((Object)c == (Object)null)
			{
				return null;
			}
			DizzinessTracker component = ((Component)c).GetComponent<DizzinessTracker>();
			if ((Object)component != (Object)null)
			{
				if ((Object)component._cachedRb != (Object)null)
				{
					return component._cachedRb;
				}
				component._cachedRb = ((Component)c).GetComponentInChildren<Rigidbody>();
				return component._cachedRb;
			}
			return ((Component)c).GetComponentInChildren<Rigidbody>();
		}

		private void Awake()
		{
			character = ((Component)this).GetComponent<Character>();
		}

		private bool IsSkeleton()
		{
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
			{
				return false;
			}
			if (character.data.isSkeleton && !character.data.dead && !character.data.fullyPassedOut)
			{
				return true;
			}
			return false;
		}

		private void Update()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			if ((Object)character == (Object)null || !character.IsLocal)
			{
				return;
			}
			isGrounded = DetectGrounded();
			isClimbing = DetectClimbing();
			bool fullyPassedOut = character.data.fullyPassedOut;
			if (wasFullyPassedOut && !fullyPassedOut)
			{
				float maxStamina = character.GetMaxStamina();
				if (maxStamina > 0.001f)
				{
					character.data.currentStamina = maxStamina;
					DizzinessPlugin.Logger.LogInfo((object)$"Recovered from pass-out: stamina restored to {maxStamina:F2}");
				}
			}
			wasFullyPassedOut = fullyPassedOut;
			if (DizzinessPlugin.IsDizzinessDisabled())
			{
				if (dizzinessValue > 0f)
				{
					dizzinessValue = Mathf.Max(0f, dizzinessValue - 0.05f * Time.deltaTime);
					MaybeSendSync();
				}
			}
			else
			{
				UpdateLocalDizziness();
				CheckForStumble(dizzinessValue);
				MaybeSendSync();
			}
			character.ClampStamina();
		}

		private bool DetectGrounded()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			if (!_groundedFieldSearched)
			{
				_groundedFieldSearched = true;
				if ((Object)character.data != (Object)null)
				{
					FieldInfo field = ((object)character.data).GetType().GetField("isGrounded", BindingFlags.Instance | BindingFlags.Public);
					if (field != null && field.FieldType == typeof(bool))
					{
						_groundedField = field;
						DizzinessPlugin.Logger.LogInfo((object)"Ground detect: using character.data.isGrounded");
					}
				}
			}
			if (_groundedField != null && (Object)character.data != (Object)null)
			{
				try
				{
					return (bool)_groundedField.GetValue(character.data);
				}
				catch
				{
				}
			}
			Rigidbody playerRigidbody = GetPlayerRigidbody(character);
			if ((Object)playerRigidbody == (Object)null)
			{
				return false;
			}
			return Physics.Raycast(((Component)playerRigidbody).transform.position + Vector3.up * 0.5f, Vector3.down, 1.5f, -1, (QueryTriggerInteraction)1);
		}

		private bool DetectClimbing()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			if (!_climbingFieldsSearched)
			{
				_climbingFieldsSearched = true;
				if ((Object)character.data != (Object)null)
				{
					Type type = ((object)character.data).GetType();
					string[] array = new string[3] { "isClimbing", "isRopeClimbing", "isVineClimbing" };
					List<FieldInfo> list = new List<FieldInfo>();
					string[] array2 = array;
					string[] array3 = array2;
					foreach (string text in array3)
					{
						FieldInfo field = type.GetField(text, BindingFlags.Instance | BindingFlags.Public);
						if (field != null && field.FieldType == typeof(bool))
						{
							list.Add(field);
							DizzinessPlugin.Logger.LogInfo((object)("Climb detect: found character.data." + text));
						}
					}
					_climbingFields = list.ToArray();
				}
			}
			if (_climbingFields == null || (Object)character.data == (Object)null)
			{
				return false;
			}
			try
			{
				FieldInfo[] climbingFields = _climbingFields;
				for (int j = 0; j < climbingFields.Length; j++)
				{
					if ((bool)climbingFields[j].GetValue(character.data))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private bool IsInvincible()
		{
			if ((Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null)
			{
				return false;
			}
			Affliction val = default(Affliction);
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)14, ref val))
			{
				return true;
			}
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)16, ref val))
			{
				return true;
			}
			return false;
		}

		private void UpdateLocalDizziness()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_006a: 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)
			if (IsResting && !character.data.fullyPassedOut)
			{
				restTimer += Time.deltaTime;
			}
			else
			{
				restTimer = 0f;
			}
			Rigidbody playerRigidbody = GetPlayerRigidbody(character);
			if ((Object)playerRigidbody == (Object)null)
			{
				return;
			}
			Vector3 linearVelocity = playerRigidbody.linearVelocity;
			float magnitude = ((Vector3)(ref linearVelocity)).magnitude;
			if (magnitude > 7f)
			{
				sustainedVelocityTimer += Time.deltaTime;
				lastHighVelocityTime = Time.time;
			}
			else
			{
				sustainedVelocityTimer = Mathf.Max(0f, sustainedVelocityTimer - Time.deltaTime * 2f);
			}
			if (!IsInvincible() && !IsSkeleton() && magnitude > 7f && sustainedVelocityTimer >= 0.25f)
			{
				float gainMultiplier = DizzinessPlugin.GetGainMultiplier();
				float num = magnitude - 7f;
				float num2 = num * num * 0.0012f * gainMultiplier;
				float num3 = Mathf.Min(num2, 0.35f);
				float num4 = Mathf.Lerp(1f, 0.1f, dizzinessValue / 0.8f);
				float num5 = num3 * num4;
				dizzinessValue = Mathf.Min(1f, dizzinessValue + num5 * Time.deltaTime);
				if (DizzinessPlugin.debugMode.Value && num5 > 0.001f)
				{
					DizzinessPlugin.Logger.LogInfo((object)$"Dizziness gain: raw={num2:F4}/s, capped={num3:F4}/s, actual={num5:F4}/s, dizziness={dizzinessValue:F3}");
				}
			}
			if (!IsSkeleton() && ((IsResting && restTimer >= 8f) || character.data.fullyPassedOut))
			{
				dizzinessValue = Mathf.Max(0f, dizzinessValue - 0.035f * Time.deltaTime);
			}
		}

		private void MaybeSendSync()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			if (Time.time - lastSyncSent < 0.2f)
			{
				return;
			}
			lastSyncSent = Time.time;
			PhotonView component = ((Component)character).GetComponent<PhotonView>();
			if ((Object)component == (Object)null || !PhotonNetwork.InRoom)
			{
				return;
			}
			try
			{
				component.RPC("Dizziness_RPC_Sync", (RpcTarget)1, new object[1] { dizzinessValue });
			}
			catch (Exception ex)
			{
				DizzinessPlugin.Logger.LogWarning((object)("RPC send failed: " + ex.Message));
			}
		}
	}
}

FaerieLanternEnhanced.dll

Decompiled a week ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FaerieLanternEnhanced")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6e98fd25e396354a38bb3faf9a061fac7078c358")]
[assembly: AssemblyProduct("FaerieLanternEnhanced")]
[assembly: AssemblyTitle("FaerieLanternEnhanced")]
[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 FaerieLanternEnhanced
{
	[BepInPlugin("jill920.faerielanternenhanced", "Faerie Lantern Enhanced", "1.0.1")]
	public class FaerieLanternEnhancedPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.faerielanternenhanced";

		public const string MOD_NAME = "Faerie Lantern Enhanced";

		public const string MOD_VERSION = "1.0.1";

		public static FaerieLanternEnhancedPlugin Instance;

		public static ManualLogSource Logger;

		public static bool IsDizzinessModInstalled = false;

		public static bool IsFatigueModInstalled = false;

		public static bool debugMode = false;

		public static float dizzinessHealRate = 0.025f;

		public static float fatigueHealRate = 0.025f;

		public static float effectRadius = 7.2f;

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableLogs", false, "Enable debug logging").Value;
			dizzinessHealRate = ((BaseUnityPlugin)this).Config.Bind<float>("Healing", "DizzinessHealRate", 0.025f, "Dizziness reduction per second while near lit Faerie Lantern").Value;
			fatigueHealRate = ((BaseUnityPlugin)this).Config.Bind<float>("Healing", "FatigueHealRate", 0.025f, "Fatigue reduction per second while near lit Faerie Lantern").Value;
			effectRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Healing", "EffectRadius", 7.2f, "Radius in meters for lantern healing effects").Value;
			CheckForInstalledMods();
			try
			{
				Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "jill920.faerielanternenhanced");
				Logger.LogInfo((object)"[Faerie Lantern Enhanced 1.0.1] Loaded successfully!");
				Logger.LogInfo((object)$"  Dizziness Mod detected: {IsDizzinessModInstalled}");
				Logger.LogInfo((object)$"  Fatigue Mod detected: {IsFatigueModInstalled}");
				Logger.LogInfo((object)$"  Dizziness heal rate: {dizzinessHealRate}/s");
				Logger.LogInfo((object)$"  Fatigue heal rate: {fatigueHealRate}/s");
				Logger.LogInfo((object)$"  Effect radius: {effectRadius}m");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to load: " + ex.Message));
			}
		}

		private void CheckForInstalledMods()
		{
			IsDizzinessModInstalled = false;
			IsFatigueModInstalled = false;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						IsDizzinessModInstalled = true;
					}
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						IsFatigueModInstalled = true;
					}
				}
				catch
				{
				}
			}
			if (!IsFatigueModInstalled)
			{
				try
				{
					IsFatigueModInstalled = Type.GetType("FatigueMod.FatigueTracker, Assembly-CSharp") != null;
				}
				catch
				{
				}
			}
			if (!IsDizzinessModInstalled)
			{
				try
				{
					IsDizzinessModInstalled = Type.GetType("DizzinessMod.DizzinessTracker, Assembly-CSharp") != null;
				}
				catch
				{
				}
			}
		}
	}
}
namespace FaerieLanternEnhanced.Patches
{
	[HarmonyPatch(typeof(ItemCooking), "RPC_CookingExplode")]
	internal static class ItemCooking_Explode_Patch
	{
		private const int FAERIE_LANTERN_ID = 43;

		private const float EXPLOSION_RADIUS = 4.8f;

		private static bool _fatigueCheckDone;

		private static bool _fatigueAvailable;

		private static bool _dizzinessCheckDone;

		private static bool _dizzinessAvailable;

		private static bool IsFatigueModPresent()
		{
			if (_fatigueCheckDone)
			{
				return _fatigueAvailable;
			}
			_fatigueCheckDone = true;
			if (FaerieLanternEnhancedPlugin.IsFatigueModInstalled)
			{
				_fatigueAvailable = true;
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						_fatigueAvailable = true;
						FaerieLanternEnhancedPlugin.IsFatigueModInstalled = true;
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)"Faerie Lantern Explosion: Fatigue Mod detected at runtime!");
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsDizzinessModPresent()
		{
			if (_dizzinessCheckDone)
			{
				return _dizzinessAvailable;
			}
			_dizzinessCheckDone = true;
			if (FaerieLanternEnhancedPlugin.IsDizzinessModInstalled)
			{
				_dizzinessAvailable = true;
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						_dizzinessAvailable = true;
						FaerieLanternEnhancedPlugin.IsDizzinessModInstalled = true;
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)"Faerie Lantern Explosion: Dizziness Mod detected at runtime!");
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		[HarmonyPrefix]
		private static void Prefix(ItemCooking __instance)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			Item item = ((ItemComponent)__instance).item;
			if ((Object)(object)item == (Object)null || item.itemID != 43)
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			bool flag = IsDizzinessModPresent();
			bool flag2 = IsFatigueModPresent();
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if ((Object)(object)allCharacter == (Object)null)
				{
					continue;
				}
				float num = Vector3.Distance(position, allCharacter.Center);
				if (!(num > 4.8f))
				{
					float num2 = 1f - num / 4.8f;
					float amount = -0.25f * num2;
					if (flag)
					{
						AddDizziness(allCharacter, amount);
					}
					if (flag2)
					{
						AddFatigue(allCharacter, amount);
					}
				}
			}
			FaerieLanternEnhancedPlugin.Logger.LogInfo((object)$"Faerie Lantern explosion: Applied status restoration within {4.8f}m");
		}

		private static void AddDizziness(Character character, float amount)
		{
			try
			{
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					float num2 = Mathf.Clamp01(num + amount);
					field.SetValue(component, num2);
					if (FaerieLanternEnhancedPlugin.debugMode)
					{
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)$"Explosion changed Dizziness: {num:F3} → {num2:F3} ({amount:F3})");
					}
				}
			}
			catch (Exception ex)
			{
				FaerieLanternEnhancedPlugin.Logger.LogWarning((object)("Failed to modify Dizziness: " + ex.Message));
			}
		}

		private static void AddFatigue(Character character, float amount)
		{
			try
			{
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					float num2 = Mathf.Clamp01(num + amount);
					field.SetValue(component, num2);
					if (FaerieLanternEnhancedPlugin.debugMode)
					{
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)$"Explosion changed Fatigue: {num:F3} → {num2:F3} ({amount:F3})");
					}
				}
			}
			catch (Exception ex)
			{
				FaerieLanternEnhancedPlugin.Logger.LogWarning((object)("Failed to modify Fatigue: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(Lantern), "Update")]
	internal static class Lantern_Update_Patch
	{
		private const int FAERIE_LANTERN_ID = 43;

		private static FieldInfo _litField;

		private static bool _fatigueCheckDone;

		private static bool _fatigueAvailable;

		private static bool IsLit(Lantern lantern)
		{
			if (_litField == null)
			{
				_litField = typeof(Lantern).GetField("lit", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			return _litField != null && (bool)_litField.GetValue(lantern);
		}

		private static bool IsFatigueModPresent()
		{
			if (_fatigueCheckDone)
			{
				return _fatigueAvailable;
			}
			_fatigueCheckDone = true;
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						_fatigueAvailable = true;
						FaerieLanternEnhancedPlugin.IsFatigueModInstalled = true;
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)"Fatigue Mod detected at runtime!");
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsDizzinessModPresent()
		{
			if (FaerieLanternEnhancedPlugin.IsDizzinessModInstalled)
			{
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						FaerieLanternEnhancedPlugin.IsDizzinessModInstalled = true;
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		[HarmonyPostfix]
		private static void Postfix(Lantern __instance)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((ItemComponent)__instance).item == (Object)null || ((ItemComponent)__instance).item.itemID != 43 || !IsLit(__instance))
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float effectRadius = FaerieLanternEnhancedPlugin.effectRadius;
			float deltaTime = Time.deltaTime;
			bool flag = IsDizzinessModPresent();
			bool flag2 = IsFatigueModPresent();
			if (!flag && !flag2)
			{
				return;
			}
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if ((Object)(object)allCharacter == (Object)null)
				{
					continue;
				}
				float num = Vector3.Distance(position, allCharacter.Center);
				if (!(num > effectRadius))
				{
					if (flag)
					{
						ReduceDizziness(allCharacter, FaerieLanternEnhancedPlugin.dizzinessHealRate * deltaTime);
					}
					if (flag2)
					{
						ReduceFatigue(allCharacter, FaerieLanternEnhancedPlugin.fatigueHealRate * deltaTime);
					}
					if (FaerieLanternEnhancedPlugin.debugMode)
					{
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)$"Faerie Lantern healing {allCharacter.characterName} (dist={num:F2}m)");
					}
				}
			}
		}

		private static void ReduceDizziness(Character character, float amount)
		{
			try
			{
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					float num2 = Mathf.Max(0f, num - amount);
					field.SetValue(component, num2);
					if (FaerieLanternEnhancedPlugin.debugMode && amount > 0.001f)
					{
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)$"Reduced Dizziness: {num:F3} → {num2:F3} (-{amount:F3})");
					}
				}
			}
			catch (Exception ex)
			{
				FaerieLanternEnhancedPlugin.Logger.LogWarning((object)("Failed to reduce Dizziness: " + ex.Message));
			}
		}

		private static void ReduceFatigue(Character character, float amount)
		{
			try
			{
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					float num2 = Mathf.Max(0f, num - amount);
					field.SetValue(component, num2);
					if (FaerieLanternEnhancedPlugin.debugMode && amount > 0.001f)
					{
						FaerieLanternEnhancedPlugin.Logger.LogInfo((object)$"Reduced Fatigue: {num:F3} → {num2:F3} (-{amount:F3})");
					}
				}
			}
			catch (Exception ex)
			{
				FaerieLanternEnhancedPlugin.Logger.LogWarning((object)("Failed to reduce Fatigue: " + ex.Message));
			}
		}
	}
}

FatigueMod.dll

Decompiled a week ago
using System;
using System.Collections;
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 Peak.Afflictions;
using Photon.Pun;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 FatigueMod
{
	[HarmonyPatch(typeof(Action_ApplyAffliction), "RunAction")]
	internal static class Action_ApplyAffliction_Patch
	{
		private static FieldInfo characterField;

		private static FieldInfo afflictionField;

		[HarmonyPrefix]
		private static void Prefix(Action_ApplyAffliction __instance)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if (characterField == null)
			{
				characterField = typeof(ItemActionBase).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			object? obj = characterField?.GetValue(__instance);
			Character val = (Character)((obj is Character) ? obj : null);
			if ((Object)(object)val == (Object)null || !val.IsLocal)
			{
				return;
			}
			if (afflictionField == null)
			{
				afflictionField = typeof(Action_ApplyAffliction).GetField("affliction", BindingFlags.Instance | BindingFlags.Public);
			}
			object? obj2 = afflictionField?.GetValue(__instance);
			Affliction val2 = (Affliction)((obj2 is Affliction) ? obj2 : null);
			if (val2 == null)
			{
				return;
			}
			FatiguePlugin.Logger.LogInfo((object)($"[DEBUG] Action_ApplyAffliction: {val2.GetAfflictionType()} " + "applied to " + val.characterName));
			Affliction_InfiniteStamina val3 = (Affliction_InfiniteStamina)(object)((val2 is Affliction_InfiniteStamina) ? val2 : null);
			if (val3 != null)
			{
				FatigueAfflictionHandler.OnAfflictionApplied(val, (Affliction)(object)val3);
				return;
			}
			Affliction_FasterBoi val4 = (Affliction_FasterBoi)(object)((val2 is Affliction_FasterBoi) ? val2 : null);
			if (val4 != null)
			{
				FatigueAfflictionHandler.OnAfflictionApplied(val, (Affliction)(object)val4);
			}
		}
	}
	[HarmonyPatch(typeof(Action_GiveExtraStamina), "RunAction")]
	internal static class Action_GiveExtraStamina_Patch
	{
		private static FieldInfo characterField;

		[HarmonyPostfix]
		private static void Postfix(Action_GiveExtraStamina __instance)
		{
			if (characterField == null)
			{
				characterField = typeof(ItemActionBase).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			object? obj = characterField?.GetValue(__instance);
			Character val = (Character)((obj is Character) ? obj : null);
			if ((Object)(object)val == (Object)null || !val.IsLocal)
			{
				return;
			}
			FatigueTracker component = ((Component)val).GetComponent<FatigueTracker>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			if (val.data.isSkeleton && !val.data.dead && !val.data.fullyPassedOut)
			{
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"Skipping fatigue reduction - target is a living skeleton");
				}
				return;
			}
			float amount = __instance.amount;
			float num = amount * FatiguePlugin.extraStaminaFatigueReductionRatio.Value;
			float fatigueValue = component.fatigueValue;
			component.fatigueValue = Mathf.Max(0f, component.fatigueValue - num);
			if (FatiguePlugin.debugMode.Value && num > 0.001f)
			{
				FatiguePlugin.Logger.LogInfo((object)($"Extra stamina ({amount:F2}) reduced fatigue by {num:F3} " + $"(from {fatigueValue:F3} to {component.fatigueValue:F3})"));
			}
		}
	}
	[HarmonyPatch(typeof(Action_ModifyStatus), "RunAction")]
	internal static class Action_ModifyStatus_Patch
	{
		[CompilerGenerated]
		private sealed class <CleanupProcessedItem>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Item item;

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

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

			[DebuggerHidden]
			public <CleanupProcessedItem>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					processedCureAlls.Remove(item);
					return false;
				}
			}

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

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

		private static HashSet<Item> processedCureAlls = new HashSet<Item>();

		private static readonly HashSet<ushort> healingItemIDs = new HashSet<ushort> { 24 };

		private static FieldInfo itemField;

		private static FieldInfo characterField;

		private static PropertyInfo characterProperty;

		[HarmonyPrefix]
		private static void Prefix(Action_ModifyStatus __instance)
		{
			if (itemField == null)
			{
				itemField = typeof(ItemActionBase).GetField("item", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			object? obj = itemField?.GetValue(__instance);
			Item val = (Item)((obj is Item) ? obj : null);
			if ((Object)(object)val == (Object)null || val.itemID != 24 || processedCureAlls.Contains(val))
			{
				return;
			}
			if (characterProperty == null)
			{
				characterProperty = typeof(ItemActionBase).GetProperty("character", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			Character val2 = null;
			if (characterProperty != null)
			{
				object? value = characterProperty.GetValue(__instance);
				val2 = (Character)((value is Character) ? value : null);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				if (characterField == null)
				{
					characterField = typeof(ItemActionBase).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic);
				}
				object? obj2 = characterField?.GetValue(__instance);
				val2 = (Character)((obj2 is Character) ? obj2 : null);
			}
			if ((Object)(object)val2 == (Object)null || !val2.IsLocal)
			{
				return;
			}
			if (val2.data.dead || val2.data.fullyPassedOut)
			{
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"Skipping fatigue reduction - target is dead or passed out");
				}
				return;
			}
			FatigueTracker component = ((Component)val2).GetComponent<FatigueTracker>();
			if (!((Object)(object)component == (Object)null))
			{
				float num = 0.15f;
				float fatigueValue = component.fatigueValue;
				component.fatigueValue = Mathf.Max(0f, component.fatigueValue - num);
				processedCureAlls.Add(val);
				((MonoBehaviour)__instance).StartCoroutine(CleanupProcessedItem(val));
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)($"Cure-All consumed: Removed {num:F3} fatigue " + $"(from {fatigueValue:F3} to {component.fatigueValue:F3})"));
				}
			}
		}

		[IteratorStateMachine(typeof(<CleanupProcessedItem>d__6))]
		private static IEnumerator CleanupProcessedItem(Item item)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CleanupProcessedItem>d__6(0)
			{
				item = item
			};
		}
	}
	[HarmonyPatch(typeof(CharacterData), "set_isSkeleton")]
	internal static class CharacterData_SetSkeleton_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(CharacterData __instance, bool value)
		{
			if (!value)
			{
				return;
			}
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			Component component2 = ((Component)component).GetComponent("FatigueMod.FatigueTracker");
			if ((Object)(object)component2 != (Object)null)
			{
				FieldInfo field = ((object)component2).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (field != null)
				{
					field.SetValue(component2, 0f);
					FatiguePlugin.Logger.LogInfo((object)"Cleared fatigue on skeleton transformation");
				}
			}
		}
	}
	[HarmonyPatch(typeof(Affliction), "OnApplied")]
	internal static class Affliction_OnApplied_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Affliction __instance)
		{
			if (!((Object)(object)__instance.character == (Object)null) && (__instance is Affliction_InfiniteStamina || __instance is Affliction_FasterBoi))
			{
				FatigueAfflictionHandler.OnAfflictionApplied(__instance.character, __instance);
			}
		}
	}
	[HarmonyPatch(typeof(Affliction), "OnRemoved")]
	internal static class Affliction_OnRemoved_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Affliction __instance)
		{
			if (!((Object)(object)__instance.character == (Object)null) && (__instance is Affliction_InfiniteStamina || __instance is Affliction_FasterBoi))
			{
				FatigueAfflictionHandler.OnAfflictionRemoved(__instance.character, __instance);
			}
		}
	}
	[HarmonyPatch(typeof(BarAffliction), "ChangeAffliction")]
	internal static class BarAffliction_ChangeAffliction_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(BarAffliction __instance, StaminaBar bar)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (((Object)((Component)__instance).gameObject).name != "FatigueCustomBar")
			{
				return true;
			}
			Character observedCharacter = Character.observedCharacter;
			if ((Object)observedCharacter == (Object)null)
			{
				return false;
			}
			FatigueTracker component = ((Component)observedCharacter).GetComponent<FatigueTracker>();
			if ((Object)component == (Object)null)
			{
				return false;
			}
			float fatigueValue = component.fatigueValue;
			__instance.size = bar.fullBar.sizeDelta.x * fatigueValue;
			if (fatigueValue > 0.01f)
			{
				if (__instance.size < bar.minAfflictionWidth)
				{
					__instance.size = bar.minAfflictionWidth;
				}
				((Component)__instance).gameObject.SetActive(true);
			}
			else
			{
				((Component)__instance).gameObject.SetActive(false);
			}
			if (FatiguePlugin.debugMode.Value && Mathf.Abs(fatigueValue - FatiguePlugin._lastLoggedFatigue) > 0.05f)
			{
				FatiguePlugin._lastLoggedFatigue = fatigueValue;
				FatiguePlugin.Logger.LogInfo((object)$"Fatigue bar updated: value={fatigueValue:F3}, size={__instance.size:F1}");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(BarAffliction), "UpdateAffliction")]
	internal static class BarAffliction_UpdateAffliction_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(BarAffliction __instance, StaminaBar bar)
		{
			if (((Object)((Component)__instance).gameObject).name != "FatigueCustomBar")
			{
				return true;
			}
			__instance.width = Mathf.Lerp(__instance.width, __instance.size, Mathf.Min(Time.deltaTime * 10f, 0.1f));
			return false;
		}
	}
	[HarmonyPatch(typeof(CharacterAfflictions))]
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class CharacterAfflictions_statusSum_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(CharacterAfflictions __instance, ref float __result)
		{
			if (!((Object)(object)__instance.character == (Object)null))
			{
				FatigueTracker component = ((Component)__instance.character).GetComponent<FatigueTracker>();
				if (!((Object)(object)component == (Object)null))
				{
					__result += component.fatigueValue;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "AddExtraStamina")]
	internal static class Character_AddExtraStamina_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance, float add)
		{
			if (!__instance.IsLocal || add <= 0f)
			{
				return;
			}
			if (__instance.data.isSkeleton && !__instance.data.dead && !__instance.data.fullyPassedOut)
			{
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"Skipping fatigue reduction - target is a living skeleton");
				}
				return;
			}
			FatigueTracker component = ((Component)__instance).GetComponent<FatigueTracker>();
			if (!((Object)(object)component == (Object)null))
			{
				float num = add * FatiguePlugin.extraStaminaFatigueReductionRatio.Value;
				float fatigueValue = component.fatigueValue;
				component.fatigueValue = Mathf.Max(0f, component.fatigueValue - num);
				if (FatiguePlugin.debugMode.Value && num > 0.001f)
				{
					FatiguePlugin.Logger.LogInfo((object)($"AddExtraStamina ({add:F2}) reduced fatigue by {num:F3} " + $"(from {fatigueValue:F3} to {component.fatigueValue:F3})"));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class Character_Awake_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if ((Object)((Component)__instance).GetComponent<FatigueTracker>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<FatigueTracker>();
			}
			if ((Object)((Component)__instance).GetComponent<FatigueRpcReceiver>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<FatigueRpcReceiver>();
			}
		}
	}
	[HarmonyPatch(typeof(Character), "HasMeaningfulTempStatuses")]
	internal static class Character_HasMeaningfulTempStatuses_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance, ref bool __result)
		{
			FatigueTracker component = ((Component)__instance).GetComponent<FatigueTracker>();
			if (!((Object)(object)component == (Object)null) && !__result && component.fatigueValue > 0.05f)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "UseStamina")]
	public static class Character_UseStamina_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Character __instance, float usage, bool useBonusStamina, ref bool __result)
		{
			if (__result && !(usage <= 0f) && !FatiguePlugin.IsFatigueDisabled())
			{
				FatigueTracker component = ((Component)__instance).GetComponent<FatigueTracker>();
				if (!((Object)(object)component == (Object)null))
				{
					component.OnStaminaUsed(usage);
				}
			}
		}
	}
	public static class FatigueAfflictionHandler
	{
		private class AfflictionData
		{
			public AfflictionType type;

			public float cachedFatigue;

			public float bonusFatigueOnEnd;

			public bool fatigueBlocked;
		}

		private static Dictionary<int, AfflictionData> activeAfflictions = new Dictionary<int, AfflictionData>();

		public static void OnAfflictionApplied(Character character, Affliction affliction)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null || !character.IsLocal)
			{
				return;
			}
			FatigueTracker component = ((Component)character).GetComponent<FatigueTracker>();
			if (!((Object)(object)component == (Object)null))
			{
				int viewID = ((MonoBehaviourPun)character).photonView.ViewID;
				Affliction_FasterBoi val = (Affliction_FasterBoi)(object)((affliction is Affliction_FasterBoi) ? affliction : null);
				if (val != null)
				{
					AfflictionData afflictionData = new AfflictionData
					{
						type = (AfflictionType)2,
						cachedFatigue = component.fatigueValue,
						bonusFatigueOnEnd = 0.1f,
						fatigueBlocked = true
					};
					activeAfflictions[viewID] = afflictionData;
					component.fatigueValue = 0f;
					FatiguePlugin.Logger.LogInfo((object)($"[Fatigue] Energy Drink consumed - Fatigue blocked for {((Affliction)val).totalTime:F1}s. " + $"Cached fatigue: {afflictionData.cachedFatigue:F3}, will add +{afflictionData.bonusFatigueOnEnd:F3} on end."));
				}
			}
		}

		private static bool IsInvincible(Character character)
		{
			if ((Object)(object)character == (Object)null || (Object)(object)character.refs?.afflictions == (Object)null)
			{
				return false;
			}
			Affliction val = default(Affliction);
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)14, ref val))
			{
				return true;
			}
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)16, ref val))
			{
				return true;
			}
			return false;
		}

		public static void OnAfflictionRemoved(Character character, Affliction affliction)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Invalid comparison between Unknown and I4
			if ((Object)(object)character == (Object)null || !character.IsLocal)
			{
				return;
			}
			FatigueTracker component = ((Component)character).GetComponent<FatigueTracker>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			int viewID = ((MonoBehaviourPun)character).photonView.ViewID;
			if (activeAfflictions.TryGetValue(viewID, out var value) && (int)value.type == 2 && affliction is Affliction_FasterBoi)
			{
				float num;
				if (IsInvincible(character))
				{
					num = value.cachedFatigue;
					FatiguePlugin.Logger.LogInfo((object)("[Fatigue] Energy Drink effect ended - Character is INVINCIBLE (BingBongShield/Milk). " + $"Restored {value.cachedFatigue:F3} fatigue (NO BONUS added)."));
				}
				else
				{
					num = value.cachedFatigue + value.bonusFatigueOnEnd;
					FatiguePlugin.Logger.LogInfo((object)($"[Fatigue] Energy Drink effect ended - Restored {value.cachedFatigue:F3} " + $"+ bonus {value.bonusFatigueOnEnd:F3} = {num:F3}"));
				}
				component.fatigueValue = Mathf.Min(1f, num);
				activeAfflictions.Remove(viewID);
			}
		}

		public static bool IsFatigueBlocked(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return false;
			}
			int viewID = ((MonoBehaviourPun)character).photonView.ViewID;
			return activeAfflictions.ContainsKey(viewID);
		}
	}
	public static class FatigueBarInjector
	{
		public static BarAffliction injectedBar;

		private static bool injectionFailed;

		public static void TryInjectBar()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Invalid comparison between Unknown and I4
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Expected O, but got Unknown
			//IL_0201: Expected O, but got Unknown
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)injectedBar != (Object)null || injectionFailed)
			{
				return;
			}
			try
			{
				if ((Object)GUIManager.instance == (Object)null)
				{
					return;
				}
				StaminaBar bar = GUIManager.instance.bar;
				if ((Object)bar == (Object)null || bar.afflictions == null || bar.afflictions.Length == 0)
				{
					return;
				}
				BarAffliction val = null;
				BarAffliction[] afflictions = bar.afflictions;
				BarAffliction[] array = afflictions;
				foreach (BarAffliction val2 in array)
				{
					if (!((Object)val2 == (Object)null) && (int)val2.afflictionType == 4)
					{
						val = val2;
						break;
					}
				}
				if ((Object)val == (Object)null)
				{
					FatiguePlugin.Logger.LogWarning((object)"Crab template bar not found in StaminaBar.afflictions");
					injectionFailed = true;
					return;
				}
				GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent);
				((Object)val3).name = "FatigueCustomBar";
				BarAffliction component = val3.GetComponent<BarAffliction>();
				if ((Object)component == (Object)null)
				{
					FatiguePlugin.Logger.LogError((object)"Cloned GameObject has no BarAffliction component");
					Object.Destroy((Object)val3);
					injectionFailed = true;
					return;
				}
				if ((Object)FatiguePlugin.FatigueIconSprite != (Object)null && (Object)component.icon != (Object)null)
				{
					component.icon.sprite = FatiguePlugin.FatigueIconSprite;
					((Graphic)component.icon).color = Color.white;
				}
				Image[] componentsInChildren = ((Component)component).GetComponentsInChildren<Image>(true);
				Image[] array2 = componentsInChildren;
				foreach (Image val4 in array2)
				{
					if (!((Object)component.icon != (Object)null) || !((Object)val4 == (Object)component.icon))
					{
						Color fatigueColor = FatiguePlugin.FatigueColor;
						fatigueColor.a = ((Graphic)val4).color.a;
						((Graphic)val4).color = fatigueColor;
					}
				}
				component.size = 0f;
				val3.SetActive(false);
				FieldInfo field = typeof(StaminaBar).GetField("afflictions", BindingFlags.Instance | BindingFlags.Public);
				if (field == null)
				{
					FatiguePlugin.Logger.LogError((object)"StaminaBar.afflictions field not found");
					Object.Destroy((Object)val3);
					injectionFailed = true;
					return;
				}
				BarAffliction[] array3 = (BarAffliction[])field.GetValue(bar);
				BarAffliction[] array4 = (BarAffliction[])(object)new BarAffliction[array3.Length + 1];
				Array.Copy(array3, array4, array3.Length);
				array4[array3.Length] = component;
				field.SetValue(bar, array4);
				injectedBar = component;
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)$"Independent bar injected. New array size: {array4.Length}");
				}
			}
			catch (Exception arg)
			{
				FatiguePlugin.Logger.LogError((object)$"Bar injection failed: {arg}");
				injectionFailed = true;
			}
		}
	}
	[BepInPlugin("jill920.fatiguefromstamina", "Fatigue Mod", "1.2.0")]
	public class FatiguePlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.fatiguefromstamina";

		public static float _lastLoggedFatigue = -1f;

		public const string MOD_NAME = "Fatigue Mod";

		public const string MOD_VERSION = "1.2.0";

		public static FatiguePlugin Instance;

		public static ManualLogSource Logger;

		public static ConfigEntry<bool> debugMode;

		public static readonly Color FatigueColor = new Color(1f, 0.5f, 0f, 1f);

		public static Sprite FatigueIconSprite;

		public const string CUSTOM_BAR_NAME = "FatigueCustomBar";

		public static ConfigEntry<string> healingItemsConfig;

		public static ConfigEntry<float> extraStaminaFatigueReductionRatio;

		public static ConfigEntry<float> baseExertionRate;

		public static ConfigEntry<float> maxExertionRate;

		public static ConfigEntry<float> exertionRampUpTime;

		public static ConfigEntry<float> baseRecoveryRate;

		public static ConfigEntry<float> minRecoveryRate;

		public static ConfigEntry<float> recoveryRampDownTime;

		public static ConfigEntry<float> exertionDecayRate;

		public static ConfigEntry<float> staminaToRecoveryPenalty;

		public const float PLAY_DEAD_RECOVERY_MULTIPLIER = 1.66f;

		public const float ENERGY_DRINK_BONUS_FATIGUE = 0.1f;

		public const float zeroStaminaFatigue = 0.035f;

		private void Awake()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Expected O, but got Unknown
			healingItemsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("Healing", "HealingItemIDs", "24", "Comma-separated list of item IDs that reduce fatigue when used");
			extraStaminaFatigueReductionRatio = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery", "ExtraStaminaFatigueReductionRatio", 0.4f, "Amount of fatigue removed per unit of extra stamina given.");
			baseExertionRate = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "BaseExertionRate", 0.04f, new ConfigDescription("Base fatigue gained per stamina used (rested state)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 0.1f), Array.Empty<object>()));
			maxExertionRate = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "MaxExertionRate", 0.12f, new ConfigDescription("Maximum fatigue gained per stamina used (fully exerted)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.08f, 0.2f), Array.Empty<object>()));
			exertionRampUpTime = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "ExertionRampUpTime", 40f, new ConfigDescription("Seconds of continuous sprinting to reach max exertion", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 60f), Array.Empty<object>()));
			baseRecoveryRate = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery", "BaseRecoveryRate", 0.0045f, new ConfigDescription("Fatigue recovered per second when fully rested", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.003f, 0.015f), Array.Empty<object>()));
			minRecoveryRate = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery", "MinRecoveryRate", 0.001f, new ConfigDescription("Minimum fatigue recovery during heavy activity", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 0.005f), Array.Empty<object>()));
			recoveryRampDownTime = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery", "RecoveryRampDownTime", 12f, new ConfigDescription("Seconds of rest to reach full recovery rate after heavy exertion", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 20f), Array.Empty<object>()));
			exertionDecayRate = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "ExertionDecayRate", 0.8f, new ConfigDescription("How fast exertion level decays when resting (per second)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 1.5f), Array.Empty<object>()));
			staminaToRecoveryPenalty = ((BaseUnityPlugin)this).Config.Bind<float>("Recovery", "StaminaToRecoveryPenalty", 0.15f, new ConfigDescription("How much stamina usage reduces recovery multiplier (per 10 stamina)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.3f), Array.Empty<object>()));
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugKeys", false, "...");
			LoadIconSprite();
			try
			{
				Harmony val = new Harmony("jill920.fatiguefromstamina");
				val.PatchAll(Assembly.GetExecutingAssembly());
				IEnumerable<MethodBase> patchedMethods = val.GetPatchedMethods();
				foreach (MethodBase item in patchedMethods)
				{
					Logger.LogInfo((object)("Patched: " + item.DeclaringType?.Name + "." + item.Name));
				}
				Logger.LogInfo((object)"[Fatigue From Stamina 1.1.0] Loaded with tug-of-war fatigue system.");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"Harmony patch failed: {arg}");
			}
		}

		private static void LoadIconSprite()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FatigueMod.Assets.fatigue_icon.png");
				if (stream == null)
				{
					Logger.LogWarning((object)"Embedded icon not found in resources!");
					return;
				}
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)1;
				if (ImageConversion.LoadImage(val, memoryStream.ToArray()))
				{
					FatigueIconSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
					Logger.LogInfo((object)$"Icon loaded: {((Texture)val).width}x{((Texture)val).height}");
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"LoadIconSprite failed: {arg}");
			}
		}

		public static float GetEtcDamageMultiplier()
		{
			try
			{
				return Ascents.etcDamageMultiplier;
			}
			catch
			{
				return 1f;
			}
		}

		public static bool IsFatigueDisabled()
		{
			return GetEtcDamageMultiplier() <= 0.001f;
		}

		public static float GetGainMultiplier()
		{
			float etcDamageMultiplier = GetEtcDamageMultiplier();
			if (etcDamageMultiplier <= 0.001f)
			{
				return 0f;
			}
			if (etcDamageMultiplier <= 0.6f)
			{
				return 1f;
			}
			if (etcDamageMultiplier <= 1.5f)
			{
				return 2f;
			}
			return 3f;
		}

		private void Update()
		{
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter != (Object)null && (Object)(object)((Component)localCharacter).GetComponent<FatigueTracker>() == (Object)null)
			{
				((Component)localCharacter).gameObject.AddComponent<FatigueTracker>();
				if ((Object)(object)((Component)localCharacter).GetComponent<FatigueRpcReceiver>() == (Object)null)
				{
					((Component)localCharacter).gameObject.AddComponent<FatigueRpcReceiver>();
				}
				Logger.LogInfo((object)"FatigueTracker attached (fallback).");
			}
			FatigueBarInjector.TryInjectBar();
			if (debugMode.Value && !((Object)(object)localCharacter == (Object)null) && Input.GetKeyDown((KeyCode)288))
			{
				FatigueTracker component = ((Component)localCharacter).GetComponent<FatigueTracker>();
				if ((Object)(object)component != (Object)null)
				{
					component.fatigueValue = 0.5f;
					Logger.LogInfo((object)"[F7] Forced fatigue = 0.5");
				}
			}
		}

		private void OnGUI()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			if (!debugMode.Value)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			FatigueTracker component = ((Component)localCharacter).GetComponent<FatigueTracker>();
			if (!((Object)(object)component == (Object)null))
			{
				GUIStyle val = new GUIStyle();
				val.fontSize = 18;
				val.normal.textColor = Color.white;
				float num = 0f;
				Rigidbody playerRigidbody = FatigueTracker.GetPlayerRigidbody(localCharacter);
				if ((Object)(object)playerRigidbody != (Object)null)
				{
					Vector3 linearVelocity = playerRigidbody.linearVelocity;
					num = ((Vector3)(ref linearVelocity)).magnitude;
				}
				float etcDamageMultiplier = GetEtcDamageMultiplier();
				float gainMultiplier = GetGainMultiplier();
				string text = (IsFatigueDisabled() ? "DISABLED" : $"x{gainMultiplier:F0}");
				float statusSum = localCharacter.refs.afflictions.statusSum;
				float maxStamina = localCharacter.GetMaxStamina();
				float currentStamina = localCharacter.data.currentStamina;
				GUI.Label(new Rect(20f, 100f, 700f, 30f), $"Speed: {num:F1}   Fatigue: {component.fatigueValue:F3}   Exertion: {component.currentExertionLevel:F2}", val);
				GUI.Label(new Rect(20f, 122f, 700f, 30f), $"Ground: {component.isGrounded}   Climb: {component.isClimbing}   RecoveryMult: {component.currentRecoveryMultiplier:F2}x", val);
				GUI.Label(new Rect(20f, 144f, 700f, 30f), $"FullyOut: {localCharacter.data.fullyPassedOut}   Sum: {statusSum:F2}   MaxStam: {maxStamina:F2}   CurStam: {currentStamina:F2}", val);
				GUI.Label(new Rect(20f, 166f, 700f, 30f), "CustomBar: " + (((Object)(object)FatigueBarInjector.injectedBar != (Object)null) ? "OK" : "missing"), val);
			}
		}
	}
	public class FatigueRpcReceiver : MonoBehaviourPun
	{
		private Character character;

		private void Awake()
		{
			character = ((Component)this).GetComponent<Character>();
		}

		[PunRPC]
		public void Fatigue_RPC_Sync(float value)
		{
			FatigueTracker component = ((Component)this).GetComponent<FatigueTracker>();
			if ((Object)(object)component != (Object)null && !component.character.IsLocal)
			{
				component.fatigueValue = Mathf.Clamp01(value);
			}
		}

		[PunRPC]
		public void RPC_ReduceFatigue(float amount)
		{
			if (!((MonoBehaviourPun)this).photonView.IsMine)
			{
				if (FatiguePlugin.debugMode.Value)
				{
					ManualLogSource logger = FatiguePlugin.Logger;
					Character obj = character;
					logger.LogInfo((object)("[FATIGUE RPC] Skipping " + ((obj != null) ? obj.characterName : null) + " - not owner"));
				}
			}
			else
			{
				if ((Object)(object)character == (Object)null || amount <= 0f)
				{
					return;
				}
				if (character.data.dead)
				{
					if (FatiguePlugin.debugMode.Value)
					{
						FatiguePlugin.Logger.LogInfo((object)("[FATIGUE RPC] Skipping " + character.characterName + " - is dead"));
					}
					return;
				}
				FatigueTracker component = ((Component)this).GetComponent<FatigueTracker>();
				if (!((Object)(object)component == (Object)null))
				{
					float fatigueValue = component.fatigueValue;
					component.fatigueValue = Mathf.Max(0f, component.fatigueValue - amount);
					if (FatiguePlugin.debugMode.Value)
					{
						FatiguePlugin.Logger.LogInfo((object)$"[FATIGUE RPC] {character.characterName}: Fatigue {fatigueValue:F3} -> {component.fatigueValue:F3} (-{amount:F3})");
					}
				}
			}
		}

		private bool IsInvincible()
		{
			if ((Object)(object)character == (Object)null || (Object)(object)character.refs?.afflictions == (Object)null)
			{
				return false;
			}
			Affliction val = default(Affliction);
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)14, ref val))
			{
				return true;
			}
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)16, ref val))
			{
				return true;
			}
			return false;
		}
	}
	public class FatigueTracker : MonoBehaviour
	{
		public Character character;

		public float fatigueValue;

		public float currentExertionLevel;

		public float currentRecoveryMultiplier;

		public bool isGrounded;

		public bool isClimbing;

		private float _lastValidStaminaUseTime;

		private float _playDeadEndTime = 0f;

		private const float PLAY_DEAD_DURATION = 4f;

		private float _staminaUsedInWindow;

		private const float EXERTION_WINDOW = 16f;

		private const float MAX_STAMINA_FOR_EXERTION = 2f;

		private float _timeAtZeroStamina;

		private float _zeroStaminaPenalty;

		private float _lastStaminaCheck;

		private float _staminaUsageRate;

		private float _staminaRateSmoothing = 0.2f;

		private float _lastStaminaTime;

		private float _lastSyncSent;

		private const float SYNC_INTERVAL = 0.2f;

		private float _smoothedVelocity;

		private float _velocitySmoothing = 0.95f;

		public bool IsPlayingDead => Time.time < _playDeadEndTime;

		public bool IsResting
		{
			get
			{
				//IL_005e: 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)
				if (isClimbing)
				{
					return false;
				}
				if (character.data.isSprinting)
				{
					return false;
				}
				Rigidbody playerRigidbody = GetPlayerRigidbody(character);
				if ((Object)(object)playerRigidbody == (Object)null)
				{
					return false;
				}
				float num = _smoothedVelocity * _velocitySmoothing;
				Vector3 linearVelocity = playerRigidbody.linearVelocity;
				_smoothedVelocity = num + ((Vector3)(ref linearVelocity)).magnitude * (1f - _velocitySmoothing);
				bool flag = _smoothedVelocity < 1.5f;
				if (FatiguePlugin.debugMode.Value && Time.frameCount % 120 == 0)
				{
					FatiguePlugin.Logger.LogInfo((object)$"IsResting: {flag}, Velocity: {_smoothedVelocity:F2}");
				}
				return flag;
			}
		}

		private bool IsInvincible()
		{
			if ((Object)(object)character == (Object)null || (Object)(object)character.refs?.afflictions == (Object)null)
			{
				return false;
			}
			Affliction val = default(Affliction);
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)14, ref val))
			{
				return true;
			}
			if (character.refs.afflictions.HasAfflictionType((AfflictionType)16, ref val))
			{
				return true;
			}
			return false;
		}

		private float GetBonusStaminaPercentage()
		{
			float extraStamina = character.data.extraStamina;
			float num = Mathf.Clamp01(extraStamina);
			if (FatiguePlugin.debugMode.Value && Time.frameCount % 300 == 0)
			{
				FatiguePlugin.Logger.LogInfo((object)$"Bonus Stamina: {extraStamina:F2} = {num:F2}%");
			}
			return num;
		}

		private bool IsImmuneToStaminaDrainFatigue()
		{
			if ((Object)(object)character == (Object)null)
			{
				return false;
			}
			if (IsSkeleton())
			{
				return true;
			}
			if (IsInvincible())
			{
				return true;
			}
			return false;
		}

		private bool IsSkeleton()
		{
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
			{
				return false;
			}
			if (character.data.isSkeleton && !character.data.dead && !character.data.fullyPassedOut)
			{
				return true;
			}
			return false;
		}

		private void Awake()
		{
			character = ((Component)this).GetComponent<Character>();
			currentExertionLevel = 0f;
			currentRecoveryMultiplier = 1f;
			_lastStaminaTime = Time.time;
			_smoothedVelocity = 0f;
			_lastStaminaCheck = character.data.currentStamina;
			_timeAtZeroStamina = 0f;
			_zeroStaminaPenalty = 0f;
			_lastValidStaminaUseTime = -1f;
		}

		public static Rigidbody GetPlayerRigidbody(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return null;
			}
			return ((Component)c).GetComponentInChildren<Rigidbody>();
		}

		private float GetCurrentMaxStamina()
		{
			return Mathf.Max(0f, 1f - character.refs.afflictions.statusSum);
		}

		private void UpdateZeroStaminaPenalty()
		{
			bool flag = IsTrulyOutOfStamina();
			float num = 0.01f;
			if (flag)
			{
				_timeAtZeroStamina += Time.deltaTime;
				float num2 = Mathf.Clamp01(_timeAtZeroStamina / 4f);
				_zeroStaminaPenalty = Mathf.MoveTowards(_zeroStaminaPenalty, num2, Time.deltaTime * 2f);
				bool flag2 = Time.time - _lastValidStaminaUseTime < 0.5f;
				if (_lastStaminaCheck > num && flag && !IsImmuneToStaminaDrainFatigue() && flag2)
				{
					float num3 = 0.035f;
					fatigueValue = Mathf.Min(1f, fatigueValue + num3);
					if (FatiguePlugin.debugMode.Value)
					{
						FatiguePlugin.Logger.LogInfo((object)($"STAMINA ZERO (Primary + Bonus)! +{num3:F3} fatigue (total: {fatigueValue:F3}) | " + $"Last valid use: {Time.time - _lastValidStaminaUseTime:F2}s ago"));
					}
				}
				else if (_lastStaminaCheck > num && flag && !flag2)
				{
					if (FatiguePlugin.debugMode.Value)
					{
						FatiguePlugin.Logger.LogInfo((object)("STAMINA ZERO but from NON-MOVEMENT action (heavy item, etc.) - No fatigue penalty applied | " + $"Last valid use: {Time.time - _lastValidStaminaUseTime:F2}s ago"));
					}
				}
				else if (_lastStaminaCheck > num && flag && IsImmuneToStaminaDrainFatigue() && FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"STAMINA ZERO but IMMUNE (Skeleton/Milk/Shield) - No fatigue penalty applied");
				}
			}
			else if (_zeroStaminaPenalty > 0f)
			{
				float num4 = 1f;
				_zeroStaminaPenalty = Mathf.MoveTowards(_zeroStaminaPenalty, 0f, Time.deltaTime * num4);
				_timeAtZeroStamina = Mathf.MoveTowards(_timeAtZeroStamina, 0f, Time.deltaTime);
			}
			_lastStaminaCheck = character.data.currentStamina + character.data.extraStamina;
			if (FatiguePlugin.debugMode.Value && _zeroStaminaPenalty > 0.01f && Time.frameCount % 60 == 0)
			{
				FatiguePlugin.Logger.LogInfo((object)($"Zero stamina penalty: {_zeroStaminaPenalty:F2} (time at zero: {_timeAtZeroStamina:F1}s) | " + $"Primary: {character.data.currentStamina:F2}, Bonus: {character.data.extraStamina:F2}"));
			}
		}

		public void OnStaminaUsed(float usage)
		{
			if (usage <= 0f)
			{
				return;
			}
			float time = Time.time;
			float num = time - _lastStaminaTime;
			bool flag = character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing;
			bool flag2 = false;
			string text = "UNKNOWN";
			if (character.data.isSprinting)
			{
				flag2 = true;
				text = "SPRINT";
			}
			else if (flag)
			{
				flag2 = true;
				text = "CLIMB";
			}
			else if (character.data.sinceJump < 0.1f)
			{
				flag2 = true;
				text = "JUMP";
			}
			else if (character.data.isGrounded && ((Vector3)(ref character.data.worldMovementInput)).magnitude > 0.5f)
			{
				flag2 = false;
				text = "MOVE";
			}
			else
			{
				text = "OTHER";
			}
			if (flag2)
			{
				_lastValidStaminaUseTime = time;
			}
			bool flag3 = character.data.currentStamina <= 0.01f && character.data.extraStamina > 0f;
			bool flag4 = character.data.currentStamina > 0.01f;
			float bonusStaminaPercentage = GetBonusStaminaPercentage();
			float num2 = 1f;
			string text2 = "PRIMARY";
			if (flag3)
			{
				num2 = Mathf.Lerp(1f, 0.4f, bonusStaminaPercentage);
				text2 = (flag ? "BONUS_CLIMB" : "BONUS");
			}
			else if (flag4)
			{
				num2 = Mathf.Lerp(1f, 0.4f, bonusStaminaPercentage);
				text2 = (flag ? "PRIMARY_CLIMB" : "PRIMARY");
			}
			float num3 = (flag ? 1f : 1f);
			float num4 = num2 * num3;
			num4 = Mathf.Clamp(num4, 0.35f, 1.2f);
			float num5 = usage / Mathf.Max(0.016f, num);
			_staminaUsageRate = Mathf.Lerp(_staminaUsageRate, num5, _staminaRateSmoothing);
			float num6 = usage * num4;
			_staminaUsedInWindow += num6;
			_lastStaminaTime = time;
			if (FatiguePlugin.debugMode.Value && usage > 0.01f)
			{
				FatiguePlugin.Logger.LogInfo((object)($"Stamina used: {usage:F2} ({text2}, action: {text}, valid: {flag2}, mult: {num4:F2}, climbing: {flag}, bonus%: {bonusStaminaPercentage:F2}) | " + $"Primary: {character.data.currentStamina:F2}, Bonus: {character.data.extraStamina:F2} | " + $"Rate: {_staminaUsageRate:F0}/s | Window total: {_staminaUsedInWindow:F1}/{2f:F0}"));
			}
			if (!IsInvincible() && !IsSkeleton() && !FatigueAfflictionHandler.IsFatigueBlocked(character) && !IsImmuneToStaminaDrainFatigue())
			{
				float num7 = Mathf.Clamp01(_staminaUsedInWindow / 2f);
				float num8 = Mathf.Clamp01((_staminaUsageRate - 30f) / 90f) * 0.6f;
				num7 = Mathf.Min(1f, num7 + num8);
				float num9 = _zeroStaminaPenalty * 0.5f;
				num7 = Mathf.Min(1f, num7 + num9);
				if (num7 > currentExertionLevel)
				{
					currentExertionLevel = Mathf.MoveTowards(currentExertionLevel, num7, Time.deltaTime * 3f);
				}
				else
				{
					currentExertionLevel = Mathf.MoveTowards(currentExertionLevel, num7, Time.deltaTime * 1f);
				}
				float num10 = Mathf.Lerp(FatiguePlugin.baseExertionRate.Value, FatiguePlugin.maxExertionRate.Value, currentExertionLevel);
				float num11 = usage * num10 * num4 * FatiguePlugin.GetGainMultiplier();
				if (num11 > 0f)
				{
					fatigueValue = Mathf.Min(1f, fatigueValue + num11);
					if (FatiguePlugin.debugMode.Value && num11 > 0.001f)
					{
						FatiguePlugin.Logger.LogInfo((object)($"  -> Fatigue +{num11:F4} (total: {fatigueValue:F3}) | " + $"Exertion: {currentExertionLevel:F2} | Rate: {num10:F3} | " + $"Source: {text2} (base: {num2:F2}, climb: {num3:F2}, final: {num4:F2})"));
					}
				}
			}
			else if (FatiguePlugin.debugMode.Value && (IsInvincible() || IsSkeleton() || IsImmuneToStaminaDrainFatigue()))
			{
				FatiguePlugin.Logger.LogInfo((object)"Fatigue gain blocked by immunity (Skeleton/Invincible/Shield)");
			}
		}

		public void SetPlayingDead(bool playing)
		{
			if (playing)
			{
				_playDeadEndTime = Time.time + 4f;
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)$"Play Dead emote started - Fatigue recovery boosted for {4f} seconds. End time: {_playDeadEndTime:F2}");
				}
			}
			else
			{
				_playDeadEndTime = 0f;
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"Play Dead emote ended");
				}
			}
		}

		private void UpdateStaminaWindow()
		{
			float num = Time.time - _lastStaminaTime;
			if (num > 0.5f)
			{
				float num2 = 0.125f;
				float num3 = Time.deltaTime * num2;
				_staminaUsedInWindow = Mathf.Max(0f, _staminaUsedInWindow - num3);
			}
			if (num > 1f)
			{
				_staminaUsageRate = Mathf.MoveTowards(_staminaUsageRate, 0f, Time.deltaTime * 20f);
			}
		}

		private float GetStaminaPercentage()
		{
			float currentMaxStamina = GetCurrentMaxStamina();
			if (currentMaxStamina <= 0f)
			{
				return 0f;
			}
			float num = character.data.currentStamina + character.data.extraStamina;
			return Mathf.Clamp01(num / currentMaxStamina);
		}

		private bool IsTrulyOutOfStamina()
		{
			return character.data.currentStamina <= 0.01f && character.data.extraStamina <= 0.01f;
		}

		private float CalculateRecoveryMultiplier()
		{
			if (character.data.passedOut || character.data.fullyPassedOut)
			{
				if (FatiguePlugin.debugMode.Value && Time.frameCount % 60 == 0)
				{
					FatiguePlugin.Logger.LogInfo((object)"Unconscious state detected - maximum recovery applied");
				}
				return 1f;
			}
			float num = 1f;
			float num2 = Mathf.Clamp01(currentExertionLevel) * 0.8f;
			num -= num2;
			float staminaDeficitPenalty = GetStaminaDeficitPenalty();
			if (!float.IsNaN(staminaDeficitPenalty) && !float.IsInfinity(staminaDeficitPenalty))
			{
				num -= staminaDeficitPenalty;
			}
			float num3 = Mathf.Clamp01(_zeroStaminaPenalty) * 0.8f;
			num -= num3;
			if (IsResting)
			{
				num += 0.15f;
			}
			num = Mathf.Clamp(num, 0f, 1f);
			if (IsPlayingDead && !float.IsNaN(num))
			{
				num *= 1.66f;
			}
			if (float.IsNaN(num) || float.IsInfinity(num))
			{
				num = 1f;
			}
			return num;
		}

		private float GetCurrentRecoveryMultiplier()
		{
			if (character.data.passedOut || character.data.fullyPassedOut)
			{
				if (FatiguePlugin.debugMode.Value && Time.frameCount % 60 == 0)
				{
					FatiguePlugin.Logger.LogInfo((object)"Unconscious state detected - maximum recovery applied");
				}
				currentRecoveryMultiplier = 1f;
				return 1f;
			}
			float num = 1f;
			float num2 = currentExertionLevel * 0.8f;
			num -= num2;
			float staminaDeficitPenalty = GetStaminaDeficitPenalty();
			num -= staminaDeficitPenalty;
			float num3 = _zeroStaminaPenalty * 0.8f;
			num -= num3;
			if (IsResting)
			{
				num += 0.15f;
			}
			if (IsPlayingDead)
			{
				num *= 1.66f;
			}
			num = (currentRecoveryMultiplier = Mathf.Clamp(num, 0f, 1.66f));
			if (FatiguePlugin.debugMode.Value && Time.frameCount % 60 == 0)
			{
				FatiguePlugin.Logger.LogInfo((object)($"Recovery calc - Exertion: {currentExertionLevel:F2} (penalty: {num2:F2}), " + $"Stamina%: {GetStaminaPercentage():F2} (penalty: {staminaDeficitPenalty:F2}), " + $"Resting: {IsResting}, PlayDead: {IsPlayingDead}, Final mult: {num:F2}"));
			}
			return num;
		}

		private float GetCurrentRecoveryRate()
		{
			float num = GetCurrentRecoveryMultiplier();
			float num2 = FatiguePlugin.baseRecoveryRate.Value * num;
			if (character.data.passedOut || character.data.fullyPassedOut)
			{
				num2 = Mathf.Max(num2, FatiguePlugin.baseRecoveryRate.Value);
			}
			return num2;
		}

		private float GetStaminaDeficitPenalty()
		{
			float num = Mathf.Clamp01(GetStaminaPercentage());
			float num2 = Mathf.Pow(1f - num, 1.5f) * 0.95f;
			return Mathf.Clamp01(num2);
		}

		private void UpdateExertionDecay()
		{
			float num = Time.time - _lastStaminaTime;
			if (num > 1f)
			{
				float num2 = 1f / FatiguePlugin.exertionRampUpTime.Value;
				float num3 = Time.deltaTime * num2 * FatiguePlugin.exertionDecayRate.Value;
				currentExertionLevel = Mathf.Max(0f, currentExertionLevel - num3);
			}
			if (FatiguePlugin.debugMode.Value && Time.frameCount % 300 == 0)
			{
				float num4 = CalculateRecoveryMultiplier();
				FatiguePlugin.Logger.LogInfo((object)($"Exertion: {currentExertionLevel:F3} | Stamina used: {_staminaUsedInWindow:F1}/{2f:F0} | " + $"Stamina %: {GetStaminaPercentage():F2} | Zero penalty: {_zeroStaminaPenalty:F2} | " + $"Recovery mult: {num4:F2} | Play Dead: {IsPlayingDead}"));
			}
		}

		private void Update()
		{
			if ((Object)(object)character == (Object)null || !character.IsLocal)
			{
				return;
			}
			isGrounded = character.data.isGrounded;
			isClimbing = character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing;
			if (!character.data.passedOut && !character.data.fullyPassedOut)
			{
				UpdateZeroStaminaPenalty();
				UpdateStaminaWindow();
				UpdateExertionDecay();
			}
			else
			{
				currentExertionLevel = Mathf.MoveTowards(currentExertionLevel, 0f, Time.deltaTime * 2f);
				_zeroStaminaPenalty = Mathf.MoveTowards(_zeroStaminaPenalty, 0f, Time.deltaTime);
			}
			float num = (currentRecoveryMultiplier = CalculateRecoveryMultiplier());
			if (!IsSkeleton() && fatigueValue > 0f)
			{
				float num2 = FatiguePlugin.baseRecoveryRate.Value * num;
				if (character.data.passedOut || character.data.fullyPassedOut)
				{
					num2 = Mathf.Max(num2, FatiguePlugin.baseRecoveryRate.Value);
				}
				if (num2 > 0f)
				{
					float num3 = fatigueValue;
					float num4 = num2 * Time.deltaTime;
					fatigueValue = Mathf.Max(0f, fatigueValue - num4);
					if (FatiguePlugin.debugMode.Value && num4 > 0.0005f && Time.frameCount % 60 == 0)
					{
						string arg = ((character.data.passedOut || character.data.fullyPassedOut) ? "UNCONSCIOUS" : "CONSCIOUS");
						FatiguePlugin.Logger.LogInfo((object)($"Recovery: {num4:F4}/s (mult: {num:F2}, {arg}) | " + $"Fatigue: {num3:F3} -> {fatigueValue:F3}"));
					}
				}
			}
			MaybeSendSync();
		}

		private void MaybeSendSync()
		{
			if (Time.time - _lastSyncSent < 0.2f)
			{
				return;
			}
			_lastSyncSent = Time.time;
			PhotonView component = ((Component)character).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null || !PhotonNetwork.InRoom)
			{
				return;
			}
			try
			{
				component.RPC("Fatigue_RPC_Sync", (RpcTarget)1, new object[1] { fatigueValue });
			}
			catch (Exception ex)
			{
				FatiguePlugin.Logger.LogWarning((object)("RPC send failed: " + ex.Message));
			}
		}
	}
}
namespace FatigueMod.Patches
{
	[HarmonyPatch(typeof(AOE), "Explode")]
	internal static class AOE_CureAll_Patch
	{
		private static FieldInfo hasExplodedField;

		private static bool isProcessing;

		static AOE_CureAll_Patch()
		{
			isProcessing = false;
			hasExplodedField = typeof(AOE).GetField("hasExploded", BindingFlags.Instance | BindingFlags.NonPublic);
		}

		[HarmonyPrefix]
		private static bool Prefix(AOE __instance)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (isProcessing)
			{
				return true;
			}
			if (hasExplodedField != null && (bool)hasExplodedField.GetValue(__instance))
			{
				return true;
			}
			if (!((Object)__instance).name.Contains("CureAll") && !((Object)__instance).name.Contains("AOE_CureAll"))
			{
				return true;
			}
			if (FatiguePlugin.debugMode.Value)
			{
				FatiguePlugin.Logger.LogInfo((object)("[CUREALL AOE] Processing " + ((Object)__instance).name));
			}
			isProcessing = true;
			try
			{
				if (hasExplodedField != null)
				{
					hasExplodedField.SetValue(__instance, true);
				}
				float statusAmount = __instance.statusAmount;
				STATUSTYPE statusType = __instance.statusType;
				STATUSTYPE[] addtlStatus = __instance.addtlStatus;
				bool hasAffliction = __instance.hasAffliction;
				Affliction affliction = __instance.affliction;
				__instance.statusAmount = 0f;
				__instance.hasAffliction = false;
				__instance.affliction = null;
				__instance.statusAmount = statusAmount;
				__instance.hasAffliction = hasAffliction;
				__instance.affliction = affliction;
				return true;
			}
			finally
			{
				isProcessing = false;
			}
		}

		[HarmonyPostfix]
		private static void Postfix(AOE __instance)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			if (isProcessing || (!((Object)__instance).name.Contains("CureAll") && !((Object)__instance).name.Contains("AOE_CureAll")))
			{
				return;
			}
			if (!PhotonNetwork.IsMasterClient)
			{
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"[CUREALL AOE] Skipping fatigue reduction - not MasterClient");
				}
				return;
			}
			if (FatiguePlugin.debugMode.Value)
			{
				FatiguePlugin.Logger.LogInfo((object)"[CUREALL AOE] Postfix - applying fatigue reduction to characters in range");
				FatiguePlugin.Logger.LogInfo((object)$"[CUREALL AOE] Position: {((Component)__instance).transform.position}, Range: {__instance.range}");
			}
			Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, __instance.range, LayerMask.op_Implicit(HelperFunctions.GetMask(__instance.mask)));
			List<Character> list = new List<Character>();
			Collider[] array2 = array;
			Character item = default(Character);
			Character val2 = default(Character);
			foreach (Collider val in array2)
			{
				if (CharacterRagdoll.TryGetCharacterFromCollider(val, ref item) && !list.Contains(item))
				{
					list.Add(item);
				}
				if (CharacterRagdoll.TryGetCharacterFromCollider(val, ref val2) && (Object)(object)val2.data.carriedPlayer != (Object)null && !list.Contains(val2.data.carriedPlayer))
				{
					list.Add(val2.data.carriedPlayer);
					if (FatiguePlugin.debugMode.Value)
					{
						FatiguePlugin.Logger.LogInfo((object)("[CUREALL AOE] Found carried player " + val2.data.carriedPlayer.characterName));
					}
				}
			}
			if (FatiguePlugin.debugMode.Value)
			{
				FatiguePlugin.Logger.LogInfo((object)$"[CUREALL AOE] Found {list.Count} characters in range");
				foreach (Character item2 in list)
				{
					FatiguePlugin.Logger.LogInfo((object)$"[CUREALL AOE]   - {item2.characterName} (IsDead: {item2.data.dead}, IsSkeleton: {item2.data.isSkeleton})");
				}
			}
			foreach (Character item3 in list)
			{
				if (item3.data.dead || item3.data.fullyPassedOut)
				{
					if (FatiguePlugin.debugMode.Value)
					{
						FatiguePlugin.Logger.LogInfo((object)("[CUREALL AOE] Skipping " + item3.characterName + " - dead or passed out"));
					}
					continue;
				}
				float num = Vector3.Distance(((Component)__instance).transform.position, item3.Center);
				if (num > __instance.range)
				{
					continue;
				}
				float num2 = Mathf.Pow(1f - num / __instance.range, __instance.factorPow);
				if (num2 < __instance.minFactor)
				{
					continue;
				}
				if (__instance.requireLineOfSigh)
				{
					RaycastHit val3 = HelperFunctions.LineCheck(((Component)__instance).transform.position, item3.Center, (LayerType)1, 0f, (QueryTriggerInteraction)1);
					if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val3)).transform))
					{
						continue;
					}
				}
				float num3 = 0.1f * num2;
				FatigueRpcReceiver component = ((Component)item3).GetComponent<FatigueRpcReceiver>();
				if ((Object)(object)component != (Object)null)
				{
					((MonoBehaviourPun)component).photonView.RPC("RPC_ReduceFatigue", ((MonoBehaviourPun)component).photonView.Owner, new object[1] { num3 });
					if (FatiguePlugin.debugMode.Value)
					{
						FatiguePlugin.Logger.LogInfo((object)$"[CUREALL AOE] Sent fatigue reduction RPC to {item3.characterName}: -{num3:F3} fatigue");
					}
				}
				else
				{
					FatiguePlugin.Logger.LogWarning((object)("[CUREALL AOE] No FatigueRpcReceiver on " + item3.characterName));
				}
			}
		}
	}
	[HarmonyPatch(typeof(CharacterAnimations), "PlayEmote")]
	internal static class CharacterAnimations_PlayEmote_Patch
	{
		[CompilerGenerated]
		private sealed class <ResetPlayDeadAfterDelay>d__2 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public FatigueTracker tracker;

			public float delay;

			public CharacterAnimations animator;

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

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

			[DebuggerHidden]
			public <ResetPlayDeadAfterDelay>d__2(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)tracker != (Object)null && tracker.IsPlayingDead)
					{
						tracker.SetPlayingDead(playing: false);
						activeResetCoroutine = null;
						if (FatiguePlugin.debugMode.Value)
						{
							FatiguePlugin.Logger.LogInfo((object)"Play Dead emote timeout - resetting recovery rate");
						}
					}
					return false;
				}
			}

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

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

		private static Coroutine activeResetCoroutine;

		[HarmonyPrefix]
		private static void Prefix(CharacterAnimations __instance, string emoteName)
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			FatigueTracker component2 = ((Component)component).GetComponent<FatigueTracker>();
			if ((Object)(object)component2 == (Object)null || !(emoteName == "A_Scout_Emote_PlayDead"))
			{
				return;
			}
			if (activeResetCoroutine != null)
			{
				((MonoBehaviour)__instance).StopCoroutine(activeResetCoroutine);
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"Previous Play Dead reset coroutine cancelled - duration refreshed");
				}
			}
			component2.SetPlayingDead(playing: true);
			activeResetCoroutine = ((MonoBehaviour)__instance).StartCoroutine(ResetPlayDeadAfterDelay(component2, 5f, __instance));
		}

		[IteratorStateMachine(typeof(<ResetPlayDeadAfterDelay>d__2))]
		private static IEnumerator ResetPlayDeadAfterDelay(FatigueTracker tracker, float delay, CharacterAnimations animator)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ResetPlayDeadAfterDelay>d__2(0)
			{
				tracker = tracker,
				delay = delay,
				animator = animator
			};
		}
	}
	[HarmonyPatch(typeof(EmoteWheel), "Choose")]
	internal static class EmoteWheel_Choose_Patch
	{
		[HarmonyPrefix]
		private static void Prefix(EmoteWheel __instance)
		{
			FieldInfo field = typeof(EmoteWheel).GetField("chosenEmoteData", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				return;
			}
			object? value = field.GetValue(__instance);
			EmoteWheelData val = (EmoteWheelData)((value is EmoteWheelData) ? value : null);
			if ((Object)(object)val == (Object)null || !(val.anim == "A_Scout_Emote_PlayDead"))
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			FatigueTracker component = ((Component)localCharacter).GetComponent<FatigueTracker>();
			if (!((Object)(object)component == (Object)null))
			{
				component.SetPlayingDead(playing: true);
				if (FatiguePlugin.debugMode.Value)
				{
					FatiguePlugin.Logger.LogInfo((object)"Play Dead emote detected via EmoteWheel.Choose()");
				}
			}
		}
	}
}

FeedingFrenzy.dll

Decompiled a week ago
using System;
using System.Collections;
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FeedingFrenzy")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+792ec908dc89689b0fce079d4b9e41033c968a90")]
[assembly: AssemblyProduct("FeedingFrenzy")]
[assembly: AssemblyTitle("FeedingFrenzy")]
[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 FeedingFrenzy
{
	[HarmonyPatch(typeof(Character), "AddExtraStamina")]
	internal static class AddExtraStamina_Multiplier_Patch
	{
		private static Dictionary<int, float> feedTimes = new Dictionary<int, float>();

		private const float FED_WINDOW = 3f;

		public static void MarkAsFed(int characterID)
		{
			feedTimes[characterID] = Time.time;
			if (FeedingFrenzyPlugin.debugMode.Value)
			{
				FeedingFrenzyPlugin.Log.LogInfo((object)$"[FeedingFrenzy] Marked character {characterID} as fed");
			}
		}

		[HarmonyPrefix]
		private static void Prefix(Character __instance, ref float add)
		{
			if (!(add <= 0f))
			{
				int ownerActorNr = ((MonoBehaviourPun)__instance).photonView.OwnerActorNr;
				if (feedTimes.TryGetValue(ownerActorNr, out var value) && Time.time - value <= 3f)
				{
					float num = add;
					add = num * FeedingFrenzyPlugin.extraStaminaMultiplier.Value;
					FeedingFrenzyPlugin.Log.LogInfo((object)("[FeedingFrenzy] " + __instance.characterName + " fed! " + $"Extra stamina multiplier: {num:F2} → {add:F2}"));
					feedTimes.Remove(ownerActorNr);
				}
			}
		}
	}
	[BepInPlugin("jill920.FeedingFrenzy", "Feeding Frenzy", "1.1.0")]
	public class FeedingFrenzyPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.FeedingFrenzy";

		public const string MOD_NAME = "Feeding Frenzy";

		public const string MOD_VERSION = "1.1.0";

		public static ConfigEntry<float> extraStaminaMultiplier;

		public static ConfigEntry<float> flatExtraStaminaBonus;

		public static ConfigEntry<bool> debugMode;

		public static FeedingFrenzyPlugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			extraStaminaMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplier", "ExtraStaminaMultiplier", 1.5f, "Multiplier applied to extra stamina from items when feeding another player.\nExample: 1.5 = 50% more stamina, 2.0 = 100% more stamina");
			flatExtraStaminaBonus = ((BaseUnityPlugin)this).Config.Bind<float>("FlatBonus", "FlatExtraStaminaBonus", 0.05f, "Flat bonus stamina given to the receiver when fed by another player.\nThis is applied AFTER the feeding animation completes.\nSet to 0 to disable.");
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugLogs", false, "Enable debug logging");
			Harmony val = Harmony.CreateAndPatchAll(typeof(GameUtils_StartFeed_Patch), "jill920.FeedingFrenzy");
			val.PatchAll(typeof(AddExtraStamina_Multiplier_Patch));
			val.PatchAll(typeof(Item_SendFeedDataRPC_Patch));
			Log.LogInfo((object)"[Feeding Frenzy 1.1.0] Loaded successfully!");
			Log.LogInfo((object)$"  Multiplier: {extraStaminaMultiplier.Value}x");
			Log.LogInfo((object)$"  Flat Bonus: +{flatExtraStaminaBonus.Value} stamina");
		}
	}
	[HarmonyPatch(typeof(GameUtils), "StartFeed")]
	internal static class GameUtils_StartFeed_Patch
	{
		[HarmonyPrefix]
		private static void Prefix(int giverID, int receiverID, ushort itemID, float totalItemTime)
		{
			Character val = default(Character);
			Character val2 = default(Character);
			if (Character.GetCharacterWithPhotonID(giverID, ref val) && Character.GetCharacterWithPhotonID(receiverID, ref val2))
			{
				AddExtraStamina_Multiplier_Patch.MarkAsFed(((MonoBehaviourPun)val2).photonView.OwnerActorNr);
				FeedingFrenzyPlugin.Log.LogInfo((object)$"[FeedingFrenzy] Native feed detected: {val.characterName} -> {val2.characterName} (Item ID: {itemID})");
			}
		}
	}
	[HarmonyPatch(typeof(Item), "SendFeedDataRPC")]
	internal static class Item_SendFeedDataRPC_Patch
	{
		[CompilerGenerated]
		private sealed class <ApplyFlatBonusAfterDelay>d__1 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Character receiver;

			public float delay;

			public int itemID;

			private float <flatBonus>5__1;

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

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

			[DebuggerHidden]
			public <ApplyFlatBonusAfterDelay>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<flatBonus>5__1 = FeedingFrenzyPlugin.flatExtraStaminaBonus.Value;
					if (<flatBonus>5__1 > 0f)
					{
						receiver.AddExtraStamina(<flatBonus>5__1);
						if (FeedingFrenzyPlugin.debugMode.Value)
						{
							FeedingFrenzyPlugin.Log.LogInfo((object)("[FeedingFrenzy] Flat bonus applied to " + receiver.characterName + " " + $"(Item ID: {itemID}) after {delay:F2}s: +{<flatBonus>5__1:F2} stamina"));
						}
					}
					return false;
				}
			}

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

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

		[HarmonyPostfix]
		private static void Postfix(Item __instance, int giverID, int recieverID, int itemID, float totalUsingTime)
		{
			Character val = default(Character);
			if (Character.GetCharacterWithPhotonID(recieverID, ref val) && val.IsLocal)
			{
				((MonoBehaviour)FeedingFrenzyPlugin.Instance).StartCoroutine(ApplyFlatBonusAfterDelay(val, totalUsingTime, itemID));
			}
		}

		[IteratorStateMachine(typeof(<ApplyFlatBonusAfterDelay>d__1))]
		private static IEnumerator ApplyFlatBonusAfterDelay(Character receiver, float delay, int itemID)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ApplyFlatBonusAfterDelay>d__1(0)
			{
				receiver = receiver,
				delay = delay,
				itemID = itemID
			};
		}
	}
}

HuddleUp.dll

Decompiled a week ago
using System;
using System.Collections;
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.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HuddleUp")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+32c891598c8d63aa827b48670b46b3dd6bc44eb0")]
[assembly: AssemblyProduct("HuddleUp")]
[assembly: AssemblyTitle("HuddleUp")]
[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 HuddleUp
{
	[HarmonyPatch(typeof(CharacterHeatEmission), "Update")]
	internal static class CharacterHeatEmission_Patch
	{
		[CompilerGenerated]
		private sealed class <CheckReductionNextFrame>d__3 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public CharacterHeatEmission heatSource;

			public Character target;

			public float coldBefore;

			public int sourceId;

			public Character giver;

			private float <coldAfter>5__1;

			private float <reduction>5__2;

			private int <targetId>5__3;

			private float <total>5__4;

			private float <reward>5__5;

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

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

			[DebuggerHidden]
			public <CheckReductionNextFrame>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<coldAfter>5__1 = target.refs.afflictions.GetCurrentStatus((STATUSTYPE)2);
					<reduction>5__2 = coldBefore - <coldAfter>5__1;
					if (<reduction>5__2 <= 0.001f)
					{
						return false;
					}
					if (!HuddleUpPlugin.IsRewardActive())
					{
						if (HuddleUpPlugin.debugMode.Value)
						{
							HuddleUpPlugin.Logger.LogInfo((object)$"[Huddle] Cold reduction detected ({<reduction>5__2:F3}) but rewards not active - skipping");
						}
						return false;
					}
					<targetId>5__3 = ((MonoBehaviourPun)target).photonView.ViewID;
					if (!HuddleUpPlugin.coldReductionTracker.ContainsKey(<targetId>5__3))
					{
						HuddleUpPlugin.coldReductionTracker[<targetId>5__3] = new Dictionary<int, float>();
					}
					if (!HuddleUpPlugin.coldReductionTracker[<targetId>5__3].ContainsKey(sourceId))
					{
						HuddleUpPlugin.coldReductionTracker[<targetId>5__3][sourceId] = 0f;
					}
					HuddleUpPlugin.coldReductionTracker[<targetId>5__3][sourceId] += <reduction>5__2;
					<total>5__4 = HuddleUpPlugin.coldReductionTracker[<targetId>5__3][sourceId];
					if (HuddleUpPlugin.debugMode.Value)
					{
						HuddleUpPlugin.Logger.LogInfo((object)("[Huddle] " + giver.characterName + " -> " + target.characterName + ": " + $"reduced cold by {<reduction>5__2:F3} (total: {<total>5__4:F3}/{HuddleUpPlugin.requiredColdReduction.Value:F2})"));
					}
					if (<total>5__4 >= HuddleUpPlugin.requiredColdReduction.Value)
					{
						HuddleUpPlugin.coldReductionTracker[<targetId>5__3][sourceId] = 0f;
						<reward>5__5 = HuddleUpPlugin.staminaReward.Value;
						target.AddExtraStamina(<reward>5__5);
						HuddleUpPlugin.Logger.LogInfo((object)($"[Huddle] {target.characterName} gained {<reward>5__5:F2} bonus stamina " + "from huddling with " + giver.characterName + "!"));
					}
					return false;
				}
			}

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

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

		private static FieldInfo _characterField;

		private static FieldInfo GetCharacterField()
		{
			if (_characterField == null)
			{
				_characterField = typeof(CharacterHeatEmission).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			return _characterField;
		}

		[HarmonyPostfix]
		private static void Postfix(CharacterHeatEmission __instance)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			FieldInfo characterField = GetCharacterField();
			if (characterField == null)
			{
				return;
			}
			object? value = characterField.GetValue(__instance);
			Character val = (Character)((value is Character) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)val == (Object)(object)localCharacter)
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			HuddleUpPlugin.UpdateHeatSourceActivity(instanceID);
			float num = Vector3.Distance(((Component)__instance).transform.position, localCharacter.Center);
			if (num >= __instance.radius)
			{
				return;
			}
			if (!HuddleUpPlugin.IsRewardActive())
			{
				if (HuddleUpPlugin.debugMode.Value)
				{
					HuddleUpPlugin.Logger.LogInfo((object)"[Huddle] Skipping tracking - rewards not active (daytime or night-only mode enabled)");
				}
			}
			else
			{
				float currentStatus = localCharacter.refs.afflictions.GetCurrentStatus((STATUSTYPE)2);
				((MonoBehaviour)HuddleUpPlugin.Instance).StartCoroutine(CheckReductionNextFrame(__instance, localCharacter, currentStatus, instanceID, val));
			}
		}

		[IteratorStateMachine(typeof(<CheckReductionNextFrame>d__3))]
		private static IEnumerator CheckReductionNextFrame(CharacterHeatEmission heatSource, Character target, float coldBefore, int sourceId, Character giver)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckReductionNextFrame>d__3(0)
			{
				heatSource = heatSource,
				target = target,
				coldBefore = coldBefore,
				sourceId = sourceId,
				giver = giver
			};
		}
	}
	[BepInPlugin("jill920.huddleup", "Huddle Up", "1.0.1")]
	public class HuddleUpPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.huddleup";

		public const string MOD_NAME = "Huddle Up";

		public const string MOD_VERSION = "1.0.1";

		public static HuddleUpPlugin Instance;

		public static ManualLogSource Logger;

		public static ConfigEntry<bool> debugMode;

		public static ConfigEntry<float> requiredColdReduction;

		public static ConfigEntry<float> staminaReward;

		public static ConfigEntry<bool> nightOnly;

		public static Dictionary<int, Dictionary<int, float>> coldReductionTracker = new Dictionary<int, Dictionary<int, float>>();

		private static Dictionary<int, float> _heatSourceLastActiveTime = new Dictionary<int, float>();

		private void Awake()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebug", false, "Enable debug logging to console");
			requiredColdReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "RequiredColdReduction", 0.025f, new ConfigDescription("Amount of cold that must be removed before rewarding stamina", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.025f, 0.1f), Array.Empty<object>()));
			staminaReward = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "StaminaReward", 0.01f, new ConfigDescription("Amount of bonus stamina to give when threshold is reached", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.025f), Array.Empty<object>()));
			nightOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "NightOnly", true, new ConfigDescription("Only grant stamina rewards from huddling at night (when cold is actually dangerous)", (AcceptableValueBase)(object)new AcceptableValueList<bool>(new bool[2] { true, false }), Array.Empty<object>()));
			try
			{
				Harmony val = new Harmony("jill920.huddleup");
				val.PatchAll(Assembly.GetExecutingAssembly());
				Logger.LogInfo((object)"[Huddle Up 1.0.1] Loaded successfully!");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Harmony patch failed: " + ex.Message));
			}
		}

		public static bool IsRewardActive()
		{
			if (!nightOnly.Value)
			{
				return true;
			}
			if ((Object)(object)DayNightManager.instance == (Object)null)
			{
				return false;
			}
			return DayNightManager.instance.isDay < 0.5f;
		}

		private void Update()
		{
			if (Time.frameCount % 3600 == 0)
			{
				CleanupInactiveSources();
			}
		}

		private void CleanupInactiveSources()
		{
			float time = Time.time;
			List<int> list = new List<int>();
			foreach (KeyValuePair<int, float> item in _heatSourceLastActiveTime)
			{
				if (time - item.Value > 30f)
				{
					list.Add(item.Key);
				}
			}
			foreach (int item2 in list)
			{
				_heatSourceLastActiveTime.Remove(item2);
				foreach (Dictionary<int, float> value in coldReductionTracker.Values)
				{
					value.Remove(item2);
				}
			}
			if (debugMode.Value && list.Count > 0)
			{
				Logger.LogInfo((object)$"Cleaned up {list.Count} inactive heat sources");
			}
		}

		public static void UpdateHeatSourceActivity(int sourceId)
		{
			_heatSourceLastActiveTime[sourceId] = Time.time;
		}
	}
}

NapberryEnhanced.dll

Decompiled a week ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("NapberryEnhanced")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9f939f10744bc87e8c173d53861967b31b4d3377")]
[assembly: AssemblyProduct("NapberryEnhanced")]
[assembly: AssemblyTitle("NapberryEnhanced")]
[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 NapberryEnhanced
{
	[BepInPlugin("jill920.napberryenhanced", "Napberry Enhanced", "1.0.0")]
	public class NapberryEnhancedPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.napberryenhanced";

		public const string MOD_NAME = "Napberry Enhanced";

		public const string MOD_VERSION = "1.0.0";

		public static NapberryEnhancedPlugin Instance;

		public static ManualLogSource Logger;

		public static bool IsDizzinessModInstalled;

		public static bool IsFatigueModInstalled;

		public static bool debugMode;

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableLogs", false, "Enable debug logging").Value;
			CheckForInstalledMods();
			try
			{
				Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "jill920.napberryenhanced");
				Logger.LogInfo((object)"[Napberry Enhanced 1.0.0] Loaded successfully!");
				Logger.LogInfo((object)$"  Dizziness Mod detected: {IsDizzinessModInstalled}");
				Logger.LogInfo((object)$"  Fatigue Mod detected: {IsFatigueModInstalled}");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to load: " + ex.Message));
			}
		}

		private void CheckForInstalledMods()
		{
			IsDizzinessModInstalled = false;
			IsFatigueModInstalled = false;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						IsDizzinessModInstalled = true;
					}
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						IsFatigueModInstalled = true;
					}
				}
				catch
				{
				}
			}
		}
	}
}
namespace NapberryEnhanced.Patches
{
	[HarmonyPatch(typeof(Item), "Consume")]
	internal static class Item_Consume_Patch
	{
		private const int NAPBERRY_ITEM_ID = 110;

		private static bool _fatigueCheckDone;

		private static bool _fatigueAvailable;

		private static bool _dizzinessCheckDone;

		private static bool _dizzinessAvailable;

		private static bool IsFatigueModPresent()
		{
			if (_fatigueCheckDone)
			{
				return _fatigueAvailable;
			}
			_fatigueCheckDone = true;
			if (NapberryEnhancedPlugin.IsFatigueModInstalled)
			{
				_fatigueAvailable = true;
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						_fatigueAvailable = true;
						NapberryEnhancedPlugin.IsFatigueModInstalled = true;
						NapberryEnhancedPlugin.Logger.LogInfo((object)"Napberry: Fatigue Mod detected at runtime!");
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsDizzinessModPresent()
		{
			if (_dizzinessCheckDone)
			{
				return _dizzinessAvailable;
			}
			_dizzinessCheckDone = true;
			if (NapberryEnhancedPlugin.IsDizzinessModInstalled)
			{
				_dizzinessAvailable = true;
				return true;
			}
			try
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						_dizzinessAvailable = true;
						NapberryEnhancedPlugin.IsDizzinessModInstalled = true;
						NapberryEnhancedPlugin.Logger.LogInfo((object)"Napberry: Dizziness Mod detected at runtime!");
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		[HarmonyPostfix]
		private static void Postfix(Item __instance, int consumerID)
		{
			if (__instance.itemID != 110)
			{
				return;
			}
			PhotonView photonView = PhotonNetwork.GetPhotonView(consumerID);
			if ((Object)(object)photonView == (Object)null)
			{
				return;
			}
			Character component = ((Component)photonView).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			bool flag = IsDizzinessModPresent();
			bool flag2 = IsFatigueModPresent();
			if (flag || flag2)
			{
				if (flag)
				{
					ClearDizziness(component);
				}
				if (flag2)
				{
					ClearFatigue(component);
				}
				if (NapberryEnhancedPlugin.debugMode)
				{
					NapberryEnhancedPlugin.Logger.LogInfo((object)("Napberry: Cleared Dizziness/Fatigue for " + component.characterName));
				}
			}
		}

		private static void ClearDizziness(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					field.SetValue(component, 0f);
					if (NapberryEnhancedPlugin.debugMode && num > 0.01f)
					{
						NapberryEnhancedPlugin.Logger.LogInfo((object)$"Napberry: Cleared Dizziness: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				NapberryEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Dizziness: " + ex.Message));
			}
		}

		private static void ClearFatigue(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					field.SetValue(component, 0f);
					if (NapberryEnhancedPlugin.debugMode && num > 0.01f)
					{
						NapberryEnhancedPlugin.Logger.LogInfo((object)$"Napberry: Cleared Fatigue: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				NapberryEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Fatigue: " + ex.Message));
			}
		}
	}
}

PandoraEnhanced.dll

Decompiled a week ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 PandoraEnhanced
{
	[BepInPlugin("jill920.pandoraenhanced", "Pandora Enhanced", "1.0.0")]
	public class PandoraEnhancedPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.pandoraenhanced";

		public const string MOD_NAME = "Pandora Enhanced";

		public const string MOD_VERSION = "1.0.0";

		public static PandoraEnhancedPlugin Instance;

		public static ManualLogSource Logger;

		public static bool IsDizzinessModInstalled { get; private set; }

		public static bool IsFatigueModInstalled { get; private set; }

		private void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			CheckForInstalledMods();
			try
			{
				Harmony val = new Harmony("jill920.pandoraenhanced");
				val.PatchAll();
				Logger.LogInfo((object)"[Pandora Enhanced 1.0.0] Loaded successfully!");
				Logger.LogInfo((object)$"  Dizziness Mod detected: {IsDizzinessModInstalled}");
				Logger.LogInfo((object)$"  Fatigue Mod detected: {IsFatigueModInstalled}");
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to load: " + ex.Message));
			}
		}

		private void CheckForInstalledMods()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					if (assembly.GetType("DizzinessMod.DizzinessTracker") != null)
					{
						IsDizzinessModInstalled = true;
					}
					if (assembly.GetType("FatigueMod.FatigueTracker") != null)
					{
						IsFatigueModInstalled = true;
					}
				}
				catch
				{
				}
			}
		}
	}
}
namespace PandoraEnhanced.Patches
{
	[HarmonyPatch(typeof(Affliction_Chaos), "OnApplied")]
	internal static class Affliction_Chaos_Patch_PreserveTotal
	{
		private static FieldInfo _isInvincibleField;

		private static bool IsInvincible(Character character)
		{
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
			{
				return false;
			}
			try
			{
				if (_isInvincibleField == null)
				{
					_isInvincibleField = typeof(CharacterData).GetField("isInvincible", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (_isInvincibleField != null)
				{
					return (bool)_isInvincibleField.GetValue(character.data);
				}
			}
			catch (Exception ex)
			{
				PandoraEnhancedPlugin.Logger.LogWarning((object)("Failed to check invincibility: " + ex.Message));
			}
			return false;
		}

		private static void ClearDizziness(Character character)
		{
			try
			{
				PandoraEnhancedPlugin.Logger.LogInfo((object)"ClearDizziness: Looking for tracker...");
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if ((Object)(object)component == (Object)null)
				{
					PandoraEnhancedPlugin.Logger.LogWarning((object)"ClearDizziness: Tracker not found!");
					return;
				}
				PandoraEnhancedPlugin.Logger.LogInfo((object)"ClearDizziness: Tracker found, getting field...");
				FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
				if (field == null)
				{
					PandoraEnhancedPlugin.Logger.LogWarning((object)"ClearDizziness: dizzinessValue field not found!");
					return;
				}
				float num = (float)field.GetValue(component);
				PandoraEnhancedPlugin.Logger.LogInfo((object)$"ClearDizziness: Current value = {num:F3}");
				if (num > 0.01f)
				{
					field.SetValue(component, 0f);
					PandoraEnhancedPlugin.Logger.LogInfo((object)$"Cleared Dizziness: {num:F3} → 0");
				}
				else
				{
					PandoraEnhancedPlugin.Logger.LogInfo((object)"ClearDizziness: Value already near 0, nothing to clear");
				}
			}
			catch (Exception ex)
			{
				PandoraEnhancedPlugin.Logger.LogError((object)("ClearDizziness failed: " + ex.Message + "\n" + ex.StackTrace));
			}
		}

		private static bool IsLivingSkeleton(Character character)
		{
			if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null)
			{
				return false;
			}
			if (character.data.isSkeleton && !character.data.dead && !character.data.fullyPassedOut)
			{
				return true;
			}
			return false;
		}

		private static void ClearFatigue(Character character)
		{
			try
			{
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
				if (!(field == null))
				{
					float num = (float)field.GetValue(component);
					if (num > 0.01f)
					{
						field.SetValue(component, 0f);
						PandoraEnhancedPlugin.Logger.LogInfo((object)$"Cleared Fatigue: {num:F3} → 0");
					}
				}
			}
			catch (Exception ex)
			{
				PandoraEnhancedPlugin.Logger.LogWarning((object)("Failed to clear Fatigue: " + ex.Message));
			}
		}

		[HarmonyPrefix]
		private static void Prefix(Affliction_Chaos __instance)
		{
			Character character = ((Affliction)__instance).character;
			if ((Object)(object)character == (Object)null || !character.IsLocal)
			{
				return;
			}
			if (IsLivingSkeleton(character))
			{
				if (PandoraEnhancedPlugin.IsDizzinessModInstalled)
				{
					ClearDizziness(character);
				}
				if (PandoraEnhancedPlugin.IsFatigueModInstalled)
				{
					ClearFatigue(character);
				}
				return;
			}
			PandoraEnhancedPlugin.Logger.LogInfo((object)"Pandora Prefix - Starting clear");
			bool flag = IsInvincible(character);
			PandoraEnhancedPlugin.Logger.LogInfo((object)$"Pandora Prefix - Invincible: {flag}");
			PandoraEnhancedPlugin.Logger.LogInfo((object)$"Pandora Prefix - Dizziness mod installed: {PandoraEnhancedPlugin.IsDizzinessModInstalled}");
			PandoraEnhancedPlugin.Logger.LogInfo((object)$"Pandora Prefix - Fatigue mod installed: {PandoraEnhancedPlugin.IsFatigueModInstalled}");
			if (PandoraEnhancedPlugin.IsDizzinessModInstalled)
			{
				PandoraEnhancedPlugin.Logger.LogInfo((object)"Attempting to clear Dizziness...");
				ClearDizziness(character);
			}
			if (PandoraEnhancedPlugin.IsFatigueModInstalled)
			{
				PandoraEnhancedPlugin.Logger.LogInfo((object)"Attempting to clear Fatigue...");
				ClearFatigue(character);
			}
			if (flag)
			{
				PandoraEnhancedPlugin.Logger.LogInfo((object)"Pandora's Chaos: Invincible active - skipping Dizziness/Fatigue addition after clear");
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Affliction_Chaos __instance)
		{
			Character character = ((Affliction)__instance).character;
			if ((Object)(object)character == (Object)null || !character.IsLocal)
			{
				return;
			}
			if (IsLivingSkeleton(character))
			{
				PandoraEnhancedPlugin.Logger.LogInfo((object)"Pandora's Chaos: Living skeleton - skipping Dizziness/Fatigue entirely");
				return;
			}
			if (IsInvincible(character))
			{
				PandoraEnhancedPlugin.Logger.LogInfo((object)"Pandora's Chaos: Invincible active - no Dizziness/Fatigue added");
				return;
			}
			bool isDizzinessModInstalled = PandoraEnhancedPlugin.IsDizzinessModInstalled;
			bool isFatigueModInstalled = PandoraEnhancedPlugin.IsFatigueModInstalled;
			if (!isDizzinessModInstalled && !isFatigueModInstalled)
			{
				return;
			}
			float statusSum = character.refs.afflictions.statusSum;
			float num = 1f - statusSum;
			if (num <= 0.01f)
			{
				PandoraEnhancedPlugin.Logger.LogInfo((object)$"Pandora's Chaos: No space for Dizziness/Fatigue (total={statusSum:F3})");
				return;
			}
			float num2 = 0f;
			float num3 = 0f;
			if (isDizzinessModInstalled && isFatigueModInstalled)
			{
				num2 = num * Random.Range(0f, 0.35f);
				float num4 = num - num2;
				num3 = num4 * Random.Range(0f, 0.5f);
			}
			else if (isDizzinessModInstalled)
			{
				num2 = num * Random.Range(0f, 0.35f);
			}
			else if (isFatigueModInstalled)
			{
				num3 = num * Random.Range(0f, 0.35f);
			}
			float num5 = num2 + num3;
			if (num5 > 0.01f)
			{
				if (isDizzinessModInstalled && num2 > 0.01f)
				{
					AddDizziness(character, num2);
				}
				if (isFatigueModInstalled && num3 > 0.01f)
				{
					AddFatigue(character, num3);
				}
				character.refs.afflictions.PushStatuses((Player)null);
				GUIManager.instance.bar.ChangeBar();
				PandoraEnhancedPlugin.Logger.LogInfo((object)($"Pandora's Chaos: Total={statusSum:F3}, " + $"Added Dizziness={num2:F3}, Fatigue={num3:F3}"));
			}
		}

		private static void AddDizziness(Character character, float amount)
		{
			try
			{
				if (IsInvincible(character))
				{
					return;
				}
				Component component = ((Component)character).GetComponent("DizzinessMod.DizzinessTracker");
				if (!((Object)(object)component == (Object)null))
				{
					FieldInfo field = ((object)component).GetType().GetField("dizzinessValue", BindingFlags.Instance | BindingFlags.Public);
					if (!(field == null))
					{
						float num = (float)field.GetValue(component);
						field.SetValue(component, Mathf.Clamp01(num + amount));
					}
				}
			}
			catch (Exception ex)
			{
				PandoraEnhancedPlugin.Logger.LogWarning((object)("Dizziness failed: " + ex.Message));
			}
		}

		private static void AddFatigue(Character character, float amount)
		{
			try
			{
				if (IsInvincible(character))
				{
					return;
				}
				Component component = ((Component)character).GetComponent("FatigueMod.FatigueTracker");
				if (!((Object)(object)component == (Object)null))
				{
					FieldInfo field = ((object)component).GetType().GetField("fatigueValue", BindingFlags.Instance | BindingFlags.Public);
					if (!(field == null))
					{
						float num = (float)field.GetValue(component);
						field.SetValue(component, Mathf.Clamp01(num + amount));
					}
				}
			}
			catch (Exception ex)
			{
				PandoraEnhancedPlugin.Logger.LogWarning((object)("Fatigue failed: " + ex.Message));
			}
		}
	}
}

RopeAnchorFix.dll

Decompiled a week 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.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using RopeAnchorFix.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RopeAnchorFix")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+547eac5980954cd1eaea844e07ee33fbadaa77c2")]
[assembly: AssemblyProduct("RopeAnchorFix")]
[assembly: AssemblyTitle("RopeAnchorFix")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 RopeAnchorFix
{
	[BepInPlugin("jill920.ropeanchorfix", "Rope Anchor Range Fix", "1.0.0")]
	public class RopeAnchorFixPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.ropeanchorfix";

		public const string MOD_NAME = "Rope Anchor Range Fix";

		public const string MOD_VERSION = "1.0.0";

		public static RopeAnchorFixPlugin Instance { get; private set; }

		public static ManualLogSource Logger { get; private set; }

		public static bool DebugMode { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			DebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableLogs", false, "Enable debug logging to console").Value;
			try
			{
				Harmony val = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "jill920.ropeanchorfix");
				Logger.LogInfo((object)"[Rope Anchor Range Fix 1.0.0] Loaded successfully!");
				Logger.LogInfo((object)$"  Blue preview range: {RopeTier_FullFix_Patch.BluePreviewRange}m");
				Logger.LogInfo((object)$"  Red preview range: {RopeTier_FullFix_Patch.RedPreviewRange}m");
				Logger.LogInfo((object)$"  Use ground position: {RopeTier_FullFix_Patch.UseGroundPosition}");
				if (DebugMode)
				{
					Logger.LogInfo((object)"  Debug logging: ENABLED");
				}
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to load: " + ex.Message));
				Logger.LogError((object)ex.StackTrace);
			}
		}
	}
}
namespace RopeAnchorFix.Patches
{
	[HarmonyPatch(typeof(RopeTier))]
	internal static class RopeTier_FullFix_Patch
	{
		[CompilerGenerated]
		private sealed class <RestoreCameraPosition>d__40 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Vector3 originalPos;

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

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

			[DebuggerHidden]
			public <RestoreCameraPosition>d__40(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)MainCamera.instance != (Object)null)
					{
						((Component)MainCamera.instance).transform.position = originalPos;
					}
					return false;
				}
			}

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

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

		private static FieldInfo? _maxAnchorGhostDistanceField;

		private static FieldInfo? _maxAnchorDistanceField;

		private static FieldInfo? _releaseCheckField;

		private static FieldInfo? _goodAnchorPlaceField;

		private static FieldInfo? _ropeAnchorField;

		private static FieldInfo? _timeWithGoodAnchorField;

		private static FieldInfo? _itemField;

		private static FieldInfo? _itemOverrideProgressField;

		private static FieldInfo? _itemOverrideForceProgressField;

		private static MethodInfo? _getBodypartMethod;

		private static FieldInfo? _mainCameraInstanceField;

		private static Vector3 _lockedAnchorPosition;

		private static bool _isCasting;

		public static float BluePreviewRange { get; set; }

		public static float RedPreviewRange { get; set; }

		public static bool UseGroundPosition { get; set; }

		public static float VerticalOffset { get; set; }

		public static bool UseConsistentRaycastHeight { get; set; }

		public static float FixedRaycastHeight { get; set; }

		static RopeTier_FullFix_Patch()
		{
			BluePreviewRange = 2f;
			RedPreviewRange = 2.5f;
			UseGroundPosition = true;
			VerticalOffset = 0.07f;
			UseConsistentRaycastHeight = true;
			FixedRaycastHeight = 1.2f;
			Type typeFromHandle = typeof(RopeTier);
			_maxAnchorGhostDistanceField = AccessTools.Field(typeFromHandle, "maxAnchorGhostDistance");
			_maxAnchorDistanceField = AccessTools.Field(typeFromHandle, "maxAnchorDistance");
			_releaseCheckField = AccessTools.Field(typeFromHandle, "releaseCheck");
			_goodAnchorPlaceField = AccessTools.Field(typeFromHandle, "goodAnchorPlace");
			_ropeAnchorField = AccessTools.Field(typeFromHandle, "ropeAnchor");
			_timeWithGoodAnchorField = AccessTools.Field(typeFromHandle, "timeWithGoodAnchor");
			_itemField = AccessTools.Field(typeFromHandle, "item");
			Type typeFromHandle2 = typeof(Item);
			_itemOverrideProgressField = AccessTools.Field(typeFromHandle2, "overrideProgress");
			_itemOverrideForceProgressField = AccessTools.Field(typeFromHandle2, "overrideForceProgress");
			_getBodypartMethod = AccessTools.Method(typeof(Character), "GetBodypart", new Type[1] { typeof(BodypartType) }, (Type[])null);
			Type typeFromHandle3 = typeof(MainCamera);
			_mainCameraInstanceField = AccessTools.Field(typeFromHandle3, "instance");
		}

		[HarmonyPatch("Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler_Update(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldfld && list[i].operand is FieldInfo fieldInfo && fieldInfo == _maxAnchorGhostDistanceField)
				{
					list[i].operand = _maxAnchorDistanceField;
					if (RopeAnchorFixPlugin.DebugMode)
					{
						RopeAnchorFixPlugin.Logger.LogInfo((object)"Patched: maxAnchorGhostDistance -> maxAnchorDistance");
					}
				}
				if (list[i].opcode == OpCodes.Callvirt && list[i].operand is MethodInfo methodInfo && methodInfo.Name == "get_Center" && methodInfo.DeclaringType == typeof(Character))
				{
					list[i].opcode = OpCodes.Call;
					list[i].operand = AccessTools.Method(typeof(RopeTier_FullFix_Patch), "GetDistancePoint", (Type[])null, (Type[])null);
					if (RopeAnchorFixPlugin.DebugMode)
					{
						RopeAnchorFixPlugin.Logger.LogInfo((object)"Patched: Character.Center -> GetDistancePoint");
					}
				}
				if (i >= 1 && list[i].opcode == OpCodes.Callvirt && list[i].operand is MethodInfo methodInfo2 && methodInfo2.Name == "get_position" && methodInfo2.DeclaringType == typeof(Transform) && i > 0 && list[i - 1].opcode == OpCodes.Ldsfld && list[i - 1].operand is FieldInfo fieldInfo2 && fieldInfo2 == _mainCameraInstanceField && RopeAnchorFixPlugin.DebugMode)
				{
					RopeAnchorFixPlugin.Logger.LogInfo((object)("Found camera position access at index " + i));
				}
			}
			return list;
		}

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		private static void Prefix_Update(RopeTier __instance)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Invalid comparison between Unknown and I4
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			if (!((MonoBehaviourPun)__instance).photonView.IsMine)
			{
				return;
			}
			if (_maxAnchorDistanceField != null)
			{
				_maxAnchorDistanceField.SetValue(__instance, BluePreviewRange);
			}
			if (_maxAnchorGhostDistanceField != null)
			{
				_maxAnchorGhostDistanceField.SetValue(__instance, RedPreviewRange);
			}
			if (UseConsistentRaycastHeight && (Object)(object)MainCamera.instance != (Object)null)
			{
				Vector3 position = ((Component)MainCamera.instance).transform.position;
				object? obj = _itemField?.GetValue(__instance);
				Item val = (Item)((obj is Item) ? obj : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.holderCharacter != (Object)null)
				{
					Character holderCharacter = val.holderCharacter;
					Vector3 characterPosition = GetCharacterPosition(holderCharacter);
					Vector3 val2 = default(Vector3);
					((Vector3)(ref val2))..ctor(position.x, characterPosition.y + FixedRaycastHeight, position.z);
					((Component)MainCamera.instance).transform.position = val2;
					if (RopeAnchorFixPlugin.DebugMode)
					{
						RopeAnchorFixPlugin.Logger.LogInfo((object)$"Camera height adjusted: {position.y:F2} -> {val2.y:F2} (fixed height: {FixedRaycastHeight}m above ground)");
					}
					((MonoBehaviour)__instance).StartCoroutine(RestoreCameraPosition(position));
				}
			}
			object? obj2 = _itemField?.GetValue(__instance);
			Item val3 = (Item)((obj2 is Item) ? obj2 : null);
			if ((Object)(object)val3 == (Object)null || (int)val3.itemState != 1)
			{
				_isCasting = false;
				return;
			}
			bool flag = _releaseCheckField != null && (bool)_releaseCheckField.GetValue(__instance);
			RaycastHit? val4 = _goodAnchorPlaceField?.GetValue(__instance) as RaycastHit?;
			object obj3 = _ropeAnchorField?.GetValue(__instance);
			if (!_isCasting && obj3 != null && val4.HasValue && !flag)
			{
				_isCasting = true;
				RaycastHit value = val4.Value;
				_lockedAnchorPosition = ((RaycastHit)(ref value)).point;
				if (RopeAnchorFixPlugin.DebugMode)
				{
					RopeAnchorFixPlugin.Logger.LogInfo((object)$"=== CASTING STARTED === Anchor locked at: {_lockedAnchorPosition}");
				}
			}
			if (_isCasting && obj3 != null && val4.HasValue)
			{
				RaycastHit value2 = val4.Value;
				((RaycastHit)(ref value2)).point = _lockedAnchorPosition;
				_goodAnchorPlaceField?.SetValue(__instance, value2);
				Character holderCharacter2 = val3.holderCharacter;
				if ((Object)(object)holderCharacter2 != (Object)null)
				{
					Vector3 characterPosition2 = GetCharacterPosition(holderCharacter2);
					float num = Vector3.Distance(_lockedAnchorPosition, characterPosition2);
					if (RopeAnchorFixPlugin.DebugMode && Time.frameCount % 30 == 0)
					{
						RopeAnchorFixPlugin.Logger.LogInfo((object)$"Cast distance: {num:F2}m / {BluePreviewRange:F2}m");
					}
					if (num > BluePreviewRange)
					{
						if (RopeAnchorFixPlugin.DebugMode)
						{
							RopeAnchorFixPlugin.Logger.LogInfo((object)$"=== CAST CANCELLED === Distance {num:F2}m > {BluePreviewRange:F2}m");
						}
						if (_itemOverrideProgressField != null)
						{
							_itemOverrideProgressField.SetValue(val3, 0f);
						}
						if (_itemOverrideForceProgressField != null)
						{
							_itemOverrideForceProgressField.SetValue(val3, false);
						}
						if (obj3 != null)
						{
							Object.DestroyImmediate((Object)(object)((Component)(RopeAnchor)obj3).gameObject);
						}
						if (_ropeAnchorField != null)
						{
							_ropeAnchorField.SetValue(__instance, null);
						}
						if (_goodAnchorPlaceField != null)
						{
							_goodAnchorPlaceField.SetValue(__instance, null);
						}
						if (_timeWithGoodAnchorField != null)
						{
							_timeWithGoodAnchorField.SetValue(__instance, 0f);
						}
						if (_releaseCheckField != null)
						{
							_releaseCheckField.SetValue(__instance, false);
						}
						_isCasting = false;
					}
				}
			}
			if (_isCasting && flag && obj3 == null)
			{
				_isCasting = false;
				if (RopeAnchorFixPlugin.DebugMode)
				{
					RopeAnchorFixPlugin.Logger.LogInfo((object)"=== CASTING COMPLETED ===");
				}
			}
		}

		[IteratorStateMachine(typeof(<RestoreCameraPosition>d__40))]
		private static IEnumerator RestoreCameraPosition(Vector3 originalPos)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RestoreCameraPosition>d__40(0)
			{
				originalPos = originalPos
			};
		}

		public static Vector3 GetDistancePoint(Character character)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return GetCharacterPosition(character);
		}

		private static Vector3 GetCharacterPosition(Character character)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 val = ((!UseGroundPosition) ? GetBodypartPosition(character) : GetGroundPosition(character));
			return val + Vector3.up * VerticalOffset;
		}

		private static Vector3 GetBodypartPosition(Character character)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//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 (_getBodypartMethod == null)
			{
				return character.Center;
			}
			try
			{
				object? obj = _getBodypartMethod.Invoke(character, new object[1] { (object)(BodypartType)0 });
				Bodypart val = (Bodypart)((obj is Bodypart) ? obj : null);
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).transform != (Object)null)
				{
					return ((Component)val).transform.position;
				}
			}
			catch (Exception ex)
			{
				if (RopeAnchorFixPlugin.DebugMode)
				{
					RopeAnchorFixPlugin.Logger.LogError((object)("Failed to get bodypart: " + ex.Message));
				}
			}
			return character.Center;
		}

		private static Vector3 GetGroundPosition(Character character)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			Vector3 center = character.Center;
			float num = 3f;
			RaycastHit val = HelperFunctions.LineCheck(center, center + Vector3.down * num, (LayerType)1, 0f, (QueryTriggerInteraction)1);
			if ((Object)(object)((RaycastHit)(ref val)).collider != (Object)null)
			{
				return ((RaycastHit)(ref val)).point + Vector3.up * 0.1f;
			}
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(center, Vector3.down, ref val2, num))
			{
				return ((RaycastHit)(ref val2)).point + Vector3.up * 0.1f;
			}
			return character.Center - Vector3.up * 0.8f;
		}
	}
}

ScuttlePenalty.dll

Decompiled a week 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 HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using ScuttlePenalty.Core;
using ScuttlePenalty.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ScuttlePenalty")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fe42d853a6b27dae0bba338b4f740d2abb3fac53")]
[assembly: AssemblyProduct("ScuttlePenalty")]
[assembly: AssemblyTitle("ScuttlePenalty")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 ScuttlePenalty
{
	[BepInPlugin("jill920.scuttlepenalty", "Scuttle Penalty", "1.5.0")]
	public class ScuttlePenaltyPlugin : BaseUnityPlugin
	{
		public const string MOD_GUID = "jill920.scuttlepenalty";

		public const string MOD_NAME = "Scuttle Penalty";

		public const string MOD_VERSION = "1.5.0";

		public static ScuttlePenaltyPlugin Instance;

		public static ManualLogSource Logger;

		public static bool DebugMode;

		public const float REGRAB_PENALTY = 0.28f;

		public const float REGRAB_WINDOW_MS = 500f;

		public const int PENALTY_START_AT = 2;

		public const float REGRAB_PENALTY_MULTIPLIER = 0.5f;

		public const float MAX_REGRAB_PENALTY_MULTIPLIER = 3.5f;

		public const float MIN_PITCH_FOR_PENALTY = 30f;

		public const float MAX_PITCH_FOR_EXPLOIT = -30f;

		public const float TENDERFOOT_BASELINE = 0.14f;

		public const float MAX_ANGLE_MULTIPLIER = 2.5f;

		public const float MIN_ANGLE_MULTIPLIER = 0.1f;

		public const float MIN_OVERDRAIN_TO_REFUND = 0.02f;

		public const float REFUND_PERCENTAGE = 0.95f;

		public const float MAX_REFUND_PER_EVENT = 0.35f;

		public const float MAX_REFUND_PER_WINDOW = 0.6f;

		public const float REFUND_WINDOW_SECONDS = 10f;

		public const float MIN_CLIMB_DURATION_SECONDS = 0.2f;

		public const float MAX_COMPENSATION_PER_WINDOW = 0.5f;

		public const float COMPENSATION_WINDOW_SECONDS = 10f;

		public const float MIN_IMMEDIATE_COMPENSATION = 0.08f;

		public const float MAX_IMMEDIATE_COMPENSATION = 0.25f;

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			string[] commandLineArgs = Environment.GetCommandLineArgs();
			string[] array = commandLineArgs;
			foreach (string text in array)
			{
				if (text.Equals("-ScuttleDebug", StringComparison.OrdinalIgnoreCase))
				{
					DebugMode = true;
					break;
				}
			}
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "jill920.scuttlepenalty");
			Logger.LogInfo((object)"[Scuttle Penalty 1.5.0] Loaded");
			Logger.LogInfo((object)("  Debug Mode: " + (DebugMode ? "ENABLED" : "DISABLED")));
			Logger.LogInfo((object)$"  Penalty: {0.28f} stamina per re-grab (starting at re-grab #{3})");
			Logger.LogInfo((object)$"  Immediate Compensation: {0.08f}-{0.25f} stamina on forced re-grabs");
			Logger.LogInfo((object)$"  Final Refund: Returns {95f}% of remaining over-drain");
		}
	}
}
namespace ScuttlePenalty.Utils
{
	public static class StaminaHelper
	{
		private static MethodInfo? _useStaminaMethod;

		public static void ApplyStaminaPenalty(Character character, float amount)
		{
			if (_useStaminaMethod == null)
			{
				_useStaminaMethod = typeof(Character).GetMethod("UseStamina", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			if (_useStaminaMethod != null)
			{
				_useStaminaMethod.Invoke(character, new object[2] { amount, true });
			}
			else
			{
				character.data.currentStamina = Mathf.Max(0f, character.data.currentStamina - amount);
			}
		}

		public static void ApplyStaminaRefund(Character character, float amount)
		{
			if (!(amount <= 0.001f))
			{
				character.AddStamina(amount);
			}
		}
	}
}
namespace ScuttlePenalty.Patches
{
	[HarmonyPatch(typeof(CharacterClimbing))]
	internal static class CharacterClimbing_StartPatch
	{
		private static void LogDebug(string message)
		{
			if (ScuttlePenaltyPlugin.DebugMode)
			{
				ScuttlePenaltyPlugin.Logger.LogInfo((object)message);
			}
		}

		private static void LogWarning(string message)
		{
			ScuttlePenaltyPlugin.Logger.LogWarning((object)message);
		}

		private static ReGrabTracker GetTracker(Character character)
		{
			int viewID = ((MonoBehaviourPun)character).photonView.ViewID;
			if (!SharedState.Trackers.ContainsKey(viewID))
			{
				SharedState.Trackers[viewID] = new ReGrabTracker();
			}
			return SharedState.Trackers[viewID];
		}

		private static CompensationTracker GetCompensationTracker(Character character)
		{
			int viewID = ((MonoBehaviourPun)character).photonView.ViewID;
			if (!SharedState.CompensationTrackers.ContainsKey(viewID))
			{
				SharedState.CompensationTrackers[viewID] = new CompensationTracker();
			}
			return SharedState.CompensationTrackers[viewID];
		}

		[HarmonyPatch("StartClimbRpc")]
		[HarmonyPrefix]
		private static void Prefix(CharacterClimbing __instance, Vector3 climbPos, Vector3 climbNormal)
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			ReGrabTracker tracker = GetTracker(component);
			int viewID = ((MonoBehaviourPun)component).photonView.ViewID;
			float time = Time.time;
			float currentStamina = component.data.currentStamina;
			float extraStamina = component.data.extraStamina;
			tracker.StartNewClimb(time, currentStamina, extraStamina);
			bool flag = SharedState.LastClimbEndTime.ContainsKey(viewID) && SharedState.LastClimbEndTime[viewID] > 0f;
			float num = (flag ? (time - SharedState.LastClimbEndTime[viewID]) : 999f);
			bool flag2 = flag && num < 0.5f;
			string text = (SharedState.LastStopReason.ContainsKey(viewID) ? SharedState.LastStopReason[viewID] : "");
			if (flag2)
			{
				float num2 = num * 1000f;
				if (text == "MOUSE1")
				{
					tracker.RegisterReGrab(time);
					int consecutiveReGrabs = tracker.ConsecutiveReGrabs;
					if (consecutiveReGrabs >= 2)
					{
						float num3 = Mathf.Min(1f + (float)(consecutiveReGrabs - 2) * 0.5f, 3.5f);
						float num4 = 0.28f * num3;
						StaminaHelper.ApplyStaminaPenalty(component, num4);
						LogWarning($"PENALTY #{consecutiveReGrabs}: -{num4:F2} stamina (re-grab after {num2:F0}ms)");
					}
					else
					{
						LogDebug($"RE-GRAB #{consecutiveReGrabs}: FREE (wall switch) - {num2:F0}ms after MOUSE1 release");
					}
					return;
				}
				tracker.CurrentClimbIsForcedReGrab = true;
				float y = component.data.lookValues.y;
				LogDebug($"FORCED RE-GRAB DETECTED: Pitch={y:F1}°, lastReason={text}, timeSinceStop={num2:F0}ms");
				if (y > 30f)
				{
					float num5 = Mathf.Clamp01((y - 30f) / 60f);
					float num6 = Mathf.Lerp(0.08f, 0.25f, num5);
					CompensationTracker compensationTracker = GetCompensationTracker(component);
					compensationTracker.ResetWindow(time);
					if (compensationTracker.CanCompensate(num6))
					{
						StaminaHelper.ApplyStaminaRefund(component, num6);
						compensationTracker.AddCompensation(num6);
						tracker.ImmediateCompensationGiven = num6;
						LogWarning($"IMMEDIATE COMPENSATION: +{num6:F3} stamina (pitch={y:F1}°)");
					}
					else if (ScuttlePenaltyPlugin.DebugMode)
					{
						LogDebug("IMMEDIATE COMPENSATION SKIPPED: Rate limit exceeded");
					}
				}
				if (tracker.ConsecutiveReGrabs > 0)
				{
					LogDebug("RE-GRAB CHAIN RESET: Previous stop was " + text);
					tracker.Reset();
				}
			}
			else if (tracker.ConsecutiveReGrabs > 0 && ScuttlePenaltyPlugin.DebugMode)
			{
				LogDebug("RE-GRAB CHAIN RESET: Long delay between climbs");
				tracker.Reset();
			}
		}
	}
	[HarmonyPatch(typeof(CharacterClimbing))]
	internal static class CharacterClimbing_StopPatch
	{
		private static void LogDebug(string message)
		{
			if (ScuttlePenaltyPlugin.DebugMode)
			{
				ScuttlePenaltyPlugin.Logger.LogInfo((object)message);
			}
		}

		private static void LogWarning(string message)
		{
			ScuttlePenaltyPlugin.Logger.LogWarning((object)message);
		}

		private static ReGrabTracker GetTracker(Character character)
		{
			int viewID = ((MonoBehaviourPun)character).photonView.ViewID;
			if (!SharedState.Trackers.ContainsKey(viewID))
			{
				SharedState.Trackers[viewID] = new ReGrabTracker();
			}
			return SharedState.Trackers[viewID];
		}

		[HarmonyPatch("StopClimbingRpc")]
		[HarmonyPrefix]
		private static void Prefix(CharacterClimbing __instance, float setFall)
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || !component.IsLocal)
			{
				return;
			}
			ReGrabTracker tracker = GetTracker(component);
			int viewID = ((MonoBehaviourPun)component).photonView.ViewID;
			float time = Time.time;
			float currentStamina = component.data.currentStamina;
			float extraStamina = component.data.extraStamina;
			tracker.EndCurrentClimb(time, currentStamina, extraStamina);
			float duration = tracker.CurrentClimb.Duration;
			float totalStaminaLost = tracker.CurrentClimb.TotalStaminaLost;
			float totalStartStamina = tracker.CurrentClimb.TotalStartStamina;
			string text = "OTHER";
			if (component.input.jumpWasPressed)
			{
				text = "JUMP";
			}
			else if (component.input.usePrimaryWasReleased)
			{
				text = "MOUSE1";
			}
			else if (setFall > 0f)
			{
				text = "VAULT";
			}
			LogDebug($"CLIMB STOPPED: Reason={text}, Duration={duration * 1000f:F0}ms, " + $"Loss={totalStaminaLost:F3}, StartStam={totalStartStamina:F3}, EndStam={currentStamina:F3}");
			if (tracker.CurrentClimbIsForcedReGrab)
			{
				float y = component.data.lookValues.y;
				LogDebug($"FORCED RE-GRAB CLIMB ENDED: Pitch={y:F1}°, Duration={duration * 1000f:F0}ms, Loss={totalStaminaLost:F3}");
				if (y > 30f && duration >= 0.2f && totalStaminaLost > 0f)
				{
					float num = RefundCalculator.CalculateRefund(duration, totalStaminaLost, totalStartStamina, y);
					if (tracker.ImmediateCompensationGiven > 0f)
					{
						float num2 = num;
						num = Mathf.Max(0f, num - tracker.ImmediateCompensationGiven);
						LogDebug($"ADJUSTING REFUND: Immediate given={tracker.ImmediateCompensationGiven:F3}, " + $"Original refund={num2:F3}, Final refund={num:F3}");
					}
					if (num > 0f)
					{
						tracker.Refund.ResetWindow(time);
						if (tracker.Refund.CanRefund(num))
						{
							StaminaHelper.ApplyStaminaRefund(component, num);
							tracker.Refund.AddRefund(num);
							float num3 = RefundCalculator.CalculateExpectedLoss(duration, y);
							float num4 = totalStaminaLost - num3;
							LogWarning($"FINAL REFUND | Pitch={y:F1}° | Duration={duration * 1000f:F0}ms | " + $"Expected={num3:F3} | Actual={totalStaminaLost:F3} | Over={num4:F3} | " + $"Refund={num:F3} | Total={tracker.Refund.RefundAmountInWindow:F3}/{0.6f:F3}");
						}
						else if (ScuttlePenaltyPlugin.DebugMode)
						{
							LogDebug("REFUND SKIPPED: Rate limit exceeded");
						}
					}
					else if (ScuttlePenaltyPlugin.DebugMode)
					{
						LogDebug("REFUND SKIPPED: Calculated refund amount was 0 after subtracting immediate compensation");
					}
				}
				else if (ScuttlePenaltyPlugin.DebugMode)
				{
					LogDebug($"REFUND SKIPPED: Conditions not met - pitch={y:F1}°, duration={duration:F2}s, loss={totalStaminaLost:F3}");
				}
				tracker.CurrentClimbIsForcedReGrab = false;
				tracker.ImmediateCompensationGiven = 0f;
			}
			SharedState.LastClimbEndTime[viewID] = time;
			SharedState.LastStopReason[viewID] = text;
		}
	}
}
namespace ScuttlePenalty.Core
{
	public class ClimbData
	{
		public float StartTime { get; set; }

		public float EndTime { get; set; }

		public float StartStamina { get; set; }

		public float EndStamina { get; set; }

		public float StartBonus { get; set; }

		public float EndBonus { get; set; }

		public float Duration => EndTime - StartTime;

		public float TotalStaminaLost => StartStamina + StartBonus - (EndStamina + EndBonus);

		public float TotalStartStamina => StartStamina + StartBonus;

		public void Reset()
		{
			StartTime = 0f;
			EndTime = 0f;
			StartStamina = 1f;
			EndStamina = 1f;
			StartBonus = 0f;
			EndBonus = 0f;
		}

		public void RecordStart(float time, float stamina, float bonus)
		{
			StartTime = time;
			StartStamina = stamina;
			StartBonus = bonus;
		}

		public void RecordEnd(float time, float stamina, float bonus)
		{
			EndTime = time;
			EndStamina = stamina;
			EndBonus = bonus;
		}
	}
	public class CompensationTracker
	{
		public float LastCompensationTime { get; private set; } = -10f;


		public float CompensationAmountInWindow { get; private set; } = 0f;


		public void ResetWindow(float currentTime)
		{
			if (currentTime - LastCompensationTime > 10f)
			{
				CompensationAmountInWindow = 0f;
				LastCompensationTime = currentTime;
			}
		}

		public bool CanCompensate(float amount)
		{
			return CompensationAmountInWindow + amount <= 0.6f;
		}

		public void AddCompensation(float amount)
		{
			CompensationAmountInWindow += amount;
		}
	}
	public static class RefundCalculator
	{
		public static float GetDifficultyBaseline()
		{
			float num = Ascents.climbStaminaMultiplier;
			if (RunSettings.GetValue((SETTINGTYPE)20000, false) == 1)
			{
				num *= 4f;
			}
			return 0.14f * num;
		}

		public static float GetExpectedDrainRate(float pitch)
		{
			float difficultyBaseline = GetDifficultyBaseline();
			if (pitch >= -30f && pitch <= 30f)
			{
				return difficultyBaseline;
			}
			if (pitch > 30f)
			{
				float num = 1f + (pitch - 30f) / 60f * 1.5f;
				return difficultyBaseline * Mathf.Min(num, 2.5f);
			}
			if (pitch < -30f)
			{
				float num2 = 1f - (Mathf.Abs(pitch) - Mathf.Abs(-30f)) / 60f * 0.9f;
				return difficultyBaseline * Mathf.Max(num2, 0.1f);
			}
			return difficultyBaseline;
		}

		public static float CalculateExpectedLoss(float duration, float pitch)
		{
			return duration * GetExpectedDrainRate(pitch);
		}

		public static float CalculateRefund(float duration, float actualLoss, float startStamina, float pitch)
		{
			float num = CalculateExpectedLoss(duration, pitch);
			float num2 = actualLoss - num;
			if (num2 <= 0.02f)
			{
				return 0f;
			}
			float num3 = num2 * 0.95f;
			num3 = Mathf.Min(num3, 0.35f);
			float num4 = Mathf.Max(0f, startStamina - (startStamina - actualLoss));
			return Mathf.Min(num3, num4);
		}
	}
	public class RefundTracker
	{
		public float LastRefundTime { get; private set; } = -10f;


		public float RefundAmountInWindow { get; private set; } = 0f;


		public void ResetWindow(float currentTime)
		{
			if (currentTime - LastRefundTime > 10f)
			{
				RefundAmountInWindow = 0f;
				LastRefundTime = currentTime;
			}
		}

		public bool CanRefund(float amount)
		{
			return RefundAmountInWindow + amount <= 0.6f;
		}

		public void AddRefund(float amount)
		{
			RefundAmountInWindow += amount;
		}
	}
	public class ReGrabTracker
	{
		public int ConsecutiveReGrabs { get; set; } = 0;


		public float LastReGrabTime { get; set; } = 0f;


		public bool CurrentClimbIsForcedReGrab { get; set; } = false;


		public float ImmediateCompensationGiven { get; set; } = 0f;


		public ClimbData CurrentClimb { get; private set; }

		public RefundTracker Refund { get; private set; }

		public ReGrabTracker()
		{
			CurrentClimb = new ClimbData();
			Refund = new RefundTracker();
			CurrentClimb.Reset();
		}

		public void Reset()
		{
			ConsecutiveReGrabs = 0;
			LastReGrabTime = 0f;
			CurrentClimbIsForcedReGrab = false;
			ImmediateCompensationGiven = 0f;
		}

		public void RegisterReGrab(float currentTime)
		{
			ConsecutiveReGrabs++;
			LastReGrabTime = currentTime;
		}

		public void StartNewClimb(float time, float stamina, float bonus)
		{
			CurrentClimb.RecordStart(time, stamina, bonus);
			CurrentClimbIsForcedReGrab = false;
			ImmediateCompensationGiven = 0f;
		}

		public void EndCurrentClimb(float time, float stamina, float bonus)
		{
			CurrentClimb.RecordEnd(time, stamina, bonus);
		}
	}
	public static class SharedState
	{
		public static Dictionary<int, float> LastClimbEndTime { get; } = new Dictionary<int, float>();


		public static Dictionary<int, string> LastStopReason { get; } = new Dictionary<int, string>();


		public static Dictionary<int, ReGrabTracker> Trackers { get; } = new Dictionary<int, ReGrabTracker>();


		public static Dictionary<int, CompensationTracker> CompensationTrackers { get; } = new Dictionary<int, CompensationTracker>();

	}
}

StaminaAdjuster.dll

Decompiled a week ago
using System;
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 HarmonyLib;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("StaminaAdjuster")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+45474b8f820e22b4b62e4177fd48df206621e63c")]
[assembly: AssemblyProduct("Allows all stamina values to be changed from a config.")]
[assembly: AssemblyTitle("StaminaAdjuster")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[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 StaminaAdjuster
{
	[HarmonyPatch(typeof(CharacterClimbing), "Start")]
	internal class Patch2
	{
		private static void Postfix(CharacterClimbing __instance)
		{
			__instance.maxStaminaUsage = 0.2f;
			__instance.minStaminaUsage = 0.01f;
		}
	}
	[BepInPlugin("StaminaAdjuster", "Stamina Adjuster", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		public const string MOD_GUID = "StaminaAdjuster";

		public const string MOD_NAME = "Stamina Adjuster";

		public const string MOD_VERSION = "1.0.1";

		public const float MAX_CLIMB_STAMINA_USAGE = 0.2f;

		public const float MIN_CLIMB_STAMINA_USAGE = 0.01f;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "StaminaAdjuster");
			Log.LogInfo((object)"[Stamina Adjuster 1.0.1] Loaded!");
			Log.LogInfo((object)$"  MaxClimbStaminaUsage: {0.2f}");
			Log.LogInfo((object)$"  MinClimbStaminaUsage: {0.01f}");
		}
	}
}