Decompiled source of JMClassMod v0.2.2

plugins/JMClassMod.dll

Decompiled 3 months 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 HarmonyLib;
using JMClassMod;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("JMClassMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("JMClassMod")]
[assembly: AssemblyTitle("JMClassMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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;
		}
	}
}
public class AbilityCooldownResetOnScene : MonoBehaviour
{
	private void Awake()
	{
		Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		Debug.Log((object)("[CooldownReset] Scene loaded: " + ((Scene)(ref scene)).name + ", resetting cooldowns."));
		CooldownResetHelper.ResetAll();
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}
}
public static class CooldownResetHelper
{
	public static void ResetAll()
	{
		MonoBehaviour[] array = Object.FindObjectsByType<MonoBehaviour>((FindObjectsSortMode)0);
		foreach (MonoBehaviour val in array)
		{
			if (val is IAbilityWithCooldown abilityWithCooldown)
			{
				abilityWithCooldown.ResetCooldown();
			}
		}
	}
}
public interface IAbilityWithCooldown
{
	void ResetCooldown();
}
[HarmonyPatch(typeof(Character), "Start")]
public class Character_Start_Patch
{
	[HarmonyPostfix]
	public static void Postfix(Character __instance)
	{
		if ((Object)(object)__instance == (Object)(object)Character.localCharacter && (Object)(object)((Component)__instance).GetComponent<MedicAbility>() == (Object)null)
		{
			((Component)__instance).gameObject.AddComponent<MedicAbility>();
		}
	}
}
[HarmonyPatch]
internal class ClassItemRestriction
{
	[HarmonyPatch(typeof(Item), "StartUsePrimary")]
	[HarmonyPrefix]
	private static bool BlockPrimary(Item __instance)
	{
		return CheckRestrictions(__instance);
	}

	[HarmonyPatch(typeof(Item), "StartUseSecondary")]
	[HarmonyPrefix]
	private static bool BlockSecondary(Item __instance)
	{
		return CheckRestrictions(__instance);
	}

	private static bool CheckRestrictions(Item item)
	{
		string text = ((item != null) ? ((Object)item).name : null) ?? "";
		if (ClassManager.CurrentClass == PlayerClass.Normal)
		{
			return true;
		}
		if ((text.Contains("Bandages") || text.Contains("FirstAidKit")) && ClassManager.CurrentClass != PlayerClass.Medic)
		{
			RestrictionPopup.ShowMessage("You can only use this item as a Medic.");
			return false;
		}
		if (text.Contains("PortableStovetopItem") && ClassManager.CurrentClass != PlayerClass.Cook)
		{
			RestrictionPopup.ShowMessage("You can only use this item as a Cook.");
			return false;
		}
		if (text.Contains("Backpack") && (ClassManager.CurrentClass == PlayerClass.Scout || ClassManager.CurrentClass == PlayerClass.Normal))
		{
			RestrictionPopup.ShowMessage("You cannot pick up a Backpack with your class.");
			return false;
		}
		return true;
	}
}
public static class ClassManager
{
	public static Dictionary<STATUSTYPE, float> CachedAfflictionMultipliers = new Dictionary<STATUSTYPE, float>();

	public static PlayerClass CurrentClass { get; private set; } = PlayerClass.Normal;


	public static void Update()
	{
		if (Input.GetKeyDown((KeyCode)276))
		{
			SetClass(PreviousClass(CurrentClass));
		}
		else if (Input.GetKeyDown((KeyCode)275))
		{
			SetClass(NextClass(CurrentClass));
		}
	}

	public static void SetClass(PlayerClass newClass)
	{
		CurrentClass = newClass;
		CachedAfflictionMultipliers = ClassModifiers.GetAllAfflictionMultipliers(CurrentClass);
		ClassAbilities.AssignAbility(newClass);
	}

	private static PlayerClass PreviousClass(PlayerClass cls)
	{
		int num = (int)(cls - 1);
		if (num < 0)
		{
			num = Enum.GetValues(typeof(PlayerClass)).Length - 1;
		}
		return (PlayerClass)num;
	}

	private static PlayerClass NextClass(PlayerClass cls)
	{
		int num = (int)(cls + 1);
		if (num >= Enum.GetValues(typeof(PlayerClass)).Length)
		{
			num = 0;
		}
		return (PlayerClass)num;
	}
}
public enum PlayerClass
{
	Normal,
	Scout,
	Medic,
	Cook,
	BigBilly
}
[HarmonyPatch]
public static class ClassPatches
{
	[HarmonyPatch(typeof(Character), "UseStamina", new Type[]
	{
		typeof(float),
		typeof(bool)
	})]
	[HarmonyPrefix]
	private static void UseStamina_Prefix(ref float __0, bool __1)
	{
		try
		{
			float staminaMultiplier = ClassModifiers.GetStaminaMultiplier(ClassManager.CurrentClass);
			__0 *= staminaMultiplier;
		}
		catch (Exception)
		{
		}
	}

	[HarmonyPatch(typeof(CharacterAfflictions), "UpdateWeight")]
	[HarmonyPostfix]
	private static void UpdateWeight_Postfix(CharacterAfflictions __instance)
	{
		try
		{
			float currentStatus = __instance.GetCurrentStatus((STATUSTYPE)7);
			float weightMultiplier = ClassModifiers.GetWeightMultiplier(ClassManager.CurrentClass);
			float num = currentStatus * weightMultiplier;
			__instance.SetStatus((STATUSTYPE)7, num);
		}
		catch (Exception)
		{
		}
	}
}
public class CooldownUI
{
	private static readonly Dictionary<string, CooldownUI> _instances = new Dictionary<string, CooldownUI>();

	private readonly string _name;

	private GameObject _root;

	private Image _circle;

	private TextMeshProUGUI _text;

	private Vector2 _targetPos;

	private float _cooldownDur;

	private float _cooldownT;

	private bool _active;

	public static CooldownUI Get(string name, Vector2 anchoredPosition)
	{
		//IL_001f: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		if (_instances.TryGetValue(name, out CooldownUI value))
		{
			value._targetPos = anchoredPosition;
			value.ApplyAnchors();
			return value;
		}
		CooldownUI cooldownUI = new CooldownUI(name, anchoredPosition);
		_instances[name] = cooldownUI;
		return cooldownUI;
	}

	private CooldownUI(string name, Vector2 anchoredPosition)
	{
		//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)
		_name = name;
		_targetPos = anchoredPosition;
		CreateUI();
		SetReadyVisuals();
	}

	private static GameObject EnsureCanvasRoot()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.Find("JMClassMod_CooldownRoot");
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		val = new GameObject("JMClassMod_CooldownRoot");
		Object.DontDestroyOnLoad((Object)(object)val);
		Canvas val2 = val.AddComponent<Canvas>();
		val2.renderMode = (RenderMode)0;
		val2.sortingOrder = 5000;
		CanvasScaler val3 = val.AddComponent<CanvasScaler>();
		val3.uiScaleMode = (ScaleMode)1;
		val3.referenceResolution = new Vector2(1920f, 1080f);
		val.AddComponent<GraphicRaycaster>();
		return val;
	}

	private void CreateUI()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_00d1: 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_0103: Expected O, but got Unknown
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		_root = EnsureCanvasRoot();
		GameObject val = new GameObject(_name + "_Circle");
		val.transform.SetParent(_root.transform, false);
		_circle = val.AddComponent<Image>();
		UI_UseItemProgress val2 = Object.FindFirstObjectByType<UI_UseItemProgress>();
		if ((Object)(object)val2 != (Object)null && (Object)(object)val2.fill != (Object)null)
		{
			_circle.sprite = val2.fill.sprite;
		}
		_circle.type = (Type)3;
		_circle.fillMethod = (FillMethod)4;
		_circle.fillOrigin = 2;
		_circle.fillClockwise = false;
		_circle.fillAmount = 0f;
		((Graphic)_circle).color = new Color(0.2f, 1f, 0.2f, 0.9f);
		((Behaviour)_circle).enabled = true;
		ApplyAnchors();
		GameObject val3 = new GameObject(_name + "_Text");
		val3.transform.SetParent(((Component)_circle).transform, false);
		_text = val3.AddComponent<TextMeshProUGUI>();
		GameObject obj = GameObject.Find("GAME/GUIManager");
		GUIManager val4 = ((obj != null) ? obj.GetComponent<GUIManager>() : null);
		if ((Object)(object)val4 != (Object)null && (Object)(object)val4.heroDayText != (Object)null)
		{
			((TMP_Text)_text).font = ((TMP_Text)val4.heroDayText).font;
		}
		((TMP_Text)_text).alignment = (TextAlignmentOptions)514;
		((Graphic)_text).color = Color.white;
		((TMP_Text)_text).fontSize = 18f;
		RectTransform rectTransform = ((TMP_Text)_text).rectTransform;
		rectTransform.anchorMin = Vector2.zero;
		rectTransform.anchorMax = Vector2.one;
		rectTransform.offsetMin = Vector2.zero;
		rectTransform.offsetMax = Vector2.zero;
	}

	private void ApplyAnchors()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_circle == (Object)null))
		{
			RectTransform rectTransform = ((Graphic)_circle).rectTransform;
			rectTransform.anchorMin = new Vector2(1f, 0f);
			rectTransform.anchorMax = new Vector2(1f, 0f);
			rectTransform.pivot = new Vector2(1f, 0f);
			rectTransform.anchoredPosition = _targetPos;
			rectTransform.sizeDelta = new Vector2(75f, 75f);
		}
	}

	private void SetReadyVisuals()
	{
		if (!((Object)(object)_circle == (Object)null) && !((Object)(object)_text == (Object)null))
		{
			_circle.fillAmount = 1f;
			((TMP_Text)_text).text = "Ready";
		}
	}

	private void SetTickVisuals()
	{
		if (!((Object)(object)_circle == (Object)null) && !((Object)(object)_text == (Object)null))
		{
			float fillAmount = ((_cooldownDur <= 0f) ? 0f : Mathf.Clamp01(1f - _cooldownT / _cooldownDur));
			_circle.fillAmount = fillAmount;
			int num = Mathf.FloorToInt(_cooldownT / 60f);
			int num2 = Mathf.FloorToInt(_cooldownT % 60f);
			((TMP_Text)_text).text = $"{num:00}:{num2:00}";
		}
	}

	public void StartCooldown(float durationSeconds)
	{
		_cooldownDur = Mathf.Max(0f, durationSeconds);
		_cooldownT = _cooldownDur;
		_active = _cooldownDur > 0f;
		if (_active)
		{
			SetTickVisuals();
		}
		else
		{
			SetReadyVisuals();
		}
		Show();
	}

	public void Update()
	{
		if (_active)
		{
			_cooldownT -= Time.deltaTime;
			if (_cooldownT <= 0f)
			{
				_cooldownT = 0f;
				_active = false;
				SetReadyVisuals();
			}
			else
			{
				SetTickVisuals();
			}
		}
	}

	public void Show()
	{
		if ((Object)(object)_circle != (Object)null)
		{
			((Component)_circle).gameObject.SetActive(true);
		}
		if ((Object)(object)_text != (Object)null)
		{
			((Component)_text).gameObject.SetActive(true);
		}
	}

	public void Hide()
	{
		if ((Object)(object)_circle != (Object)null)
		{
			((Component)_circle).gameObject.SetActive(false);
		}
		if ((Object)(object)_text != (Object)null)
		{
			((Component)_text).gameObject.SetActive(false);
		}
	}

	public static void Remove(string name)
	{
		if (_instances.TryGetValue(name, out CooldownUI value) && (Object)(object)value._circle != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)value._circle).gameObject);
		}
	}
}
public class MedicAbility : MonoBehaviour, IAbilityWithCooldown
{
	public KeyCode abilityKey = (KeyCode)102;

	public float holdTime = 1f;

	public float cooldown = 300f;

	private float holdTimer;

	private float nextReadyTime;

	private static MedicAbility? _instance;

	private CooldownUI _ui;

	private void Awake()
	{
		if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
		{
			Object.Destroy((Object)(object)this);
		}
		else
		{
			_instance = this;
		}
	}

	private void Start()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		_ui = CooldownUI.Get("Cook Ability", new Vector2(-20f, 140f));
		_ui.Show();
	}

	private void Update()
	{
		//IL_004a: 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)Character.localCharacter == (Object)null)
		{
			return;
		}
		if (ClassManager.CurrentClass != PlayerClass.Cook)
		{
			_ui.Hide();
			return;
		}
		_ui.Show();
		_ui.Update();
		bool flag = Time.time >= nextReadyTime;
		if (Input.GetKey(abilityKey) && flag)
		{
			holdTimer += Time.deltaTime;
			if (holdTimer >= holdTime)
			{
				ActivateMedicAbility();
				holdTimer = 0f;
				nextReadyTime = Time.time + cooldown;
				_ui.StartCooldown(cooldown);
			}
		}
		if (Input.GetKeyUp(abilityKey))
		{
			holdTimer = 0f;
		}
	}

	private void OnDisable()
	{
		if (_ui != null)
		{
			_ui.Hide();
		}
	}

	private void OnDestroy()
	{
		if (_ui != null)
		{
			_ui.Hide();
		}
	}

	private void ActivateMedicAbility()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: 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_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: 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)
		Camera main = Camera.main;
		Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.forward : ((Component)Character.localCharacter).transform.forward);
		Vector3 val2 = Character.localCharacter.Center + Vector3.up * 1f + val * 1f;
		Quaternion val3 = Quaternion.LookRotation(val);
		GameObject val4 = PhotonNetwork.Instantiate("0_items/BounceShroom", val2, val3, (byte)0, (object[])null);
		Rigidbody val5 = val4.GetComponent<Rigidbody>() ?? val4.AddComponent<Rigidbody>();
		val5.isKinematic = false;
		val5.useGravity = true;
		val5.AddForce(val * 200f, (ForceMode)1);
	}

	public void ResetCooldown()
	{
		nextReadyTime = 0f;
		holdTimer = 0f;
		if (_ui != null)
		{
			_ui.StartCooldown(0f);
			_ui.Show();
		}
	}
}
public static class ReflectionUtils
{
	public static T GetPrivateField<T>(object obj, string fieldName)
	{
		FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			throw new Exception($"Field '{fieldName}' not found in {obj.GetType()}");
		}
		return (T)field.GetValue(obj);
	}

	public static void SetPrivateField(object obj, string fieldName, object value)
	{
		FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (field == null)
		{
			throw new Exception($"Field '{fieldName}' not found in {obj.GetType()}");
		}
		field.SetValue(obj, value);
	}

	public static T GetPrivateFieldByType<T>(object obj)
	{
		FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
		FieldInfo[] array = fields;
		foreach (FieldInfo fieldInfo in array)
		{
			if (typeof(T).IsAssignableFrom(fieldInfo.FieldType))
			{
				return (T)fieldInfo.GetValue(obj);
			}
		}
		throw new Exception($"No private field of type {typeof(T)} found in {obj.GetType()}");
	}

	public static T InvokePrivateMethod<T>(object obj, string methodName, params object[] args)
	{
		MethodInfo method = obj.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
		if (method == null)
		{
			throw new Exception($"Method '{methodName}' not found in {obj.GetType()}");
		}
		return (T)method.Invoke(obj, args);
	}

	public static void InvokePrivateMethod(object obj, string methodName, params object[] args)
	{
		MethodInfo method = obj.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
		if (method == null)
		{
			throw new Exception($"Method '{methodName}' not found in {obj.GetType()}");
		}
		method.Invoke(obj, args);
	}

	public static float GetStatus(object obj, STATUSTYPE type)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		MethodInfo method = obj.GetType().GetMethod("GetStatus", BindingFlags.Instance | BindingFlags.NonPublic);
		if (method == null)
		{
			throw new Exception($"Method 'GetStatus' not found in {obj.GetType()}");
		}
		return (float)method.Invoke(obj, new object[1] { type });
	}

	public static void SetStatus(object obj, STATUSTYPE type, float value)
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		MethodInfo method = obj.GetType().GetMethod("SetStatus", BindingFlags.Instance | BindingFlags.NonPublic);
		if (method == null)
		{
			throw new Exception($"Method 'SetStatus' not found in {obj.GetType()}");
		}
		method.Invoke(obj, new object[2] { type, value });
	}
}
public class RestrictionPopup : MonoBehaviour
{
	private static RestrictionPopup? instance;

	private string message = "";

	private float showUntil;

	private void Awake()
	{
		instance = this;
	}

	private void OnGUI()
	{
		//IL_0024: 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)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		if (Time.time < showUntil && !string.IsNullOrEmpty(message))
		{
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)4,
				fontSize = 20
			};
			val.normal.textColor = Color.black;
			GUIStyle val2 = val;
			float num = 400f;
			float num2 = 30f;
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((float)Screen.width - num) / 2f, (float)Screen.height / 2f - 100f, num, num2);
			GUI.Label(val3, message, val2);
		}
	}

	public static void ShowMessage(string msg, float duration = 1f)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		if ((Object)(object)instance == (Object)null)
		{
			GameObject val = new GameObject("RestrictionPopup");
			instance = val.AddComponent<RestrictionPopup>();
			Object.DontDestroyOnLoad((Object)(object)val);
		}
		instance.message = msg;
		instance.showUntil = Time.time + duration;
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace PeakClassMod
{
	[HarmonyPatch(typeof(Item), "Interact")]
	public static class BackpackPickupRestriction
	{
		private static bool Prefix(Item __instance, Character interactor)
		{
			if (!(__instance is Backpack))
			{
				return true;
			}
			if (ClassManager.CurrentClass == PlayerClass.Scout || ClassManager.CurrentClass == PlayerClass.Cook)
			{
				RestrictionPopup.ShowMessage("Your class cannot pick up Backpacks!");
				Debug.Log((object)$"[JMClassMod] Prevented {ClassManager.CurrentClass} from picking up a Backpack");
				return false;
			}
			return true;
		}
	}
	public static class ClassCookingRestriction
	{
		[HarmonyPatch(typeof(Campfire), "GetInteractTime")]
		public static class Campfire_GetInteractTime_Patch
		{
			private static void Postfix(Character interactor, ref float __result)
			{
				if (ClassManager.CurrentClass != PlayerClass.Cook && ClassManager.CurrentClass != 0 && (Object)(object)interactor.data.currentItem != (Object)null && interactor.data.currentItem.cooking.canBeCooked)
				{
					__result = 0f;
				}
			}
		}

		[HarmonyPatch(typeof(Campfire), "IsInteractible")]
		public static class Campfire_IsInteractible_Patch
		{
			private static void Postfix(Character interactor, ref bool __result)
			{
				if (ClassManager.CurrentClass != PlayerClass.Cook && ClassManager.CurrentClass != 0 && (Object)(object)interactor.data.currentItem != (Object)null && interactor.data.currentItem.cooking.canBeCooked)
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Campfire), "Interact_CastFinished")]
		public static class Campfire_InteractFinished_Patch
		{
			private static bool Prefix(Character interactor)
			{
				if (ClassManager.CurrentClass != PlayerClass.Cook && ClassManager.CurrentClass != 0 && (Object)(object)interactor.data.currentItem != (Object)null && interactor.data.currentItem.cooking.canBeCooked)
				{
					return false;
				}
				return true;
			}
		}
	}
}
namespace JMClassMod
{
	public class FasterBoiAbility : MonoBehaviour, IAbilityWithCooldown
	{
		[CompilerGenerated]
		private sealed class <ApplyInjuryAfter>d__18 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			public Character local;

			public float amount;

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

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

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

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

			private bool MoveNext()
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: 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)local != (Object)null && amount > 0f)
					{
						local.refs.afflictions.AddStatus((STATUSTYPE)0, amount, false);
						Debug.Log((object)$"[FasterBoiAbility] Applied Injury {amount} after FasterBoi ended.");
					}
					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();
			}
		}

		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime;

		public float cooldownSeconds = 240f;

		public float duration = 4f;

		public float moveSpeedMod = 0.5f;

		public float climbSpeedMod = 0.75f;

		public float drowsyOnEnd = 0.65f;

		public float injuryOnEnd = 0.05f;

		public float climbDelay;

		private float _hold;

		private float _cooldownLeft;

		private bool _uiAvailable;

		private CooldownUI? _ui;

		private void Start()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_ui = CooldownUI.Get("Scout FasterBoi", new Vector2(-20f, 140f));
				_uiAvailable = true;
				_ui.Hide();
			}
			catch
			{
				_uiAvailable = false;
			}
		}

		private void Update()
		{
			//IL_00c7: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if (!Object.op_Implicit((Object)(object)localCharacter))
			{
				return;
			}
			if (ClassManager.CurrentClass != PlayerClass.Scout)
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (_uiAvailable && _ui != null)
			{
				_ui.Show();
			}
			if (_cooldownLeft > 0f)
			{
				_cooldownLeft -= Time.deltaTime;
				if (_cooldownLeft < 0f)
				{
					_cooldownLeft = 0f;
				}
			}
			if (_uiAvailable && _ui != null)
			{
				_ui.Update();
			}
			if (_cooldownLeft > 0f)
			{
				if (Input.GetKeyUp(abilityKey))
				{
					_hold = 0f;
				}
				return;
			}
			if (Input.GetKey(abilityKey))
			{
				_hold += Time.deltaTime;
				if (_hold >= holdTime)
				{
					_hold = 0f;
					Activate(localCharacter);
				}
			}
			if (Input.GetKeyUp(abilityKey))
			{
				_hold = 0f;
			}
		}

		private void OnDisable()
		{
			if (_ui != null)
			{
				_ui.Hide();
			}
		}

		private void OnDestroy()
		{
			if (_ui != null)
			{
				_ui.Hide();
			}
		}

		private void Activate(Character local)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			try
			{
				Affliction_FasterBoi val = new Affliction_FasterBoi
				{
					totalTime = duration,
					moveSpeedMod = moveSpeedMod,
					climbSpeedMod = climbSpeedMod,
					drowsyOnEnd = drowsyOnEnd,
					climbDelay = climbDelay
				};
				local.refs.afflictions.AddAffliction((Affliction)(object)val, false);
				((MonoBehaviour)this).StartCoroutine(ApplyInjuryAfter(local, duration, injuryOnEnd));
				_cooldownLeft = cooldownSeconds;
				if (_uiAvailable && _ui != null)
				{
					_ui.StartCooldown(cooldownSeconds);
				}
				Debug.Log((object)($"[FasterBoiAbility] Activated: duration {duration}s, " + $"speed x{moveSpeedMod}, climb x{climbSpeedMod}, " + $"drowsy {drowsyOnEnd}, injury {injuryOnEnd} on end."));
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[FasterBoiAbility] Exception: {arg}");
			}
		}

		[IteratorStateMachine(typeof(<ApplyInjuryAfter>d__18))]
		private IEnumerator ApplyInjuryAfter(Character local, float delay, float amount)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ApplyInjuryAfter>d__18(0)
			{
				local = local,
				delay = delay,
				amount = amount
			};
		}

		public void ResetCooldown()
		{
			_cooldownLeft = 0f;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(0f);
				_ui.Show();
			}
		}
	}
	public class Affliction_FasterBoiInjury : Affliction_FasterBoi
	{
		public float injuryOnEnd = 1f;

		public override void OnRemoved()
		{
			((Affliction_FasterBoi)this).OnRemoved();
			if (injuryOnEnd > 1f)
			{
				((Affliction)this).character.refs.afflictions.AddStatus((STATUSTYPE)0, injuryOnEnd, false);
				Debug.Log((object)$"[FasterBoiInjury] Added Injury {injuryOnEnd} on end.");
			}
		}
	}
	public class HealAfflictionAbility : MonoBehaviour, IAbilityWithCooldown
	{
		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime = 1f;

		public float cooldownSeconds = 300f;

		[Header("Per-Stat Heal Amounts")]
		public float injuryHealAmount = 0.05f;

		public float hotHealAmount = 0.1f;

		public float coldHealAmount = 0.1f;

		public float poisonHealAmount = 0.1f;

		private float _hold;

		private float _cooldownLeft;

		private bool _uiAvailable;

		private CooldownUI? _ui;

		private void Start()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_ui = CooldownUI.Get("Medic Heal", new Vector2(-20f, 140f));
				_uiAvailable = true;
				_ui.Hide();
			}
			catch
			{
				_uiAvailable = false;
			}
		}

		private void Update()
		{
			//IL_00c7: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if (!Object.op_Implicit((Object)(object)localCharacter))
			{
				return;
			}
			if (ClassManager.CurrentClass != PlayerClass.Medic)
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (_uiAvailable && _ui != null)
			{
				_ui.Show();
			}
			if (_cooldownLeft > 0f)
			{
				_cooldownLeft -= Time.deltaTime;
				if (_cooldownLeft < 0f)
				{
					_cooldownLeft = 0f;
				}
			}
			if (_uiAvailable && _ui != null)
			{
				_ui.Update();
			}
			if (_cooldownLeft > 0f)
			{
				if (Input.GetKeyUp(abilityKey))
				{
					_hold = 0f;
				}
				return;
			}
			if (Input.GetKey(abilityKey))
			{
				_hold += Time.deltaTime;
				if (_hold >= holdTime)
				{
					_hold = 0f;
					TryHeal(localCharacter);
				}
			}
			if (Input.GetKeyUp(abilityKey))
			{
				_hold = 0f;
			}
		}

		private void OnDisable()
		{
			if (_ui != null)
			{
				_ui.Hide();
			}
		}

		private void OnDestroy()
		{
			if (_ui != null)
			{
				_ui.Hide();
			}
		}

		private void TryHeal(Character local)
		{
			Character val = FindTargetCharacter() ?? local;
			try
			{
				if ((Object)(object)val == (Object)(object)local)
				{
					ApplyHeals(val);
					RestrictionPopup.ShowMessage("Healed yourself", 2f);
				}
				else
				{
					RestrictionPopup.ShowMessage("Healed " + ((Object)val).name, 2f);
					PhotonView component = ((Component)val).GetComponent<PhotonView>();
					if ((Object)(object)component != (Object)null)
					{
						component.RPC("RPC_ApplyHealAndNotify", component.Owner, new object[5]
						{
							((Object)local).name,
							injuryHealAmount,
							hotHealAmount,
							coldHealAmount,
							poisonHealAmount
						});
					}
				}
				_cooldownLeft = cooldownSeconds;
				if (_uiAvailable && _ui != null)
				{
					_ui.StartCooldown(cooldownSeconds);
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[HealAfflictionAbility] AdjustStatus threw: {arg}");
			}
		}

		private void ApplyHeals(Character target)
		{
			target.refs.afflictions.AdjustStatus((STATUSTYPE)0, 0f - Mathf.Abs(injuryHealAmount), false);
			target.refs.afflictions.AdjustStatus((STATUSTYPE)8, 0f - Mathf.Abs(hotHealAmount), false);
			target.refs.afflictions.AdjustStatus((STATUSTYPE)2, 0f - Mathf.Abs(coldHealAmount), false);
			target.refs.afflictions.AdjustStatus((STATUSTYPE)3, 0f - Mathf.Abs(poisonHealAmount), false);
		}

		private Character? FindTargetCharacter()
		{
			//IL_0021: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			Camera val = Camera.main ?? Object.FindFirstObjectByType<Camera>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			Ray val2 = default(Ray);
			((Ray)(ref val2))..ctor(((Component)val).transform.position, ((Component)val).transform.forward);
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val2, ref val3, 3f, -1, (QueryTriggerInteraction)1))
			{
				return ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Character>();
			}
			return null;
		}

		public void ResetCooldown()
		{
			_cooldownLeft = 0f;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(0f);
				_ui.Show();
			}
		}

		[PunRPC]
		private void RPC_ApplyHealAndNotify(string healerName, float inj, float hot, float cold, float poison)
		{
			try
			{
				Character.localCharacter.refs.afflictions.AdjustStatus((STATUSTYPE)0, 0f - Mathf.Abs(inj), false);
				Character.localCharacter.refs.afflictions.AdjustStatus((STATUSTYPE)8, 0f - Mathf.Abs(hot), false);
				Character.localCharacter.refs.afflictions.AdjustStatus((STATUSTYPE)2, 0f - Mathf.Abs(cold), false);
				Character.localCharacter.refs.afflictions.AdjustStatus((STATUSTYPE)3, 0f - Mathf.Abs(poison), false);
				RestrictionPopup.ShowMessage(healerName + " has healed you.", 2f);
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[HealAfflictionAbility] RPC_ApplyHealAndNotify failed: {arg}");
			}
		}
	}
	public class NapBerryAbility : MonoBehaviour, IAbilityWithCooldown
	{
		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime = 1f;

		public float cooldownSeconds = 1200f;

		public STATUSTYPE effectType = (STATUSTYPE)6;

		public float drowsyAmount = 1.25f;

		private float _hold;

		private float _cooldownLeft;

		private bool _uiAvailable;

		private CooldownUI? _ui;

		private void Start()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_ui = CooldownUI.Get("NapBerry Ability", new Vector2(-20f, 140f));
				_uiAvailable = true;
				_ui.Hide();
			}
			catch
			{
				_uiAvailable = false;
			}
		}

		private void Update()
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if (!Object.op_Implicit((Object)(object)localCharacter))
			{
				return;
			}
			if (ClassManager.CurrentClass != PlayerClass.BigBilly)
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (_uiAvailable && _ui != null)
			{
				_ui.Show();
			}
			if (_cooldownLeft > 0f)
			{
				_cooldownLeft -= Time.deltaTime;
				if (_cooldownLeft < 0f)
				{
					_cooldownLeft = 0f;
				}
			}
			if (_uiAvailable && _ui != null)
			{
				_ui.Update();
				if (_cooldownLeft <= 0f)
				{
					_ui.Show();
				}
			}
			if (_cooldownLeft > 0f)
			{
				if (Input.GetKeyUp(abilityKey))
				{
					_hold = 0f;
				}
				return;
			}
			if (Input.GetKey(abilityKey))
			{
				_hold += Time.deltaTime;
				if (_hold >= holdTime)
				{
					_hold = 0f;
					ApplyNapBerry(localCharacter);
				}
			}
			if (Input.GetKeyUp(abilityKey))
			{
				_hold = 0f;
			}
		}

		private void OnDisable()
		{
			if (_ui != null)
			{
				_ui.Hide();
			}
		}

		private void OnDestroy()
		{
			if (_ui != null)
			{
				_ui.Hide();
			}
		}

		private void ApplyNapBerry(Character local)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CharacterAfflictions afflictions = local.refs.afflictions;
				foreach (STATUSTYPE value in Enum.GetValues(typeof(STATUSTYPE)))
				{
					if ((int)value != 6)
					{
						afflictions.AdjustStatus(value, -9999f, false);
					}
				}
				afflictions.AdjustStatus(effectType, Mathf.Abs(drowsyAmount), false);
				_cooldownLeft = cooldownSeconds;
				if (_uiAvailable && _ui != null)
				{
					_ui.StartCooldown(cooldownSeconds);
				}
				Debug.Log((object)"[NapBerryAbility] Cleansed all statuses and applied Drowsy.");
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[NapBerryAbility] Exception: {arg}");
			}
		}

		public void ResetCooldown()
		{
			_cooldownLeft = 0f;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(0f);
				_ui.Show();
			}
		}
	}
	[HarmonyPatch]
	internal static class CharacterAfflictionPatches
	{
		[HarmonyPatch(typeof(CharacterAfflictions), "UpdateWeight")]
		[HarmonyPostfix]
		private static void AfterUpdateWeight(CharacterAfflictions __instance)
		{
			ApplyStaminaModifiers(__instance);
		}

		[HarmonyPatch(typeof(CharacterAfflictions), "AddStatus")]
		[HarmonyPostfix]
		private static void AfterAddStatus(CharacterAfflictions __instance, STATUSTYPE statusType, float amount)
		{
			ApplyStaminaModifiers(__instance);
		}

		[HarmonyPatch(typeof(CharacterAfflictions), "SubtractStatus")]
		[HarmonyPostfix]
		private static void AfterSubtractStatus(CharacterAfflictions __instance, STATUSTYPE statusType, float amount)
		{
			ApplyStaminaModifiers(__instance);
		}

		[HarmonyPatch(typeof(CharacterAfflictions), "ClearAllStatus")]
		[HarmonyPostfix]
		private static void AfterClearAllStatus(CharacterAfflictions __instance)
		{
			ApplyStaminaModifiers(__instance);
		}

		private static void ApplyStaminaModifiers(CharacterAfflictions aff)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0049: Invalid comparison between Unknown and I4
			if (!((Object)(object)aff == (Object)null) && !((Object)(object)aff.character == (Object)null) && aff.character.IsLocal)
			{
				Character character = aff.character;
				float num = 0f;
				for (int i = 0; i < aff.currentStatuses.Length; i++)
				{
					float num2 = aff.currentStatuses[i];
					STATUSTYPE val = (STATUSTYPE)i;
					num = (((int)val == 0) ? (num + num2 * 0.5f) : (((int)val != 7) ? (num + num2 * 0.2f) : (num + num2 * 0.25f)));
				}
				num = Mathf.Clamp01(num);
			}
		}
	}
	public static class ClassAbilities
	{
		private static GameObject _container;

		private static PlayerClass _lastClass = (PlayerClass)(-1);

		public static void AssignAbility(PlayerClass cls)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if ((Object)(object)Character.localCharacter == (Object)null)
			{
				return;
			}
			if ((Object)(object)_container == (Object)null)
			{
				_container = new GameObject("JMClassMod_Abilities");
				Object.DontDestroyOnLoad((Object)(object)_container);
			}
			if (_lastClass != cls || !HasAbilityFor(cls))
			{
				DestroyIfExists<FasterBoiAbility>();
				DestroyIfExists<MedicAbility>();
				DestroyIfExists<HealAfflictionAbility>();
				DestroyIfExists<NapBerryAbility>();
				switch (cls)
				{
				case PlayerClass.Scout:
					_container.AddComponent<FasterBoiAbility>();
					break;
				case PlayerClass.Cook:
					_container.AddComponent<MedicAbility>();
					break;
				case PlayerClass.Medic:
					_container.AddComponent<HealAfflictionAbility>();
					break;
				case PlayerClass.BigBilly:
					_container.AddComponent<NapBerryAbility>();
					break;
				}
				_lastClass = cls;
			}
		}

		private static void DestroyIfExists<T>() where T : Component
		{
			T val = (((Object)(object)_container != (Object)null) ? _container.GetComponent<T>() : default(T));
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}

		private static bool HasAbilityFor(PlayerClass cls)
		{
			return cls switch
			{
				PlayerClass.Cook => (Object)(object)_container.GetComponent<MedicAbility>() != (Object)null, 
				PlayerClass.Medic => (Object)(object)_container.GetComponent<HealAfflictionAbility>() != (Object)null, 
				PlayerClass.Scout => (Object)(object)_container.GetComponent<FasterBoiAbility>() != (Object)null, 
				PlayerClass.BigBilly => (Object)(object)_container.GetComponent<NapBerryAbility>() != (Object)null, 
				_ => false, 
			};
		}
	}
	public static class ClassModifiers
	{
		public static float GetStaminaMultiplier(PlayerClass playerClass)
		{
			return playerClass switch
			{
				PlayerClass.Scout => 0.7f, 
				PlayerClass.Medic => 1f, 
				PlayerClass.Cook => 1.1f, 
				PlayerClass.BigBilly => 1.4f, 
				_ => 1f, 
			};
		}

		public static float GetWeightMultiplier(PlayerClass playerClass)
		{
			return playerClass switch
			{
				PlayerClass.Scout => 3f, 
				PlayerClass.Medic => 1.25f, 
				PlayerClass.Cook => 0.9f, 
				PlayerClass.BigBilly => 0.7f, 
				_ => 1f, 
			};
		}

		public static Dictionary<STATUSTYPE, float> GetAllAfflictionMultipliers(PlayerClass playerClass)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<STATUSTYPE, float> dictionary = new Dictionary<STATUSTYPE, float>();
			foreach (STATUSTYPE value in Enum.GetValues(typeof(STATUSTYPE)))
			{
				dictionary[value] = GetAfflictionMultiplier(playerClass, value);
			}
			return dictionary;
		}

		public static float GetAfflictionMultiplier(PlayerClass playerClass, STATUSTYPE status)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_002e: 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_0043: Invalid comparison between Unknown and I4
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Invalid comparison between Unknown and I4
			switch (playerClass)
			{
			case PlayerClass.Scout:
				if ((int)status == 3)
				{
					return 1.25f;
				}
				if ((int)status == 8)
				{
					return 1.25f;
				}
				break;
			case PlayerClass.Medic:
				if ((int)status == 0)
				{
					return 0.75f;
				}
				if ((int)status == 6)
				{
					return 0.5f;
				}
				break;
			case PlayerClass.Cook:
				if ((int)status == 1)
				{
					return 0.75f;
				}
				if ((int)status == 8)
				{
					return 0.8f;
				}
				break;
			case PlayerClass.BigBilly:
				if ((int)status == 1)
				{
					return 1.25f;
				}
				if ((int)status == 3)
				{
					return 0.5f;
				}
				if ((int)status == 2)
				{
					return 0.5f;
				}
				break;
			}
			return 1f;
		}
	}
	public class ClassUI : MonoBehaviour
	{
		private static readonly Dictionary<STATUSTYPE, string> AfflictionNames = new Dictionary<STATUSTYPE, string>
		{
			{
				(STATUSTYPE)1,
				"Hunger Rate"
			},
			{
				(STATUSTYPE)2,
				"Cold Damage"
			},
			{
				(STATUSTYPE)8,
				"Heat Damage"
			},
			{
				(STATUSTYPE)0,
				"Fall Damage"
			},
			{
				(STATUSTYPE)3,
				"Poison Damage"
			},
			{
				(STATUSTYPE)6,
				"Drowsiness"
			}
		};

		private static bool showHUD = false;

		private static readonly KeyCode toggleKey = (KeyCode)273;

		private void Awake()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void Start()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			ApplySceneGate(((Scene)(ref activeScene)).name);
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			ApplySceneGate(((Scene)(ref scene)).name);
		}

		private void ApplySceneGate(string sceneName)
		{
			bool enabled = sceneName == "Airport";
			showHUD = false;
			((Behaviour)this).enabled = enabled;
		}

		private void Update()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(toggleKey))
			{
				showHUD = !showHUD;
			}
		}

		private void OnGUI()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if (!showHUD)
			{
				return;
			}
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				fontSize = 12
			};
			val.normal.textColor = Color.cyan;
			GUIStyle val2 = val;
			GUILayout.BeginArea(new Rect(10f, 20f, 300f, 400f));
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Current Class: {ClassManager.CurrentClass}", val2, Array.Empty<GUILayoutOption>());
			float staminaMultiplier = ClassModifiers.GetStaminaMultiplier(ClassManager.CurrentClass);
			GUILayout.Label($"Stamina Multiplier: {staminaMultiplier}x", val2, Array.Empty<GUILayoutOption>());
			float weightMultiplier = ClassModifiers.GetWeightMultiplier(ClassManager.CurrentClass);
			GUILayout.Label($"Weight Multiplier: {weightMultiplier}x", val2, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			foreach (KeyValuePair<STATUSTYPE, float> cachedAfflictionMultiplier in ClassManager.CachedAfflictionMultipliers)
			{
				float value = cachedAfflictionMultiplier.Value;
				if (!Mathf.Approximately(value, 1f))
				{
					string text;
					if (!AfflictionNames.ContainsKey(cachedAfflictionMultiplier.Key))
					{
						STATUSTYPE key = cachedAfflictionMultiplier.Key;
						text = ((object)(STATUSTYPE)(ref key)).ToString();
					}
					else
					{
						text = AfflictionNames[cachedAfflictionMultiplier.Key];
					}
					string arg = text;
					GUILayout.Label($"{arg}: {value}x", val2, Array.Empty<GUILayoutOption>());
				}
			}
			GUILayout.Space(10f);
			GUILayout.Label("Press ← or → to change class", val2, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Press {toggleKey} to toggle HUD", val2, Array.Empty<GUILayoutOption>());
			GUILayout.EndVertical();
			GUILayout.EndArea();
		}
	}
	public static class ConfigManager
	{
		public static float MaxStaminaBarCoefficient { get; set; } = 1f;


		public static float StaminaUsageCoefficient { get; set; } = 1f;


		public static float StaminaRecoveryCoefficient { get; set; } = 1f;


		public static float WeightStatusCoefficient { get; set; } = 1f;


		public static float HungerStatusCoefficient { get; set; } = 1f;


		public static bool EnableExtraStamina { get; set; } = false;


		public static void ResetToDefault()
		{
			MaxStaminaBarCoefficient = 1f;
			StaminaUsageCoefficient = 1f;
			StaminaRecoveryCoefficient = 1f;
			WeightStatusCoefficient = 1f;
			HungerStatusCoefficient = 1f;
			EnableExtraStamina = false;
		}
	}
	[BepInPlugin("com.jm.classmod", "JMClassMod", "1.0.0")]
	public class JMClassMod : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <ResetCooldownsDelayed>d__3 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private float <timeout>5__2;

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

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

			[DebuggerHidden]
			public <ResetCooldownsDelayed>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;
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<timeout>5__2 = 5f;
					break;
				case 3:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Character.localCharacter == (Object)null && <timeout>5__2 > 0f)
				{
					<timeout>5__2 -= Time.unscaledDeltaTime;
					<>2__current = null;
					<>1__state = 3;
					return true;
				}
				CooldownResetHelper.ResetAll();
				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 readonly Harmony _harmony = new Harmony("com.jm.classmod");

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			_harmony.PatchAll();
			GameObject val = new GameObject("ClassUI");
			val.AddComponent<ClassUI>();
			Object.DontDestroyOnLoad((Object)(object)val);
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviour)this).StartCoroutine(ResetCooldownsDelayed(scene));
		}

		[IteratorStateMachine(typeof(<ResetCooldownsDelayed>d__3))]
		private IEnumerator ResetCooldownsDelayed(Scene scene)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ResetCooldownsDelayed>d__3(0);
		}

		private void Update()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name == "Airport")
			{
				ClassManager.Update();
			}
		}
	}
	[HarmonyPatch(typeof(CharacterAfflictions), "AddStatus")]
	public static class Patch_AfflictionMultipliers
	{
		private static void Prefix(CharacterAfflictions __instance, STATUSTYPE statusType, ref float amount)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance.character == (Object)null) && __instance.character.IsLocal && ClassManager.CachedAfflictionMultipliers.TryGetValue(statusType, out var value) && !Mathf.Approximately(value, 1f))
			{
				amount *= value;
			}
		}
	}
	public class UIBootstrap : MonoBehaviour
	{
		private static bool _initialized;

		[RuntimeInitializeOnLoadMethod(/*Could not decode attribute arguments.*/)]
		private static void Init()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!_initialized)
			{
				Debug.Log((object)"[JMClassMod] Bootstrapping CooldownUI system.");
				CooldownUI cooldownUI = CooldownUI.Get("Bootstrap", new Vector2(0f, -200f));
				cooldownUI.Hide();
				_initialized = true;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}