Decompiled source of Super Hard and Extreme v2.0.0

SuperHardKnuckle.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace SuperHardKnuckle;

internal static class Buddy
{
	public const string GivenFlag = "skmod_run_buddy_given";

	public const string OldSavedFlag = "skmod_buddy_given";

	[ThreadStatic]
	public static bool Granting;

	public static float Left = -1f;

	private static readonly HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static float runTime;

	private static bool granted;

	private static bool gaveUp;

	private static int attempts;

	private static float verifyAt = -1f;

	private static Trinket trinket;

	public static void Reset()
	{
		Left = -1f;
		runTime = 0f;
		granted = false;
		gaveUp = false;
		names.Clear();
		attempts = 0;
		verifyAt = -1f;
		trinket = null;
	}

	public static void Tick()
	{
		if (!Cfg.BuddyEnabled.Value)
		{
			Left = -1f;
			return;
		}
		ENT_Player val = Util.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || (Object)(object)Inventory.instance == (Object)null || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused))
		{
			return;
		}
		runTime += Time.deltaTime;
		if (!granted && !gaveUp && runTime > 2f)
		{
			Grant();
		}
		if (!granted)
		{
			return;
		}
		if (verifyAt > 0f && runTime >= verifyAt)
		{
			if (HasBuddyInInventory())
			{
				verifyAt = -1f;
				Util.Debug("Calming Buddy is in the inventory.");
			}
			else if (attempts < 3 && (Object)(object)trinket != (Object)null)
			{
				attempts++;
				Util.Debug("Calming Buddy missing from inventory, giving it again (try " + attempts + ").");
				Granting = true;
				try
				{
					trinket.Activate(0f);
				}
				catch (Exception ex)
				{
					Util.LogOnce("buddyretry", "Retry failed: " + ex.Message);
				}
				finally
				{
					Granting = false;
				}
				verifyAt = runTime + 3f;
			}
			else
			{
				verifyAt = -1f;
				Util.LogOnce("buddygone", "Calming Buddy never showed up in the inventory.");
			}
		}
		if (Left < 0f)
		{
			Left = Cfg.BuddyPetSeconds.Value;
		}
		Left -= Time.deltaTime;
		if (!(Left <= 0f))
		{
			return;
		}
		Left = Cfg.BuddyPetSeconds.Value;
		Util.Debug("You forgot to pet your Calming Buddy.");
		try
		{
			((GameEntity)val).Kill("calmingbuddy", DamageInfo.CreateDamageInfo(99999f, "calmingbuddy"));
		}
		catch (Exception ex2)
		{
			Util.LogOnce("buddykill", "Buddy kill failed: " + ex2.Message);
		}
	}

	private static void Grant()
	{
		Trinket val = FindTrinket();
		if ((Object)(object)val == (Object)null)
		{
			gaveUp = true;
			Util.LogOnce("nobuddy", "Calming Buddy trinket not found - the buddy rule is off this run.");
			return;
		}
		if (val.itemsToGrant != null)
		{
			foreach (Item_Object item in val.itemsToGrant)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				names.Add(Util.Clean(((Object)item).name));
				if (item.itemData != null)
				{
					if (!string.IsNullOrEmpty(item.itemData.prefabName))
					{
						names.Add(item.itemData.prefabName);
					}
					if (!string.IsNullOrEmpty(item.itemData.itemName))
					{
						names.Add(item.itemData.itemName);
					}
				}
			}
		}
		if (names.Count == 0)
		{
			gaveUp = true;
			Util.LogOnce("buddynoitem", "Calming Buddy trinket '" + ((Object)val).name + "' has no item to pet - the buddy rule is off this run.");
			return;
		}
		bool flag = HasBuddyInInventory();
		if (!flag)
		{
			try
			{
				flag = CL_GameManager.HasActiveFlag("skmod_run_buddy_given", false);
			}
			catch
			{
			}
		}
		if (!flag)
		{
			Granting = true;
			try
			{
				val.Activate(0f);
			}
			catch (Exception ex)
			{
				Util.LogOnce("buddygrant", "Giving the Calming Buddy failed: " + ex.Message);
				gaveUp = true;
				return;
			}
			finally
			{
				Granting = false;
			}
			try
			{
				CL_GameManager.SetGameFlag("skmod_run_buddy_given", true, "", false, false);
			}
			catch
			{
			}
			if (!HasBuddyInInventory())
			{
				Util.Debug("Calming Buddy trinket ran but no buddy item showed up in the inventory yet.");
			}
		}
		granted = true;
		trinket = val;
		verifyAt = runTime + 3f;
		Left = Cfg.BuddyPetSeconds.Value;
		Util.Debug("Calming Buddy given (" + ((Object)val).name + "): " + string.Join(", ", new List<string>(names).ToArray()));
	}

	private static Trinket FindTrinket()
	{
		WKAssetDatabase val = Util.Db();
		List<Trinket> list = new List<Trinket>();
		if ((Object)(object)val != (Object)null && val.trinketAssets != null)
		{
			list.AddRange(val.trinketAssets);
		}
		M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
		if ((Object)(object)currentGamemode != (Object)null && (Object)(object)currentGamemode.availableTrinkets != (Object)null && currentGamemode.availableTrinkets.trinkets != null)
		{
			list.AddRange(currentGamemode.availableTrinkets.trinkets);
		}
		foreach (Trinket item in list)
		{
			if (!((Object)(object)item == (Object)null) && !item.isBinding)
			{
				string text = (((Object)item).name + " " + item.title).ToLowerInvariant().Replace(" ", "");
				if (text.Contains("calmingbuddy") || (text.Contains("calm") && text.Contains("buddy")))
				{
					return item;
				}
			}
		}
		foreach (Trinket item2 in list)
		{
			if (!((Object)(object)item2 == (Object)null) && !item2.isBinding && (((Object)item2).name + " " + item2.title).ToLowerInvariant().Contains("buddy"))
			{
				return item2;
			}
		}
		return null;
	}

	private static bool HasBuddyInInventory()
	{
		try
		{
			Inventory instance = Inventory.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			foreach (Item item in instance.GetItems(true, true, true))
			{
				if (IsBuddy(item))
				{
					return true;
				}
			}
		}
		catch
		{
		}
		return false;
	}

	public static bool IsBuddy(Item item)
	{
		if (item == null || names.Count == 0)
		{
			return false;
		}
		if (item.prefabName == null || !names.Contains(item.prefabName))
		{
			if (item.itemName != null)
			{
				return names.Contains(item.itemName);
			}
			return false;
		}
		return true;
	}

	public static void OnUse(Item item)
	{
		if (granted && IsBuddy(item))
		{
			Left = Cfg.BuddyPetSeconds.Value;
			Util.Debug("Petted the Calming Buddy.");
		}
	}
}
internal static class RedRoaches
{
	private static float timer;

	private static readonly List<GameObject> spawned = new List<GameObject>();

	public static void Reset()
	{
		timer = 0f;
		spawned.Clear();
	}

	public unsafe static void Tick()
	{
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		if (Cfg.RedRoachSpawnSeconds.Value <= 0f || Zones.Current == Zone.None)
		{
			return;
		}
		ENT_Player val = Util.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused) || ((Object)(object)CL_EventManager.currentLevel != (Object)null && CL_EventManager.currentLevel.safeArea))
		{
			return;
		}
		timer += Time.deltaTime;
		if (timer < Cfg.RedRoachSpawnSeconds.Value)
		{
			return;
		}
		timer = 0f;
		spawned.RemoveAll((GameObject g) => (Object)(object)g == (Object)null || !g.activeInHierarchy);
		if (spawned.Count >= Cfg.RedRoachMax.Value)
		{
			return;
		}
		GameObject val2 = Util.FindPrefabNamed("roach_explosive");
		if (!((Object)(object)val2 == (Object)null) && Util.SpotAroundPlayer(8f, 18f, out var pos))
		{
			Transform parent = null;
			try
			{
				parent = WorldLoader.GetCurrentLevelParentRoot();
			}
			catch
			{
			}
			GameObject val3 = Util.Spawn(val2, pos + Vector3.up * 0.3f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), parent);
			if ((Object)(object)val3 != (Object)null)
			{
				spawned.Add(val3);
				EntityRules.MarkSpawned(val3);
				Util.Debug("Red roach spawned at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString());
			}
		}
	}
}
internal static class SilosSturges
{
	private static float timer;

	private static readonly List<GameObject> spawned = new List<GameObject>();

	public static void Reset()
	{
		timer = 0f;
		spawned.Clear();
	}

	public unsafe static void Tick()
	{
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		if (Zones.Current != Zone.Silos || Cfg.SilosSturgeInterval.Value <= 0f)
		{
			return;
		}
		ENT_Player val = Util.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused))
		{
			return;
		}
		timer += Time.deltaTime;
		if (timer < Cfg.SilosSturgeInterval.Value)
		{
			return;
		}
		timer = 0f;
		spawned.RemoveAll((GameObject g) => (Object)(object)g == (Object)null || !g.activeInHierarchy);
		if (spawned.Count >= Cfg.SilosSturgeMax.Value)
		{
			return;
		}
		GameObject val2 = Util.FindPrefabNamed("sturge");
		if (!((Object)(object)val2 == (Object)null) && Util.SpotAroundPlayer(12f, 22f, out var pos))
		{
			Transform parent = null;
			try
			{
				parent = WorldLoader.GetCurrentLevelParentRoot();
			}
			catch
			{
			}
			GameObject val3 = Util.Spawn(val2, pos + Vector3.up * 2.5f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), parent);
			if ((Object)(object)val3 != (Object)null)
			{
				spawned.Add(val3);
				EntityRules.MarkSpawned(val3);
				Util.Debug("Sturge spawned in the Silos at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString());
			}
		}
	}
}
internal static class CavityRoute
{
	public const string Flag = "skmod_run_cavity_done";

	public const string OldSavedFlag = "skmod_cavity_done";

	private static bool doneLocal;

	private static M_Level lastLevel;

	private static M_Level levelBeforeCavity;

	private static bool inCavity;

	private static bool ratKingSeen;

	private static bool ratKingDealt;

	private static bool hasBreakRoom;

	private static Vector3 breakRoomPos;

	private static M_Level breakRoomLevel;

	private static bool hasOutside;

	private static Vector3 lastOutsidePos;

	private static readonly Queue<Vector3> history = new Queue<Vector3>();

	private static float blockCooldown;

	private static float nextTick;

	public static bool Done
	{
		get
		{
			if (doneLocal)
			{
				return true;
			}
			try
			{
				return CL_GameManager.HasActiveFlag("skmod_run_cavity_done", false);
			}
			catch
			{
				return false;
			}
		}
	}

	public static void Reset()
	{
		doneLocal = false;
		lastLevel = null;
		levelBeforeCavity = null;
		inCavity = false;
		ratKingSeen = (ratKingDealt = false);
		hasBreakRoom = false;
		breakRoomLevel = null;
		hasOutside = false;
		blockCooldown = 0f;
		history.Clear();
	}

	private static bool HasAny(string text, string csv)
	{
		string[] array = csv.Split(',');
		for (int i = 0; i < array.Length; i++)
		{
			string text2 = array[i].Trim().ToLowerInvariant();
			if (text2.Length > 0 && text.Contains(text2))
			{
				return true;
			}
		}
		return false;
	}

	public static void Tick()
	{
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0302: Unknown result type (might be due to invalid IL or missing references)
		//IL_0325: Unknown result type (might be due to invalid IL or missing references)
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0347: Unknown result type (might be due to invalid IL or missing references)
		//IL_034c: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		if (!Cfg.CavityRoute.Value)
		{
			return;
		}
		ENT_Player val = Util.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead())
		{
			return;
		}
		M_Level currentLevel = CL_EventManager.currentLevel;
		M_Subregion currentSubregion = CL_EventManager.currentSubregion;
		bool flag = ((((Object)(object)currentLevel != (Object)null) ? (currentLevel.levelName + " " + ((Object)currentLevel).name) : "") + " " + (((Object)(object)currentSubregion != (Object)null) ? (currentSubregion.subregionName + " " + ((Object)currentSubregion).name) : "")).ToLowerInvariant().Contains("cavity");
		bool flag2 = IsServiceShaft(currentLevel, currentSubregion);
		bool flag3 = false;
		try
		{
			flag3 = val.IsGrounded(false);
		}
		catch
		{
		}
		if (Zones.Current == Zone.Habitation && (Object)(object)currentLevel != (Object)null && currentLevel.safeArea && !flag && !flag2 && flag3)
		{
			hasBreakRoom = true;
			breakRoomPos = ((Component)val).transform.position;
			breakRoomLevel = currentLevel;
		}
		if (!flag2 && !flag && flag3 && Time.unscaledTime >= nextTick)
		{
			nextTick = Time.unscaledTime + 0.5f;
			history.Enqueue(((Component)val).transform.position);
			while (history.Count > 10)
			{
				history.Dequeue();
			}
			hasOutside = true;
			lastOutsidePos = history.Peek();
		}
		if (inCavity)
		{
			List<DEN_RatKing> activeRatKings = DEN_RatKing.activeRatKings;
			bool flag4 = false;
			if (activeRatKings != null)
			{
				foreach (DEN_RatKing item in activeRatKings)
				{
					if ((Object)(object)item != (Object)null && !((GameEntity)item).dead && ((Component)item).gameObject.activeInHierarchy)
					{
						flag4 = true;
						ratKingSeen = true;
					}
				}
			}
			if (ratKingSeen && !flag4 && !ratKingDealt)
			{
				ratKingDealt = true;
				Util.Debug("Body cavity: Rat King dealt with.");
			}
		}
		if ((Object)(object)currentLevel != (Object)(object)lastLevel)
		{
			M_Level val2 = lastLevel;
			lastLevel = currentLevel;
			if (flag && !inCavity)
			{
				inCavity = true;
				levelBeforeCavity = val2;
				ratKingSeen = (ratKingDealt = false);
				Util.Debug("Entered the body cavity from " + (((Object)(object)val2 != (Object)null) ? val2.levelName : "?"));
			}
			else if (!flag && inCavity)
			{
				inCavity = false;
				bool flag5 = (Object)(object)currentLevel != (Object)(object)levelBeforeCavity;
				if ((flag5 || ratKingDealt) && !Done)
				{
					Complete(flag5 ? "reached the end of the body cavity" : "came back after dealing with the Rat King");
				}
				else
				{
					Util.Debug("Left the body cavity without finishing it.");
				}
			}
		}
		if (flag2 && !Done && Time.unscaledTime >= blockCooldown)
		{
			blockCooldown = Time.unscaledTime + 1.5f;
			Vector3? val3 = (hasOutside ? new Vector3?(lastOutsidePos) : (hasBreakRoom ? new Vector3?(breakRoomPos) : ((Vector3?)null)));
			if (val3.HasValue && GroundBelow(val3.Value))
			{
				CL_GameManager.gMan.TeleportPlayer(val3.Value + Vector3.up * 0.2f);
				Util.Debug("Security Shaft is sealed - pushed back to " + ((object)val3.Value/*cast due to .constrained prefix*/).ToString());
			}
			Hud.Flash("SECURITY GATE SEALED - beat the Body Cavity first");
		}
	}

	public static void OnChamberLeft()
	{
		if (Cfg.CavityRoute.Value && inCavity && !Done)
		{
			Complete("left the body cavity chamber");
		}
	}

	private static void Complete(string why)
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		doneLocal = true;
		try
		{
			CL_GameManager.SetGameFlag("skmod_run_cavity_done", true, "", false, false);
		}
		catch (Exception ex)
		{
			Util.LogOnce("cavflag", "Could not save the body cavity flag: " + ex.Message);
		}
		Util.Debug("Body cavity beaten (" + why + "). Security Shaft unlocked.");
		Hud.Flash("BODY CAVITY BEATEN - the security gate opens");
		if (hasBreakRoom && (Object)(object)breakRoomLevel != (Object)null && ((Component)breakRoomLevel).gameObject.activeInHierarchy && GroundBelow(breakRoomPos))
		{
			CL_GameManager.gMan.TeleportPlayer(breakRoomPos + Vector3.up * 0.2f);
			Util.Debug("Teleported back to the break room (" + breakRoomLevel.levelName + ").");
		}
		else
		{
			Util.Debug("Break room isn't loaded any more, so no teleport back.");
		}
	}

	private static bool IsServiceShaft(M_Level lv, M_Subregion sr)
	{
		string text = (((Object)(object)lv != (Object)null) ? (lv.levelName + " " + ((Object)lv).name).ToLowerInvariant() : "");
		if (text.Contains("intro") || text.Contains("interlude") || text.Contains("cavity"))
		{
			return false;
		}
		if ((Object)(object)lv != (Object)null && lv.safeArea)
		{
			return false;
		}
		if (text.Length > 0 && HasAny(text, Cfg.ServiceShaftKeywords.Value))
		{
			return true;
		}
		string text2 = (((Object)(object)sr != (Object)null) ? (sr.subregionName + " " + ((Object)sr).name).ToLowerInvariant() : "");
		if (text.Length > 0 && (text2.Contains("service shaft") || text2.Contains("service_shaft")))
		{
			return !text2.Contains("ending");
		}
		return false;
	}

	public static void OnFlag(string name, bool state)
	{
		if (state && !string.IsNullOrEmpty(name) && Cfg.CavityRoute.Value && !Done)
		{
			string text = name.ToLowerInvariant();
			if (text.Contains("cavity") && !text.Contains("intro") && (text.Contains("complete") || text.Contains("finish") || text.Contains("beat") || text.Contains("end") || text.Contains("escape") || text.Contains("exit") || text.Contains("done") || text.Contains("win")))
			{
				Complete("game flag " + name);
			}
		}
	}

	private static bool GroundBelow(Vector3 pos)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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_0015: Unknown result type (might be due to invalid IL or missing references)
		return Physics.Raycast(pos + Vector3.up * 1f, Vector3.down, 3f, -1, (QueryTriggerInteraction)1);
	}

	public static bool IsAmalgam(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		return HasAny(name.ToLowerInvariant(), Cfg.AmalgamKeywords.Value);
	}
}
internal static class EntityRules
{
	private static readonly HashSet<int> seen = new HashSet<int>();

	private static readonly HashSet<int> clones = new HashSet<int>();

	private static float nextScan;

	private static float nextFaceCheck;

	private static int faceClonesThisVisit;

	private static Zone lastZone;

	private static int dronesThisZone;

	public static void Reset()
	{
		seen.Clear();
		clones.Clear();
		faceClonesThisVisit = 0;
		dronesThisZone = 0;
		lastZone = Zone.None;
		Util.ResetCaches();
	}

	public static bool IsClone(GameObject g)
	{
		if ((Object)(object)g != (Object)null)
		{
			return clones.Contains(((Object)g).GetInstanceID());
		}
		return false;
	}

	public static void Tick()
	{
		if (Zones.Current != lastZone)
		{
			lastZone = Zones.Current;
			faceClonesThisVisit = 0;
			dronesThisZone = 0;
		}
		if (Time.unscaledTime >= nextScan)
		{
			nextScan = Time.unscaledTime + 0.25f;
			Scan();
		}
		if (Zones.Current == Zone.Abyss && Time.unscaledTime >= nextFaceCheck)
		{
			nextFaceCheck = Time.unscaledTime + 1f;
			KeepFaces();
		}
	}

	private static void Scan()
	{
		List<GameEntity> entities = GameEntity.entities;
		if (entities == null)
		{
			return;
		}
		GameEntity[] array = entities.ToArray();
		foreach (GameEntity val in array)
		{
			if (!((Object)(object)val == (Object)null) && !(val is ENT_Player) && seen.Add(((Object)val).GetInstanceID()))
			{
				try
				{
					OnNewEntity(val);
				}
				catch (Exception ex)
				{
					Util.LogOnce("ent" + ((object)val).GetType().Name, "Rule for " + ((object)val).GetType().Name + " failed: " + ex.Message);
				}
			}
		}
	}

	private static void OnNewEntity(GameEntity e)
	{
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_0319: Unknown result type (might be due to invalid IL or missing references)
		Zone current = Zones.Current;
		string text = ((Object)((Component)e).gameObject).name.ToLowerInvariant();
		bool num = clones.Contains(((Object)((Component)e).gameObject).GetInstanceID());
		DEN_RatKing val = (DEN_RatKing)(object)((e is DEN_RatKing) ? e : null);
		if (val != null)
		{
			val.speed *= Cfg.RatKingSpeedMult.Value;
			Util.Debug("Rat King speed x" + Cfg.RatKingSpeedMult.Value);
		}
		DEN_Teeth val2 = (DEN_Teeth)(object)((e is DEN_Teeth) ? e : null);
		if (val2 != null && current == Zone.Habitation)
		{
			float value = Cfg.TeethSpeedMult.Value;
			val2.baseSpeed *= value;
			val2.chargeSpeed *= value;
			val2.walkSpeed *= value;
			val2.jumpSpeed *= value;
			Util.Debug("Teeth speed x" + value);
		}
		DEN_VentThing val3 = (DEN_VentThing)(object)((e is DEN_VentThing) ? e : null);
		if (val3 != null && current == Zone.Habitation)
		{
			float value2 = Cfg.VentThingSpeedMult.Value;
			val3.handSpeed *= value2;
			val3.pullForce *= value2;
			Util.Debug("Vent thing speed/pull x" + value2);
		}
		if (num || Util.HasGameEntityAncestor(e) || (Object)(object)((Component)e).GetComponent<Item_Object>() != (Object)null)
		{
			return;
		}
		bool flag = e is Denizen || e is AIGameEntity;
		int num2 = 0;
		string why = null;
		if (current == Zone.Silos && (e is DEN_Bloodbug || (flag && text.Contains("bloodbug"))))
		{
			num2 = Cfg.SilosBloodbugExtra.Value;
			why = "bloodbug";
		}
		else if (e is DEN_Barnacle || (flag && text.Contains("barnacle") && !text.Contains("zombie") && !text.Contains("tentacle")))
		{
			switch (current)
			{
			case Zone.Pipeworks:
				num2 = Cfg.PipeworksBarnacleExtra.Value;
				why = "barnacle";
				break;
			case Zone.Nest:
				num2 = Cfg.NestBarnacleExtra.Value;
				why = "barnacle";
				break;
			}
		}
		else if (current == Zone.Pipeworks && e is DEN_Hopper && !(e is DEN_Hopper_Tick))
		{
			num2 = Cfg.PipeworksHopperExtra.Value;
			why = "hopper roach";
		}
		if (e is DEN_Turret)
		{
			num2 = Cfg.TurretExtra.Value;
			why = "turret";
		}
		if (current == Zone.Silos && flag && text.Contains("sturge"))
		{
			num2 = Cfg.SilosSturgeExtra.Value;
			why = "sturge";
		}
		if (flag && SpawnRules.IsRedRoach(text))
		{
			num2 = Cfg.RedRoachExtra.Value;
			why = "red roach";
		}
		if (num2 > 0)
		{
			MakeCopies(e, num2, why);
		}
		if (current == Zone.Habitation && (e is DEN_Turret || e is DEN_GantryTurret) && dronesThisZone < 8 && Random.value < Cfg.TurretDroneChance.Value)
		{
			GameObject val4 = Util.FindPrefabWith<DEN_Drone>();
			if ((Object)(object)val4 != (Object)null)
			{
				Vector3 pos = ((Component)e).transform.position + Vector3.up * 2f + Random.insideUnitSphere * 1.5f;
				MarkClone(Util.Spawn(val4, pos, Quaternion.identity, ((Component)e).transform.parent));
				dronesThisZone++;
				Util.Debug("Drone spawned next to turret " + ((Object)((Component)e).gameObject).name);
			}
		}
	}

	private static void MakeCopies(GameEntity e, int count, string why)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: 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)
		for (int i = 0; i < count; i++)
		{
			Vector3 val = Util.NearbySpot(((Component)e).transform);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)e).gameObject, val, ((Component)e).transform.rotation, ((Component)e).transform.parent);
			((Object)val2).name = ((Object)((Component)e).gameObject).name;
			if (!val2.activeSelf)
			{
				val2.SetActive(true);
			}
			MarkClone(val2);
		}
		Util.Debug("+" + count + " " + why + " (" + ((Object)((Component)e).gameObject).name + ") in " + Zones.Current);
	}

	public static void MarkSpawned(GameObject g)
	{
		MarkClone(g);
	}

	private static void MarkClone(GameObject g)
	{
		if (!((Object)(object)g == (Object)null))
		{
			clones.Add(((Object)g).GetInstanceID());
			GameEntity[] componentsInChildren = g.GetComponentsInChildren<GameEntity>(true);
			foreach (GameEntity val in componentsInChildren)
			{
				seen.Add(((Object)val).GetInstanceID());
				clones.Add(((Object)((Component)val).gameObject).GetInstanceID());
			}
		}
	}

	private static void KeepFaces()
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		List<DEN_Face> faceInstances = DEN_Face.faceInstances;
		if (faceInstances == null)
		{
			return;
		}
		List<DEN_Face> list = faceInstances.Where((DEN_Face f) => (Object)(object)f != (Object)null && ((Component)f).gameObject.activeInHierarchy && !((GameEntity)f).dead).ToList();
		if (list.Count == 0 || list.Count >= Cfg.AbyssFaceCount.Value || faceClonesThisVisit >= Cfg.AbyssFaceCount.Value * 2)
		{
			return;
		}
		DEN_Face val = list[0];
		int num = Cfg.AbyssFaceCount.Value - list.Count;
		for (int num2 = 0; num2 < num; num2++)
		{
			Vector3 val2 = Random.insideUnitSphere * 12f;
			GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.position + val2, ((Component)val).transform.rotation, ((Component)val).transform.parent);
			((Object)val3).name = ((Object)((Component)val).gameObject).name;
			if (!val3.activeSelf)
			{
				val3.SetActive(true);
			}
			MarkClone(val3);
			faceClonesThisVisit++;
		}
		Util.Debug("Abyss: faces topped up to " + Cfg.AbyssFaceCount.Value);
	}
}
internal static class Hud
{
	private static GUIStyle style;

	private static GUIStyle big;

	private static string flash;

	private static float flashUntil;

	public static void Flash(string text)
	{
		flash = text;
		flashUntil = Time.unscaledTime + 4f;
	}

	public static void Draw()
	{
		//IL_00e0: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Expected O, but got Unknown
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		if (Cfg.ShowHud.Value && Mode.IsActive() && (!((Object)(object)CL_GameManager.gMan != (Object)null) || !CL_GameManager.gMan.isPaused))
		{
			if (style == null)
			{
				style = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)1
				};
				style.normal.textColor = new Color(1f, 0.25f, 0.2f, 0.85f);
				big = new GUIStyle(style)
				{
					fontSize = 30
				};
				big.normal.textColor = new Color(1f, 0.15f, 0.1f, 1f);
			}
			float num = Screen.width;
			GUI.Label(new Rect(0f, 6f, num, 24f), "SUPER HARD", style);
			if (Timers.MotherLeft >= 0f)
			{
				GUI.Label(new Rect(0f, 34f, num, 40f), "MOTHER: " + Mathf.CeilToInt(Timers.MotherLeft) + "s", big);
			}
			if (flash != null && Time.unscaledTime < flashUntil)
			{
				GUI.Label(new Rect(0f, (float)Screen.height * 0.3f, num, 40f), flash, big);
			}
		}
	}
}
internal static class ItemRules
{
	private static readonly HashSet<int> seenItems = new HashSet<int>();

	private static readonly HashSet<int> seenVendors = new HashSet<int>();

	private static Dictionary<string, string> extraMap;

	private static readonly Regex tierRx = new Regex("_T([2-9])(?=$|_)", RegexOptions.Compiled);

	public static void Reset()
	{
		seenItems.Clear();
		seenVendors.Clear();
		extraMap = null;
	}

	public static void SlowTick()
	{
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		Zone current = Zones.Current;
		ENT_Player val = Util.Player();
		Item_Object[] array = Object.FindObjectsByType<Item_Object>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		foreach (Item_Object val2 in array)
		{
			if ((Object)(object)val2 == (Object)null || !seenItems.Add(((Object)val2).GetInstanceID()))
			{
				continue;
			}
			try
			{
				if ((val2.itemData != null && (val2.itemData.hasBeenPickedUp || val2.itemData.inBag)) || ((Object)(object)val != (Object)null && ((Component)val2).transform.IsChildOf(((Component)val).transform)) || (Object)(object)((Component)val2).GetComponentInParent<Inventory>() != (Object)null)
				{
					continue;
				}
				string text = ItemName(val2);
				if (Cfg.CavityRoute.Value && CavityRoute.IsAmalgam(text))
				{
					Util.Debug("No Amalgamator on Super Hard: removed " + text);
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
				else if (current != Zone.Silos && current != Zone.Abyss)
				{
					seenItems.Remove(((Object)val2).GetInstanceID());
				}
				else if (current == Zone.Abyss && text.ToLowerInvariant().Contains("artifact"))
				{
					Util.Debug("Abyss: removed artifact " + text);
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
				else
				{
					if (current != Zone.Silos)
					{
						continue;
					}
					string text2 = TierOne(text);
					if (text2 == null)
					{
						continue;
					}
					GameObject val3 = Util.ItemPrefab(text2);
					if ((Object)(object)val3 == (Object)null)
					{
						Util.DebugOnce("noT1" + text2, "Silos: wanted to swap " + text + " -> " + text2 + " but no such item.");
						continue;
					}
					GameObject val4 = Util.Spawn(val3, ((Component)val2).transform.position, ((Component)val2).transform.rotation, ((Component)val2).transform.parent);
					Item_Object val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<Item_Object>() : null);
					if ((Object)(object)val5 != (Object)null)
					{
						seenItems.Add(((Object)val5).GetInstanceID());
					}
					Util.Debug("Silos: swapped " + text + " -> " + text2);
					Object.Destroy((Object)(object)((Component)val2).gameObject);
					continue;
				}
			}
			catch (Exception ex)
			{
				Util.LogOnce("item" + ((Object)val2).name, "Item rule failed on " + ((Object)val2).name + ": " + ex.Message);
			}
		}
		if (current == Zone.Silos)
		{
			FixVendors();
		}
	}

	private static void FixVendors()
	{
		ENV_Vendor_Disk[] array = Object.FindObjectsByType<ENV_Vendor_Disk>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		foreach (ENV_Vendor_Disk val in array)
		{
			if (!((Object)(object)val == (Object)null) && seenVendors.Add(((Object)val).GetInstanceID()) && !((Object)(object)val.purchaseObject == (Object)null))
			{
				Item_Object val2 = TierOneObject(val.purchaseObject);
				if ((Object)(object)val2 != (Object)null)
				{
					Util.Debug("Silos: disk vendor now sells " + ((Object)val2).name + " instead of " + ((Object)val.purchaseObject).name);
					val.purchaseObject = val2;
				}
			}
		}
		ENV_VendingMachine[] array2 = Object.FindObjectsByType<ENV_VendingMachine>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		foreach (ENV_VendingMachine val3 in array2)
		{
			if ((Object)(object)val3 == (Object)null || !seenVendors.Add(((Object)val3).GetInstanceID()) || val3.purchaseList == null)
			{
				continue;
			}
			foreach (Purchase purchase in val3.purchaseList)
			{
				if (purchase != null && !((Object)(object)purchase.itemObject == (Object)null))
				{
					Item_Object val4 = TierOneObject(purchase.itemObject);
					if ((Object)(object)val4 != (Object)null)
					{
						Util.Debug("Silos: vending machine slot " + ((Object)purchase.itemObject).name + " -> " + ((Object)val4).name);
						purchase.itemObject = val4;
					}
				}
			}
		}
	}

	private static Item_Object TierOneObject(Item_Object io)
	{
		string text = TierOne(Util.Clean(((Object)io).name));
		if (text == null)
		{
			return null;
		}
		GameObject val = Util.ItemPrefab(text);
		if (!((Object)(object)val != (Object)null))
		{
			return null;
		}
		return val.GetComponent<Item_Object>();
	}

	private static string ItemName(Item_Object io)
	{
		string text = null;
		try
		{
			if (io.itemData != null)
			{
				text = io.itemData.prefabName;
			}
		}
		catch
		{
		}
		if (string.IsNullOrEmpty(text))
		{
			text = ((Object)((Component)io).gameObject).name;
		}
		return Util.Clean(text);
	}

	public static string TierOne(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return null;
		}
		if (extraMap == null)
		{
			extraMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			string[] array = Cfg.TierOneMap.Value.Split(';', ',');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split('=');
				if (array2.Length == 2 && array2[0].Trim().Length > 0 && array2[1].Trim().Length > 0)
				{
					extraMap[array2[0].Trim()] = array2[1].Trim();
				}
			}
		}
		if (extraMap.TryGetValue(name, out var value))
		{
			return value;
		}
		if (tierRx.IsMatch(name))
		{
			return tierRx.Replace(name, "_T1");
		}
		return null;
	}
}
internal static class Mode
{
	public const string SettingId = "skmod_super";

	public const string Title = "SUPER HARD";

	private static GamemodeSetting setting;

	internal static readonly HashSet<string> HardIds = new HashSet<string>();

	internal static readonly HashSet<string> SurvivalIds = new HashSet<string>();

	private static readonly HashSet<M_Gamemode> injected = new HashSet<M_Gamemode>();

	private static float nextMenuTick;

	private static int cacheFrame = -1;

	private static bool cacheValue;

	[ThreadStatic]
	internal static bool InCheck;

	private static bool leaderboardsTouched;

	private static bool leaderboardsBefore;

	private static readonly Dictionary<M_Subregion, KeyValuePair<float, bool>> cavityBackup = new Dictionary<M_Subregion, KeyValuePair<float, bool>>();

	internal static bool Broken;

	public static string Description => "Everything at once: +20% gravity, 3-second grip, no trinkets, weaker hammer, Remains every 10 minutes, 40% Engraved Doors, red roaches always, Hard Mode + Survival on. Every zone gets nastier.";

	public static GamemodeSetting Setting => setting;

	public static void MenuTick()
	{
		if (Time.unscaledTime < nextMenuTick)
		{
			return;
		}
		nextMenuTick = Time.unscaledTime + 1f;
		try
		{
			WKAssetDatabase val = Util.Db();
			if ((Object)(object)val != (Object)null && val.gamemodeAssets != null)
			{
				foreach (M_Gamemode gamemodeAsset in val.gamemodeAssets)
				{
					EnsureInjected(gamemodeAsset);
				}
			}
			EnsureInjected(CL_GameManager.GetCurrentGamemode());
		}
		catch (Exception ex)
		{
			Util.LogOnce("menutick", "Gamemode scan failed: " + ex.Message);
		}
	}

	public static void RemoveEverywhere()
	{
		foreach (M_Gamemode item in injected)
		{
			if ((Object)(object)item != (Object)null && item.gamemodeSettings != null)
			{
				item.gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_super");
			}
		}
	}

	public static void EnsureInjected(M_Gamemode mode)
	{
		if ((Object)(object)mode == (Object)null || mode.gamemodeSettings == null)
		{
			return;
		}
		List<GamemodeSetting> gamemodeSettings = mode.gamemodeSettings;
		if (Broken)
		{
			gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_super");
		}
		else
		{
			if (gamemodeSettings.Count == 0)
			{
				return;
			}
			GamemodeSetting val = null;
			GamemodeSetting val2 = null;
			GamemodeSetting val3 = null;
			foreach (GamemodeSetting item in gamemodeSettings)
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)setting)
				{
					continue;
				}
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = item;
				}
				string text = (item.id + " " + item.title + " " + ((Object)item).name).ToLowerInvariant();
				if (text.Contains("hard"))
				{
					HardIds.Add(item.id);
					if ((Object)(object)val == (Object)null)
					{
						val = item;
					}
				}
				if (text.Contains("iron") && (Object)(object)val2 == (Object)null)
				{
					val2 = item;
				}
				if (text.Contains("surviv"))
				{
					SurvivalIds.Add(item.id);
				}
			}
			if ((Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null && !mode.allowHardmode)
			{
				return;
			}
			if (!gamemodeSettings.Any((GamemodeSetting s) => (Object)(object)s != (Object)null && s.id == "skmod_super"))
			{
				GamemodeSetting val4 = val ?? val2 ?? val3;
				if ((Object)(object)val4 == (Object)null)
				{
					return;
				}
				if ((Object)(object)setting == (Object)null)
				{
					setting = Create(val4);
				}
				gamemodeSettings.Add(setting);
			}
			if (injected.Add(mode))
			{
				Util.Debug("Added SUPER HARD to gamemode '" + mode.gamemodeName + "'. Its settings: " + string.Join(", ", (from s in gamemodeSettings
					where (Object)(object)s != (Object)null
					select s.id + " (" + s.title + ")").ToArray()));
				BlacklistTrinkets(mode);
			}
		}
	}

	private static GamemodeSetting Create(GamemodeSetting template)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		GamemodeSetting obj = Object.Instantiate<GamemodeSetting>(template);
		((Object)obj).name = "GamemodeSetting_SuperHard";
		((Object)obj).hideFlags = (HideFlags)32;
		obj.id = "skmod_super";
		obj.title = "SUPER HARD";
		obj.description = Description;
		obj.color = new Color(1f, 0.12f, 0.08f, 1f);
		obj.exclusiveSettings = new List<string>();
		obj.nameAppend = "Super Hard";
		obj.leaderboardAppendID = "superhardmod";
		obj.allowDownstream = false;
		obj.downstreamId = "";
		return obj;
	}

	private static void BlacklistTrinkets(M_Gamemode mode)
	{
		try
		{
			List<Trinket> list = new List<Trinket>();
			if ((Object)(object)mode.availableTrinkets != (Object)null && mode.availableTrinkets.trinkets != null)
			{
				list.AddRange(mode.availableTrinkets.trinkets);
			}
			WKAssetDatabase val = Util.Db();
			if ((Object)(object)val != (Object)null && val.trinketAssets != null)
			{
				list.AddRange(val.trinketAssets);
			}
			foreach (Trinket item in list)
			{
				if (!((Object)(object)item == (Object)null) && !item.isBinding)
				{
					if (item.settingBlacklist == null)
					{
						item.settingBlacklist = new List<string>();
					}
					if (!item.settingBlacklist.Contains("skmod_super"))
					{
						item.settingBlacklist.Add("skmod_super");
					}
				}
			}
		}
		catch (Exception ex)
		{
			Util.LogOnce("trinketbl", "Trinket blacklist failed: " + ex.Message);
		}
	}

	public static bool IsActive()
	{
		if (cacheFrame == Time.frameCount)
		{
			return cacheValue;
		}
		cacheFrame = Time.frameCount;
		cacheValue = false;
		try
		{
			if ((Object)(object)CL_GameManager.gMan == (Object)null)
			{
				return false;
			}
			cacheValue = IsOnFor(CL_GameManager.GetCurrentGamemode());
		}
		catch
		{
			cacheValue = false;
		}
		return cacheValue;
	}

	public static bool IsOnFor(M_Gamemode mode)
	{
		if ((Object)(object)mode == (Object)null)
		{
			return false;
		}
		if (InCheck)
		{
			return false;
		}
		InCheck = true;
		try
		{
			return mode.HasActiveSetting("skmod_super");
		}
		catch
		{
			return false;
		}
		finally
		{
			InCheck = false;
		}
	}

	public static void ApplyGlobalToggles(bool active)
	{
		try
		{
			if (active && Cfg.DisableLeaderboards.Value)
			{
				if (!leaderboardsTouched)
				{
					leaderboardsBefore = WK_Leaderboard_Core.disableLeaderboards;
					leaderboardsTouched = true;
				}
				WK_Leaderboard_Core.disableLeaderboards = true;
			}
			else if (leaderboardsTouched)
			{
				WK_Leaderboard_Core.disableLeaderboards = leaderboardsBefore;
				leaderboardsTouched = false;
			}
		}
		catch (Exception ex)
		{
			Util.LogOnce("lb", "Leaderboard toggle failed: " + ex.Message);
		}
		try
		{
			if (active)
			{
				if (cavityBackup.Count != 0)
				{
					return;
				}
				WKAssetDatabase val = Util.Db();
				if (!((Object)(object)val != (Object)null) || val.subRegionAssets == null)
				{
					return;
				}
				{
					foreach (M_Subregion subRegionAsset in val.subRegionAssets)
					{
						if (!((Object)(object)subRegionAsset == (Object)null) && (((Object)subRegionAsset).name + " " + subRegionAsset.subregionName).ToLowerInvariant().Contains("cavity"))
						{
							cavityBackup[subRegionAsset] = new KeyValuePair<float, bool>(subRegionAsset.chance, subRegionAsset.guaranteeIfNotVisited);
							subRegionAsset.chance = Mathf.Max(subRegionAsset.chance, 1f);
							subRegionAsset.guaranteeIfNotVisited = true;
							Util.Debug("Forcing body cavity route: " + ((Object)subRegionAsset).name);
						}
					}
					return;
				}
			}
			if (cavityBackup.Count <= 0)
			{
				return;
			}
			foreach (KeyValuePair<M_Subregion, KeyValuePair<float, bool>> item in cavityBackup)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					item.Key.chance = item.Value.Key;
					item.Key.guaranteeIfNotVisited = item.Value.Value;
				}
			}
			cavityBackup.Clear();
		}
		catch (Exception ex2)
		{
			Util.LogOnce("cavity", "Body cavity forcing failed: " + ex2.Message);
		}
	}
}
internal static class Patches
{
	private static int ok;

	private static int failed;

	[ThreadStatic]
	private static bool hopperHit;

	private static readonly FieldRef<DEN_Hopper_Tick, bool> tickAttached = Util.SafeFieldRef<DEN_Hopper_Tick, bool>("isAttached");

	private static readonly FieldRef<DEN_Hopper_Tick, float> tickDrained = Util.SafeFieldRef<DEN_Hopper_Tick, float>("currentBloodDrained");

	private static readonly FieldRef<DEN_Hopper_Tick, GameEntity> tickTarget = Util.SafeFieldRef<DEN_Hopper_Tick, GameEntity>("attachTarget");

	internal static bool MassPatched;

	public static void ApplyAll(Harmony h)
	{
		P(h, typeof(UI_GamemodeScreen_Panel), "FillSettings", null, "FillSettings_Pre");
		P(h, typeof(UI_GamemodeScreen), "Initialize", new Type[1] { typeof(M_Gamemode) }, "ScreenInit_Pre");
		P(h, typeof(UI_GamemodeSetting), "Initialize", new Type[2]
		{
			typeof(GamemodeSetting),
			typeof(UI_GamemodeScreen_Panel)
		}, null, null, "SettingInit_Finalizer");
		P(h, typeof(UI_GamemodeScreen_Panel), "FillSettings", null, null, null, "FillSettings_Finalizer");
		P(h, typeof(M_Gamemode), "HasActiveSetting", new Type[1] { typeof(string) }, null, "HasActiveSetting_Post");
		P(h, typeof(M_Gamemode), "GetActiveSettings", Type.EmptyTypes, null, "GetActiveSettings_Post");
		P(h, typeof(M_Gamemode), "IsHardMode", Type.EmptyTypes, null, "ModeIsHard_Post");
		P(h, typeof(CL_GameManager), "IsHardmode", Type.EmptyTypes, null, "GameIsHard_Post");
		P(h, typeof(Trinket), "Activate", null, "Trinket_Activate_Pre");
		P(h, typeof(HandItem), "TryUse", Type.EmptyTypes, "HandItemUse_Pre");
		P(h, typeof(HandItem_Buff_Grub), "Activate", Type.EmptyTypes, "HandItemUse_Pre");
		P(h, typeof(ENT_Player), "HandStamina", null, "HandStamina_Pre", "HandStamina_Post");
		P(h, typeof(ENT_Player), "Damage", new Type[1] { typeof(DamageInfo) }, "PlayerDamage_Pre", "PlayerDamage_Post");
		P(h, typeof(HandItem_Melee), "Hit", Type.EmptyTypes, "Melee_Pre", "Melee_Post");
		P(h, typeof(HandItem_Melee), "OnChargeAttackHit", null, "Melee_Pre", "Melee_Post");
		P(h, typeof(SpawnSettings), "RandomCheck", null, null, "RandomCheck_Post");
		P(h, typeof(UT_SpawnChance), "Check", Type.EmptyTypes, "SpawnChance_Pre");
		P(h, typeof(UT_EventChance), "Check", Type.EmptyTypes, "EventChance_Pre");
		P(h, typeof(UT_SpawnEntityByID), "Start", Type.EmptyTypes, "SpawnById_Pre");
		P(h, typeof(UT_SpawnEntityByID), "Spawn", Type.EmptyTypes, "SpawnById_Pre");
		P(h, typeof(SpawnTable), "GetRandomSpawnObject", Type.EmptyTypes, "SpawnTable_Pre");
		P(h, typeof(ENT_Player), "AddPerk", null, "AddPerk_Pre");
		P(h, typeof(UT_ChamberLoader), "LeaveChamber", Type.EmptyTypes, null, "LeaveChamber_Post");
		P(h, typeof(UT_BranchGenerator), "MovePlayerIntoBranch", Type.EmptyTypes, "Branch_Pre");
		P(h, typeof(CL_GameManager), "SetGameFlag", null, "SetGameFlag_Pre");
		P(h, typeof(CL_Button), "Interact", Type.EmptyTypes, null, "Button_Post");
		P(h, typeof(CL_Button), "Interact", new Type[1] { typeof(InteractionInfo) }, null, "Button_Post");
		P(h, typeof(CL_HoldButton), "Update", Type.EmptyTypes, null, "HoldButton_Post");
		P(h, typeof(DEN_Hopper_Tick), "Damage", new Type[1] { typeof(DamageInfo) }, "Tick_Damage_Pre");
		P(h, typeof(DEN_Hopper_Tick), "Detach", Type.EmptyTypes, "Tick_Detach_Pre");
		P(h, typeof(DEN_BasicDenizen), "Kill", new Type[2]
		{
			typeof(string),
			typeof(DamageInfo)
		}, "Tick_Kill_Pre");
		P(h, typeof(Denizen), "Kill", new Type[2]
		{
			typeof(string),
			typeof(DamageInfo)
		}, "Tick_Kill_Pre");
		P(h, typeof(DEN_Teeth), "Despawn", Type.EmptyTypes, "Teeth_Despawn_Pre");
		MassPatched = P(h, typeof(DEN_DeathFloor), "Update", Type.EmptyTypes, "Mass_Update_Pre");
		Plugin.Log.LogInfo((object)("Patches: " + ok + " applied, " + failed + " failed."));
	}

	private static bool P(Harmony h, Type t, string method, Type[] args, string prefix, string postfix = null, string finalizer = null)
	{
		//IL_0044: 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)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			MethodInfo methodInfo = ((args == null) ? AccessTools.Method(t, method, (Type[])null, (Type[])null) : AccessTools.Method(t, method, args, (Type[])null));
			if (methodInfo == null)
			{
				throw new MissingMethodException(t.Name, method);
			}
			h.Patch((MethodBase)methodInfo, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Patches), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Patches), postfix, (Type[])null), (HarmonyMethod)null, (finalizer == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Patches), finalizer, (Type[])null), (HarmonyMethod)null);
			ok++;
			return true;
		}
		catch (Exception ex)
		{
			failed++;
			Plugin.Log.LogWarning((object)("Could not patch " + t.Name + "." + method + ": " + ex.Message + " (that rule is off)"));
			return false;
		}
	}

	private static void FillSettings_Pre(UI_GamemodeScreen_Panel __instance)
	{
		try
		{
			Mode.EnsureInjected(__instance.GetGamemode());
		}
		catch (Exception ex)
		{
			Util.LogOnce("fill", "Inject failed: " + ex.Message);
		}
	}

	private static Exception SettingInit_Finalizer(Exception __exception, GamemodeSetting setting)
	{
		if (__exception == null)
		{
			return null;
		}
		if ((Object)(object)setting == (Object)null || setting.id != "skmod_super")
		{
			return __exception;
		}
		Plugin.Log.LogError((object)("SUPER HARD button failed to build, removing it so the menu keeps working: " + __exception));
		Mode.Broken = true;
		return null;
	}

	private static Exception FillSettings_Finalizer(Exception __exception)
	{
		if (__exception != null && !Mode.Broken && (Object)(object)Mode.Setting != (Object)null)
		{
			Plugin.Log.LogError((object)("Run setup crashed with SUPER HARD added, removing it: " + __exception));
			Mode.Broken = true;
			Mode.RemoveEverywhere();
		}
		return __exception;
	}

	private static void ScreenInit_Pre(M_Gamemode mode)
	{
		try
		{
			Mode.EnsureInjected(mode);
		}
		catch (Exception ex)
		{
			Util.LogOnce("init", "Inject failed: " + ex.Message);
		}
	}

	private static bool ForcedId(string id)
	{
		if (id != null && id != "skmod_super")
		{
			if (!Cfg.ForceHardMode.Value || !Mode.HardIds.Contains(id))
			{
				if (Cfg.ForceSurvival.Value)
				{
					return Mode.SurvivalIds.Contains(id);
				}
				return false;
			}
			return true;
		}
		return false;
	}

	private static void HasActiveSetting_Post(M_Gamemode __instance, string id, ref bool __result)
	{
		if (!__result && !Mode.InCheck && ForcedId(id) && Mode.IsOnFor(__instance))
		{
			__result = true;
		}
	}

	private static void GetActiveSettings_Post(M_Gamemode __instance, ref List<GamemodeSetting> __result)
	{
		if (Mode.InCheck || (Object)(object)__instance == (Object)null || __instance.gamemodeSettings == null || !Mode.IsOnFor(__instance))
		{
			return;
		}
		List<GamemodeSetting> list = ((__result != null) ? new List<GamemodeSetting>(__result) : new List<GamemodeSetting>());
		foreach (GamemodeSetting gamemodeSetting in __instance.gamemodeSettings)
		{
			if ((Object)(object)gamemodeSetting != (Object)null && ForcedId(gamemodeSetting.id) && !list.Contains(gamemodeSetting))
			{
				list.Add(gamemodeSetting);
			}
		}
		__result = list;
	}

	private static void ModeIsHard_Post(M_Gamemode __instance, ref bool __result)
	{
		if (!__result && Cfg.ForceHardMode.Value && !Mode.InCheck && Mode.IsOnFor(__instance))
		{
			__result = true;
		}
	}

	private static void GameIsHard_Post(ref bool __result)
	{
		if (!__result && Cfg.ForceHardMode.Value && !Mode.InCheck && Mode.IsActive())
		{
			__result = true;
		}
	}

	private static bool Trinket_Activate_Pre(Trinket __instance)
	{
		if ((Object)(object)__instance == (Object)null || __instance.isBinding || Buddy.Granting || !Mode.IsActive())
		{
			return true;
		}
		Util.Debug("Trinket blocked: " + __instance.title);
		return false;
	}

	private static void HandItemUse_Pre(HandItem __instance)
	{
		if ((Object)(object)__instance == (Object)null || !Mode.IsActive())
		{
			return;
		}
		try
		{
			Buddy.OnUse(__instance.item);
		}
		catch
		{
		}
	}

	private static void HandStamina_Pre(Hand curhand, out float __state)
	{
		__state = curhand?.gripStrength ?? (-1f);
	}

	private static void HandStamina_Post(ENT_Player __instance, Hand curhand, float __state)
	{
		if (__state < 0f || curhand == null || !Mode.IsActive())
		{
			return;
		}
		try
		{
			if (!curhand.IsHanging() || PlayerRules.HasInfiniteStamina(__instance))
			{
				return;
			}
			float gripStrengthMax = curhand.GetGripStrengthMax();
			if (!(gripStrengthMax <= 0f))
			{
				float num = __state - gripStrengthMax / Mathf.Max(0.25f, Cfg.HangSeconds.Value) * Time.deltaTime;
				if (curhand.gripStrength > num)
				{
					curhand.gripStrength = Mathf.Max(0f, num);
				}
			}
		}
		catch (Exception ex)
		{
			Util.LogOnce("stam", "Grip drain failed: " + ex.Message);
		}
	}

	private static void PlayerDamage_Post(ENT_Player __instance)
	{
		if (!hopperHit)
		{
			return;
		}
		hopperHit = false;
		if ((Object)(object)__instance == (Object)null || ((GameEntity)__instance).dead)
		{
			return;
		}
		Util.Debug("Hopper roach hit - instant death.");
		try
		{
			((GameEntity)__instance).Kill("hopper", DamageInfo.CreateDamageInfo(99999f, "hopper"));
		}
		catch (Exception ex)
		{
			Util.LogOnce("hopkill", "Hopper kill failed: " + ex.Message);
		}
	}

	private static void PlayerDamage_Pre(DamageInfo info)
	{
		hopperHit = false;
		if (info == null || !Mode.IsActive())
		{
			return;
		}
		try
		{
			GameObject val = (((Object)(object)info.sourceEntity != (Object)null) ? ((Component)info.sourceEntity).gameObject : info.sourceObject);
			string text = ((((Object)(object)val != (Object)null) ? (((Object)val).name + " " + ((Object)val.transform.root).name) : "") + " " + info.type + " " + ((info.tags != null) ? string.Join(" ", info.tags.ToArray()) : "")).ToLowerInvariant();
			Zone current = Zones.Current;
			float amount = info.amount;
			if ((Object)(object)val != (Object)null && Cfg.HopperInstakill.Value)
			{
				DEN_Hopper componentInParent = val.GetComponentInParent<DEN_Hopper>();
				if ((Object)(object)componentInParent != (Object)null && !(componentInParent is DEN_Hopper_Tick) && (((object)componentInParent).GetType() == typeof(DEN_Hopper) || ((Object)((Component)componentInParent).gameObject).name.ToLowerInvariant().Contains("hopper")))
				{
					info.amount = 99999f;
					hopperHit = true;
				}
			}
			if (current == Zone.Silos && text.Contains("sturge"))
			{
				info.amount *= Cfg.SturgeDamageMult.Value;
			}
			if (current == Zone.Pipeworks && text.Contains("steam"))
			{
				info.amount *= Cfg.SteamDamageMult.Value;
			}
			if (current == Zone.Habitation && (text.Contains("turret") || ((Object)(object)val != (Object)null && ((Object)(object)val.GetComponentInParent<DEN_Turret>() != (Object)null || (Object)(object)val.GetComponentInParent<DEN_GantryTurret>() != (Object)null))))
			{
				info.amount *= Cfg.TurretDamageMult.Value;
			}
			if (info.amount != amount)
			{
				Util.DebugOnce("dmg" + text, "Damage " + amount + " -> " + info.amount + " from: " + text);
			}
		}
		catch (Exception ex)
		{
			Util.LogOnce("pdmg", "Damage rule failed: " + ex.Message);
		}
	}

	private static bool IsHammer(HandItem_Melee m)
	{
		if ((Object)(object)m != (Object)null && ((object)m).GetType() == typeof(HandItem_Melee) && !m.banHammer)
		{
			return ((Object)((Component)m).gameObject).name.ToLowerInvariant().Contains("hammer");
		}
		return false;
	}

	private static void Melee_Pre(HandItem_Melee __instance, out Vector2 __state)
	{
		//IL_000b: 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_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		__state = new Vector2(float.NaN, float.NaN);
		if (IsHammer(__instance) && Mode.IsActive())
		{
			__state = new Vector2(__instance.damage, __instance.chargeAttackDamage);
			__instance.damage *= Cfg.HammerDamageMult.Value;
			__instance.chargeAttackDamage *= Cfg.HammerDamageMult.Value;
		}
	}

	private static void Melee_Post(HandItem_Melee __instance, Vector2 __state)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		if (!float.IsNaN(__state.x) && !((Object)(object)__instance == (Object)null))
		{
			__instance.damage = __state.x;
			__instance.chargeAttackDamage = __state.y;
		}
	}

	private static void RandomCheck_Post(SpawnSettings __instance, ref bool __result)
	{
		if (__instance == null || !Mode.IsActive())
		{
			return;
		}
		try
		{
			SpawnRules.Decide(__instance, ref __result);
		}
		catch (Exception ex)
		{
			Util.LogOnce("rc", "Spawn rule failed: " + ex.Message);
		}
	}

	private static void SpawnChance_Pre(UT_SpawnChance __instance)
	{
		if (!Mode.IsActive())
		{
			return;
		}
		try
		{
			SpawnRules.RegisterComponent((MonoBehaviour)(object)__instance, __instance.spawnSettings, (UnityEventBase)(object)__instance.onSuccess, "");
		}
		catch
		{
		}
	}

	private static void EventChance_Pre(UT_EventChance __instance)
	{
		if (!Mode.IsActive())
		{
			return;
		}
		try
		{
			SpawnRules.RegisterComponent((MonoBehaviour)(object)__instance, __instance.spawnSettings, (UnityEventBase)(object)__instance.successEvent, "");
		}
		catch
		{
		}
	}

	private static void SpawnById_Pre(UT_SpawnEntityByID __instance)
	{
		if (!Mode.IsActive())
		{
			return;
		}
		try
		{
			string extra = __instance.idToSpawn + " " + SpawnRules.PrefabDescription(__instance.idToSpawn, __instance.customDatabase);
			SpawnRules.RegisterComponent((MonoBehaviour)(object)__instance, __instance.spawnSettings, null, extra);
		}
		catch
		{
		}
	}

	private static void SpawnTable_Pre(SpawnTable __instance)
	{
		if (!Mode.IsActive())
		{
			return;
		}
		try
		{
			SpawnRules.RegisterTable(__instance);
		}
		catch
		{
		}
	}

	private static bool AddPerk_Pre(Perk perk, ref Perk __result)
	{
		if ((Object)(object)perk == (Object)null || !Cfg.CavityRoute.Value || !Mode.IsActive())
		{
			return true;
		}
		if (!CavityRoute.IsAmalgam(perk.id + " " + perk.title + " " + ((Object)perk).name))
		{
			return true;
		}
		Util.Debug("No Amalgamator on Super Hard: blocked perk " + perk.id);
		__result = null;
		return false;
	}

	private static void LeaveChamber_Post(UT_ChamberLoader __instance)
	{
		if (Mode.IsActive())
		{
			Util.Debug("Left chamber via " + (((Object)(object)__instance != (Object)null) ? ((Object)((Component)__instance).gameObject).name : "?"));
			CavityRoute.OnChamberLeft();
		}
	}

	private static void Branch_Pre(UT_BranchGenerator __instance)
	{
		if (Mode.IsActive() && !((Object)(object)__instance == (Object)null))
		{
			Util.Debug("Moving into branch from " + ((Object)((Component)__instance).gameObject).name + " (level " + (((Object)(object)__instance.currentLevel != (Object)null) ? __instance.currentLevel.levelName : "?") + ")");
		}
	}

	private static void SetGameFlag_Pre(string name, bool state)
	{
		if (Mode.IsActive() && !(name == "skmod_run_cavity_done"))
		{
			if (!name.StartsWith("unlock_"))
			{
				Util.DebugOnce("flag" + name + state, "Game flag set: " + name + " = " + state + "   [" + Zones.Where + "]");
			}
			CavityRoute.OnFlag(name, state);
		}
	}

	private static void Button_Post(CL_Button __instance)
	{
		if ((Object)(object)__instance == (Object)null || !__instance.hasBeenPressed || !Mode.IsActive())
		{
			return;
		}
		try
		{
			Timers.OnButtonPressed((Component)(object)__instance);
		}
		catch
		{
		}
	}

	private static void HoldButton_Post(CL_HoldButton __instance)
	{
		if ((Object)(object)__instance == (Object)null || !__instance.hasFinished || Zones.Current != Zone.Nest || !Mode.IsActive())
		{
			return;
		}
		try
		{
			Timers.OnButtonPressed((Component)(object)__instance);
		}
		catch
		{
		}
	}

	private static bool TickStillSucking(DEN_Hopper_Tick t)
	{
		if ((Object)(object)t == (Object)null || !Cfg.TicksHoldOn.Value || tickAttached == null || tickDrained == null)
		{
			return false;
		}
		try
		{
			if (!tickAttached.Invoke(t))
			{
				return false;
			}
			GameEntity obj = ((tickTarget != null) ? tickTarget.Invoke(t) : null);
			ENT_Player val = (ENT_Player)(object)((obj is ENT_Player) ? obj : null);
			if (val == null || ((GameEntity)val).dead || CL_GameManager.isDead())
			{
				return false;
			}
			return tickDrained.Invoke(t) < t.maxBloodDrain;
		}
		catch
		{
			return false;
		}
	}

	private static bool Tick_Damage_Pre(DEN_Hopper_Tick __instance, ref bool __result)
	{
		if (!Mode.IsActive())
		{
			return true;
		}
		if (Zones.Current != Zone.Nest && !TickStillSucking(__instance))
		{
			return true;
		}
		__result = false;
		return false;
	}

	private static bool Tick_Detach_Pre(DEN_Hopper_Tick __instance)
	{
		if (!Mode.IsActive() || !TickStillSucking(__instance))
		{
			return true;
		}
		Util.DebugOnce("tickhold" + ((Object)__instance).GetInstanceID(), "Tick won't let go until it's full.");
		return false;
	}

	private static bool Tick_Kill_Pre(Denizen __instance)
	{
		if (Mode.IsActive())
		{
			DEN_Hopper_Tick val = (DEN_Hopper_Tick)(object)((__instance is DEN_Hopper_Tick) ? __instance : null);
			if (val != null)
			{
				return !TickStillSucking(val);
			}
		}
		return true;
	}

	private static bool Teeth_Despawn_Pre()
	{
		if (!Cfg.TeethStaysUntilHidden.Value || !Mode.IsActive() || Zones.Current != Zone.Habitation)
		{
			return true;
		}
		ENT_Player val = Util.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead())
		{
			return true;
		}
		float num = 1f;
		try
		{
			num = ((GameEntity)val).GetVisibility();
		}
		catch
		{
			return true;
		}
		if (num < Cfg.HiddenVisibility.Value)
		{
			Util.Debug("Hidden (visibility " + num.ToString("0.00") + ") - Teeth may leave.");
			return true;
		}
		Util.DebugOnce("teethstay", "Teeth tried to leave but you're not hidden (visibility " + num.ToString("0.00") + ").");
		return false;
	}

	private static void Mass_Update_Pre(DEN_DeathFloor __instance)
	{
		ApplyMass(__instance);
	}

	internal static void ApplyMass(DEN_DeathFloor __instance)
	{
		if ((Object)(object)__instance == (Object)null || !Mode.IsActive())
		{
			return;
		}
		float num = Cfg.MassSpeedMult.Value;
		if (Zones.Current == Zone.Silos)
		{
			num *= Cfg.SilosMassMult.Value;
		}
		else if (Zones.Current == Zone.Nest && Zones.NestLastSection)
		{
			float num2 = 1f;
			if ((Object)(object)CL_EventManager.currentSubregion != (Object)null && CL_EventManager.currentSubregion.massSpeedMult > 0.05f)
			{
				num2 *= CL_EventManager.currentSubregion.massSpeedMult;
			}
			if ((Object)(object)CL_EventManager.currentLevel != (Object)null && CL_EventManager.currentLevel.massSpeedMult > 0.05f)
			{
				num2 *= CL_EventManager.currentLevel.massSpeedMult;
			}
			num = ((Mathf.Abs(num2 - 1f) > 0.01f) ? (1f / num2) : 1f);
		}
		if (!(Mathf.Abs(num - 1f) > 0.001f))
		{
			return;
		}
		try
		{
			__instance.SetUpdateSpeedMultiplier(num);
		}
		catch (Exception ex)
		{
			Util.LogOnce("mass", "Mass speed failed: " + ex.Message);
		}
	}
}
internal static class PlayerRules
{
	private static ENT_Player gravityPlayer;

	private static float appliedMult = 1f;

	private static float poisonTimer;

	private static bool fallKillDone;

	private static readonly FieldRef<ENT_Player, bool> infiniteStamina = Util.SafeFieldRef<ENT_Player, bool>("infiniteStamina");

	public static void Reset()
	{
		gravityPlayer = null;
		appliedMult = 1f;
		poisonTimer = 0f;
		fallKillDone = false;
	}

	public static void Tick()
	{
		ENT_Player val = Util.Player();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if ((Object)(object)gravityPlayer != (Object)(object)val)
		{
			gravityPlayer = val;
			appliedMult = Cfg.GravityMult.Value;
			val.gravity *= appliedMult;
			Util.Debug("Gravity x" + appliedMult + " -> " + val.gravity);
		}
		if (((GameEntity)val).dead || CL_GameManager.isDead())
		{
			return;
		}
		if (Zones.Current == Zone.Nest && Cfg.NestWaterDps.Value > 0f && val.IsSwimming())
		{
			poisonTimer += Time.deltaTime;
			if (poisonTimer >= 0.5f)
			{
				poisonTimer = 0f;
				float num = Mathf.Max(1f, ((GameEntity)val).maxHealth * Cfg.NestWaterDps.Value / 100f * 0.5f);
				try
				{
					((GameEntity)val).Damage(DamageInfo.CreateDamageInfo(num, "poison"));
				}
				catch (Exception ex)
				{
					Util.LogOnce("poison", "Water poison failed: " + ex.Message);
				}
			}
		}
		else
		{
			poisonTimer = 0f;
		}
		if (Zones.Current == Zone.Abyss && !fallKillDone)
		{
			float num2 = 0f;
			try
			{
				num2 = val.GetCurrentFallDistance();
			}
			catch
			{
			}
			if (num2 >= Cfg.AbyssFallDeath.Value)
			{
				fallKillDone = true;
				Util.Debug("Fell " + num2.ToString("0") + " m in the Abyss - the nightmare takes you.");
				try
				{
					((GameEntity)val).Kill("nightmare", DamageInfo.CreateDamageInfo(99999f, "nightmare"));
				}
				catch (Exception ex2)
				{
					Util.LogOnce("fallkill", "Abyss fall kill failed: " + ex2.Message);
				}
			}
		}
		if (fallKillDone && !((GameEntity)val).dead)
		{
			fallKillDone = false;
		}
	}

	public static bool HasInfiniteStamina(ENT_Player p)
	{
		if (infiniteStamina == null || (Object)(object)p == (Object)null)
		{
			return false;
		}
		try
		{
			return infiniteStamina.Invoke(p);
		}
		catch
		{
			return false;
		}
	}
}
[BepInPlugin("com.wkmods.superhardknuckle", "SuperHardKnuckle", "1.0.12")]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "com.wkmods.superhardknuckle";

	public const string NAME = "SuperHardKnuckle";

	public const string VERSION = "1.0.12";

	internal static Plugin Instance;

	internal static ManualLogSource Log;

	internal static Harmony Harmony;

	private CL_GameManager lastGameManager;

	private float nextSlowTick;

	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Cfg.Bind(((BaseUnityPlugin)this).Config);
		Harmony = new Harmony("com.wkmods.superhardknuckle");
		Patches.ApplyAll(Harmony);
		Log.LogInfo((object)"SuperHardKnuckle 1.0.12 loaded. Pick SUPER HARD next to Hard Mode / Iron Knuckle on the run setup screen.");
	}

	private void Update()
	{
		try
		{
			Mode.MenuTick();
			CL_GameManager gMan = CL_GameManager.gMan;
			if ((Object)(object)gMan != (Object)(object)lastGameManager)
			{
				lastGameManager = gMan;
				if ((Object)(object)gMan != (Object)null)
				{
					OnNewRun();
				}
			}
			bool num = Mode.IsActive();
			Mode.ApplyGlobalToggles(num);
			if (num && !((Object)(object)gMan == (Object)null))
			{
				Zones.Tick();
				PlayerRules.Tick();
				EntityRules.Tick();
				Timers.Tick();
				CavityRoute.Tick();
				Buddy.Tick();
				SilosSturges.Tick();
				RedRoaches.Tick();
				if (!Patches.MassPatched)
				{
					Patches.ApplyMass(DEN_DeathFloor.instance);
				}
				if (Time.unscaledTime >= nextSlowTick)
				{
					nextSlowTick = Time.unscaledTime + 1f;
					ItemRules.SlowTick();
				}
			}
		}
		catch (Exception ex)
		{
			Util.LogOnce("update", "Update error: " + ex);
		}
	}

	private void OnNewRun()
	{
		EntityRules.Reset();
		ItemRules.Reset();
		Timers.Reset();
		PlayerRules.Reset();
		Zones.Reset();
		CavityRoute.Reset();
		Buddy.Reset();
		SilosSturges.Reset();
		RedRoaches.Reset();
		SpawnRules.RegisterAssetOwners();
		ClearOldSavedFlags();
	}

	private static void ClearOldSavedFlags()
	{
		string[] array = new string[2] { "skmod_buddy_given", "skmod_cavity_done" };
		foreach (string text in array)
		{
			try
			{
				if (CL_GameManager.HasActiveFlag(text, false))
				{
					CL_GameManager.SetGameFlag(text, false, "", true, false);
					Log.LogInfo((object)("Cleared leftover saved flag " + text));
				}
			}
			catch
			{
			}
		}
	}

	private void OnGUI()
	{
		try
		{
			Hud.Draw();
		}
		catch (Exception ex)
		{
			Util.LogOnce("gui", "HUD error: " + ex.Message);
		}
	}
}
internal static class Cfg
{
	public static ConfigEntry<bool> DebugLog;

	public static ConfigEntry<bool> ShowHud;

	public static ConfigEntry<bool> ForceHardMode;

	public static ConfigEntry<bool> ForceSurvival;

	public static ConfigEntry<bool> DisableLeaderboards;

	public static ConfigEntry<float> GravityMult;

	public static ConfigEntry<float> HangSeconds;

	public static ConfigEntry<float> HammerDamageMult;

	public static ConfigEntry<float> EngravedDoorChance;

	public static ConfigEntry<string> RedRoachKeywords;

	public static ConfigEntry<float> RemainsInterval;

	public static ConfigEntry<float> MassSpeedMult;

	public static ConfigEntry<bool> HopperInstakill;

	public static ConfigEntry<bool> TicksHoldOn;

	public static ConfigEntry<int> RedRoachExtra;

	public static ConfigEntry<float> RedRoachSpawnSeconds;

	public static ConfigEntry<int> RedRoachMax;

	public static ConfigEntry<int> TurretExtra;

	public static ConfigEntry<int> SilosSturgeExtra;

	public static ConfigEntry<bool> BuddyEnabled;

	public static ConfigEntry<float> BuddyPetSeconds;

	public static ConfigEntry<float> SilosSturgeInterval;

	public static ConfigEntry<int> SilosSturgeMax;

	public static ConfigEntry<int> SilosBloodbugExtra;

	public static ConfigEntry<float> SilosMassMult;

	public static ConfigEntry<float> SturgeDamageMult;

	public static ConfigEntry<string> TierOneMap;

	public static ConfigEntry<int> PipeworksBarnacleExtra;

	public static ConfigEntry<int> PipeworksHopperExtra;

	public static ConfigEntry<float> SteamDamageMult;

	public static ConfigEntry<bool> CavityRoute;

	public static ConfigEntry<string> ServiceShaftKeywords;

	public static ConfigEntry<string> AmalgamKeywords;

	public static ConfigEntry<float> RatKingSpeedMult;

	public static ConfigEntry<float> TeethSpeedMult;

	public static ConfigEntry<bool> TeethStaysUntilHidden;

	public static ConfigEntry<float> HiddenVisibility;

	public static ConfigEntry<float> VentThingSpeedMult;

	public static ConfigEntry<float> TurretDamageMult;

	public static ConfigEntry<float> TurretDroneChance;

	public static ConfigEntry<int> AbyssFaceCount;

	public static ConfigEntry<float> AbyssFallDeath;

	public static ConfigEntry<int> NestBarnacleExtra;

	public static ConfigEntry<float> MotherSeconds;

	public static ConfigEntry<int> MotherButtons;

	public static ConfigEntry<float> MotherRoomRadius;

	public static ConfigEntry<float> NestWaterDps;

	public static ConfigEntry<string> NestLastSectionKeywords;

	public static void Bind(ConfigFile c)
	{
		DebugLog = c.Bind<bool>("General", "DebugLog", true, "Write what the mod changes (zones, boosted spawns, clones, replaced items) to the BepInEx log. Handy for tuning.");
		ShowHud = c.Bind<bool>("General", "ShowHud", true, "Show the small SUPER HARD label and timers on screen.");
		ForceHardMode = c.Bind<bool>("General", "ForceHardMode", true, "Super Hard always includes vanilla Hard Mode.");
		ForceSurvival = c.Bind<bool>("General", "ForceSurvival", true, "Super Hard always turns on the Survival setting (if the gamemode has one).");
		DisableLeaderboards = c.Bind<bool>("General", "DisableLeaderboards", true, "Don't submit modded Super Hard runs to the online leaderboards.");
		GravityMult = c.Bind<float>("Global", "GravityMult", 1.2f, "Player gravity multiplier (1.2 = +20%).");
		HangSeconds = c.Bind<float>("Global", "HangSeconds", 3f, "A full grip drains in this many seconds while hanging.");
		HammerDamageMult = c.Bind<float>("Global", "HammerDamageMult", 0.6f, "Hammer damage multiplier.");
		EngravedDoorChance = c.Bind<float>("Global", "EngravedDoorChance", 0.4f, "Spawn chance for Engraved Doors.");
		RedRoachKeywords = c.Bind<string>("Global", "RedRoachNames", "roach_explosive,redroach,red_roach,roach_red", "Names that count as red roaches (the game calls them Denizen_Roach_Explosive).");
		RedRoachExtra = c.Bind<int>("Global", "RedRoachExtraCopies", 3, "Extra copies of every red roach that appears.");
		RedRoachSpawnSeconds = c.Bind<float>("Global", "RedRoachSpawnSeconds", 35f, "A red roach also spawns near you this often, everywhere (0 = off).");
		RedRoachMax = c.Bind<int>("Global", "RedRoachMaxAlive", 8, "Most extra red roaches from the timer alive at once.");
		TurretExtra = c.Bind<int>("Global", "TurretExtraCopies", 2, "Extra copies of every turret, and every turret spawn chance is forced on.");
		HopperInstakill = c.Bind<bool>("Global", "HopperRoachInstakill", true, "Getting hurt by a hopper roach (Denizen_Hopper) kills you instantly, everywhere.");
		TicksHoldOn = c.Bind<bool>("Global", "TicksCantBeThrownOff", true, "Tick roaches can't be thrown off or killed while latched on - they let go only once they've drunk their fill.");
		MassSpeedMult = c.Bind<float>("Global", "MassSpeedMult", 1.6f, "Mass speed everywhere. The Silos multiplier stacks on top of this, and the Nest's last section stays at 1x.");
		RemainsInterval = c.Bind<float>("Global", "RemainsIntervalSeconds", 600f, "A Remains spawns near you every this many seconds.");
		BuddyEnabled = c.Bind<bool>("Global", "CalmingBuddy", true, "You always start with the Calming Buddy and must pet it (use it in your hand) regularly or you die.");
		BuddyPetSeconds = c.Bind<float>("Global", "CalmingBuddyPetSeconds", 300f, "Seconds you can go without petting the Calming Buddy.");
		SilosSturgeInterval = c.Bind<float>("Silos", "SturgeEverySeconds", 25f, "A Sturge spawns near you this often in the Silos (0 = off).");
		SilosSturgeMax = c.Bind<int>("Silos", "SturgeMaxAlive", 8, "Most extra Sturges from the timer alive at once.");
		SilosSturgeExtra = c.Bind<int>("Silos", "SturgeExtraCopies", 1, "Extra copies of every Sturge that appears in the Silos.");
		SilosBloodbugExtra = c.Bind<int>("Silos", "BloodbugExtra", 1, "Extra copies of every bloodbug (any variant). 1 = double.");
		SilosMassMult = c.Bind<float>("Silos", "MassSpeedMult", 0.6f, "Mass speed multiplier in the Silos.");
		SturgeDamageMult = c.Bind<float>("Silos", "SturgeDamageMult", 2f, "Sturge damage multiplier.");
		TierOneMap = c.Bind<string>("Silos", "TierOneReplacements", "Item_RebarRope=Item_Rebar", "Extra item swaps for Silos (name=replacement; ...). Anything ending _T2/_T3 is swapped to _T1 automatically.");
		PipeworksBarnacleExtra = c.Bind<int>("Pipeworks", "BarnacleExtra", 1, "Extra copies of every barnacle in Pipeworks.");
		PipeworksHopperExtra = c.Bind<int>("Pipeworks", "HopperExtra", 1, "Extra copies of every hopper roach in Pipeworks.");
		SteamDamageMult = c.Bind<float>("Pipeworks", "SteamDamageMult", 2.5f, "Steam pipe damage multiplier.");
		CavityRoute = c.Bind<bool>("Habitation", "SecurityShaftNeedsBodyCavity", true, "The Security Shaft stays sealed until you beat the Body Cavity shortcut in this run. Beating it sends you back to the Habitation break room.");
		ServiceShaftKeywords = c.Bind<string>("Habitation", "ServiceShaftLevelKeywords", "habitation_shaft_0,habitation_shaft_1,habitation_shaft_to,security", "Level names that count as the shaft behind the break-room gate (the game calls it Service Shaft). The break room (M3_Habitation_Shaft_Intro) never counts.");
		AmalgamKeywords = c.Bind<string>("Habitation", "AmalgamatorKeywords", "amalgam", "Items/perks with these names are never given out (the Amalgamator).");
		RatKingSpeedMult = c.Bind<float>("Habitation", "RatKingSpeedMult", 2.5f, "Rat King speed multiplier.");
		TeethSpeedMult = c.Bind<float>("Habitation", "TeethSpeedMult", 1.8f, "Teeth speed multiplier.");
		TeethStaysUntilHidden = c.Bind<bool>("Habitation", "TeethStaysUntilHidden", true, "Teeth won't despawn until you are hidden.");
		HiddenVisibility = c.Bind<float>("Habitation", "HiddenVisibility", 0.35f, "You count as hidden when the game's visibility value is below this.");
		VentThingSpeedMult = c.Bind<float>("Habitation", "VentThingSpeedMult", 1.8f, "Vent thing hand speed and pull multiplier.");
		TurretDamageMult = c.Bind<float>("Habitation", "TurretDamageMult", 2f, "Turret damage multiplier.");
		TurretDroneChance = c.Bind<float>("Habitation", "TurretDroneChance", 0.5f, "Chance a drone spawns next to each turret.");
		AbyssFaceCount = c.Bind<int>("Abyss", "FaceCount", 5, "How many faces hunt you in the Abyss.");
		AbyssFallDeath = c.Bind<float>("Abyss", "FallDeathMeters", 100f, "Falling this far in the Abyss kills you.");
		NestBarnacleExtra = c.Bind<int>("Nest", "BarnacleExtra", 2, "Extra copies of every barnacle in the Nest.");
		MotherSeconds = c.Bind<float>("Nest", "MotherSeconds", 30f, "Seconds you get near the Mother before she kills you.");
		MotherButtons = c.Bind<int>("Nest", "MotherSavedAfterButtons", 3, "Pressing this many different buttons in the Mother's room saves her and stops the timer.");
		MotherRoomRadius = c.Bind<float>("Nest", "MotherRoomRadius", 80f, "Buttons within this many metres of the Mother count as hers.");
		NestWaterDps = c.Bind<float>("Nest", "WaterPoisonPercentPerSecond", 8f, "Percent of max health lost per second while in Nest water.");
		NestLastSectionKeywords = c.Bind<string>("Nest", "LastSectionKeywords", "mother", "Level/subregion names that count as the Nest's last section (the final subregion always counts).");
	}
}
internal static class SpawnRules
{
	private sealed class RefEq : IEqualityComparer<SpawnSettings>
	{
		public bool Equals(SpawnSettings a, SpawnSettings b)
		{
			return a == b;
		}

		public int GetHashCode(SpawnSettings s)
		{
			return RuntimeHelpers.GetHashCode(s);
		}
	}

	private static readonly Dictionary<SpawnSettings, string> owners = new Dictionary<SpawnSettings, string>(new RefEq());

	private static string[] redRoachKeys;

	public static void RegisterAssetOwners()
	{
		redRoachKeys = null;
		try
		{
			WKAssetDatabase val = Util.Db();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (val.sessionEvents != null)
			{
				foreach (SessionEvent sessionEvent in val.sessionEvents)
				{
					if ((Object)(object)sessionEvent != (Object)null && sessionEvent.spawnSettings != null)
					{
						owners[sessionEvent.spawnSettings] = ("event " + sessionEvent.id + " " + ((Object)sessionEvent).name).ToLowerInvariant();
					}
				}
			}
			if (val.subRegionAssets != null)
			{
				foreach (M_Subregion subRegionAsset in val.subRegionAssets)
				{
					if ((Object)(object)subRegionAsset != (Object)null && subRegionAsset.spawnSettings != null)
					{
						owners[subRegionAsset.spawnSettings] = ("subregion " + ((Object)subRegionAsset).name + " " + subRegionAsset.subregionName).ToLowerInvariant();
					}
				}
			}
			if (val.perkAssets == null)
			{
				return;
			}
			foreach (Perk perkAsset in val.perkAssets)
			{
				if ((Object)(object)perkAsset != (Object)null && perkAsset.spawnSettings != null)
				{
					owners[perkAsset.spawnSettings] = ("perk " + perkAsset.id).ToLowerInvariant();
				}
			}
		}
		catch (Exception ex)
		{
			Util.LogOnce("owners", "Spawn owner scan failed: " + ex.Message);
		}
	}

	public static void RegisterComponent(MonoBehaviour c, SpawnSettings s, UnityEventBase ev, string extra)
	{
		if (!((Object)(object)c == (Object)null) && s != null && !owners.ContainsKey(s))
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(((object)c).GetType().Name).Append(' ').Append(extra)
				.Append(' ');
			Transform val = ((Component)c).transform;
			int num = 0;
			while (num < 3 && (Object)(object)val != (Object)null)
			{
				stringBuilder.Append(((Object)val).name).Append(' ');
				num++;
				val = val.parent;
			}
			if (ev != null)
			{
				DescribeEvent(ev, stringBuilder);
			}
			owners[s] = stringBuilder.ToString().ToLowerInvariant();
		}
	}

	public static void RegisterTable(SpawnTable table)
	{
		if ((Object)(object)table == (Object)null || table.spawnList == null)
		{
			return;
		}
		foreach (SpawnTableAsset spawn in table.spawnList)
		{
			if (spawn == null || spawn.spawnSettings == null || owners.ContainsKey(spawn.spawnSettings))
			{
				continue;
			}
			StringBuilder stringBuilder = new StringBuilder("table ").Append(((Object)table).name).Append(' ').Append(spawn.name)
				.Append(' ');
			if (spawn.prefabs != null)
			{
				foreach (GameObject prefab in spawn.prefabs)
				{
					if ((Object)(object)prefab != (Object)null)
					{
						DescribeHierarchy(prefab, stringBuilder);
					}
				}
			}
			owners[spawn.spawnSettings] = stringBuilder.ToString().ToLowerInvariant();
		}
	}

	public static string PrefabDescription(string id, string database)
	{
		try
		{
			GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(id, database);
			if ((Object)(object)assetGameObject == (Object)null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			DescribeHierarchy(assetGameObject, stringBuilder);
			return stringBuilder.ToString();
		}
		catch
		{
			return "";
		}
	}

	private static void DescribeEvent(UnityEventBase ev, StringBuilder sb)
	{
		int persistentEventCount = ev.GetPersistentEventCount();
		for (int i = 0; i < persistentEventCount; i++)
		{
			Object persistentTarget = ev.GetPersistentTarget(i);
			if (persistentTarget == (Object)null)
			{
				continue;
			}
			GameObject val = (GameObject)(object)((persistentTarget is GameObject) ? persistentTarget : null);
			if ((Object)(object)val == (Object)null)
			{
				Component val2 = (Component)(object)((persistentTarget is Component) ? persistentTarget : null);
				if (val2 != null)
				{
					val = val2.gameObject;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				DescribeHierarchy(val, sb);
			}
			else
			{
				sb.Append(persistentTarget.name).Append(' ');
			}
		}
	}

	private static void DescribeHierarchy(GameObject g, StringBuilder sb)
	{
		sb.Append(((Object)g).name).Append(' ');
		if (g.GetComponentsInChildren<Transform>(true).Length > 40)
		{
			return;
		}
		HashSet<string> hashSet = new HashSet<string>();
		MonoBehaviour[] componentsInChildren = g.GetComponentsInChildren<MonoBehaviour>(true);
		foreach (MonoBehaviour val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null))
			{
				if (val is GameEntity)
				{
					hashSet.Add(((object)val).GetType().Name);
				}
				UT_SpawnEntityByID val2 = (UT_SpawnEntityByID)(object)((val is UT_SpawnEntityByID) ? val : null);
				if (val2 != null)
				{
					sb.Append(val2.idToSpawn).Append(' ');
				}
			}
		}
		foreach (string item in hashSet)
		{
			sb.Append(item).Append(' ');
		}
	}

	public static void Decide(SpawnSettings s, ref bool result)
	{
		if (owners.TryGetValue(s, out var value) && !string.IsNullOrEmpty(value))
		{
			float? num = null;
			string text = null;
			if (Zones.Current == Zone.Habitation && value.Contains("cavity"))
			{
				num = 1f;
				text = "body cavity forced";
			}
			else if (IsRedRoach(value))
			{
				num = 1f;
				text = "red roach always";
			}
			else if (value.Contains("turret"))
			{
				num = 1f;
				text = "turrets always";
			}
			else if (value.Contains("engraved"))
			{
				num = Cfg.EngravedDoorChance.Value;
				text = "engraved door " + (Cfg.EngravedDoorChance.Value * 100f).ToString("0") + "%";
			}
			if (num.HasValue)
			{
				bool flag = result;
				result = num.Value >= 1f || Random.value < num.Value;
				Util.DebugOnce(text + value, "Spawn rule '" + text + "' on: " + Short(value) + " (" + flag + " -> " + result + ")");
			}
		}
	}

	public static bool IsRedRoach(string desc)
	{
		string[] array;
		if (redRoachKeys == null)
		{
			List<string> list = new List<string>();
			array = Cfg.RedRoachKeywords.Value.Split(',');
			foreach (string text in array)
			{
				if (text.Trim().Length > 0)
				{
					list.Add(text.Trim().ToLowerInvariant());
				}
			}
			redRoachKeys = list.ToArray();
		}
		array = redRoachKeys;
		foreach (string value in array)
		{
			if (desc.Contains(value))
			{
				return true;
			}
		}
		return false;
	}

	private static string Short(string s)
	{
		if (s.Length <= 160)
		{
			return s;
		}
		return s.Substring(0, 160) + "...";
	}
}
internal static class Timers
{
	public static float RemainsTimer;

	public static float MotherLeft = -1f;

	private static DEN_Mother timedMother;

	private static bool motherDone;

	private static bool motherSaved;

	private static readonly HashSet<int> motherButtons = new HashSet<int>();

	public static void Reset()
	{
		RemainsTimer = 0f;
		MotherLeft = -1f;
		timedMother = null;
		motherDone = false;
		motherSaved = false;
		motherButtons.Clear();
	}

	public static void Tick()
	{
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		ENT_Player val = Util.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || ((Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.isPaused))
		{
			return;
		}
		RemainsTimer += Time.deltaTime;
		if (RemainsTimer >= Cfg.RemainsInterval.Value)
		{
			RemainsTimer = 0f;
			SpawnRemains();
		}
		if (Zones.Current == Zone.Nest)
		{
			DEN_Mother instance = DEN_Mother.instance;
			if ((Object)(object)instance != (Object)null && ((Component)instance).gameObject.activeInHierarchy && !((GameEntity)instance).dead)
			{
				if ((Object)(object)instance != (Object)(object)timedMother)
				{
					timedMother = instance;
					MotherLeft = -1f;
					motherDone = false;
					motherSaved = false;
					motherButtons.Clear();
				}
				if (motherSaved)
				{
					MotherLeft = -1f;
					return;
				}
				float num = Vector3.Distance(((Component)val).transform.position, ((Component)instance).transform.position);
				if (MotherLeft < 0f && !motherDone && num < 35f)
				{
					MotherLeft = Cfg.MotherSeconds.Value;
					Util.Debug("Mother section: " + MotherLeft + " seconds.");
				}
				if (!(MotherLeft >= 0f))
				{
					return;
				}
				if (num > 70f)
				{
					MotherLeft = -1f;
					motherDone = true;
					Util.Debug("Made it past the Mother.");
					return;
				}
				MotherLeft -= Time.deltaTime;
				if (MotherLeft <= 0f)
				{
					MotherLeft = -1f;
					motherDone = true;
					Util.Debug("Mother timer ran out.");
					try
					{
						instance.Enrage(true);
					}
					catch (Exception ex)
					{
						Util.LogOnce("enrage", "Enrage failed: " + ex.Message);
					}
					try
					{
						instance.KillPlayer();
					}
					catch (Exception ex2)
					{
						Util.LogOnce("motherkill", "Mother kill failed: " + ex2.Message);
					}
				}
			}
			else if (MotherLeft >= 0f)
			{
				MotherLeft = -1f;
				motherDone = true;
			}
		}
		else
		{
			MotherLeft = -1f;
		}
	}

	public static void OnButtonPressed(Component button)
	{
		//IL_0037: 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)
		if ((Object)(object)button == (Object)null || motherSaved || Zones.Current != Zone.Nest)
		{
			return;
		}
		DEN_Mother instance = DEN_Mother.instance;
		if (!((Object)(object)instance == (Object)null) && !((GameEntity)instance).dead && !(Vector3.Distance(button.transform.position, ((Component)instance).transform.position) > Cfg.MotherRoomRadius.Value) && motherButtons.Add(((Object)button).GetInstanceID()))
		{
			Util.Debug("Mother's room button pressed: " + ((Object)button.gameObject).name + " (" + motherButtons.Count + "/" + Cfg.MotherButtons.Value + ")");
			if (motherButtons.Count >= Cfg.MotherButtons.Value)
			{
				motherSaved = true;
				motherDone = true;
				timedMother = instance;
				MotherLeft = -1f;
				Util.Debug("The Mother is saved - her timer stops.");
				Hud.Flash("SHE IS SAVED");
			}
		}
	}

	private unsafe static void SpawnRemains()
	{
		//IL_0047: 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)
		GameObject val = Util.FindPrefabWith<DEN_Remains_Active>();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if (!Util.SpotAroundPlayer(14f, 26f, out var pos))
		{
			RemainsTimer = Cfg.RemainsInterval.Value - 15f;
			return;
		}
		Transform parent = null;
		try
		{
			parent = WorldLoader.GetCurrentLevelParentRoot();
		}
		catch
		{
		}
		GameObject val2 = Util.Spawn(val, pos, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), parent);
		DEN_Remains_Active val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponentInChildren<DEN_Remains_Active>(true) : null);
		if ((Object)(object)val3 != (Object)null)
		{
			val3.active = true;
		}
		Util.Debug("Remains spawned at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString() + " (" + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "failed") + ")");
		Hud.Flash("Something remains...");
	}
}
internal static class Util
{
	private static readonly HashSet<string> once = new HashSet<string>();

	private static WKAssetDatabase dbCache;

	private static int dbScene = -1;

	private static CL_GameManager dbGameManager;

	private static float dbRetryAt;

	private static readonly Dictionary<Type, GameObject> prefabByType = new Dictionary<Type, GameObject>();

	private static readonly Dictionary<string, GameObject> itemByName = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

	private static readonly Dictionary<string, GameObject> prefabByName = new Dictionary<string, GameObject>();

	public static void Debug(string msg)
	{
		if (Cfg.DebugLog != null && Cfg.DebugLog.Value)
		{
			Plugin.Log.LogInfo((object)msg);
		}
	}

	public static void DebugOnce(string key, string msg)
	{
		if (once.Add("d:" + key))
		{
			Debug(msg);
		}
	}

	public static void LogOnce(string key, string msg)
	{
		if (once.Add("e:" + key))
		{
			Plugin.Log.LogWarning((object)msg);
		}
	}

	public static string Clean(string n)
	{
		if (n == null)
		{
			return "";
		}
		int num = n.IndexOf("(Clone)", StringComparison.Ordinal);
		if (num >= 0)
		{
			n = n.Substring(0, num);
		}
		return n.Trim();
	}

	public static ENT_Player Player()
	{
		try
		{
			return ENT_Player.GetPlayer();
		}
		catch
		{
			return null;
		}
	}

	public static WKAssetDatabase Db()
	{
		//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_0008: Unknown result type (might be due to invalid IL or missing references)
		Scene activeScene = SceneManager.GetActiveScene();
		int num = SceneHandle.op_Implicit(((Scene)(ref activeScene)).handle);
		if (num != dbScene || (Object)(object)CL_GameManager.gMan != (Object)(object)dbGameManager || ((Object)(object)dbCache == (Object)null && Time.unscaledTime >= dbRetryAt))
		{
			dbRetryAt = Time.unscaledTime + 5f;
			dbScene = num;
			dbGameManager = CL_GameManager.gMan;
			try
			{
				dbCache = CL_AssetManager.GetFullCombinedAssetDatabase();
			}
			catch
			{
				dbCache = null;
			}
		}
		return dbCache;
	}

	public static void ResetCaches()
	{
		prefabByType.Clear();
		itemByName.Clear();
		prefabByName.Clear();
	}

	public static GameObject FindPrefabWith<T>() where T : Component
	{
		if (prefabByType.TryGetValue(typeof(T), out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		GameObject val = null;
		try
		{
			WKAssetDatabase val2 = Db();
			if ((Object)(object)val2 != (Object)null)
			{
				val = Scan<T>(val2.denizenPrefabs) ?? Scan<T>(val2.entityPrefabs);
			}
			if ((Object)(object)val == (Object)null && (Object)(object)CL_GameManager.gMan != (Object)null && CL_GameManager.gMan.gameEntityPrefabs != null)
			{
				foreach (GameEntity gameEntityPrefab in CL_GameManager.gMan.gameEntityPrefabs)
				{
					if ((Object)(object)gameEntityPrefab != (Object)null && (Object)(object)((Component)gameEntityPrefab).GetComponentInChildren<T>(true) != (Object)null)
					{
						val = ((Component)gameEntityPrefab).gameObject;
						break;
					}
				}
			}
		}
		catch (Exception ex)
		{
			LogOnce("prefab" + typeof(T).Name, "Prefab search for " + typeof(T).Name + " failed: " + ex.Message);
		}
		prefabByType[typeof(T)] = val;
		if ((Object)(object)val == (Object)null)
		{
			LogOnce("noprefab" + typeof(T).Name, "No prefab with " + typeof(T).Name + " found, that rule is skipped.");
		}
		else
		{
			Debug("Using prefab '" + ((Object)val).name + "' for " + typeof(T).Name);
		}
		return val;
	}

	public static GameObject FindPrefabNamed(string part)
	{
		part = part.ToLowerInvariant();
		if (prefabByName.TryGetValue(part, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		GameObject val = null;
		try
		{
			WKAssetDatabase val2 = Db();
			List<List<GameObject>> list = new List<List<GameObject>>();
			if ((Object)(object)val2 != (Object)null)
			{
				list.Add(val2.denizenPrefabs);
				list.Add(val2.entityPrefabs);
			}
			foreach (List<GameObject> item in list)
			{
				if (item == null)
				{
					continue;
				}
				foreach (GameObject item2 in item)
				{
					if (!((Object)(object)item2 == (Object)null))
					{
						string text = ((Object)item2).name.ToLowerInvariant();
						if (text.Contains(part) && ((Object)(object)val == (Object)null || text == "denizen_" + part || (text.Length < ((Object)val).name.Length && ((Object)val).name.ToLowerInvariant() != "denizen_" + part)))
						{
							val = item2;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			LogOnce("pname" + part, "Prefab search for '" + part + "' failed: " + ex.Message);
		}
		prefabByName[part] = val;
		if ((Object)(object)val == (Object)null)
		{
			LogOnce("nopname" + part, "No prefab named like '" + part + "' found, that rule is skipped.");
		}
		else
		{
			Debug("Using prefab '" + ((Object)val).name + "' for '" + part + "'");
		}
		return val;
	}

	private static GameObject Scan<T>(List<GameObject> list) where T : Component
	{
		if (list == null)
		{
			return null;
		}
		foreach (GameObject item in list)
		{
			if ((Object)(object)item != (Object)null && (Object)(object)item.GetComponentInChildren<T>(true) != (Object)null)
			{
				return item;
			}
		}
		return null;
	}

	public static GameObject ItemPrefab(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return null;
		}
		if (itemByName.Count == 0)
		{
			try
			{
				WKAssetDatabase val = Db();
				if ((Object)(object)val != (Object)null && val.itemPrefabs != null)
				{
					foreach (GameObject itemPrefab in val.itemPrefabs)
					{
						if ((Object)(object)itemPrefab != (Object)null && !itemByName.ContainsKey(((Object)itemPrefab).name))
						{
							itemByName[((Object)itemPrefab).name] = itemPrefab;
						}
					}
				}
			}
			catch (Exception ex)
			{
				LogOnce("itemdb", "Item list failed: " + ex.Message);
			}
		}
		itemByName.TryGetValue(name, out var value);
		return value;
	}

	public static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot, Transform parent = null)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: 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)
		if ((Object)(object)prefab == (Object)null)
		{
			return null;
		}
		bool activeSelf = prefab.activeSelf;
		if (activeSelf)
		{
			prefab.SetActive(false);
		}
		GameObject val;
		try
		{
			val = (((Object)(object)parent != (Object)null) ? Object.Instantiate<GameObject>(prefab, pos, rot, parent) : Object.Instantiate<GameObject>(prefab, pos, rot));
		}
		finally
		{
			if (activeSelf)
			{
				prefab.SetActive(true);
			}
		}
		((Object)val).name = Clean(((Object)prefab).name);
		val.SetActive(true);
		return val;
	}

	public static Vector3 NearbySpot(Transform t)
	{
		//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)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: 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_0060: 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_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//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_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: 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_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: 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_0162: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = t.position;
		Vector3 up = t.up;
		float num = 0.05f;
		bool flag = false;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(position + up * 0.5f, -up, ref val, 3f, -1, (QueryTriggerInteraction)1) && !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(t))
		{
			flag = true;
			num = Mathf.Max(0.02f, Vector3.Dot(position - ((RaycastHit)(ref val)).point, ((RaycastHit)(ref val)).normal));
		}
		RaycastHit val4 = default(RaycastHit);
		RaycastHit val5 = default(RaycastHit);
		for (int i = 0; i < 12; i++)
		{
			Vector3 val2 = Random.onUnitSphere;
			val2 -= Vector3.Project(val2, up);
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
			{
				continue;
			}
			((Vector3)(ref val2)).Normalize();
			Vector3 val3 = position + val2 * Random.Range(1.5f, 4f);
			if (!Physics.Linecast(position + up * 0.3f, val3 + up * 0.3f, ref val4, -1, (QueryTriggerInteraction)1) || ((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(t))
			{
				if (!flag)
				{
					return val3;
				}
				if (Physics.Raycast(val3 + up * 1f, -up, ref val5, 4f, -1, (QueryTriggerInteraction)1) && !((Component)((RaycastHit)(ref val5)).collider).transform.IsChildOf(t))
				{
					return ((RaycastHit)(ref val5)).point + ((RaycastHit)(ref v

ExtremeKnuckle.dll

Decompiled 2 hours 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.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ExtremeKnuckle;

public class AlwaysHunterTag : MonoBehaviour
{
}
public static class Chaser
{
	public const float FirstDelay = 20f;

	public const float RespawnDelay = 25f;

	public const float SpeedFactor = 0.55f;

	private const float TooFar = 160f;

	private static DEN_Hunter hunter;

	private static GameObject prefab;

	private static float baseSpeed;

	private static float spawnAt = -1f;

	private static float farTime;

	private static bool warnedNoPrefab;

	public static void Reset()
	{
		hunter = null;
		spawnAt = Time.time + 20f;
		farTime = 0f;
	}

	public static bool Is(GameObject g)
	{
		if ((Object)(object)g != (Object)null)
		{
			return (Object)(object)g.GetComponent<AlwaysHunterTag>() != (Object)null;
		}
		return false;
	}

	public static void Tick()
	{
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		ENT_Player val = Ext.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || Ext.Paused())
		{
			return;
		}
		if (spawnAt < 0f)
		{
			spawnAt = Time.time + 20f;
		}
		if (!((Object)(object)hunter != (Object)null) || ((GameEntity)hunter).dead || !((Component)hunter).gameObject.activeInHierarchy)
		{
			if ((Object)(object)hunter != (Object)null)
			{
				hunter = null;
				spawnAt = Time.time + 25f;
				Ext.Debug("The Hunter is gone... for now.");
			}
			if (Time.time >= spawnAt)
			{
				Spawn(val);
			}
			return;
		}
		try
		{
			float num = baseSpeed * 0.55f;
			hunter.speedIncreaseRate = 0f;
			hunter.startSpeed = num;
			if (R.Get(hunter, "curSpeed", 0f) > num)
			{
				R.Set(hunter, "curSpeed", num);
			}
			R.Set(hunter, "active", true);
			((Denizen)hunter).diesInMass = false;
		}
		catch
		{
		}
		float num2 = Vector3.Distance(((Component)hunter).transform.position, ((Component)val).transform.position);
		farTime = ((num2 > 160f) ? (farTime + Time.deltaTime) : 0f);
		if (!(farTime > 8f))
		{
			return;
		}
		farTime = 0f;
		if (!SHB.Util.SpotAroundPlayer(45f, 70f, out var pos))
		{
			return;
		}
		try
		{
			((Component)hunter).transform.position = pos;
			hunter.WipeTrackPositions();
			hunter.ResetSegments();
			Ext.Debug("The Hunter caught up with you (" + num2.ToString("0") + " m away).");
		}
		catch (Exception ex)
		{
			Ext.LogOnce("hunttp", "Hunter catch-up failed: " + ex.Message);
		}
	}

	private static void Spawn(ENT_Player p)
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		spawnAt = Time.time + 5f;
		if ((Object)(object)prefab == (Object)null)
		{
			prefab = FindPrefab();
		}
		if ((Object)(object)prefab == (Object)null)
		{
			if (!warnedNoPrefab)
			{
				warnedNoPrefab = true;
				Plugin.Log.LogWarning((object)"EXTREME: couldn't find a Hunter prefab, the always-on Hunter is off for now (will keep looking).");
			}
			return;
		}
		if (!SHB.Util.SpotAroundPlayer(40f, 60f, out var pos))
		{
			pos = ((Component)p).transform.position - ((Component)p).transform.forward * 45f + Vector3.down * 10f;
		}
		try
		{
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity);
			((Object)val).name = "EXTREME_Hunter";
			val.AddComponent<AlwaysHunterTag>();
			val.SetActive(true);
			SHB.EntityRules.MarkSpawned(val);
			hunter = val.GetComponent<DEN_Hunter>() ?? val.GetComponentInChildren<DEN_Hunter>(true);
			if ((Object)(object)hunter == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				Ext.LogOnce("nohunt", "Hunter prefab has no DEN_Hunter on it.");
				return;
			}
			baseSpeed = ((hunter.startSpeed > 0.01f) ? hunter.startSpeed : 5f);
			hunter.startSpeed = baseSpeed * 0.55f;
			hunter.speedIncreaseRate = 0f;
			R.Set(hunter, "active", true);
			((Denizen)hunter).diesInMass = false;
			SHB.Hud.Flash("IT'S FOLLOWING YOU");
			Ext.Debug("The always-on Hunter spawned " + Vector3.Distance(pos, ((Component)p).transform.position).ToString("0") + " m away (speed x" + 0.55f + ").");
		}
		catch (Exception ex)
		{
			Ext.LogOnce("huntspawn", "Hunter spawn failed: " + ex);
		}
	}

	private static GameObject FindPrefab()
	{
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			UT_Hunter_Controller[] array = Resources.FindObjectsOfTypeAll<UT_Hunter_Controller>();
			foreach (UT_Hunter_Controller val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.hunterPrefab != (Object)null)
				{
					return ((Component)val.hunterPrefab).gameObject;
				}
			}
			WKAssetDatabase val2 = SHB.Util.Db();
			if ((Object)(object)val2 != (Object)null)
			{
				List<GameObject>[] array2 = new List<GameObject>[2] { val2.denizenPrefabs, val2.entityPrefabs };
				foreach (List<GameObject> list in array2)
				{
					if (list == null)
					{
						continue;
					}
					foreach (GameObject item in list)
					{
						object obj = ((item is GameObject) ? item : null);
						if (obj == null)
						{
							GameObject obj2 = ((item is Component) ? item : null);
							obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
						}
						GameObject val3 = (GameObject)obj;
						if ((Object)(object)val3 != (Object)null && (Object)(object)val3.GetComponentInChildren<DEN_Hunter>(true) != (Object)null)
						{
							return val3;
						}
					}
				}
			}
			GameObject val4 = SHB.Util.FindPrefabWith<DEN_Hunter>() ?? SHB.Util.FindPrefabNamed("Hunter");
			if ((Object)(object)val4 != (Object)null && (Object)(object)val4.GetComponentInChildren<DEN_Hunter>(true) != (Object)null)
			{
				return val4;
			}
			DEN_Hunter[] array3 = Resources.FindObjectsOfTypeAll<DEN_Hunter>();
			foreach (DEN_Hunter val5 in array3)
			{
				if ((Object)(object)val5 != (Object)null)
				{
					Scene scene = ((Component)val5).gameObject.scene;
					if (!((Scene)(ref scene)).IsValid() && !Is(((Component)val5).gameObject))
					{
						return ((Component)val5).gameObject;
					}
				}
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("huntfind", "Hunter prefab search failed: " + ex.Message);
		}
		return null;
	}
}
public static class Drones
{
	private static int extraThisZone;

	private static SHB.Zone lastZone;

	private const int MaxPerZone = 12;

	public static void OnTurret(GameEntity turret)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		if (Ext.Zone != lastZone)
		{
			lastZone = Ext.Zone;
			extraThisZone = 0;
		}
		if (Ext.Zone != SHB.Zone.Habitation || (Object)(object)turret == (Object)null || SHB.EntityRules.IsClone(((Component)turret).gameObject) || extraThisZone >= 12 || Random.value >= 0.5f)
		{
			return;
		}
		try
		{
			GameObject val = SHB.Util.FindPrefabWith<DEN_Drone>();
			if ((Object)(object)val == (Object)null)
			{
				Ext.DebugOnce("nodrone", "No drone prefab found for the second drone.");
				return;
			}
			Transform transform = ((Component)turret).transform;
			Vector3 pos = transform.position + Vector3.up * 2.5f + Random.insideUnitSphere * 1.5f;
			GameObject val2 = SHB.Util.Spawn(val, pos, Quaternion.identity, transform.parent);
			if ((Object)(object)val2 != (Object)null)
			{
				SHB.EntityRules.MarkSpawned(val2);
				extraThisZone++;
				Ext.Debug("Second drone next to turret " + ((Object)((Component)turret).gameObject).name);
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("drone2", "Second drone failed: " + ex.Message);
		}
	}
}
public class ExtremeTag : MonoBehaviour
{
}
public class EntityRule
{
	public string Name;

	public Tune Tune = new Tune();

	public int ExtraCopies;

	public bool Escalates = true;

	public Action<GameEntity> Custom;
}
public static class EntityTuner
{
	private static readonly HashSet<int> seen = new HashSet<int>();

	private static int copiesThisSubregion;

	private static string lastWhere = "";

	private const int MaxCopiesPerSubregion = 90;

	public static bool PendingBonusCopy;

	public static readonly List<GameEntity> RecentHostiles = new List<GameEntity>();

	public static void Reset()
	{
		seen.Clear();
		copiesThisSubregion = 0;
		lastWhere = "";
		PendingBonusCopy = false;
		RecentHostiles.Clear();
	}

	public static void Scan()
	{
		List<GameEntity> entities = GameEntity.entities;
		if (entities == null)
		{
			return;
		}
		string text = Ext.Where;
		if (text != lastWhere)
		{
			lastWhere = text;
			copiesThisSubregion = 0;
		}
		GameEntity[] array = entities.ToArray();
		foreach (GameEntity val in array)
		{
			if ((Object)(object)val == (Object)null || val is ENT_Player)
			{
				continue;
			}
			GameObject gameObject = ((Component)val).gameObject;
			if (!((Object)(object)gameObject == (Object)null) && seen.Add(((Object)gameObject).GetInstanceID()))
			{
				try
				{
					OnNew(val);
				}
				catch (Exception ex)
				{
					Ext.LogOnce("ent" + ((object)val).GetType().Name, "EXTREME rule for " + ((object)val).GetType().Name + " failed: " + ex.Message);
				}
			}
		}
		RecentHostiles.RemoveAll((GameEntity x) => (Object)(object)x == (Object)null || x.dead);
	}

	private static void OnNew(GameEntity e)
	{
		GameObject gameObject = ((Component)e).gameObject;
		if (Chaser.Is(gameObject))
		{
			return;
		}
		bool flag = (Object)(object)gameObject.GetComponent<ExtremeTag>() != (Object)null;
		bool flag2 = SHB.EntityRules.IsClone(gameObject);
		string n = ((Object)gameObject).name.ToLowerInvariant();
		EntityRule entityRule = Rules.For(e, n, Ext.Zone);
		if (entityRule == null)
		{
			return;
		}
		if (!flag2 && !flag)
		{
			int num = entityRule.ExtraCopies;
			if (PendingBonusCopy && num >= 0 && Rules.IsHostile(e))
			{
				PendingBonusCopy = false;
				if (Random.value < 0.5f)
				{
					num++;
					Ext.Debug("Anti-camping bonus copy for " + ((Object)gameObject).name);
				}
			}
			if (num > 0)
			{
				MakeCopies(e, num, entityRule.Name);
			}
		}
		if (!flag)
		{
			Tune tune = entityRule.Tune;
			if (entityRule.Escalates)
			{
				float num2 = Ext.EscalationBonus();
				if (num2 > 0f)
				{
					Tune tune2 = new Tune
					{
						Speed = tune.Speed * (1f + num2),
						Detect = tune.Detect,
						Time = tune.Time,
						Damage = tune.Damage
					};
					foreach (KeyValuePair<string, float> item in tune.Extra)
					{
						tune2.Extra[item.Key] = item.Value;
					}
					foreach (string item2 in tune.Skip)
					{
						tune2.Skip.Add(item2);
					}
					tune = tune2;
				}
			}
			int num3 = Tuner.Apply(e, tune);
			_ = ((AIGameEntity)(((e is AIGameEntity) ? e : null)?)).sight;
			num3 += Tuner.ApplyPathfinding(gameObject, tune.Speed);
			entityRule.Custom?.Invoke(e);
			gameObject.AddComponent<ExtremeTag>();
			Ext.DebugOnce("tune" + entityRule.Name + Ext.Zone, "Tuned " + entityRule.Name + " (" + ((Object)gameObject).name + ", " + ((object)e).GetType().Name + ") in " + Ext.Zone.ToString() + ": speed x" + tune.Speed.ToString("0.##") + ", detection x" + tune.Detect.ToString("0.##") + ", timing x" + tune.Time.ToString("0.##") + ", damage x" + tune.Damage.ToString("0.##") + " (" + num3 + " fields)");
		}
		if (Rules.IsHostile(e))
		{
			RecentHostiles.Add(e);
		}
		DEN_Strider val = (DEN_Strider)(object)((e is DEN_Strider) ? e : null);
		if (val != null)
		{
			Striders.Track(val);
		}
	}

	public static void MakeCopies(GameEntity e, int count, string why)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if (copiesThisSubregion >= 90)
		{
			Ext.DebugOnce("cap" + lastWhere, "Extra-copy cap reached for this area (" + 90 + ").");
			return;
		}
		count = Mathf.Min(count, 90 - copiesThisSubregion);
		GameObject gameObject = ((Component)e).gameObject;
		Transform transform = ((Component)e).transform;
		int num = 0;
		for (int i = 0; i < count; i++)
		{
			try
			{
				Vector3 val = SHB.Util.NearbySpot(transform);
				GameObject obj = Object.Instantiate<GameObject>(gameObject, val, transform.rotation, transform.parent);
				((Object)obj).name = ((Object)gameObject).name;
				obj.SetActive(gameObject.activeSelf);
				SHB.EntityRules.MarkSpawned(obj);
				num++;
			}
			catch (Exception ex)
			{
				Ext.LogOnce("copy" + why, "Copy of " + why + " failed: " + ex.Message);
				break;
			}
		}
		copiesThisSubregion += num;
		if (num > 0)
		{
			Ext.Debug("+" + num + " " + why + " (" + ((Object)gameObject).name + ") in " + Ext.Zone);
		}
	}

	public unsafe static GameObject SpawnNearPlayer(GameObject source, float min, float max, string why)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)source == (Object)null)
		{
			return null;
		}
		if (!SHB.Util.SpotAroundPlayer(min, max, out var pos))
		{
			return null;
		}
		GameObject val = Object.Instantiate<GameObject>(source, pos, Quaternion.identity, source.transform.parent);
		((Object)val).name = ((Object)source).name;
		val.SetActive(true);
		SHB.EntityRules.MarkSpawned(val);
		Ext.Debug(why + ": " + ((Object)source).name + " at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString());
		return val;
	}
}
public static class Ext
{
	public const string SettingId = "skmod_extreme";

	public const string Title = "EXTREME";

	private static GamemodeSetting setting;

	private static readonly HashSet<M_Gamemode> injected = new HashSet<M_Gamemode>();

	public static bool Broken;

	private static float nextMenuTick;

	private static int cacheFrame = -1;

	private static bool cacheValue;

	[ThreadStatic]
	private static bool inCheck;

	private static ProgressionUnlock safeUnlock;

	private static string lastRegionKey = "";

	private static string lastSubKey = "";

	public static float RegionTime;

	public static float SubregionTime;

	private static readonly HashSet<string> once = new HashSet<string>();

	public static string Description => "The hardest run possible. Includes SUPER HARD, Hard Mode, Survival and Iron Knuckle. +50% gravity, half health, a Hunter that never stops chasing you, 1-minute Calming Buddy, swarms of red roaches and turrets, a 2.2x Mass, faster and deadlier enemies in every zone, 3x vendor prices, no trinkets, no shortcuts.";

	public static SHB.Zone Zone => SHB.Zones.Current;

	public static string Where => (SHB.Zones.Where ?? "").ToLowerInvariant();

	public static bool SelectedFor(M_Gamemode mode)
	{
		if ((Object)(object)mode == (Object)null || StatManager.saveData == null || inCheck)
		{
			return false;
		}
		inCheck = true;
		try
		{
			GameModeData gameMode = StatManager.saveData.GetGameMode(mode.gamemodeName);
			return gameMode != null && gameMode.activeSettings != null && gameMode.activeSettings.Contains("skmod_extreme");
		}
		catch
		{
			return false;
		}
		finally
		{
			inCheck = false;
		}
	}

	public static bool IsOn()
	{
		if (cacheFrame == Time.frameCount)
		{
			return cacheValue;
		}
		cacheFrame = Time.frameCount;
		cacheValue = false;
		try
		{
			if ((Object)(object)CL_GameManager.gMan == (Object)null)
			{
				return false;
			}
			cacheValue = SelectedFor(CL_GameManager.GetCurrentGamemode()) || SelectedFor(CL_GameManager.GetBaseGamemode());
		}
		catch
		{
			cacheValue = false;
		}
		return cacheValue;
	}

	public static bool IsForcedId(string id)
	{
		if (!string.IsNullOrEmpty(id))
		{
			switch (id)
			{
			case "skmod_extreme":
				break;
			case "skmod_super":
			case "hardmode":
				return true;
			default:
				try
				{
					if (SHB.Mode.HardIds.Contains(id) || SHB.Mode.SurvivalIds.Contains(id))
					{
						return true;
					}
				}
				catch
				{
				}
				return false;
			}
		}
		return false;
	}

	public static void IsSettingActive_Post(SaveData __instance, string gameModeName, string settingID, ref bool __result)
	{
		if (__result || inCheck)
		{
			return;
		}
		inCheck = true;
		try
		{
			if (IsForcedId(settingID))
			{
				GameModeData gameMode = __instance.GetGameMode(gameModeName);
				if (gameMode != null && gameMode.activeSettings != null && gameMode.activeSettings.Contains("skmod_extreme"))
				{
					__result = true;
				}
			}
		}
		catch
		{
		}
		finally
		{
			inCheck = false;
		}
	}

	public static void MenuTick()
	{
		if (Time.unscaledTime < nextMenuTick)
		{
			return;
		}
		nextMenuTick = Time.unscaledTime + 1f;
		try
		{
			WKAssetDatabase val = SHB.Util.Db();
			if ((Object)(object)val != (Object)null && val.gamemodeAssets != null)
			{
				foreach (M_Gamemode gamemodeAsset in val.gamemodeAssets)
				{
					EnsureInjected(gamemodeAsset);
				}
			}
			EnsureInjected(CL_GameManager.GetCurrentGamemode());
		}
		catch (Exception ex)
		{
			LogOnce("menutick", "Gamemode scan failed: " + ex.Message);
		}
	}

	public static void EnsureInjected(M_Gamemode mode)
	{
		if ((Object)(object)mode == (Object)null || mode.gamemodeSettings == null)
		{
			return;
		}
		List<GamemodeSetting> gamemodeSettings = mode.gamemodeSettings;
		if (Broken || SHB.Mode.Broken)
		{
			gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_extreme");
			return;
		}
		int num = gamemodeSettings.FindIndex((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_super");
		if (num < 0)
		{
			return;
		}
		if (!gamemodeSettings.Any((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_extreme"))
		{
			if ((Object)(object)setting == (Object)null)
			{
				setting = Create(gamemodeSettings[num]);
			}
			if ((Object)(object)setting == (Object)null)
			{
				return;
			}
			gamemodeSettings.Insert(num + 1, setting);
		}
		if (injected.Add(mode))
		{
			Debug("Added EXTREME to gamemode '" + mode.gamemodeName + "'.");
		}
	}

	private static GamemodeSetting Create(GamemodeSetting template)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		GamemodeSetting obj = Object.Instantiate<GamemodeSetting>(template);
		((Object)obj).name = "GamemodeSetting_Extreme";
		((Object)obj).hideFlags = (HideFlags)32;
		obj.id = "skmod_extreme";
		obj.title = "EXTREME";
		obj.description = Description;
		obj.color = new Color(0.55f, 0f, 0f, 1f);
		obj.exclusiveSettings = new List<string>();
		obj.nameAppend = "Extreme";
		obj.leaderboardAppendID = "extrememod";
		obj.allowDownstream = false;
		obj.downstreamId = "";
		obj.unlock = SafeUnlock();
		return obj;
	}

	public static ProgressionUnlock SafeUnlock()
	{
		if ((Object)(object)safeUnlock != (Object)null)
		{
			return safeUnlock;
		}
		safeUnlock = ScriptableObject.CreateInstance<ProgressionUnlock>();
		((Object)safeUnlock).name = "Unlock_ModSetting";
		((Object)safeUnlock).hideFlags = (HideFlags)32;
		safeUnlock.id = "skmod_unlock";
		safeUnlock.unlockRequirements = new List<UnlockRequirement>();
		safeUnlock.state = true;
		safeUnlock.unlockHint = "";
		safeUnlock.unlockTitle = "";
		safeUnlock.unlockDescription = "";
		safeUnlock.showProgression = false;
		return safeUnlock;
	}

	public static void Sanitize(GamemodeSetting s)
	{
		if (!((Object)(object)s == (Object)null))
		{
			bool flag = s.id == "skmod_extreme" || s.id == "skmod_super";
			if ((Object)(object)s.unlock == (Object)null || (flag && s.unlock.unlockRequirements == null))
			{
				s.unlock = SafeUnlock();
			}
			if (s.unlock.unlockRequirements == null)
			{
				s.unlock.unlockRequirements = new List<UnlockRequirement>();
			}
			if (s.title == null)
			{
				s.title = s.id ?? "";
			}
			if (s.description == null)
			{
				s.description = "";
			}
			if (s.exclusiveSettings == null)
			{
				s.exclusiveSettings = new List<string>();
			}
		}
	}

	public static bool SafeFillSettings(UI_GamemodeScreen_Panel panel)
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		M_Gamemode gamemode;
		try
		{
			gamemode = panel.GetGamemode();
			try
			{
				EnsureInjected(gamemode);
			}
			catch (Exception ex)
			{
				LogOnce("fill", "EXTREME inject failed: " + ex.Message);
			}
			if ((Object)(object)gamemode == (Object)null || gamemode.gamemodeSettings == null || (Object)(object)panel.settingRoot == (Object)null)
			{
				return true;
			}
		}
		catch (Exception ex2)
		{
			LogOnce("fillpre", "Run setup pre-check failed, using the game's own code: " + ex2.Message);
			return true;
		}
		try
		{
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in panel.settingRoot)
			{
				Transform val = item;
				list.Add(((Component)val).gameObject);
			}
			foreach (GameObject item2 in list)
			{
				Object.Destroy((Object)(object)item2);
			}
		}
		catch (Exception ex3)
		{
			LogOnce("filldel", "Clearing old setting buttons failed: " + ex3.Message);
		}
		GamemodeSetting[] array = gamemode.gamemodeSettings.ToArray();
		foreach (GamemodeSetting val2 in array)
		{
			if ((Object)(object)val2 == (Object)null)
			{
				gamemode.gamemodeSettings.Remove(val2);
				continue;
			}
			UI_GamemodeSetting val3 = null;
			try
			{
				Sanitize(val2);
				UI_GamemodeSetting val4 = (((Object)(object)val2.gamemodeButtonAsset != (Object)null) ? val2.gamemodeButtonAsset : panel.gamemodeSettingAsset);
				if ((Object)(object)val4 == (Object)null)
				{
					LogOnce("noasset" + val2.id, "No button asset for setting " + val2.id);
					continue;
				}
				val3 = Object.Instantiate<UI_GamemodeSetting>(val4, panel.settingRoot);
				val3.Initialize(val2, panel);
			}
			catch (Exception ex4)
			{
				Plugin.Log.LogError((object)("Setting button '" + val2.id + "' failed to build (the run setup screen still opens): " + ex4));
				if (val2.id == "skmod_extreme" || val2.id == "skmod_super")
				{
					if ((Object)(object)val3 != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)val3).gameObject);
					}
					if (val2.id == "skmod_extreme")
					{
						Broken = true;
						RemoveEverywhere();
					}
				}
			}
		}
		return false;
	}

	public static void RemoveEverywhere()
	{
		foreach (M_Gamemode item in injected)
		{
			if ((Object)(object)item != (Object)null && item.gamemodeSettings != null)
			{
				item.gamemodeSettings.RemoveAll((GamemodeSetting x) => (Object)(object)x != (Object)null && x.id == "skmod_extreme");
			}
		}
	}

	public static bool InSafeRoom()
	{
		string text = Where;
		if (!text.Contains("safe") && !text.Contains("break room"))
		{
			return text.Contains("breakroom");
		}
		return true;
	}

	public static bool Sub(params string[] keys)
	{
		string text = Where;
		for (int i = 0; i < keys.Length; i++)
		{
			if (text.Contains(keys[i]))
			{
				return true;
			}
		}
		return false;
	}

	public static void ResetRegion()
	{
		lastRegionKey = (lastSubKey = "");
		RegionTime = (SubregionTime = 0f);
	}

	public static void TrackRegion()
	{
		string text = (((Object)(object)CL_EventManager.currentRegion != (Object)null) ? ((Object)CL_EventManager.currentRegion).name : "");
		string text2 = (((Object)(object)CL_EventManager.currentSubregion != (Object)null) ? ((Object)CL_EventManager.currentSubregion).name : "");
		if (text != lastRegionKey)
		{
			lastRegionKey = text;
			RegionTime = 0f;
		}
		if (text2 != lastSubKey)
		{
			lastSubKey = text2;
			SubregionTime = 0f;
		}
		if ((Object)(object)CL_GameManager.gMan != (Object)null && !CL_GameManager.gMan.isPaused)
		{
			RegionTime += Time.deltaTime;
			SubregionTime += Time.deltaTime;
		}
	}

	public static float EscalationBonus()
	{
		return Zone switch
		{
			SHB.Zone.Pipeworks => 0.1f, 
			SHB.Zone.Habitation => 0.2f, 
			SHB.Zone.Abyss => 0.3f, 
			SHB.Zone.Nest => 0.4f, 
			_ => 0f, 
		};
	}

	public static void Debug(string msg)
	{
		if (Plugin.DebugLog == null || Plugin.DebugLog.Value)
		{
			Plugin.Log.LogInfo((object)("[EXTREME] " + msg));
		}
	}

	public static void DebugOnce(string key, string msg)
	{
		if (once.Add(key))
		{
			Debug(msg);
		}
	}

	public static void LogOnce(string key, string msg)
	{
		if (once.Add("!" + key))
		{
			Plugin.Log.LogWarning((object)msg);
		}
	}

	public static ENT_Player Player()
	{
		return SHB.Util.Player();
	}

	public static bool PlayerAlive()
	{
		ENT_Player val = Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead)
		{
			return false;
		}
		try
		{
			if (CL_GameManager.isDead())
			{
				return false;
			}
		}
		catch
		{
		}
		return true;
	}

	public static bool Paused()
	{
		if ((Object)(object)CL_GameManager.gMan != (Object)null)
		{
			return CL_GameManager.gMan.isPaused;
		}
		return false;
	}

	public static string Describe(DamageInfo info, out GameObject src)
	{
		src = (((Object)(object)info.sourceEntity != (Object)null) ? ((Component)info.sourceEntity).gameObject : info.sourceObject);
		string text = (((Object)(object)src != (Object)null) ? (((Object)src).name + " " + ((Object)src.transform.root).name) : "");
		text = text + " " + info.type;
		if (info.tags != null && info.tags.Count > 0)
		{
			text = text + " " + string.Join(" ", info.tags.ToArray());
		}
		return text.ToLowerInvariant();
	}
}
public static class Items
{
	private static readonly HashSet<int> seenItems = new HashSet<int>();

	private static readonly HashSet<int> pricedVendors = new HashSet<int>();

	private static readonly HashSet<int> stockedVendors = new HashSet<int>();

	private static readonly string[] Banned = new string[7] { "amalgam", "revive", "extralife", "extra_life", "extra life", "1up", "oneup" };

	private static readonly string[] Critical = new string[20]
	{
		"key", "card", "fuse", "valve", "crank", "battery", "part", "quest", "artifact", "mother",
		"door", "lever", "progress", "story", "piton", "rebar", "rope", "hammer", "grapple", "buddy"
	};

	private static readonly string[] Consumable = new string[15]
	{
		"item_", "pill", "injector", "food", "ration", "bandage", "medkit", "heal", "flare", "soda",
		"can_", "candy", "snack", "drink", "battery"
	};

	public static void Reset()
	{
		seenItems.Clear();
		pricedVendors.Clear();
		stockedVendors.Clear();
	}

	private static bool HasAny(string s, string[] keys)
	{
		foreach (string value in keys)
		{
			if (s.Contains(value))
			{
				return true;
			}
		}
		return false;
	}

	public static void SlowTick()
	{
		ENT_Player val = Ext.Player();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Item_Object[] array = Object.FindObjectsByType<Item_Object>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		foreach (Item_Object val2 in array)
		{
			if ((Object)(object)val2 == (Object)null || !seenItems.Add(((Object)val2).GetInstanceID()))
			{
				continue;
			}
			try
			{
				if ((val2.itemData == null || (!val2.itemData.hasBeenPickedUp && !val2.itemData.inBag)) && !((Component)val2).transform.IsChildOf(((Component)val).transform))
				{
					string text = SHB.ItemRules.ItemName(val2).ToLowerInvariant();
					if (HasAny(text, Banned))
					{
						Ext.Debug("Removed " + text + " (not allowed in EXTREME)");
						Object.Destroy((Object)(object)((Component)val2).gameObject);
					}
				}
			}
			catch
			{
			}
		}
		ENV_Vendor_Disk[] array2 = Object.FindObjectsByType<ENV_Vendor_Disk>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		foreach (ENV_Vendor_Disk val3 in array2)
		{
			if ((Object)(object)val3 != (Object)null && pricedVendors.Add(((Object)val3).GetInstanceID()))
			{
				val3.cost *= 3;
				Ext.DebugOnce("diskv", "Disk vendor prices x3 (" + val3.cost + ")");
			}
		}
		ENV_Vendor_Event[] array3 = Object.FindObjectsByType<ENV_Vendor_Event>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		foreach (ENV_Vendor_Event val4 in array3)
		{
			if ((Object)(object)val4 != (Object)null && pricedVendors.Add(((Object)val4).GetInstanceID()))
			{
				val4.cost *= 3;
				Ext.DebugOnce("evv", "Event vendor prices x3 (" + val4.cost + ")");
			}
		}
	}

	public static void Vending_Post(ENV_VendingMachine __instance)
	{
		if ((Object)(object)__instance == (Object)null || !Ext.IsOn())
		{
			return;
		}
		try
		{
			int instanceID = ((Object)__instance).GetInstanceID();
			if (__instance.purchaseList != null && pricedVendors.Add(instanceID))
			{
				foreach (Purchase purchase in __instance.purchaseList)
				{
					if (purchase != null)
					{
						purchase.price *= 3;
					}
				}
			}
			if (__instance.buttons == null || !stockedVendors.Add(instanceID))
			{
				return;
			}
			Random random = new Random(R.Get(__instance, "localSeed", 0) ^ 0x5EED);
			int num = 0;
			int num2 = 0;
			List<VendingButton> list = new List<VendingButton>();
			VendingButton[] buttons = __instance.buttons;
			foreach (VendingButton val in buttons)
			{
				if (val != null && val.available)
				{
					list.Add(val);
				}
			}
			num2 = list.Count;
			int num3 = Mathf.Max(1, Mathf.RoundToInt((float)num2 * 0.4f));
			for (int num4 = list.Count - 1; num4 > 0; num4--)
			{
				int index = random.Next(num4 + 1);
				VendingButton value = list[num4];
				list[num4] = list[index];
				list[index] = value;
			}
			for (int j = 0; j < list.Count; j++)
			{
				if (j < num3)
				{
					num++;
				}
				else
				{
					list[j].available = false;
				}
			}
			R.Call(__instance, "UpdateButtons");
			Ext.Debug("Vending machine: prices x3, stock " + num + "/" + num2);
		}
		catch (Exception ex)
		{
			Ext.LogOnce("vend", "Vendor rule failed: " + ex.Message);
		}
	}

	public static bool Decide_Pre(SpawnSettings __0, ref bool __1)
	{
		if (!Ext.IsOn())
		{
			return true;
		}
		string text = Desc(__0);
		if (text != null && text.Contains("cavity"))
		{
			if (__1)
			{
				Ext.DebugOnce("cav" + text.GetHashCode(), "Shortcut disabled: " + text);
			}
			__1 = false;
			return false;
		}
		return true;
	}

	public static void Decide_Post(SpawnSettings __0, ref bool __1)
	{
		if (!Ext.IsOn())
		{
			return;
		}
		string text = Desc(__0);
		if (string.IsNullOrEmpty(text) || text.Contains("cavity"))
		{
			return;
		}
		bool flag = __1;
		SHB.Zone zone = Ext.Zone;
		if (!text.Contains("item_") && !text.Contains("item "))
		{
			if (((zone == SHB.Zone.Abyss && Ext.Sub("deadman", "dead man", "handle")) || (zone == SHB.Zone.Nest && Ext.Sub("infested", "hot zone", "hotzone", "feeding", "trough")) || (zone == SHB.Zone.Habitation && Ext.Sub("delta"))) && HasAny(text, new string[12]
			{
				"hazard", "trap", "steam", "laser", "electr", "spike", "orchid", "spore", "mine", "denizen_",
				"den_", "turret"
			}) && !text.Contains("roach_gold") && !text.Contains("buddy"))
			{
				__1 = true;
			}
		}
		else if (__1 && HasAny(text, Consumable) && !HasAny(text, Critical))
		{
			float num = 0.35f * ((zone == SHB.Zone.Silos) ? 0.5f : 1f);
			if (Random.value > num)
			{
				__1 = false;
			}
		}
		if (flag != __1)
		{
			Ext.DebugOnce("dec" + text.GetHashCode() + __1, "Spawn " + (__1 ? "forced on" : "removed") + ": " + text);
		}
	}

	private static string Desc(SpawnSettings s)
	{
		if (s == null)
		{
			return null;
		}
		return SHB.SpawnRules.Owner(s);
	}
}
public static class MassRules
{
	private static readonly HashSet<int> quieted = new HashSet<int>();

	private static float lastLogged = -1f;

	public static void Reset()
	{
		quieted.Clear();
		lastLogged = -1f;
	}

	public static float CurrentMult()
	{
		SHB.Zone zone = Ext.Zone;
		float regionTime = Ext.RegionTime;
		float subregionTime = Ext.SubregionTime;
		switch (zone)
		{
		case SHB.Zone.Silos:
			if (!(subregionTime >= 240f))
			{
				return 1.1f;
			}
			return 1.4f;
		case SHB.Zone.Pipeworks:
			if (Ext.Sub("organ"))
			{
				return Mathf.Lerp(2.2f, 2.6f, Mathf.InverseLerp(90f, 300f, subregionTime));
			}
			break;
		}
		if (zone == SHB.Zone.Nest && (SHB.Zones.NestLastSection || Ext.Sub("feeding", "trough")))
		{
			if (!(subregionTime >= 180f))
			{
				return 2.2f;
			}
			return 2.75f;
		}
		return Mathf.Min(2.75f, 2.2f + 0.1f * Mathf.Floor(regionTime / 180f));
	}

	public static bool ApplyMass_Pre(DEN_DeathFloor __0)
	{
		if ((Object)(object)__0 == (Object)null || !Ext.IsOn())
		{
			return true;
		}
		try
		{
			float num = CurrentMult();
			__0.SetUpdateSpeedMultiplier(num);
			if (quieted.Add(((Object)__0).GetInstanceID()))
			{
				__0.globalVolume *= 0.6f;
				Ext.Debug("The Mass: 40% quieter, speed x" + num.ToString("0.00"));
			}
			if (Mathf.Abs(num - lastLogged) > 0.04f)
			{
				lastLogged = num;
				Ext.Debug("Mass speed now x" + num.ToString("0.00") + " (" + Ext.Zone.ToString() + ")");
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("mass", "Mass rule failed: " + ex.Message);
		}
		return false;
	}
}
public static class ExtTimers
{
	private static DEN_Mother timedMother;

	private static bool motherDone;

	public const float MotherStart = 50f;

	public const float MotherEscape = 100f;

	public static void Reset()
	{
		timedMother = null;
		motherDone = false;
	}

	public static bool Tick_Pre()
	{
		if (!Ext.IsOn())
		{
			return true;
		}
		try
		{
			Tick();
		}
		catch (Exception ex)
		{
			Ext.LogOnce("timers", "Timer rule failed: " + ex.Message);
		}
		return false;
	}

	private static void Tick()
	{
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		ENT_Player val = Ext.Player();
		if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || CL_GameManager.isDead() || Ext.Paused())
		{
			return;
		}
		if (!Ext.InSafeRoom())
		{
			SHB.Timers.RemainsTimer += Time.deltaTime;
		}
		if (SHB.Timers.RemainsTimer >= SHB.Cfg.RemainsInterval.Value)
		{
			SHB.Timers.RemainsTimer = 0f;
			int num = 0;
			DEN_Remains_Active[] array = Object.FindObjectsByType<DEN_Remains_Active>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (DEN_Remains_Active val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && !((GameEntity)val2).dead)
				{
					num++;
				}
			}
			if (num < 2)
			{
				SHB.Timers.SpawnRemains();
			}
			else
			{
				Ext.Debug("Remains timer: already 2 Remains hunting you.");
			}
		}
		if (Ext.Zone != SHB.Zone.Nest)
		{
			SHB.Timers.MotherLeft = -1f;
			return;
		}
		DEN_Mother instance = DEN_Mother.instance;
		if ((Object)(object)instance == (Object)null || !((Component)instance).gameObject.activeInHierarchy || ((GameEntity)instance).dead)
		{
			if (SHB.Timers.MotherLeft >= 0f)
			{
				SHB.Timers.MotherLeft = -1f;
				motherDone = true;
			}
			return;
		}
		if ((Object)(object)instance != (Object)(object)timedMother)
		{
			timedMother = instance;
			motherDone = false;
			SHB.Timers.MotherLeft = -1f;
		}
		float num2 = Vector3.Distance(((Component)val).transform.position, ((Component)instance).transform.position);
		if (SHB.Timers.MotherLeft < 0f && !motherDone && num2 < 50f)
		{
			SHB.Timers.MotherLeft = SHB.Cfg.MotherSeconds.Value;
			SHB.Hud.Flash("SHE SEES YOU - RUN");
			Ext.Debug("Mother: " + SHB.Timers.MotherLeft + " s to get 100 m away.");
		}
		if (SHB.Timers.MotherLeft < 0f)
		{
			return;
		}
		if (num2 > 100f)
		{
			SHB.Timers.MotherLeft = -1f;
			motherDone = true;
			SHB.Hud.Flash("ESCAPED");
			Ext.Debug("Escaped the Mother.");
			return;
		}
		SHB.Timers.MotherLeft -= Time.deltaTime;
		if (SHB.Timers.MotherLeft > 0f)
		{
			return;
		}
		SHB.Timers.MotherLeft = -1f;
		motherDone = true;
		Ext.Debug("Mother escape countdown ran out.");
		try
		{
			instance.Enrage(true);
		}
		catch (Exception ex)
		{
			Ext.LogOnce("enrage", "Enrage failed: " + ex.Message);
		}
		try
		{
			instance.KillPlayer();
		}
		catch (Exception ex2)
		{
			Ext.LogOnce("mkill", "Mother kill failed: " + ex2.Message);
			((GameEntity)val).Kill("mother");
		}
	}
}
public static class ExtHud
{
	private static GUIStyle label;

	private static GUIStyle big;

	public static bool Draw_Pre()
	{
		if (!Ext.IsOn())
		{
			return true;
		}
		try
		{
			Draw();
		}
		catch (Exception ex)
		{
			Ext.LogOnce("hud", "HUD failed: " + ex.Message);
		}
		return false;
	}

	private static void Draw()
	{
		//IL_0026: 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_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		//IL_004b: 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_005d: Expected O, but got Unknown
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		if (SHB.Cfg.ShowHud.Value && !Ext.Paused())
		{
			if (label == null)
			{
				label = new GUIStyle(GUI.skin.label)
				{
					fontSize = 15,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)1
				};
				big = new GUIStyle(label)
				{
					fontSize = 30
				};
				big.normal.textColor = new Color(1f, 0.12f, 0.08f, 1f);
			}
			if (Plugin.ShowLabel.Value)
			{
				float num = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * 3.2f);
				label.normal.textColor = new Color(0.45f + 0.25f * num, 0f, 0f, 0.55f + 0.45f * num);
				label.fontSize = 15 + Mathf.RoundToInt(num * 2f);
				GUI.Label(new Rect(0f, 6f, (float)Screen.width, 26f), "EXTREME", label);
			}
			if (SHB.Timers.MotherLeft >= 0f)
			{
				GUI.Label(new Rect(0f, 34f, (float)Screen.width, 40f), "MOTHER: " + Mathf.CeilToInt(SHB.Timers.MotherLeft) + "s", big);
			}
			if (SHB.Hud.flash != null && Time.unscaledTime < SHB.Hud.flashUntil)
			{
				GUI.Label(new Rect(0f, (float)Screen.height * 0.3f, (float)Screen.width, 40f), SHB.Hud.flash, big);
			}
		}
	}
}
public static class Overrides
{
	private static bool applied;

	private static bool savedSaveFlag;

	private static readonly Dictionary<ConfigEntryBase, object> backup = new Dictionary<ConfigEntryBase, object>();

	public const float Gravity = 1.5f;

	private static List<KeyValuePair<ConfigEntryBase, object>> Targets()
	{
		List<KeyValuePair<ConfigEntryBase, object>> t = new List<KeyValuePair<ConfigEntryBase, object>>();
		S(SHB.Cfg.ForceHardMode, true);
		S(SHB.Cfg.ForceSurvival, true);
		S(SHB.Cfg.DisableLeaderboards, true);
		S(SHB.Cfg.GravityMult, 1.5f);
		S(SHB.Cfg.HangSeconds, 7f);
		S(SHB.Cfg.HammerDamageMult, 0.35f);
		S(SHB.Cfg.EngravedDoorChance, 0.8f);
		S((ConfigEntryBase)(object)SHB.Cfg.RemainsInterval, 240f);
		S(SHB.Cfg.MassSpeedMult, 2.2f);
		S(SHB.Cfg.HopperInstakill, true);
		S(SHB.Cfg.TicksHoldOn, true);
		S(SHB.Cfg.RedRoachExtra, 5);
		S(SHB.Cfg.RedRoachSpawnSeconds, 10f);
		S(SHB.Cfg.RedRoachMax, 16);
		S(SHB.Cfg.TurretExtra, 3);
		S(SHB.Cfg.BuddyEnabled, true);
		S(SHB.Cfg.BuddyPetSeconds, 60f);
		S(SHB.Cfg.SilosSturgeInterval, 12f);
		S(SHB.Cfg.SilosSturgeMax, 16);
		S(SHB.Cfg.SilosSturgeExtra, 3);
		S(SHB.Cfg.SilosBloodbugExtra, 3);
		S(SHB.Cfg.SilosMassMult, 0.5f);
		S(SHB.Cfg.SturgeDamageMult, 3f);
		S(SHB.Cfg.PipeworksBarnacleExtra, 4);
		S(SHB.Cfg.PipeworksHopperExtra, 3);
		S(SHB.Cfg.SteamDamageMult, 4f);
		S(SHB.Cfg.CavityRoute, false);
		S(SHB.Cfg.TeethSpeedMult, 3f);
		S(SHB.Cfg.TeethStaysUntilHidden, true);
		S(SHB.Cfg.VentThingSpeedMult, 3f);
		S(SHB.Cfg.TurretDamageMult, 4f);
		S(SHB.Cfg.TurretDroneChance, 1f);
		S(SHB.Cfg.AbyssFaceCount, 8);
		S(SHB.Cfg.AbyssFallDeath, 40f);
		S(SHB.Cfg.NestBarnacleExtra, 5);
		S((ConfigEntryBase)(object)SHB.Cfg.MotherSeconds, 15f);
		S(SHB.Cfg.NestWaterDps, 20f);
		return t;
		void S(ConfigEntryBase e, object v)
		{
			if (e != null)
			{
				t.Add(new KeyValuePair<ConfigEntryBase, object>(e, v));
			}
		}
	}

	public static void Apply(bool on)
	{
		if (on == applied)
		{
			return;
		}
		ConfigFile val = ((SHB.Cfg.DebugLog != null) ? SHB.Cfg.DebugLog.ConfigFile : null);
		if (on)
		{
			if (val != null)
			{
				savedSaveFlag = val.SaveOnConfigSet;
				val.SaveOnConfigSet = false;
			}
			backup.Clear();
			foreach (KeyValuePair<ConfigEntryBase, object> item in Targets())
			{
				try
				{
					backup[item.Key] = item.Key.BoxedValue;
					item.Key.BoxedValue = item.Value;
				}
				catch (Exception ex)
				{
					Ext.LogOnce("ov" + (object)item.Key.Definition, "Could not override " + ((object)item.Key.Definition)?.ToString() + ": " + ex.Message);
				}
			}
			applied = true;
			Ext.Debug("SUPER HARD numbers switched to EXTREME (" + backup.Count + " values).");
			return;
		}
		foreach (KeyValuePair<ConfigEntryBase, object> item2 in backup)
		{
			try
			{
				item2.Key.BoxedValue = item2.Value;
			}
			catch
			{
			}
		}
		backup.Clear();
		if (val != null)
		{
			val.SaveOnConfigSet = savedSaveFlag;
		}
		applied = false;
		Ext.Debug("EXTREME off: SUPER HARD numbers restored.");
	}
}
public static class Patches
{
	private static int ok;

	private static int failed;

	private static bool cavityZeroed;

	private static void P(Harmony h, Type t, string method, Type[] args, string prefix = null, string postfix = null, string finalizer = null, int priority = 400)
	{
		try
		{
			MethodBase methodBase = ((args == null) ? AccessTools.Method(t, method, (Type[])null, (Type[])null) : AccessTools.Method(t, method, args, (Type[])null));
			if (methodBase == null)
			{
				failed++;
				Plugin.Log.LogWarning((object)("EXTREME: method not found: " + t?.Name + "." + method));
			}
			else
			{
				h.Patch(methodBase, Hm(prefix), Hm(postfix), (HarmonyMethod)null, Hm(finalizer), (HarmonyMethod)null);
				ok++;
			}
		}
		catch (Exception ex)
		{
			failed++;
			Plugin.Log.LogWarning((object)("EXTREME: patch " + t?.Name + "." + method + " failed: " + ex.Message));
		}
		HarmonyMethod Hm(string n)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if (n != null)
			{
				return new HarmonyMethod(typeof(Patches).GetMethod(n, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
				{
					priority = priority
				};
			}
			return null;
		}
	}

	public static void ApplyAll(Harmony h)
	{
		P(h, SHB.T("Plugin"), "Update", null, "SHUpdate_Pre");
		P(h, SHB.T("Mode"), "ApplyGlobalToggles", null, null, "GlobalToggles_Post");
		P(h, SHB.T("SpawnRules"), "Decide", null, "Decide_Pre", "Decide_Post");
		P(h, SHB.T("Timers"), "Tick", null, "Timers_Pre");
		P(h, SHB.T("Hud"), "Draw", null, "Hud_Pre");
		P(h, SHB.T("Patches"), "ApplyMass", null, "Mass_Pre");
		P(h, SHB.T("Buddy"), "OnUse", null, null, "BuddyUse_Post");
		P(h, typeof(SaveData), "IsSettingActive", new Type[2]
		{
			typeof(string),
			typeof(string)
		}, null, "IsSettingActive_Post");
		P(h, typeof(UI_GamemodeScreen_Panel), "FillSettings", null, "FillSettings_Pre", null, "FillSettings_Fin", 0);
		P(h, typeof(UI_GamemodeScreen), "Initialize", new Type[1] { typeof(M_Gamemode) }, "ScreenInit_Pre", null, null, 200);
		P(h, typeof(UI_GamemodeSetting), "Initialize", new Type[2]
		{
			typeof(GamemodeSetting),
			typeof(UI_GamemodeScreen_Panel)
		}, "SettingInit_Pre", null, "SettingInit_Fin", 800);
		P(h, typeof(CL_GameManager), "AreAchievementsAllowed", null, null, "Achievements_Post");
		P(h, typeof(CL_AchievementManager), "SetAchievementValue", new Type[2]
		{
			typeof(string),
			typeof(bool)
		}, "SetAchievement_Pre");
		P(h, typeof(ENT_Player), "FallingDamage", null, "Falling_Pre", "Falling_Post");
		P(h, typeof(ENT_Player), "Damage", new Type[1] { typeof(DamageInfo) }, "Damage_Pre", null, null, 200);
		P(h, typeof(ENT_Player), "AddPerk", new Type[3]
		{
			typeof(Perk),
			typeof(int),
			typeof(bool)
		}, "AddPerk_Pre");
		P(h, typeof(InjuryType), "GetInjury", null, "Scope_Pre", null, "Scope_Fin");
		P(h, typeof(DEN_Phage), "OnAttackHit", null, "Scope_Pre", null, "Scope_Fin");
		P(h, typeof(DEN_Mask), "Update", null, "Scope_Pre", null, "Scope_Fin");
		P(h, typeof(SaveData), "LoadDataIntoPlayer", null, "Scope_Pre", null, "Scope_Fin");
		P(h, typeof(ENV_VendingMachine), "GenerateOptions", null, null, "Vending_Post");
		P(h, typeof(Denizen), "Kill", new Type[2]
		{
			typeof(string),
			typeof(DamageInfo)
		}, null, "Kill_Post");
		P(h, typeof(DEN_BasicDenizen), "Kill", new Type[2]
		{
			typeof(string),
			typeof(DamageInfo)
		}, null, "Kill_Post");
		P(h, typeof(DEN_Barnacle), "Kill", new Type[2]
		{
			typeof(string),
			typeof(DamageInfo)
		}, null, "Kill_Post");
		Plugin.Log.LogInfo((object)("EXTREME patches: " + ok + " applied, " + failed + " failed."));
	}

	private static void SHUpdate_Pre()
	{
		Plugin.BeforeSuperHard();
	}

	private static void GlobalToggles_Post(bool active)
	{
		try
		{
			if (Ext.IsOn())
			{
				foreach (KeyValuePair<M_Subregion, KeyValuePair<float, bool>> item in SHB.Mode.cavityBackup)
				{
					if ((Object)(object)item.Key != (Object)null && (item.Key.chance != 0f || item.Key.guaranteeIfNotVisited))
					{
						item.Key.chance = 0f;
						item.Key.guaranteeIfNotVisited = false;
						Ext.Debug("Shortcut closed: " + ((Object)item.Key).name);
					}
				}
				cavityZeroed = true;
			}
			else
			{
				if (!cavityZeroed)
				{
					return;
				}
				cavityZeroed = false;
				{
					foreach (KeyValuePair<M_Subregion, KeyValuePair<float, bool>> item2 in SHB.Mode.cavityBackup)
					{
						if ((Object)(object)item2.Key != (Object)null)
						{
							if (active)
							{
								item2.Key.chance = Mathf.Max(item2.Value.Key, 1f);
								item2.Key.guaranteeIfNotVisited = true;
							}
							else
							{
								item2.Key.chance = item2.Value.Key;
								item2.Key.guaranteeIfNotVisited = item2.Value.Value;
							}
						}
					}
					return;
				}
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("cavity", "Shortcut rule failed: " + ex.Message);
		}
	}

	private static bool Decide_Pre(SpawnSettings __0, ref bool __1)
	{
		return Items.Decide_Pre(__0, ref __1);
	}

	private static void Decide_Post(SpawnSettings __0, ref bool __1)
	{
		Items.Decide_Post(__0, ref __1);
	}

	private static bool Timers_Pre()
	{
		return ExtTimers.Tick_Pre();
	}

	private static void BuddyUse_Post(Item __0)
	{
		PlayerRules.BuddyUse_Post(__0);
	}

	private static bool Hud_Pre()
	{
		return ExtHud.Draw_Pre();
	}

	private static bool Mass_Pre(DEN_DeathFloor __0)
	{
		return MassRules.ApplyMass_Pre(__0);
	}

	private static void IsSettingActive_Post(SaveData __instance, string gameModeName, string settingID, ref bool __result)
	{
		Ext.IsSettingActive_Post(__instance, gameModeName, settingID, ref __result);
	}

	private static bool FillSettings_Pre(UI_GamemodeScreen_Panel __instance)
	{
		try
		{
			return Ext.SafeFillSettings(__instance);
		}
		catch (Exception ex)
		{
			Ext.LogOnce("fillsafe", "Safe run setup failed, using the game's own code: " + ex.Message);
			return true;
		}
	}

	private static Exception FillSettings_Fin(Exception __exception)
	{
		if (__exception == null)
		{
			return null;
		}
		Plugin.Log.LogError((object)("Run setup settings crashed; the screen opens anyway: " + __exception));
		if (!Ext.Broken)
		{
			Ext.Broken = true;
			Ext.RemoveEverywhere();
		}
		return null;
	}

	private static void ScreenInit_Pre(M_Gamemode __0)
	{
		try
		{
			Ext.EnsureInjected(__0);
		}
		catch (Exception ex)
		{
			Ext.LogOnce("init", "EXTREME inject failed: " + ex.Message);
		}
	}

	private static void SettingInit_Pre(GamemodeSetting __0)
	{
		try
		{
			Ext.Sanitize(__0);
		}
		catch
		{
		}
	}

	private static Exception SettingInit_Fin(Exception __exception, GamemodeSetting __0)
	{
		if (__exception == null)
		{
			return null;
		}
		Plugin.Log.LogError((object)("Setting button '" + (((Object)(object)__0 != (Object)null) ? __0.id : "?") + "' failed to build: " + __exception));
		if ((Object)(object)__0 != (Object)null && __0.id == "skmod_extreme")
		{
			Ext.Broken = true;
		}
		return null;
	}

	private static void Achievements_Post(ref bool __result)
	{
		if (__result && Ext.IsOn())
		{
			__result = false;
		}
	}

	private static bool SetAchievement_Pre()
	{
		return !Ext.IsOn();
	}

	private static void Falling_Pre(ENT_Player __instance, out PlayerRules.FallState __state)
	{
		PlayerRules.Falling_Pre(__instance, out __state);
	}

	private static void Falling_Post(ENT_Player __instance, PlayerRules.FallState __state)
	{
		PlayerRules.Falling_Post(__instance, __state);
	}

	private static void Damage_Pre(ENT_Player __instance, DamageInfo __0)
	{
		PlayerRules.Damage_Pre(__instance, __0);
	}

	private static bool AddPerk_Pre(Perk __0, ref Perk __result)
	{
		return PlayerRules.AddPerk_Pre(__0, ref __result);
	}

	private static void Scope_Pre()
	{
		PlayerRules.PerkScope_Pre();
	}

	private static Exception Scope_Fin(Exception __exception)
	{
		PlayerRules.PerkScope_Post();
		return __exception;
	}

	private static void Vending_Post(ENV_VendingMachine __instance)
	{
		Items.Vending_Post(__instance);
	}

	private static void Kill_Post(Denizen __instance)
	{
		Pressure.OnKill(__instance);
	}
}
public static class PlayerRules
{
	public struct FallState
	{
		public bool falling;

		public float dist;

		public float ignore;

		public bool valid;
	}

	public const float LethalFall = 25f;

	public const float AbyssLethalFall = 40f;

	private static float fallTimer;

	private static int perkScope;

	public const float HealthFactor = 0.5f;

	private static int healthPlayer;

	private static float baseMaxHealth;

	private static readonly string[] Electric = new string[6] { "electr", "spark", "shock", "zap", "lightning", "taser" };

	private static readonly string[] Bio = new string[9] { "orchid", "spore", "flesh", "bio", "growth", "fung", "acid", "goo", "infest" };

	private static float lastBuddyBoost = -99f;

	public const float BuddyStaminaFraction = 0.2f;

	public const float BuddyStaminaCooldown = 3f;

	public static void Reset()
	{
		fallTimer = 0f;
		healthPlayer = 0;
	}

	public static void Tick()
	{
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		ENT_Player val = Ext.Player();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		try
		{
			if ((Object)(object)SHB.PlayerRules.gravityPlayer == (Object)(object)val && Mathf.Abs(SHB.PlayerRules.appliedMult - 1.5f) > 0.001f && SHB.PlayerRules.appliedMult > 0.01f)
			{
				val.gravity = val.gravity / SHB.PlayerRules.appliedMult * 1.5f;
				SHB.PlayerRules.appliedMult = 1.5f;
				Ext.Debug("Gravity set to x" + 1.5f + " -> " + val.gravity);
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("grav", "Gravity rule failed: " + ex.Message);
		}
		try
		{
			int instanceID = ((Object)val).GetInstanceID();
			if (instanceID != healthPlayer)
			{
				healthPlayer = instanceID;
				baseMaxHealth = ((GameEntity)val).maxHealth;
			}
			float num = baseMaxHealth * 0.5f;
			if (((GameEntity)val).maxHealth > num + 0.001f)
			{
				if (((GameEntity)val).maxHealth > baseMaxHealth + 0.001f)
				{
					baseMaxHealth = ((GameEntity)val).maxHealth;
				}
				num = (((GameEntity)val).maxHealth = baseMaxHealth * 0.5f);
				Ext.DebugOnce("hp" + instanceID + num, "Max health halved: " + num.ToString("0.#"));
			}
			if (((GameEntity)val).health > ((GameEntity)val).maxHealth)
			{
				((GameEntity)val).health = ((GameEntity)val).maxHealth;
			}
		}
		catch (Exception ex2)
		{
			Ext.LogOnce("hp", "Health rule failed: " + ex2.Message);
		}
		if (!Ext.PlayerAlive() || Ext.Paused())
		{
			return;
		}
		if (R.Get(val, "falling", fallback: false))
		{
			fallTimer += Time.deltaTime;
		}
		else
		{
			fallTimer = 0f;
		}
		if (Ext.Zone != SHB.Zone.Abyss || !(fallTimer > 2.5f) || DEN_Face.faceInstances == null || DEN_Face.faceInstances.Count <= 0)
		{
			return;
		}
		Vector3 overrideTargetPosition = ((Component)val).transform.position + Vector3.down * 20f;
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(((Component)val).transform.position, Vector3.down, ref val2, 300f, -1, (QueryTriggerInteraction)1))
		{
			overrideTargetPosition = ((RaycastHit)(ref val2)).point;
		}
		foreach (DEN_Face faceInstance in DEN_Face.faceInstances)
		{
			if ((Object)(object)faceInstance != (Object)null && !((GameEntity)faceInstance).dead)
			{
				try
				{
					((AIGameEntity)faceInstance).SetOverrideTargetPosition(overrideTargetPosition);
				}
				catch
				{
				}
			}
		}
		Ext.DebugOnce("facefall" + Mathf.FloorToInt(Time.time / 10f), "Falling for 2.5 s in the Abyss: the faces head for your landing spot.");
	}

	public static void Falling_Pre(ENT_Player __instance, out FallState __state)
	{
		__state = default(FallState);
		if (Ext.IsOn() && !((Object)(object)__instance == (Object)null))
		{
			__state = new FallState
			{
				falling = R.Get(__instance, "falling", fallback: false),
				dist = R.Get(__instance, "curFallDistance", 0f),
				ignore = R.Get(__instance, "ignoreFallDamageTime", 0f),
				valid = true
			};
		}
	}

	public static void Falling_Post(ENT_Player __instance, FallState __state)
	{
		if (!__state.valid || (Object)(object)__instance == (Object)null || ((GameEntity)__instance).dead || !__state.falling || R.Get(__instance, "falling", fallback: false))
		{
			return;
		}
		try
		{
			float num = ((Ext.Zone == SHB.Zone.Abyss) ? 40f : 25f);
			if (!(__state.dist < num) && !(__state.ignore > 0f) && !__instance.IsHanging() && !__instance.IsSwimming() && !R.Get(__instance, "noclip", fallback: false) && (!((Object)(object)CL_GameManager.gMan != (Object)null) || !CL_GameManager.gMan.IsReviving()))
			{
				Ext.Debug("Fell " + __state.dist.ToString("0.0") + " m (limit " + num + " m): dead.");
				((GameEntity)__instance).Kill("falling");
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("fall", "Fall rule failed: " + ex.Message);
		}
	}

	public static void Damage_Pre(ENT_Player __instance, DamageInfo info)
	{
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		if (info == null || !Ext.IsOn())
		{
			return;
		}
		try
		{
			GameObject src;
			string text = Ext.Describe(info, out src);
			GameEntity val = (((Object)(object)src != (Object)null) ? src.GetComponentInParent<GameEntity>() : null);
			float amount = info.amount;
			string text2 = (info.type ?? "").ToLowerInvariant();
			string text3 = Instakill(text2, text, src, val);
			if (text3 != null)
			{
				info.amount = 99999f;
				Ext.Debug("Instant death: " + text3 + " (" + text.Trim() + ")");
			}
			else
			{
				float num = 1f;
				if (text2 == "falling")
				{
					num = 2.5f;
				}
				else if (val is DEN_Bloodbug && !text.Contains("spit") && !text.Contains("swarm"))
				{
					num = 2.5f;
				}
				else if (val is DEN_Drone)
				{
					num = 2.5f;
				}
				else if ((Object)(object)val == (Object)null || (!(val is Denizen) && !(val is AIGameEntity)))
				{
					num = EnvMult(text2, text);
				}
				info.amount *= num;
			}
			float num2 = 1f;
			if (__instance.IsHanging())
			{
				num2 *= 2f;
			}
			if (text.Contains("explo") || text.Contains("gasbag") || SHB.SpawnRules.IsRedRoach(text))
			{
				num2 *= 2f;
			}
			if (num2 != 1f)
			{
				info.force *= num2;
			}
			if (info.amount != amount)
			{
				Ext.DebugOnce("dmg" + text.GetHashCode(), "Damage " + amount.ToString("0.##") + " -> " + info.amount.ToString("0.##") + " from: " + text.Trim());
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("pdmg", "EXTREME damage rule failed: " + ex.Message);
		}
	}

	private static string Instakill(string type, string desc, GameObject src, GameEntity srcEnt)
	{
		if (srcEnt is DEN_Teeth || type == "teeth")
		{
			return "caught by Teeth";
		}
		if (srcEnt is DEN_Face)
		{
			return "caught by a Nightmare face";
		}
		if (desc.Contains("crush"))
		{
			return "crusher";
		}
		if (Ext.Sub("delta") && (desc.Contains("laser") || ((Object)(object)src != (Object)null && (Object)(object)src.GetComponentInParent<DEN_Deathwall>() != (Object)null)))
		{
			return "Delta Labs laser";
		}
		return null;
	}

	private static bool HasAny(string s, string[] keys)
	{
		foreach (string value in keys)
		{
			if (s.Contains(value))
			{
				return true;
			}
		}
		return false;
	}

	private static float EnvMult(string type, string desc)
	{
		switch (type)
		{
		default:
			if (!desc.Contains("steam"))
			{
				SHB.Zone zone = Ext.Zone;
				if (zone == SHB.Zone.Nest && Ext.Sub("hot zone", "hotzone", "hot-zone", "hot_zone"))
				{
					return 3f;
				}
				if (zone == SHB.Zone.Nest && Ext.Sub("infested") && HasAny(desc, Bio))
				{
					return 2.5f;
				}
				if (zone == SHB.Zone.Abyss && Ext.Sub("deadman", "dead man", "handle"))
				{
					return 2.5f;
				}
				if (zone == SHB.Zone.Habitation && Ext.Sub("pier") && desc.Contains("fog"))
				{
					return 3f;
				}
				if (zone == SHB.Zone.Silos && HasAny(desc, Electric))
				{
					return 3f;
				}
				return 1f;
			}
			goto case "poison";
		case "poison":
		case "hunger":
		case "nonlethal":
		case "drowned":
			return 1f;
		}
	}

	public static void BuddyUse_Post(Item item)
	{
		try
		{
			if (item == null || !Ext.IsOn() || !SHB.Buddy.IsBuddy(item))
			{
				return;
			}
			ENT_Player val = Ext.Player();
			if ((Object)(object)val == (Object)null || ((GameEntity)val).dead || val.hands == null || !val.IsGrounded(false) || val.IsHanging() || Time.time - lastBuddyBoost < 3f)
			{
				return;
			}
			lastBuddyBoost = Time.time;
			for (int i = 0; i < val.hands.Length; i++)
			{
				if (val.hands[i] != null)
				{
					val.hands[i].AddGripStrength(val.GetCurrentGripStrengthTimer(i) * 0.2f);
				}
			}
			Ext.Debug("Petted the Calming Buddy on the ground: +" + 20f.ToString("0") + "% grip.");
		}
		catch (Exception ex)
		{
			Ext.LogOnce("buddystam", "Buddy stamina failed: " + ex.Message);
		}
	}

	public static void PerkScope_Pre()
	{
		perkScope++;
	}

	public static void PerkScope_Post()
	{
		if (perkScope > 0)
		{
			perkScope--;
		}
	}

	public static bool AddPerk_Pre(Perk perk, ref Perk __result)
	{
		if ((Object)(object)perk == (Object)null || !Ext.IsOn())
		{
			return true;
		}
		if (!(perk.id + " " + perk.title + " " + ((Object)perk).name).ToLowerInvariant().Contains("amalgam"))
		{
			return true;
		}
		Ext.Debug("EXTREME: blocked perk " + perk.id + " (Amalgamator)");
		__result = null;
		return false;
	}
}
[BepInPlugin("com.wkmods.extremeknuckle", "ExtremeKnuckle", "1.2.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string GUID = "com.wkmods.extremeknuckle";

	public const string NAME = "ExtremeKnuckle";

	public const string VERSION = "1.2.0";

	public static Plugin Instance;

	public static ManualLogSource Log;

	public static Harmony Harmony;

	public static ConfigEntry<bool> DebugLog;

	public static ConfigEntry<bool> ShowLabel;

	private CL_GameManager lastGameManager;

	private float nextSlowTick;

	private float nextEntityScan;

	private float nextWorldScan;

	private void Awake()
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", true, "Write everything EXTREME changes (tuned enemies, extra copies, hazards, vendors, deaths) to BepInEx/LogOutput.log.");
		ShowLabel = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowLabel", true, "Show the pulsing EXTREME label at the top of the screen.");
		Harmony = new Harmony("com.wkmods.extremeknuckle");
		Patches.ApplyAll(Harmony);
		Log.LogInfo((object)"ExtremeKnuckle 1.2.0 loaded. Pick EXTREME on the run setup screen (next to SUPER HARD).");
	}

	public static void BeforeSuperHard()
	{
		try
		{
			Overrides.Apply(Ext.IsOn());
		}
		catch (Exception ex)
		{
			Ext.LogOnce("pre", "Pre-tick error: " + ex);
		}
	}

	private void Update()
	{
		try
		{
			Ext.MenuTick();
			if ((Object)(object)CL_GameManager.gMan != (Object)(object)lastGameManager)
			{
				lastGameManager = CL_GameManager.gMan;
				if ((Object)(object)lastGameManager != (Object)null)
				{
					OnNewRun();
				}
			}
			bool num = Ext.IsOn();
			Overrides.Apply(num);
			if (num && !((Object)(object)CL_GameManager.gMan == (Object)null))
			{
				Ext.TrackRegion();
				PlayerRules.Tick();
				Pressure.Tick();
				Striders.Tick();
				Chaser.Tick();
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime >= nextEntityScan)
				{
					nextEntityScan = unscaledTime + 0.25f;
					EntityTuner.Scan();
				}
				if (unscaledTime >= nextWorldScan)
				{
					nextWorldScan = unscaledTime + 1.5f;
					WorldTuner.Scan();
				}
				if (unscaledTime >= nextSlowTick)
				{
					nextSlowTick = unscaledTime + 1f;
					Items.SlowTick();
				}
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("update", "Update error: " + ex);
		}
	}

	private void OnNewRun()
	{
		EntityTuner.Reset();
		WorldTuner.Reset();
		Items.Reset();
		PlayerRules.Reset();
		Pressure.Reset();
		Striders.Reset();
		Chaser.Reset();
		ExtTimers.Reset();
		MassRules.Reset();
		Ext.ResetRegion();
	}

	private void OnGUI()
	{
	}
}
public static class Pressure
{
	private static Vector3 anchor;

	private static float campTime;

	private static float nextAmbushAt;

	private static float bonusTimer;

	private static bool alerted;

	private static bool hasAnchor;

	private static readonly HashSet<int> killed = new HashSet<int>();

	private static readonly List<DEN_EngravedDoor> doors = new List<DEN_EngravedDoor>();

	private static readonly HashSet<int> doorsPassed = new HashSet<int>();

	private static float waveAt = -1f;

	private static readonly List<GameObject> attracted = new List<GameObject>();

	public static void Reset()
	{
		hasAnchor = false;
		campTime = 0f;
		alerted = false;
		nextAmbushAt = 60f;
		bonusTimer = 0f;
		killed.Clear();
		doors.Clear();
		doorsPassed.Clear();
		waveAt = -1f;
	}

	public static void Tick()
	{
		//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_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: 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_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		if (!Ext.PlayerAlive() || Ext.Paused())
		{
			return;
		}
		Vector3 position = ((Component)Ext.Player()).transform.position;
		float deltaTime = Time.deltaTime;
		bool flag = Ext.InSafeRoom();
		if (!flag)
		{
			bonusTimer += deltaTime;
			if (bonusTimer >= 300f)
			{
				bonusTimer = 0f;
				EntityTuner.PendingBonusCopy = true;
				Ext.Debug("5 minutes outside safe rooms: next spawn may get a bonus copy.");
			}
		}
		Vector3 val;
		if (!(!hasAnchor || flag))
		{
			val = position - anchor;
			if (!(((Vector3)(ref val)).sqrMagnitude > 9f))
			{
				campTime += deltaTime;
				if (campTime >= 30f && !alerted)
				{
					alerted = true;
					Ext.Debug("Camping for 30 s: " + AlertAround(position, 45f, int.MaxValue, null) + " enemies come to investigate.");
				}
				if (campTime >= nextAmbushAt)
				{
					nextAmbushAt += 20f;
					if (Random.value < 0.5f)
					{
						Ambush("Camping ambush", 1);
					}
				}
				goto IL_0137;
			}
		}
		anchor = position;
		hasAnchor = true;
		campTime = 0f;
		alerted = false;
		nextAmbushAt = 60f;
		goto IL_0137;
		IL_0137:
		for (int num = doors.Count - 1; num >= 0; num--)
		{
			DEN_EngravedDoor val2 = doors[num];
			if ((Object)(object)val2 == (Object)null)
			{
				doors.RemoveAt(num);
			}
			else if (!doorsPassed.Contains(((Object)val2).GetInstanceID()))
			{
				val = ((Component)val2).transform.position - position;
				if (((Vector3)(ref val)).sqrMagnitude < 12.25f)
				{
					doorsPassed.Add(((Object)val2).GetInstanceID());
					waveAt = Time.time + 4f;
				}
			}
		}
		if (waveAt > 0f && Time.time >= waveAt)
		{
			waveAt = -1f;
			if (!flag)
			{
				Ambush("Engraved Door wave", 2);
			}
		}
	}

	public static void OnEngravedDoor(GameEntity g)
	{
		DEN_EngravedDoor val = (DEN_EngravedDoor)(object)((g is DEN_EngravedDoor) ? g : null);
		if (val != null && !doors.Contains(val))
		{
			doors.Add(val);
		}
	}

	private static void Ambush(string why, int count)
	{
		List<GameEntity> recentHostiles = EntityTuner.RecentHostiles;
		AIGameEntity ai = default(AIGameEntity);
		for (int i = 0; i < count; i++)
		{
			GameEntity val = null;
			for (int j = 0; j < 8; j++)
			{
				if (recentHostiles.Count <= 0)
				{
					break;
				}
				GameEntity val2 = recentHostiles[Random.Range(0, recentHostiles.Count)];
				if ((Object)(object)val2 != (Object)null && !val2.dead && ((Component)val2).gameObject.activeInHierarchy && !(val2 is DEN_Turret) && !(val2 is DEN_Barnacle) && !(val2 is DEN_Strider))
				{
					val = val2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Ext.DebugOnce("noamb" + Ext.Where, why + ": nothing nearby to send.");
				break;
			}
			GameObject val3 = EntityTuner.SpawnNearPlayer(((Component)val).gameObject, 9f, 18f, why);
			if ((Object)(object)val3 != (Object)null && val3.TryGetComponent<AIGameEntity>(ref ai))
			{
				Alert(ai);
			}
		}
	}

	private static void Alert(AIGameEntity ai)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		ENT_Player val = Ext.Player();
		if ((Object)(object)ai == (Object)null || (Object)(object)val == (Object)null)
		{
			return;
		}
		try
		{
			ai.SetTarget(((Component)val).transform);
		}
		catch
		{
		}
		try
		{
			ai.SetTargetPosition(((Component)val).transform.position);
		}
		catch
		{
		}
	}

	private static int AlertAround(Vector3 pos, float radius, int max, Func<GameEntity, bool> filter)
	{
		//IL_0076: 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_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		List<GameEntity> entities = GameEntity.entities;
		if (entities == null)
		{
			return 0;
		}
		GameEntity[] array = entities.ToArray();
		foreach (GameEntity val in array)
		{
			if (num >= max)
			{
				break;
			}
			if ((Object)(object)val == (Object)null || val.dead)
			{
				continue;
			}
			AIGameEntity val2 = (AIGameEntity)(object)((val is AIGameEntity) ? val : null);
			if (val2 != null && Rules.IsHostile(val) && !(val is DEN_Mother) && !(val is DEN_Turret) && (filter == null || filter(val)))
			{
				Vector3 val3 = ((Component)val).transform.position - pos;
				if (!(((Vector3)(ref val3)).sqrMagnitude > radius * radius))
				{
					Alert(val2);
					num++;
				}
			}
		}
		return num;
	}

	public static void OnKill(Denizen d)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: 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)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)d == (Object)null || !Ext.IsOn() || !killed.Add(((Object)d).GetInstanceID()))
		{
			return;
		}
		try
		{
			string text = ((Object)((Component)d).gameObject).name.ToLowerInvariant();
			SHB.Zone zone = Ext.Zone;
			Vector3 position = ((Component)d).transform.position;
			if (zone == SHB.Zone.Silos && (d is DEN_Bloodbug || text.Contains("bloodbug")) && Random.value < 0.35f)
			{
				GameObject source = SHB.Util.FindPrefabNamed("Denizen_Bloodbug") ?? ((Component)d).gameObject;
				for (int i = 0; i < 2; i++)
				{
					EntityTuner.SpawnNearPlayer(source, 10f, 20f, "Bloodbug death attracts another");
				}
			}
			else if (zone == SHB.Zone.Pipeworks && d is DEN_Barnacle && Random.value < 0.4f)
			{
				ENT_Player val = Ext.Player();
				int num = 0;
				GameEntity[] array = GameEntity.entities.ToArray();
				foreach (GameEntity obj in array)
				{
					DEN_Barnacle val2 = (DEN_Barnacle)(object)((obj is DEN_Barnacle) ? obj : null);
					if (val2 == null || !((Object)(object)val2 != (Object)(object)d) || ((GameEntity)val2).dead)
					{
						continue;
					}
					Vector3 val3 = ((Component)val2).transform.position - position;
					if (((Vector3)(ref val3)).sqrMagnitude < 324f && (Object)(object)val != (Object)null)
					{
						try
						{
							val2.ReachTongues(((Component)val).transform);
							num++;
						}
						catch
						{
						}
					}
				}
				if (num > 0)
				{
					Ext.Debug("Barnacle killed: " + num + " nearby barnacles lash out.");
				}
			}
			else if (zone == SHB.Zone.Nest && (text.Contains("sprider") || text.Contains("spider")))
			{
				int num2 = AlertAround(position, 35f, 4, delegate(GameEntity e)
				{
					string text2 = ((Object)((Component)e).gameObject).name.ToLowerInvariant();
					return text2.Contains("sprider") || text2.Contains("spider");
				});
				if (num2 > 0)
				{
					Ext.Debug("Sprider killed: " + num2 + " Spriders alerted.");
				}
			}
			else if (zone == SHB.Zone.Nest && (d is DEN_BasicDenizen_Flier_Swarm || text.Contains("swarm")))
			{
				AlertAround(position, 30f, 6, (GameEntity e) => e is DEN_BasicDenizen_Flier_Swarm || ((Object)((Component)e).gameObject).name.ToLowerInvariant().Contains("swarm"));
			}
			else if (zone == SHB.Zone.Nest && text.Contains("aunt"))
			{
				AlertAround(position, 30f, 2, (GameEntity e) => ((Object)((Component)e).gameObject).name.ToLowerInvariant().Contains("aunt"));
			}
		}
		catch (Exception ex)
		{
			Ext.LogOnce("onkill", "Kill rule failed: " + ex.Message);
		}
	}
}
public static class R
{
	private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

	private static readonly Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>();

	private static readonly Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>();

	private static FieldInfo F(Type t, string name)
	{
		string key = t.FullName + "." + name;
		if (fields.TryGetValue(key, out var value))
		{
			return value;
		}
		Type type = t;
		while (type != null && value == null)
		{
			value = type.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			type = type.BaseType;
		}
		fields[key] = value;
		return value;
	}

	public static T Get<T>(object o, string name, T fallback = default(T))
	{
		if (o == null)
		{
			return fallback;
		}
		try
		{
			FieldInfo fieldInfo = F(o.GetType(), name);
			return (fieldInfo != null && fieldInfo.GetValue(o) is T val) ? val : fallback;
		}
		catch
		{
			return fallback;
		}
	}

	public static void Set(object o, string name, object value)
	{
		if (o == null)
		{
			return;
		}
		try
		{
			FieldInfo fieldInfo = F(o.GetType(), name);
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(o, value);
			}
		}
		catch
		{
		}
	}

	public static void Mul(object o, string name, float k)
	{
		if (o == null || k == 1f)
		{
			return;
		}
		try
		{
			FieldInfo fieldInfo = F(o.GetType(), name);
			if (fieldInfo != null && fieldInfo.FieldType == typeof(float))
			{
				fieldInfo.SetValue(o, (float)fieldInfo.GetValue(o) * k);
			}
		}
		catch
		{
		}
	}

	public static object Call(object o, string name, params object[] args)
	{
		if (o == null)
		{
			return null;
		}
		Type type = o.GetType();
		string key = type.FullName + "::" + name;
		if (!methods.TryGetValue(key, out var value))
		{
			Type type2 = type;
			while (type2 != null && value == null)
			{
				MethodInfo[] array = type2.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in array)
				{
					if (methodInfo.Name == name && methodInfo.GetParameters().Length == args.Length)
					{
						value = methodInfo;
						break;
					}
				}
				type2 = type2.BaseType;
			}
			methods[key] = value;
		}
		try
		{
			return (value != null) ? value.Invoke(o, args) : null;
		}
		catch
		{
			return null;
		}
	}
}
public static class Rules
{
	private static bool Has(string n, params string[] keys)
	{
		for (int i = 0; i < keys.Length; i++)
		{
			if (n.Contains(keys[i]))
			{
				return true;
			}
		}
		return false;
	}

	public static bool IsHostile(GameEntity e)
	{
		if ((Object)(object)e == (Object)null)
		{
			return false;
		}
		if (e is DEN_Roach || e is DEN_Critter || e is DEN_SlugGrub || e is DEN_Mother || e is DEN_EngravedDoor)
		{
			return false;
		}
		string text = ((Object)((Component)e).gameObject).name.ToLowerInvariant();
		if (text.Contains("roach") && !SHB.SpawnRules.IsRedRoach(text))
		{
			return false;
		}
		if (text.Contains("buddy"))
		{
			return false;
		}
		if (!(e is Denizen))
		{
			return e is AIGameEntity;
		}
		return true;
	}

	private static bool IsUnique(GameEntity e)
	{
		if (!(e is DEN_Teeth) && !(e is DEN_Hunter) && !(e is DEN_Face) && !(e is DEN_VentThing) && !(e is DEN_Remains_Active) && !(e is DEN_RatKing) && !(e is DEN_Mother) && !(e is DEN_Mask) && !(e is DEN_Phage) && !(e is DEN_Tracker) && !(e is DEN_Pseudopod))
		{
			return e is DEN_SimpleChaseKiller;
		}
		return true;
	}

	public static EntityRule For(GameEntity e, string n, SHB.Zone z)
	{
		EntityRule entityRule = new EntityRule();
		Tune tune = entityRule.Tune;
		bool flag = z == SHB.Zone.Nest;
		bool flag2 = z == SHB.Zone.Pipeworks;
		bool flag3 = z == SHB.Zone.Habitation;
		bool flag4 = z == SHB.Zone.Abyss;
		if (e is DEN_Hopper_Tick)
		{
			entityRule.Name = "tick roach";
			tune.Speed = (flag ? 2f : 1.5f);
			tune.Detect = 2f;
			tune.Set("drainDamage", flag ? 3f : 2f);
			if (flag)
			{
				tune.Set("maxBloodDrain", 1.5f);
				entityRule.ExtraCopies = 3;
			}
			return entityRule;
		}
		if (e is DEN_Hopper || (Has(n, "hopper") && !Has(n, "tick")))
		{
			entityRule.Name = "hopper roach";
			tune.Speed = 1.6f;
			tune.Detect = 2f;
			tune.Time = 0.5f;
			entityRule.ExtraCopies = ((!flag2) ? 2 : 0);
			return entityRule;
		}
		if (SHB.SpawnRules.IsRedRoach(n))
		{
			entityRule.Name = "red roach";
			tune.Speed = 1.5f;
			entityRule.Escalates = false;
			entityRule.Custom = delegate(GameEntity g)
			{
				ScaleExplosions(((Component)g).gameObject, 1.5f, 1f);
			};
			return entityRule;
		}
		if (e is DEN_Roach || e is DEN_Critter || e is DEN_SlugGrub)
		{
			return null;
		}
		if (e is DEN_GantryTurret)
		{
			entityRule.Name = "gantry turret";
			tune.Speed = 1.5f;
			tune.Set("repositionTimerMin", 0.5f).Set("repositionTimerMax", 0.5f);
			return entityRule;
		}
		if (e is DEN_Turret)
		{
			entityRule.Name = "turret";
			entityRule.Escalates = false;
			tune.Set("lookSpeed", 2.5f).Set("shootDelay", 0.5f).Set("maxRange", 1.75f)
				.Set("spinScanSpeed", 1.6f)
				.Set("horizontalTurnSpeed", 2.5f)
				.Set("verticalTurnSpeed", 2.5f);
			tune.NoDamageField("damage");
			entityRule.Custom = delegate(GameEntity g)
			{
				Drones.OnTurret(g);
			};
			return entityRule;
		}
		if (e is DEN_Drone)
		{
			entityRule.Name = "drone";
			tune.Speed = 1.75f;
			tune.Detect = 2f;
			tune.Time = 0.5f;
			tune.Set("chargeCooldown", 0.5f);
			return entityRule;
		}
		if (e is DEN_Remains_Active)
		{
			entityRule.Name = "Remains";
			entityRule.Escalates = false;
			tune.Set("moveSpeed", 1.5f).Set("moveSpeedRand", 1.5f).Set("viewRadius", 2f)
				.Set("scanDistance", 2f);
			return entityRule;
		}
		if (e is DEN_EngravedDoor)
		{
			entityRule.Name = "Engraved Door";
			entityRule.Escalates = false;
			tune.Set("damage", 2f).Set("damageTime", 2f / 3f).Set("pullForce", 1.5f)
				.Set("lookForce", 1.5f)
				.Set("lookFreq", 1.5f);
			entityRule.Custom = delegate(GameEntity g)
			{
				Pressure.OnEngravedDoor(g);
			};
			return entityRule;
		}
		if (e is DEN_Teeth)
		{
			entityRule.Name = "Teeth";
			entityRule.Escalates = false;
			tune.Set("aggressionRate", 2f).Set("attackDamage", 99999f).Set("jumpArcHeight", 1.5f);
			return entityRule;
		}
		if (e is DEN_VentThing)
		{
			entityRule.Name = "Vent Thing";
			entityRule.Escalates = false;
			tune.Set("activationDistance", 1.8f).Set("retreatTime", 0.4f).Set("finalStrikeSpeedMult", 1.5f)
				.Set("handRetreatSpeed", 3f);
			return entityRule;
		}
		if (e is DEN_Face)
		{
			entityRule.Name = "Nightmare face";
			entityRule.Escalates = false;
			tune.Set("baseVelocityMult", 1.6f).Set("aggressionIncreaseRate", 2f).Set("commandSpeedMult", 1.6f);
			return entityRule;
		}
		if (e is DEN_Hunter)
		{
			entityRule.Name = "Hunter";
			entityRule.Escalates = false;
			tune.Set("startSpeed", 2.5f).Set("lurchSpeed", 2.5f).Set("turnSpeed", 2f)
				.Set("stunTime", 0.35f)
				.Set("freezeTime", 0.35f)
				.Set("slamRecoveryRate", 2.5f)
				.Set("collisionDamage", 3f)
				.Set("trackPositionDistance", 2f);
			tune.Detect = 2f;
			return entityRule;
		}
		if (e is DEN_Strider)
		{
			entityRule.Name = "strider";
			entityRule.Escalates = false;
			tune.Set("speed", 1.8f).Set("acceleration", 1.8f).Set("turnSpeed", 1.5f);
			return entityRule;
		}
		if (IsUnique(e))
		{
			return null;
		}
		if (e is DEN_Bloodbug || Has(n, "bloodbug"))
		{
			if (Has(n, "spit"))
			{
				entityRule.Name = "spitter bloodbug";
				tune.Detect = 2f;
				tune.Time = 0.4f;
				tune.Damage = 3f;
				tune.Set("rangedAttackCooldown", 0.4f).Set("projectileShootDelay", 0.5f);
				entityRule.ExtraCopies = (flag ? 3 : 0);
				return entityRule;
			}
			if (e is DEN_BasicDenizen_Flier_Swarm || Has(n, "swarm"))
			{
				entityRule.Name = "swarm bloodbug";
				tune.Speed = 1.75f;
				tune.Detect = 2f;
				tune.Time = 0.5f;
				tune.Damage = 3f;
				entityRule.Custom = delegate(GameEntity g)
				{
					DEN_BasicDenizen_Flier_Swarm val = (DEN_BasicDenizen_Flier_Swarm)(object)((g is DEN_BasicDenizen_Flier_Swarm) ? g : null);
					if (val != null)
					{
						val.swarmCount *= 3;
					}
				};
				return entityRule;
			}
			entityRule.Name = "bloodbug";
			tune.Speed = 1.7f;
			tune.Detect = 2f;
			tune.Time = 0.4f;
			return entityRule;
		}
		if (Has(n, "sturge"))
		{
			entityRule.Name = "Sturge";
			tune.Detect = 2f;
			tune.Time = 0.5714286f;
			tune.NoDamageField("meleeAttackHitDamage");
			return entityRule;
		}
		if (e is DEN_Barnacle_Zombie || Has(n, "zombie"))
		{
			entityRule.Name = (Has(n, "security") ? "security barnacle zombie" : (Has(n, "scientist") ? "scientist barnacle zombie" : "barnacle zombie"));
			tune.Speed = 1.9f;
			tune.Time = 0.4f;
			tune.Damage = 3f;
			if (Has(n, "scientist"))
			{
				tune.Detect = 2f;
			}
			tune.Set("timeToAttack", 0.4f);
			if (flag)
			{
				entityRule.ExtraCopies = 3;
			}
			entityRule.Custom = delegate(GameEntity g)
			{
				if (Has(n, "security"))
				{
					BoostHealth(g, 1.5f);
				}
			};
			return entityRule;
		}
		if (e is DEN_Barnacle || Has(n, "barnacle"))
		{
			entityRule.Name = "barnacle";
			entityRule.Escalates = false;
			float mult = (flag ? 2f : 1.6f);
			tune.Set("attackDistance", mult).Set("scanDistance", mult).Set("damage", 3f)
				.Set("attackRate", flag ? 0.3f : 0.5f)
				.Set("tongueSpeed", flag ? 2.5f : 2f)
				.Set("tongueRetractSpeed", 1.8f)
				.Set("tongueAimTime", 0.6f)
				.Set("pullStrength", 1.3f);
			return entityRule;
		}
		if (e is DEN_Gasbag || Has(n, "gasbag"))
		{
			entityRule.Name = (flag ? "vernal gasbag" : "gasbag");
			tune.Speed = (flag ? 1.75f : 2f);
			tune.Detect = 2f;
			tune.Set("explodeDamage", 3f).Set("explodeForce", 2f);
			entityRule.ExtraCopies = (flag ? 2 : (flag2 ? 3 : 0));
			entityRule.Custom = delegate(GameEntity g)
			{
				ScaleExplosions(((Component)g).gameObject, 2f, 3f);
			};
			return entityRule;
		}
		if (Has(n, "sprider", "spider"))
		{
			entityRule.Name = "Sprider";
			tune.Speed = 2f;
			tune.Damage = 2.5f;
			tune.Detect = 2f;
			tune.Time = 0.4f;
			entityRule.ExtraCopies = (flag ? 4 : 0);
			return entityRule;
		}
		if (Has(n, "aunt"))
		{
			entityRule.Name = "Grub Aunt";
			tune.Speed = 1.75f;
			tune.Damage = 3f;
			tune.Detect = 2f;
			entityRule.ExtraCopies = (flag ? 2 : 0);
			return entityRule;
		}
		if (Has(n, "sister"))
		{
			entityRule.Name = "Grub Sister";
			tune.Speed = 1.5f;
			tune.Time = 0.5f;
			tune.Set("spotTime", 0.4f);
			return entityRule;
		}
		if (Has(n, "myzont"))
		{
			entityRule.Name = "Myzont";
			tune.Speed = 1.75f;
			tune.Time = 0.25f;
			tune.Detect = 2f;
			tune.Damage = 2.5f;
			tune.Set("memoryLength", 2f);
			entityRule.ExtraCopies = (flag ? 2 : 0);
			return entityRule;
		}
		if (e is DEN_Ravelin || Has(n, "ravelin"))
		{
			entityRule.Name = "Ravelin";
			tune.Speed = 1.6f;
			tune.Time = 0.5f;
			tune.Damage = 3f;
			tune.Detect = 1.75f;
			entityRule.ExtraCopies = (flag ? 1 : 0);
			return entityRule;
		}
		if (!IsHostile(e))
		{
			return null;
		}
		entityRule.Name = ((object)e).GetType().Name;
		if (flag3)
		{
			tune.Detect = 1.75f;
			if (e is DEN_BasicDenizen || e is DEN_BasicFlier || e is DEN_BasicNavigator || e is DEN_GiantRoach)
			{
				entityRule.ExtraCopies = 2;
			}
		}
		else if (flag)
		{
			tune.Time = 0.5f;
			tune.Detect = 1.5f;
		}
		else if (flag4)
		{
			tune.Detect = 1.5f;
		}
		return entityRule;
	}

	private static void BoostHealth(GameEntity g, float mult)
	{
		g.maxHealth *= mult;
		g.health *= mult;
		ENT_Hitbox[] componentsInChildren = ((Component)g).GetComponentsInChildren<ENT_Hitbox>(true);
		foreach (ENT_Hitbox obj in componentsInChildren)
		{
			obj.maxHealth *= mult;
			obj.health *= mult;
		}
	}

	public static void ScaleExplosions(GameObject g, float radius, float damage)
	{
		if (!((Object)(object)g == (Object)null))
		{
			UT_Explosion[] componentsInChildren = g.GetComponentsInChildren<UT_Explosion>(true);
			foreach (UT_Explosion obj in componentsInChildren)
			{
				obj.maxDistance *= radius;
				obj.damageMult *= damage;
			}
		}
	}
}
public static class SHB
{
	public enum Zone
	{
		None,
		Silos,
		Pipeworks,
		Habitation,
		Abyss,
		Nest
	}

	public static class Zones
	{
		public static Zone Current
		{
			get
			{
				try
				{
					object obj = Get("Zones", "Current");
					return (obj != null) ? ((Zone)Convert.ToInt32(obj)) : Zone.None;
				}
				catch
				{
					return Zone.None;
				}
			}
		}

		public static string Where => G("Zones", "Where", "");

		public static bool NestLastSection => G("Zones", "NestLastSection", fallback: false);
	}

	public static class Timers
	{
		public static float MotherLeft
		{
			get
			{
				return G("Timers", "MotherLeft", -1f);
			}
			set
			{
				Set("Timers", "MotherLeft", value);
			}
		}

		public static float RemainsTimer
		{
			get
			{
				return G("Timers", "RemainsTimer", 0f);
			}
			set
			{
				Set("Timers", "RemainsTimer", value);
			}
		}

		public static void SpawnRemains()
		{
			Call("Timers", "SpawnRemains");
		}
	}

	public static class Mode
	{
		public const string SettingId = "skmod_super";

		public static bool Broken => G("Mode", "Broken", fallback: false);

		public static HashSet<string> HardIds => G<HashSet<string>>("Mode", "HardIds") ?? new HashSet<string>();

		public static HashSet<string> SurvivalIds => G<HashSet<string>>("Mode", "SurvivalIds") ?? new HashSet<string>();

		public static Dictionary<M_Subregion, KeyValuePair<float, bool>> cavityBackup => G<Dictionary<M_Subregion, KeyValuePair<float, bool>>>("Mode", "cavityBackup") ?? new Dictionary<M_Subregion, KeyValuePair<float, bool>>();
	}

	public static class PlayerRules
	{
		public static ENT_Player gravityPlayer => G<ENT_Player>("PlayerRules", "gravityPlayer");

		public static float appliedMult
		{
			get
			{
				return G("PlayerRules", "appliedMult", 1f);
			}
			set
			{
				Set("PlayerRules", "appliedMult", value);
			}
		}
	}

	public static class Hud
	{
		public static string flash => G<string>("Hud", "flash");

		public static float flashUntil => G("Hud", "flashUntil", 0f);

		public static void Flash(string text)
		{
			try
			{
				Call("Hud", "Flash", text);
			}
			catch
			{
			}
		}
	}

	public static class Buddy
	{
		public static bool IsBuddy(Item item)
		{
			try
			{
				object obj = Call("Buddy", "IsBuddy", item);
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}
	}

	public static class EntityRules
	{
		public static bool IsClone(GameObject g)
		{
			try
			{
				object obj = Call("EntityRules", "IsClone", g);
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		public static void MarkSpawned(GameObject g)
		{
			try
			{
				Call("EntityRules", "MarkSpawned", g);
			}
			catch
			{
			}
		}
	}

	public static class SpawnRules
	{
		public static bool IsRedRoach(string desc)
		{
			try
			{
				object obj = Call("SpawnRules", "IsRedRoach", desc);
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		public static string Owner(object spawnSettings)
		{
			if (spawnSettings == null)
			{
				return null;
			}
			try
			{
				return (Get("SpawnRules", "owners") is IDictionary dictionary && dictionary.Contains(spawnSettings)) ? (dictionary[spawnSettings] as string) : null;
			}
			catch
			{
				return null;
			}
		}
	}

	public static class ItemRules
	{
		public static string ItemName(Item_Object io)
		{
			try
			{
				return (Call("ItemRules", "ItemName", io) as string) ?? ((Object)io).name;
			}
			catch
			{
				return ((Object)(object)io != (Object)null) ? ((Object)io).name : "";
			}
		}
	}

	public static class Util
	{
		public static ENT_Player Player()
		{
			try
			{
				object obj = Call("Util", "Player");
				return (ENT_Player)((obj is ENT_Player) ? obj : null);
			}
			catch
			{
				return null;
			}
		}

		public static WKAssetDatabase Db()
		{
			try
			{
				object obj = Call("Util", "Db");
				return (WKAssetDatabase)((obj is WKAssetDatabase) ? obj : null);
			}
			catch
			{
				return null;
			}
		}

		public static Vector3 NearbySpot(Transform t)
		{
			//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_0029: 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_0033: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object obj = Call("Util", "NearbySpot", t);
				if (obj is Vector3)
				{
					return (Vector3)obj;
				}
			}
			catch
			{
			}
			return t.position + Random.insideUnitSphere * 2f;
		}

		public static bool SpotAroundPlayer(float min, float max, out Vector3 pos)
		{
			//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)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			pos = Vector3.zero;
			try
			{
				object[] array = new object[3]
				{
					min,
					max,
					Vector3.zero
				};
				object obj = Call("Util", "SpotAroundPlayer", array);
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				int result = num & (flag ? 1 : 0);
				if (array[2] is Vector3 val)
				{
					pos = val;
				}
				return (byte)result != 0;
			}
			catch
			{
				return false;
			}
		}

		public static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot, Transform parent)
		{
			//IL_0016: 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_0045: 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)
			try
			{
				object obj = Call("Util", "Spawn", prefab, pos, rot, parent);
				return (GameObject)((obj is GameObject) ? obj : null);
			}
			catch
			{
				return ((Object)(object)prefab != (Object)null) ? Object.Instantiate<GameObject>(prefab, pos, rot, parent) : null;
			}
		}

		public static GameObject FindPrefabNamed(string part)
		{
			try
			{
				object obj = Call("Util", "FindPrefabNamed", part);
				return (GameObject)((obj is GameObject) ? obj : null);
			}
			catch
			{
				return null;
			}
		}

		public static GameObject FindPrefabWith<TC>()
		{
			try
			{
				MethodInfo methodInfo = M("Util", "FindPrefabWith");
				return (GameObject)((methodInfo != null) ? /*isinst with value type is only supported in some contexts*/: null);
			}
			catch
			{
				return null;
			}
		}
	}

	public static class Cfg
	{
		public static ConfigEntryBase DebugLog => E("DebugLog");

		public static ConfigEntry<bool> ShowHud => E<bool>("ShowHud");

		public static ConfigEntryBase ForceHardMode => E("ForceHardMode");

		public static ConfigEntryBase ForceSurvival => E("ForceSurvival");

		public static ConfigEntryBase DisableLeaderboards => E("DisableLeaderboards");

		public static ConfigEntryBase GravityMult => E("GravityMult");

		public static ConfigEntryBase HangSeconds => E("HangSeconds");

		public static ConfigEntryBase HammerDamageMult => E("HammerDamageMult");

		public static ConfigEntryBase EngravedDoorChance => E("EngravedDoorChance");

		public static ConfigEntry<float> RemainsInterval => E<float>("RemainsInterval");

		public static ConfigEntryBase MassSpeedMult => E("MassSpeedMult");

		public static ConfigEntryBase HopperInstakill => E("HopperInstakill");

		public static ConfigEntryBase TicksHoldOn => E("TicksHoldOn");

		public static ConfigEntryBase RedRoachExtra => E("RedRoachExtra");

		public static ConfigEntryBase RedRoachSpawnSeconds => E("RedRoachSpawnSeconds");

		public static ConfigEntryBase RedRoachMax => E("RedRoachMax");

		public static ConfigEntryBase TurretExtra => E("TurretExtra");

		public static ConfigEntryBase BuddyEnabled => E("BuddyEnabled");

		public static ConfigEntryBase BuddyPetSeconds => E("BuddyPetSeconds");

		public static ConfigEntryBase SilosSturgeInterval => E("SilosSturgeInterval");

		public static ConfigEntryBase SilosSturgeMax => E("SilosSturgeMax");

		public static ConfigEntryBase SilosSturgeExtra => E("SilosSturgeExtra");

		public static ConfigEntryBase SilosBloodbugExtra => E("SilosBloodbugExtra");

		public static ConfigEntryBase SilosMassMult => E("SilosMassMult");

		public static ConfigEntryBase SturgeDamageMult => E("SturgeDamageMult");

		public static ConfigEntryBase PipeworksBarnacleExtra => E("PipeworksBarnacleExtra");

		public static ConfigEntryBase PipeworksHopperExtra => E("PipeworksHopperExtra");

		public static ConfigEntryBase SteamDamageMult => E("SteamDamageMult");

		public static ConfigEntryBase CavityRoute => E("CavityRoute");

		public static ConfigEntryBase TeethSpeedMult => E("TeethSpeedMult");

		public static ConfigEntryBase TeethStaysUntilHidden => E("TeethStaysUntilHidden");

		public static ConfigEntryBase VentThingSpeedMult => E("VentThingSpeedMult");

		public static ConfigEntryBase TurretDamageMult => E("TurretDamageMult");

		public static ConfigEntryBase TurretDroneChance => E("TurretDroneChance");

		public static ConfigEntryBase AbyssFaceCount => E("AbyssFaceCount");

		public static ConfigEntryBase AbyssFallDeath => E("AbyssFallDeath");

		public static ConfigEntryBase NestBarnacleExtra => E("NestBarnacleExtra");

		public static ConfigEntry<float> MotherSeconds => E<float>("MotherSeconds");

		public static ConfigEntryBase NestWaterDps => E("NestWaterDps");

		private static ConfigEntryBase E(string name)
		{
			object obj = Get("Cfg", name);
			return (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null);
		}

		private static ConfigEntry<TV> E<TV>(string name)
		{
			return Get("Cfg", name) as ConfigEntry<TV>;
		}
	}

	private const BindingFlags All = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

	private static readonly Dictionary<string, Type> types = new Dictionary<string, Type>();

	private static readonly Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>();

	private static readonly Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>();

	public static Type T(string name)
	{
		if (types.TryGetValue(name, out var value))
		{
			return value;
		}
		value = AccessTools.TypeByName("SuperHardKnuckle." + name);
		if (value == null)
		{
			Plugin.Log.LogWarning((object)("EXTREME: SuperHard type not found: " + name));
		}
		types[name] = value;
		return value;
	}

	private static FieldInfo F(string type, string field)
	{
		string text = type + "." + field;
		if (fields.TryGetValue(text, out var value))
		{
			return value;
		}
		Type type2 = T(type);
		value = ((type2 != null) ? type2.GetField(field, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
		if (value == null)
		{
			Plugin.Log.LogWarning((object)("EXTREME: SuperHard field not found: " + text));
		}
		fields[text] = value;
		return value;
	}

	private static MethodInfo M(string type, string method)
	{
		string text = type + "." + method;
		if (methods.TryGetValue(text, out var value))
		{
			return value;
		}
		Type type2 = T(type);
		value = ((type2 != null) ? type2.GetMethod(method, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) : null);
		if (value == null)
		{
			Plugin.Log.LogWarning((object)("EXTREME: SuperHard method not found: " + text));
		}
		methods[text] = value;
		return value;
	}

	private static object Get(string type, string field)
	{
		FieldInfo fieldInfo = F(type, field);
		if (!(fieldInfo != null))
		{
			return null;
		}
		return fieldInfo.GetValue(null);
	}

	private static void Set(string type, string field, object v)
	{
		FieldInfo fieldInfo = F(type, field);
		if (fieldInfo != null)
		{
			fieldInfo.SetValue(null, v);
		}
	}

	private static object Call(string type, string method, params object[] args)
	{
		MethodInfo methodInfo = M(type, method);
		if (!(methodInfo != null))
		{
			return null;
		}
		return methodInfo.Invoke(null, args);
	}

	private static TV G<TV>(string type, string field, TV fallback = default(TV))
	{
		object obj = Get(type, field);
		if (obj is TV)
		{
			return (TV)obj;
		}
		return fallback;
	}
}
public static class Striders
{
	private class S
	{
		public DEN_Strider d;

		public float speed;

		public float accel;

		public float onTime;

		public bool fast;
	}

	private static readonly List<S> list = new List<S>();

	public static void Reset()
	{
		list.Clear();
	}

	public static void Track(DEN_Strider d)
	{
		foreach (S item in list)
		{
			if ((Object)(object)item.d == (Object)(object)d)
			{
				return;
			}
		}
		list.Add(new S
		{
			d = d,
			speed = d.speed,
			accel = d.acceleration
		});
	}

	public static void Tick()
	{
		//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_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		if (list.Count == 0)
		{
			return;
		}
		ENT_Player val = Ext.Player();
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Vector3 position = ((Component)val).transform.position;
		Vector2 val2 = default(Vector2);
		for (int num = list.Count - 1; num >= 0; num--)
		{
			S s = list[num];
			if ((Object)(object)s.d == (Object)null)
			{
				list.RemoveAt(num);
			}
			else
			{
				Vector3 position2 = ((Component)s.d).transform.position;
				((Vector2)(ref val2))..ctor(position.x - position2.x, position.z - position2.z);
				bool flag = ((Vector2)(ref val2)).sqrMagnitude < 1