Decompiled source of ClassModF v0.1.1

ClassMod-F.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using ClassModF;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("ClassMod-F")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("ClassMod-F")]
[assembly: AssemblyTitle("ClassMod-F")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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 enum PlayerClass
{
	Normal,
	Scout,
	Herbalist,
	Forager,
	Ranger,
	Tinkerer
}
public static class ClassManager
{
	private static readonly PlayerClass[] SelectionOrder = new PlayerClass[6]
	{
		PlayerClass.Normal,
		PlayerClass.Ranger,
		PlayerClass.Scout,
		PlayerClass.Forager,
		PlayerClass.Herbalist,
		PlayerClass.Tinkerer
	};

	public static Dictionary<int, float> CachedAfflictionMultipliers = new Dictionary<int, 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 bool IsInAirport()
	{
		//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)
		try
		{
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name == "Airport")
			{
				return true;
			}
			if ((Object)(object)Character.localCharacter != (Object)null)
			{
				return Character.localCharacter.inAirport;
			}
		}
		catch
		{
		}
		return false;
	}

	public static bool IsPlayableLevel(string sceneName)
	{
		if (!string.IsNullOrEmpty(sceneName))
		{
			return sceneName.StartsWith("Level_", StringComparison.OrdinalIgnoreCase);
		}
		return false;
	}

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

	private static PlayerClass PreviousClass(PlayerClass cls)
	{
		int num = Array.IndexOf(SelectionOrder, cls);
		if (num < 0)
		{
			return SelectionOrder[SelectionOrder.Length - 1];
		}
		return SelectionOrder[(num - 1 + SelectionOrder.Length) % SelectionOrder.Length];
	}

	private static PlayerClass NextClass(PlayerClass cls)
	{
		int num = Array.IndexOf(SelectionOrder, cls);
		if (num < 0)
		{
			return SelectionOrder[0];
		}
		return SelectionOrder[(num + 1) % SelectionOrder.Length];
	}
}
[HarmonyPatch]
public static class ClassPatches
{
	[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, true);
		}
		catch
		{
		}
	}
}
public interface IAbilityWithCooldown
{
	void ResetCooldown();
}
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 var 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_0055: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.Find("ClassModF_CooldownRoot");
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		val = new GameObject("ClassModF_CooldownRoot");
		Object.DontDestroyOnLoad((Object)(object)val);
		Canvas obj = val.AddComponent<Canvas>();
		obj.renderMode = (RenderMode)0;
		obj.sortingOrder = 5000;
		CanvasScaler obj2 = val.AddComponent<CanvasScaler>();
		obj2.uiScaleMode = (ScaleMode)0;
		obj2.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_00e5: 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_0117: Expected O, but got Unknown
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: 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)
		_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)Object.FindFirstObjectByType<UI_UseItemProgress>() != (Object)null && (Object)(object)Object.FindFirstObjectByType<UI_UseItemProgress>().fill != (Object)null)
		{
			_circle.sprite = val2.fill.sprite;
		}
		_circle.type = (Type)3;
		_circle.fillMethod = (FillMethod)4;
		_circle.fillOrigin = 2;
		_circle.fillClockwise = false;
		_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 val4 = GameObject.Find("GAME/GUIManager");
		GUIManager val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<GUIManager>() : null);
		if ((Object)(object)val5 != (Object)null && (Object)(object)val5.heroDayText != (Object)null)
		{
			((TMP_Text)_text).font = ((TMP_Text)val5.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_0024: 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)
		//IL_004e: 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_006e: 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 HideAll()
	{
		foreach (CooldownUI value in _instances.Values)
		{
			value.Hide();
		}
	}

	public static void Remove(string name)
	{
		if (_instances.TryGetValue(name, out var value) && (Object)(object)value._circle != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)value._circle).gameObject);
		}
	}
}
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_0077: 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;
			GUI.Label(new Rect(((float)Screen.width - num) / 2f, (float)Screen.height / 2f - 100f, num, num2), 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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		if ((Object)(object)instance == (Object)null)
		{
			GameObject val = new GameObject("RestrictionPopup");
			instance = val.AddComponent<RestrictionPopup>();
			Object.DontDestroyOnLoad((Object)val);
		}
		instance.message = msg;
		instance.showUntil = Time.time + duration;
	}
}
namespace ClassModF
{
	[BepInPlugin("com.classmod.f", "ClassMod-F", "1.0.0")]
	public class ClassModF : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("com.classmod.f");

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			_harmony.PatchAll();
			GameObject val = new GameObject("ClassUI");
			val.AddComponent<ClassUI>();
			Object.DontDestroyOnLoad((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));
			if (!ClassManager.IsPlayableLevel(((Scene)(ref scene)).name))
			{
				CooldownUI.HideAll();
			}
		}

		private IEnumerator ResetCooldownsDelayed(Scene scene)
		{
			//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)
			if (!ClassManager.IsPlayableLevel(((Scene)(ref scene)).name))
			{
				CooldownUI.HideAll();
				yield break;
			}
			yield return null;
			yield return null;
			float timeout = 5f;
			while ((Object)(object)Character.localCharacter == (Object)null && timeout > 0f)
			{
				timeout -= Time.unscaledDeltaTime;
				yield return null;
			}
			foreach (IAbilityWithCooldown item in Object.FindObjectsByType<MonoBehaviour>((FindObjectsSortMode)0).OfType<IAbilityWithCooldown>())
			{
				item.ResetCooldown();
			}
		}

		private void Update()
		{
			if (ClassManager.IsInAirport())
			{
				ClassManager.Update();
			}
		}
	}
	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("ClassModF_Abilities");
				Object.DontDestroyOnLoad((Object)(object)_container);
			}
			if (_lastClass != cls || !HasAbilityFor(cls))
			{
				DestroyIfExists<ScoutAbility>();
				DestroyIfExists<RangerAbility>();
				DestroyIfExists<ForagerAbility>();
				DestroyIfExists<HerbalistAbility>();
				DestroyIfExists<TinkererAbility>();
				switch (cls)
				{
				case PlayerClass.Scout:
					_container.AddComponent<ScoutAbility>();
					break;
				case PlayerClass.Ranger:
					_container.AddComponent<RangerAbility>();
					break;
				case PlayerClass.Forager:
					_container.AddComponent<ForagerAbility>();
					break;
				case PlayerClass.Herbalist:
					_container.AddComponent<HerbalistAbility>();
					break;
				case PlayerClass.Tinkerer:
					_container.AddComponent<TinkererAbility>();
					break;
				}
				_lastClass = cls;
			}
		}

		private static void DestroyIfExists<T>() where T : Component
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			if ((Object)(object)_container == (Object)null)
			{
				return;
			}
			T[] components = _container.GetComponents<T>();
			foreach (T val in components)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static bool HasAbilityFor(PlayerClass cls)
		{
			if ((Object)(object)_container == (Object)null)
			{
				return false;
			}
			return cls switch
			{
				PlayerClass.Forager => (Object)(object)_container.GetComponent<ForagerAbility>() != (Object)null, 
				PlayerClass.Herbalist => (Object)(object)_container.GetComponent<HerbalistAbility>() != (Object)null, 
				PlayerClass.Scout => (Object)(object)_container.GetComponent<ScoutAbility>() != (Object)null, 
				PlayerClass.Ranger => (Object)(object)_container.GetComponent<RangerAbility>() != (Object)null, 
				PlayerClass.Tinkerer => (Object)(object)_container.GetComponent<TinkererAbility>() != (Object)null, 
				_ => false, 
			};
		}
	}
	public static class ClassModifiers
	{
		private const bool Enabled = false;

		public static float GetStaminaMultiplier(PlayerClass playerClass)
		{
			return 1f;
		}

		public static float GetWeightMultiplier(PlayerClass playerClass)
		{
			return 1f;
		}

		public static Dictionary<int, float> GetAllAfflictionMultipliers(PlayerClass playerClass)
		{
			Dictionary<int, float> dictionary = new Dictionary<int, float>();
			for (int i = 0; i < 9; i++)
			{
				dictionary[i] = 1f;
			}
			return dictionary;
		}

		public static float GetAfflictionMultiplier(PlayerClass playerClass, int status)
		{
			return 1f;
		}
	}
	public class ClassUI : MonoBehaviour
	{
		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)
		{
			showHUD = false;
			((Behaviour)this).enabled = true;
		}

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

		private void OnGUI()
		{
			//IL_0030: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00aa: 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_00c1: Expected O, but got Unknown
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: 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_00eb: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_011e: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Expected O, but got Unknown
			//IL_01b0: 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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			if (showHUD)
			{
				bool num = ClassManager.CurrentClass == PlayerClass.Normal;
				float num2 = (num ? 145f : 320f);
				GUI.Box(new Rect(10f, 10f, 330f, num2), "");
				GUILayout.BeginArea(new Rect(20f, 20f, 310f, num2 - 20f));
				GUILayout.Label("CLASS SELECTION", new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1
				}, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Current Class: {ClassManager.CurrentClass}", new GUIStyle(GUI.skin.label)
				{
					fontSize = 13
				}, Array.Empty<GUILayoutOption>());
				if (!num)
				{
					GUILayout.Label("Description", new GUIStyle(GUI.skin.label)
					{
						fontStyle = (FontStyle)1
					}, Array.Empty<GUILayoutOption>());
					GUILayout.Label(GetClassDescription(ClassManager.CurrentClass), new GUIStyle(GUI.skin.label)
					{
						fontSize = 11,
						wordWrap = true
					}, Array.Empty<GUILayoutOption>());
					GUILayout.Label("Ability", new GUIStyle(GUI.skin.label)
					{
						fontStyle = (FontStyle)1
					}, Array.Empty<GUILayoutOption>());
					GUILayout.Label(GetClassAbility(ClassManager.CurrentClass), new GUIStyle(GUI.skin.label)
					{
						fontSize = 11,
						wordWrap = true
					}, Array.Empty<GUILayoutOption>());
					GUILayout.Label("Disadvantage", new GUIStyle(GUI.skin.label)
					{
						fontStyle = (FontStyle)1
					}, Array.Empty<GUILayoutOption>());
					GUILayout.Label(GetClassDisadvantage(ClassManager.CurrentClass), new GUIStyle(GUI.skin.label)
					{
						fontSize = 11,
						wordWrap = true
					}, Array.Empty<GUILayoutOption>());
				}
				GUILayout.Label("Controls:", new GUIStyle(GUI.skin.label)
				{
					fontSize = 12,
					fontStyle = (FontStyle)1
				}, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Up Arrow - Toggle HUD", Array.Empty<GUILayoutOption>());
				GUILayout.Label("Left/Right - Change Class", Array.Empty<GUILayoutOption>());
				GUILayout.Label("F - Use Ability", Array.Empty<GUILayoutOption>());
				GUILayout.EndArea();
			}
		}

		private string GetClassDescription(PlayerClass playerClass)
		{
			return playerClass switch
			{
				PlayerClass.Scout => "The Scout excels in speed.", 
				PlayerClass.Forager => "The Forager gathers food from the current biome.", 
				PlayerClass.Herbalist => "The Herbalist specializes in natural remedies.", 
				PlayerClass.Ranger => "The Ranger survives through resilience and stamina.", 
				PlayerClass.Tinkerer => "The Tinkerer creates tools from scavenged parts.", 
				_ => "", 
			};
		}

		private string GetClassAbility(PlayerClass playerClass)
		{
			return playerClass switch
			{
				PlayerClass.Scout => "F: Adrenaline Rush, increasing movement and climbing speed.", 
				PlayerClass.Forager => "F: Forage Food, spawning a food item from the biome.", 
				PlayerClass.Herbalist => "F: Forage Herbs, spawning a healing item from the biome.", 
				PlayerClass.Ranger => "F: Survival Instinct, granting invincibility and bonus stamina.", 
				PlayerClass.Tinkerer => "F: Tinker Tools, spawning a random useful tool.", 
				_ => "", 
			};
		}

		private string GetClassDisadvantage(PlayerClass playerClass)
		{
			return playerClass switch
			{
				PlayerClass.Scout => "Heavy drowsiness after the speed effect ends.", 
				PlayerClass.Forager => "Drowsiness after foraging.", 
				PlayerClass.Herbalist => "Drowsiness after foraging.", 
				PlayerClass.Ranger => "Heavy drowsiness after invincibility ends.", 
				PlayerClass.Tinkerer => "Significant drowsiness after crafting.", 
				_ => "", 
			};
		}
	}
	public class ScoutAbility : MonoBehaviour, IAbilityWithCooldown
	{
		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime;

		public float cooldownSeconds = 600f;

		public float duration = 11f;

		public float moveSpeedMod = 0.75f;

		public float climbSpeedMod = 1.75f;

		public float drowsyOnEnd = 0.75f;

		public float injuryOnEnd;

		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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (!ClassManager.IsPlayableLevel(((Scene)(ref activeScene)).name))
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.IsInAirport())
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			try
			{
				Affliction_FasterBoi val = new Affliction_FasterBoi
				{
					totalTime = duration,
					moveSpeedMod = moveSpeedMod,
					climbSpeedMod = climbSpeedMod,
					drowsyOnEnd = 0f,
					climbDelay = climbDelay
				};
				local.refs.afflictions.AddAffliction((Affliction)(object)val, false);
				((MonoBehaviour)this).StartCoroutine(ApplyDrowsyAfterDelay(local, duration));
				_cooldownLeft = cooldownSeconds;
				if (_uiAvailable && _ui != null)
				{
					_ui.StartCooldown(cooldownSeconds);
				}
			}
			catch (Exception)
			{
			}
		}

		private IEnumerator ApplyDrowsyAfterDelay(Character local, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			if ((Object)(object)local != (Object)null)
			{
				Affliction_AdjustDrowsyOverTime val = new Affliction_AdjustDrowsyOverTime(0.075f, 10f);
				local.refs.afflictions.AddAffliction((Affliction)(object)val, false);
			}
		}

		public void ResetCooldown()
		{
			_cooldownLeft = 0f;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(0f);
				_ui.Show();
			}
		}
	}
	public class RangerAbility : MonoBehaviour, IAbilityWithCooldown
	{
		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime;

		public float cooldownSeconds = 600f;

		public int effectType = 6;

		public float drowsyAmount = 7.5f;

		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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (!ClassManager.IsPlayableLevel(((Scene)(ref activeScene)).name))
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.IsInAirport())
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.CurrentClass != PlayerClass.Ranger)
			{
				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_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: Expected O, but got Unknown
			try
			{
				Affliction_Invincibility val = new Affliction_Invincibility
				{
					totalTime = 15f
				};
				local.refs.afflictions.AddAffliction((Affliction)(object)val, false);
				local.AddExtraStamina(0.5f);
				((MonoBehaviour)this).StartCoroutine(ApplyDrowsyAfterDelay(local, ((Affliction)val).totalTime));
				_cooldownLeft = cooldownSeconds;
				if (_uiAvailable && _ui != null)
				{
					_ui.StartCooldown(cooldownSeconds);
				}
			}
			catch (Exception)
			{
			}
		}

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

		private IEnumerator ApplyDrowsyAfterDelay(Character local, float delay)
		{
			yield return (object)new WaitForSeconds(delay);
			if ((Object)(object)local != (Object)null)
			{
				Affliction_AdjustDrowsyOverTime val = new Affliction_AdjustDrowsyOverTime(0.075f, 10f);
				local.refs.afflictions.AddAffliction((Affliction)(object)val, false);
			}
		}
	}
	public class ForagerAbility : MonoBehaviour, IAbilityWithCooldown
	{
		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime;

		public float cooldownSeconds = 300f;

		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("Forager Ability", new Vector2(-20f, 140f));
				_uiAvailable = true;
				_ui.Hide();
			}
			catch
			{
				_uiAvailable = false;
			}
		}

		private void Update()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (!ClassManager.IsPlayableLevel(((Scene)(ref activeScene)).name))
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.IsInAirport())
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.CurrentClass != PlayerClass.Forager)
			{
				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;
					TryForage(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 TryForage(Character local)
		{
			_cooldownLeft = cooldownSeconds;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(cooldownSeconds);
			}
			try
			{
				string itemForBiome = GetItemForBiome();
				SpawnBiome spawnBiome = ItemSpawner.DetectBiome();
				if (!string.IsNullOrEmpty(itemForBiome) && (spawnBiome == SpawnBiome.Caldera || spawnBiome == SpawnBiome.Kiln || spawnBiome == SpawnBiome.Swamp || spawnBiome == SpawnBiome.Temple))
				{
					RestrictionPopup.ShowMessage("you find something worth taking", 5f);
				}
				else if (string.IsNullOrEmpty(itemForBiome))
				{
					RestrictionPopup.ShowMessage("you find nothing worth taking", 5f);
				}
				if (!string.IsNullOrEmpty(itemForBiome))
				{
					((MonoBehaviour)this).StartCoroutine(SpawnDelayed(itemForBiome, local));
				}
				local.refs.afflictions.AddStatus((STATUSTYPE)6, 0.25f, false, true, true, false);
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[ClassMod-F] TryForage: {arg}");
			}
		}

		private IEnumerator SpawnDelayed(string itemPrefab, Character local)
		{
			yield return (object)new WaitForSeconds(0.2f);
			if (!string.IsNullOrEmpty(itemPrefab) && !((Object)(object)local == (Object)null))
			{
				ItemSpawner.SpawnInHand(local, itemPrefab);
			}
		}

		private string GetItemForBiome()
		{
			return ItemSpawner.SelectWeighted(ItemSpawner.DetectBiome(), new Dictionary<SpawnBiome, (string, float)[]>
			{
				{
					SpawnBiome.Shore,
					ItemSpawner.Loot("Item_Coconut", "Apple Berry Red", "Apple Berry Yellow", "Mushroom Normie", "Mushroom Lace", "Mushroom Cluster", "Mushroom Chubby")
				},
				{
					SpawnBiome.Tropics,
					ItemSpawner.Loot("Item_Coconut", "Apple Berry Red", "Apple Berry Yellow", "Pepper Berry", "Berrynana Yellow", "Berrynana Blue", "Berrynana Brown", "Clusterberry Yellow", "Clusterberry Black", "Mushroom Normie", "Mushroom Lace", "Mushroom Cluster", "Mushroom Chubby", "Kingberry Purple")
				},
				{
					SpawnBiome.Roots,
					ItemSpawner.Loot("Shroomberry_Red", "Shroomberry_Yellow", "Mushroom Normie", "Mushroom Lace", "Mushroom Cluster", "Mushroom Chubby")
				},
				{
					SpawnBiome.Alpine,
					ItemSpawner.Loot(("Winterberry Orange", 1f), ("Napberry", 0.1f))
				},
				{
					SpawnBiome.Mesa,
					ItemSpawner.Loot("Item_Coconut", "Prickleberry_Red", "Mushroom Normie", "Mushroom Lace", "Mushroom Cluster", "Mushroom Chubby")
				},
				{
					SpawnBiome.Caldera,
					ItemSpawner.Loot(("Airplane Food", 0.5f), ("Granola Bar", 1f), ("TrailMix", 1f))
				},
				{
					SpawnBiome.Swamp,
					ItemSpawner.Loot(("Airplane Food", 0.5f), ("Granola Bar", 1f), ("TrailMix", 1f))
				},
				{
					SpawnBiome.Temple,
					ItemSpawner.Loot(("Airplane Food", 0.5f), ("Granola Bar", 1f), ("TrailMix", 1f))
				},
				{
					SpawnBiome.Kiln,
					ItemSpawner.Loot(("Airplane Food", 0.5f), ("Granola Bar", 1f), ("TrailMix", 1f))
				},
				{
					SpawnBiome.Peak,
					Array.Empty<(string, float)>()
				}
			});
		}

		public void ResetCooldown()
		{
			_cooldownLeft = 0f;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(0f);
				_ui.Show();
			}
		}
	}
	public class HerbalistAbility : MonoBehaviour, IAbilityWithCooldown
	{
		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime;

		public float cooldownSeconds = 300f;

		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("Herbalist Ability", new Vector2(-20f, 140f));
				_uiAvailable = true;
				_ui.Hide();
			}
			catch
			{
				_uiAvailable = false;
			}
		}

		private void Update()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (!ClassManager.IsPlayableLevel(((Scene)(ref activeScene)).name))
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.IsInAirport())
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.CurrentClass != PlayerClass.Herbalist)
			{
				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;
					TryForage(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 TryForage(Character local)
		{
			_cooldownLeft = cooldownSeconds;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(cooldownSeconds);
			}
			try
			{
				string itemForBiome = GetItemForBiome();
				SpawnBiome spawnBiome = ItemSpawner.DetectBiome();
				if (!string.IsNullOrEmpty(itemForBiome) && (spawnBiome == SpawnBiome.Caldera || spawnBiome == SpawnBiome.Kiln || spawnBiome == SpawnBiome.Swamp || spawnBiome == SpawnBiome.Temple))
				{
					RestrictionPopup.ShowMessage("you find something worth taking", 5f);
				}
				else if (string.IsNullOrEmpty(itemForBiome))
				{
					RestrictionPopup.ShowMessage("you find nothing worth taking", 5f);
				}
				if (!string.IsNullOrEmpty(itemForBiome))
				{
					((MonoBehaviour)this).StartCoroutine(SpawnDelayed(itemForBiome, local));
				}
				local.refs.afflictions.AddStatus((STATUSTYPE)6, 0.25f, false, true, true, false);
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[ClassMod-F] TryForage (Herbalist): {arg}");
			}
		}

		private IEnumerator SpawnDelayed(string itemPrefab, Character local)
		{
			yield return (object)new WaitForSeconds(0.2f);
			if (!string.IsNullOrEmpty(itemPrefab) && !((Object)(object)local == (Object)null))
			{
				ItemSpawner.SpawnInHand(local, itemPrefab);
			}
		}

		private string GetItemForBiome()
		{
			return ItemSpawner.SelectWeighted(ItemSpawner.DetectBiome(), new Dictionary<SpawnBiome, (string, float)[]>
			{
				{
					SpawnBiome.Shore,
					ItemSpawner.Loot(("MedicinalRoot", 1f), ("HealingPuffShroom", 0.1f))
				},
				{
					SpawnBiome.Tropics,
					ItemSpawner.Loot(("MedicinalRoot", 1f), ("Clusterberry Red", 1f), ("HealingPuffShroom", 0.1f))
				},
				{
					SpawnBiome.Roots,
					ItemSpawner.Loot(("MedicinalRoot", 1f), ("HealingPuffShroom", 0.1f))
				},
				{
					SpawnBiome.Alpine,
					ItemSpawner.Loot(("HealingPuffShroom", 1f), ("Winterberry Yellow", 1f), ("Napberry", 0.1f))
				},
				{
					SpawnBiome.Mesa,
					ItemSpawner.Loot(("Prickleberry_Gold", 1f), ("MedicinalRoot", 0.25f), ("HealingPuffShroom", 0.1f))
				},
				{
					SpawnBiome.Caldera,
					ItemSpawner.Loot(("Lollipop", 0.25f), ("Energy Drink", 1f), ("FortifiedMilk", 0.5f), ("Sports Drink", 1f))
				},
				{
					SpawnBiome.Swamp,
					ItemSpawner.Loot(("Lollipop", 0.25f), ("Energy Drink", 1f), ("FortifiedMilk", 0.5f), ("Sports Drink", 1f))
				},
				{
					SpawnBiome.Temple,
					ItemSpawner.Loot(("Lollipop", 0.25f), ("Energy Drink", 1f), ("FortifiedMilk", 0.5f), ("Sports Drink", 1f))
				},
				{
					SpawnBiome.Kiln,
					ItemSpawner.Loot(("Lollipop", 0.25f), ("Energy Drink", 1f), ("FortifiedMilk", 0.5f), ("Sports Drink", 1f))
				},
				{
					SpawnBiome.Peak,
					Array.Empty<(string, float)>()
				}
			});
		}

		public void ResetCooldown()
		{
			_cooldownLeft = 0f;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(0f);
				_ui.Show();
			}
		}
	}
	public class TinkererAbility : MonoBehaviour, IAbilityWithCooldown
	{
		public KeyCode abilityKey = (KeyCode)102;

		public float holdTime;

		public float cooldownSeconds = 600f;

		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("Tinker Ability", new Vector2(-20f, 140f));
				_uiAvailable = true;
				_ui.Hide();
			}
			catch
			{
				_uiAvailable = false;
			}
		}

		private void Update()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null)
			{
				return;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (!ClassManager.IsPlayableLevel(((Scene)(ref activeScene)).name))
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.IsInAirport())
			{
				if (_uiAvailable && _ui != null)
				{
					_ui.Hide();
				}
				return;
			}
			if (ClassManager.CurrentClass != PlayerClass.Tinkerer)
			{
				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;
					TryTinker(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 TryTinker(Character local)
		{
			_cooldownLeft = cooldownSeconds;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(cooldownSeconds);
			}
			try
			{
				string itemForBiome = GetItemForBiome();
				SpawnBiome spawnBiome = ItemSpawner.DetectBiome();
				if (!string.IsNullOrEmpty(itemForBiome) && (spawnBiome == SpawnBiome.Caldera || spawnBiome == SpawnBiome.Kiln || spawnBiome == SpawnBiome.Swamp || spawnBiome == SpawnBiome.Temple || spawnBiome == SpawnBiome.Mesa || spawnBiome == SpawnBiome.Tropics || spawnBiome == SpawnBiome.Roots || spawnBiome == SpawnBiome.Alpine || spawnBiome == SpawnBiome.Shore))
				{
					RestrictionPopup.ShowMessage("You pieced together something useful", 5f);
				}
				else if (string.IsNullOrEmpty(itemForBiome))
				{
					RestrictionPopup.ShowMessage("you find nothing worth tinkering with", 5f);
				}
				if (!string.IsNullOrEmpty(itemForBiome))
				{
					((MonoBehaviour)this).StartCoroutine(SpawnDelayed(itemForBiome, local));
				}
				local.refs.afflictions.AddStatus((STATUSTYPE)6, 0.5f, false, true, true, false);
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[ClassMod-F] TryTinker: {arg}");
			}
		}

		private IEnumerator SpawnDelayed(string itemPrefab, Character local)
		{
			yield return (object)new WaitForSeconds(0.2f);
			if (!string.IsNullOrEmpty(itemPrefab) && !((Object)(object)local == (Object)null))
			{
				ItemSpawner.SpawnInHand(local, itemPrefab);
			}
		}

		private string GetItemForBiome()
		{
			SpawnBiome biome = ItemSpawner.DetectBiome();
			(string, float)[] value = ItemSpawner.Loot(("ClimbingSpike", 1f), ("PortableStovetopItem", 0.5f), ("RopeSpool", 1f), ("ScoutCannonItem", 1f), ("Pirate Compass", 0.1f));
			return ItemSpawner.SelectWeighted(biome, new Dictionary<SpawnBiome, (string, float)[]>
			{
				{
					SpawnBiome.Shore,
					value
				},
				{
					SpawnBiome.Tropics,
					value
				},
				{
					SpawnBiome.Roots,
					value
				},
				{
					SpawnBiome.Alpine,
					value
				},
				{
					SpawnBiome.Mesa,
					value
				},
				{
					SpawnBiome.Caldera,
					value
				},
				{
					SpawnBiome.Swamp,
					value
				},
				{
					SpawnBiome.Kiln,
					value
				},
				{
					SpawnBiome.Temple,
					value
				},
				{
					SpawnBiome.Peak,
					Array.Empty<(string, float)>()
				}
			});
		}

		public void ResetCooldown()
		{
			_cooldownLeft = 0f;
			if (_uiAvailable && _ui != null)
			{
				_ui.StartCooldown(0f);
				_ui.Show();
			}
		}
	}
	public enum SpawnBiome
	{
		Shore,
		Tropics,
		Roots,
		Alpine,
		Mesa,
		Caldera,
		Kiln,
		Swamp,
		Temple,
		Peak
	}
	public static class ItemSpawner
	{
		private static readonly MethodInfo SpawnItemInHandMethod = typeof(CharacterItems).GetMethod("SpawnItemInHand", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);

		public static SpawnBiome DetectBiome()
		{
			//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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0021: Expected I4, but got Unknown
			//IL_0066: 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_0082: Expected I4, but got Unknown
			MapHandler instance = Singleton<MapHandler>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return SpawnBiome.Shore;
			}
			BiomeType currentBiome = instance.GetCurrentBiome();
			Segment currentSegment = instance.GetCurrentSegment();
			return (int)currentBiome switch
			{
				0 => SpawnBiome.Shore, 
				1 => SpawnBiome.Tropics, 
				7 => SpawnBiome.Roots, 
				2 => SpawnBiome.Alpine, 
				6 => SpawnBiome.Mesa, 
				3 => SpawnBiome.Caldera, 
				8 => SpawnBiome.Swamp, 
				9 => SpawnBiome.Temple, 
				4 => SpawnBiome.Kiln, 
				5 => SpawnBiome.Peak, 
				_ => (currentSegment - 1) switch
				{
					0 => SpawnBiome.Tropics, 
					1 => SpawnBiome.Alpine, 
					2 => SpawnBiome.Caldera, 
					4 => SpawnBiome.Peak, 
					_ => SpawnBiome.Shore, 
				}, 
			};
		}

		public static bool SpawnInHand(Character character, string itemName)
		{
			if ((Object)(object)character == (Object)null || string.IsNullOrEmpty(itemName))
			{
				return false;
			}
			Item val = ResolveItem(itemName);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)("[ClassMod-F] Item não encontrado: " + itemName));
				return false;
			}
			if ((Object)(object)GameUtils.instance != (Object)null)
			{
				GameUtils.instance.InstantiateAndGrab(val, character, 1);
				return true;
			}
			if ((Object)(object)character.refs?.items != (Object)null && SpawnItemInHandMethod != null)
			{
				try
				{
					SpawnItemInHandMethod.Invoke(character.refs.items, new object[1] { ((Object)((Component)val).gameObject).name });
					return true;
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("[ClassMod-F] Spawn via reflection falhou: " + ex.Message));
				}
			}
			return false;
		}

		private static Item ResolveItem(string itemName)
		{
			Item[] array = Resources.FindObjectsOfTypeAll<Item>();
			foreach (Item val in array)
			{
				if ((Object)(object)val != (Object)null && (((Object)((Component)val).gameObject).name == itemName || ((Object)val).name == itemName || (val.UIData != null && val.UIData.itemName == itemName)))
				{
					return val;
				}
			}
			try
			{
				return ObjectDatabaseAsset<ItemDatabase, Item>.GetObjectFromString(itemName);
			}
			catch
			{
				return null;
			}
		}

		public static (string item, float weight)[] Loot(params string[] items)
		{
			(string, float)[] array = new(string, float)[items.Length];
			for (int i = 0; i < items.Length; i++)
			{
				array[i] = (items[i], 1f);
			}
			return array;
		}

		public static (string item, float weight)[] Loot(params (string item, float weight)[] items)
		{
			return items;
		}

		public static string SelectWeighted(SpawnBiome biome, Dictionary<SpawnBiome, (string item, float weight)[]> lootTables)
		{
			if (!lootTables.TryGetValue(biome, out (string, float)[] value) || value.Length == 0)
			{
				return null;
			}
			float num = 0f;
			(string, float)[] array = value;
			for (int i = 0; i < array.Length; i++)
			{
				(string, float) tuple = array[i];
				num += tuple.Item2;
			}
			float num2 = Random.value * num;
			array = value;
			for (int i = 0; i < array.Length; i++)
			{
				(string, float) tuple2 = array[i];
				num2 -= tuple2.Item2;
				if (num2 <= 0f)
				{
					return tuple2.Item1;
				}
			}
			return value[^1].Item1;
		}
	}
}