Decompiled source of ExtraModes v1.0.1

plugins/Nebulaetrix.WK_Extra_Modes.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using WK_Extra_Modes.Core;
using WK_Extra_Modes.Helpers;
using WK_Extra_Modes.Modes;
using WK_Extra_Modes.Patches.WorldPatches;
using WK_Extra_Modes.Save;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Nebulaetrix.WK_Extra_Modes")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+727e94a82ade1f2ea71d0c2a41837bb821131287")]
[assembly: AssemblyProduct("Nebulaetrix.WK_Extra_Modes")]
[assembly: AssemblyTitle("Nebulaetrix.WK_Extra_Modes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WK_Extra_Modes
{
	[BepInPlugin("Nebulaetrix.WK_Extra_Modes", "Nebulaetrix.WK_Extra_Modes", "1.0.1")]
	public class ExtraModes : BaseUnityPlugin
	{
		private bool patched;

		private static Harmony _harmony;

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (patched)
			{
				Logger.LogWarning((object)"Already Patched");
			}
			Logger = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("Nebulaetrix.WK_Extra_Modes");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			if (Assets.Load())
			{
				SceneManager.sceneLoaded += UI.OnSceneLoad;
				Logger.LogInfo((object)"Plugin Nebulaetrix.WK_Extra_Modes is loaded!");
				patched = true;
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Nebulaetrix.WK_Extra_Modes";

		public const string PLUGIN_NAME = "Nebulaetrix.WK_Extra_Modes";

		public const string PLUGIN_VERSION = "1.0.1";
	}
}
namespace WK_Extra_Modes.Save
{
	[Serializable]
	public class RunData
	{
		public string ModeName;

		public bool Completed;

		public int Score;

		public float AscentRate;

		public float TimeTaken;
	}
	[Serializable]
	public class SaveData
	{
		public Dictionary<string, RunData> ModeRuns = new Dictionary<string, RunData>();
	}
	public static class SaveManager
	{
		private static SaveData _cachedData;

		private static string SaveDirectory => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "SaveData");

		private static string SavePath => Path.Combine(SaveDirectory, "save.json");

		public static SaveData LoadData()
		{
			try
			{
				if (_cachedData != null)
				{
					return _cachedData;
				}
				ExtraModes.Logger.LogDebug((object)("Loading run data from: " + SavePath));
				if (!Directory.Exists(SaveDirectory))
				{
					Directory.CreateDirectory(SaveDirectory);
				}
				if (!File.Exists(SavePath))
				{
					ExtraModes.Logger.LogWarning((object)("Save file not found. Creating default data at " + SavePath + "."));
					_cachedData = new SaveData();
					SaveDataToFile(_cachedData);
					return _cachedData;
				}
				string text = File.ReadAllText(SavePath);
				_cachedData = JsonConvert.DeserializeObject<SaveData>(text) ?? new SaveData();
				ExtraModes.Logger.LogInfo((object)"Save data loaded successfully.");
				return _cachedData;
			}
			catch (Exception ex)
			{
				ExtraModes.Logger.LogError((object)("Error loading save data: " + ex.Message));
				_cachedData = new SaveData();
				return _cachedData;
			}
		}

		public static void SaveRun(RunData runData)
		{
			try
			{
				SaveData saveData = LoadData();
				if (saveData.ModeRuns.TryGetValue(runData.ModeName, out var value))
				{
					if (runData.Score > value.Score)
					{
						ExtraModes.Logger.LogInfo((object)$"New high score for {runData.ModeName}: {runData.Score} (old: {value.Score})");
						saveData.ModeRuns[runData.ModeName] = runData;
						SaveDataToFile(saveData);
						_cachedData = saveData;
					}
					else
					{
						ExtraModes.Logger.LogInfo((object)$"Score {runData.Score} not higher than existing score {value.Score} for {runData.ModeName}. Not saving.");
					}
				}
				else
				{
					ExtraModes.Logger.LogInfo((object)$"Saving new run for mode {runData.ModeName}: {runData.Score}");
					saveData.ModeRuns[runData.ModeName] = runData;
					SaveDataToFile(saveData);
					_cachedData = saveData;
				}
			}
			catch (Exception ex)
			{
				ExtraModes.Logger.LogError((object)("Error saving run data: " + ex.Message));
			}
		}

		private static void SaveDataToFile(SaveData saveData)
		{
			try
			{
				string contents = JsonConvert.SerializeObject((object)saveData, (Formatting)1);
				File.WriteAllText(SavePath, contents);
				ExtraModes.Logger.LogInfo((object)"Save data written to file successfully.");
			}
			catch (Exception ex)
			{
				ExtraModes.Logger.LogError((object)("Error writing save data to file: " + ex.Message));
			}
		}
	}
}
namespace WK_Extra_Modes.Patches.WorldPatches
{
	[HarmonyPatch(typeof(Event_Cold))]
	public class EventColdPatch
	{
		[HarmonyPatch("LateUpdate")]
		[HarmonyPostfix]
		private static void ForceInvokeBlizzard(Event_Cold __instance)
		{
			if (WindTunnelMode.Enabled)
			{
				WindTunnelMode.UpdateBlizzardEvent();
			}
		}
	}
	[HarmonyPatch(typeof(Inventory))]
	internal class InventoryPatch
	{
		[HarmonyPatch("AddItemToHand")]
		[HarmonyPrefix]
		private static void AddItemToHandPatch(ref Item i, ref Hand playerHand, Inventory __instance)
		{
			if (i != null && i.itemName == "Note")
			{
				BabyMode.IsHoldingNote = true;
			}
		}

		[HarmonyPatch("ClearItemFromHand")]
		[HarmonyPrefix]
		private static void ItemIPatch(ref Item i)
		{
			CheckItemInHand(i);
		}

		[HarmonyPrefix]
		[HarmonyPatch("DropItemFromHand")]
		[HarmonyPatch("DestroyItemInHand")]
		private static void HandIntPatch(ref int h, Inventory __instance)
		{
			Item currentItem = __instance.itemHands[h].currentItem;
			if (currentItem != null)
			{
				CheckItemInHand(currentItem);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("AddItemToInventoryScreen", new Type[]
		{
			typeof(Vector3),
			typeof(Item),
			typeof(bool),
			typeof(bool)
		})]
		[HarmonyPatch("DropItemIntoWorld")]
		private static void ItemItemPatch(ref Item item)
		{
			CheckItemInHand(item);
		}

		private static void CheckItemInHand(Item item)
		{
			if (item.itemName == "Note")
			{
				BabyMode.IsHoldingNote = false;
			}
		}

		[HarmonyPatch("ShowInventory")]
		[HarmonyPrefix]
		private static bool PlayerAwakePatch()
		{
			return !MarkMode.Enabled;
		}
	}
	[HarmonyPatch(typeof(M_Level))]
	public class MLevelPatch
	{
		[HarmonyPatch("OnLevelActivate")]
		[HarmonyPostfix]
		private static void OnLevelActivatePatch(M_Level __instance)
		{
			if (MarathonMode.Enabled)
			{
				CoroutineRunner.Run(MarathonMode.SetGiftRoomParams(__instance));
			}
		}
	}
	[HarmonyPatch(typeof(UT_TriggerZone))]
	public class UtTriggerZonePatch
	{
		[HarmonyPatch("OnTriggerEnter")]
		[HarmonyPrefix]
		private static void LaserFieldPatch(UT_TriggerZone __instance)
		{
			if (((Object)((Component)__instance).gameObject).name == "Event-MovingSecurityZone" && (ZenMode.Enabled || BackwardMode.Enabled))
			{
				GameObjectHelper.Disable(((Component)__instance).gameObject, "LaserField");
			}
		}
	}
	[HarmonyPatch(typeof(WorldLoader))]
	public class WorldLoaderPatch
	{
		internal static Action OnWorldLoaded;

		[HarmonyPatch("Initialize")]
		[HarmonyPostfix]
		private static void InitializePatch()
		{
			if (WindTunnelMode.Enabled)
			{
				WindTunnelMode.AddBlizzardEvent();
			}
		}

		[HarmonyPatch("GetClosestLevelToPosition")]
		[HarmonyPostfix]
		private static void GetCurrentLevel(LevelInfo __result)
		{
			if (__result != null && MarathonMode.Enabled)
			{
				MarathonMode.UpdateColdEvent(__result);
			}
		}

		[HarmonyPatch("GenerateLevels")]
		[HarmonyPostfix]
		private static void GenerateLevelsPostPatch()
		{
			ExtraModes.Logger.LogDebug((object)"Broadcasting OnWorldLoaded");
			OnWorldLoaded?.Invoke();
		}
	}
}
namespace WK_Extra_Modes.Patches.DENPatches
{
	[HarmonyPatch(typeof(DEN_Bloodbug))]
	internal class DenBloodbugPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void BloodbugPatch(DEN_Bloodbug __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.ZenBloodbug(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_DeathFloor))]
	internal class DenDeathFloorPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void DeathFloorPatch(DEN_DeathFloor __instance)
		{
			if (ZenMode.Enabled || BackwardMode.Enabled)
			{
				GameObjectHelper.Disable(((Component)__instance).gameObject, "DeathFloor");
			}
		}
	}
	[HarmonyPatch(typeof(DEN_Teeth))]
	internal class DenTeethPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		private static void TeethPatch(DEN_Teeth __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.ZenTeeth(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_Turret))]
	internal class DenTurretPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void TeethPatch(DEN_Turret __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.ZenTurret(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_VentThing))]
	internal class DenVentThingPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		private static void VentThingPatch(DEN_VentThing __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.ZenVentThing(__instance);
			}
		}
	}
}
namespace WK_Extra_Modes.Patches.CLPatches
{
	[HarmonyPatch(typeof(CL_GameManager))]
	public class ClGameManagerPatch
	{
		[HarmonyPatch("EndGameSequence")]
		[HarmonyPostfix]
		private static void SaveModeData(ref bool win, CL_GameManager __instance)
		{
			if (ModeRegistry.ModeConfigs.Values.Any((ModeUIConfig c) => c.IsEnabled))
			{
				ExtraModes.Logger.LogDebug((object)"Disabling stats");
				CL_GameManager.gamemode.allowAchievements = false;
				CL_GameManager.gamemode.allowCheatedScores = false;
				CL_GameManager.gMan.allowScores = false;
				CommandConsole.hasCheated = true;
				float score = __instance.GetPlayerAscent() * __instance.GetPlayerAscentRate();
				SaveModeRun(win, score, __instance.GetGameTime(), __instance.GetPlayerAscentRate());
			}
		}

		private static void SaveModeRun(bool win, float score, float time, float ascentRate)
		{
			ExtraModes.Logger.LogDebug((object)$"Saving: Won:{win}, Score:{score}, Time:{time}, Ascent Rate:{ascentRate}");
			List<ModeUIConfig> source = ModeRegistry.ModeConfigs.Values.Where((ModeUIConfig c) => c.IsEnabled).ToList();
			float num = score;
			if (win)
			{
				num = score * 5f;
			}
			string modeName = string.Join("+", source.Select((ModeUIConfig c) => c.InternalName));
			RunData runData = new RunData
			{
				ModeName = modeName,
				Completed = win,
				TimeTaken = time,
				Score = Mathf.RoundToInt(num),
				AscentRate = ascentRate
			};
			SaveManager.SaveRun(runData);
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeScreen))]
	public class ClGamemodeScreenPatch
	{
		[HarmonyPatch("LoadGamemode")]
		[HarmonyPrefix]
		private static bool LoadLevelsPatch(CL_GameManager __instance)
		{
			if (MarathonMode.Enabled)
			{
				return !MarathonMode.LoadLibraryLevels();
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ENT_Player))]
	internal class ClPlayerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void PlayerAwakePatch(ENT_Player __instance)
		{
			if (HelpingHandMode.Enabled)
			{
				HelpingHandMode.SetPerks(__instance);
			}
			if (DisorientedMode.Enabled)
			{
				DisorientedMode.SetCameraTransform(__instance);
			}
			if (ArmlessMode.Enabled)
			{
				ArmlessMode.Amputate(__instance);
			}
			if (ZeroGravMode.Enabled)
			{
				ZeroGravMode.SetGravity(__instance);
			}
		}

		[HarmonyPatch("Movement")]
		[HarmonyPrefix]
		private static void PlayerMovementPrePatch(ENT_Player __instance)
		{
			if (LeglessMode.Enabled)
			{
				LeglessMode.Amputate(__instance);
			}
		}

		[HarmonyPatch("Movement")]
		[HarmonyPostfix]
		private static void PlayerMovementPostPatch(ENT_Player __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.SetPlayerHp(__instance);
			}
			if (GlassMode.Enabled)
			{
				GlassMode.SetPlayerHp(__instance);
			}
			if (BabyMode.Enabled)
			{
				BabyMode.ApplyBabyModeToPlayer(__instance);
			}
		}

		[HarmonyPatch("FixedUpdate")]
		[HarmonyPostfix]
		private static void FixedUpdatePatch(ENT_Player __instance)
		{
			if (CombustMode.Enabled)
			{
				CombustMode.RandomlyCombust(__instance);
			}
		}

		[HarmonyPatch("InteractCheck")]
		[HarmonyPrefix]
		private static void InteractCheckPatch(ref int hand, ENT_Player __instance)
		{
			if (DevilDaggerMode.Enabled)
			{
				DevilDaggerMode.SpawnRebar(hand, __instance);
			}
		}
	}
}
namespace WK_Extra_Modes.Modes
{
	public class LevelsList
	{
		internal static List<string> orderedLevels = new List<string>
		{
			"M1_Intro_01", "M1_Silos_Air_01", "M1_Silos_Air_02", "M1_Silos_Air_03", "M1_Silos_Air_04", "M1_Silos_Air_05", "M1_Silos_Air_06", "M1_Silos_Air_07", "M1_Silos_Air_08", "M1_Silos_Air_09",
			"M1_Silos_Air_10", "M1_Silos_SafeArea_01", "M1_Silos_Broken_01", "M1_Silos_Broken_02", "M1_Silos_Broken_03", "M1_Silos_Broken_04", "M1_Silos_Broken_05", "M1_Silos_Broken_06", "M1_Silos_Broken_07", "M1_Silos_Broken_08",
			"M1_Silos_Broken_09", "M1_Silos_Broken_10", "M1_Silos_SafeArea_Endless_01", "M1_Silos_Storage_01", "M1_Silos_Storage_02", "M1_Silos_Storage_03", "M1_Silos_Storage_04", "M1_Silos_Storage_05", "M1_Silos_Storage_06", "M1_Silos_Storage_07",
			"M1_Silos_Storage_08", "M1_Silos_Storage_09", "M1_Silos_Storage_10", "M1_Silos_Storage_11", "M1_Silos_Storage_12", "M1_Silos_Storage_13", "M1_Silos_Storage_14", "M1_Silos_Storage_15", "M1_Silos_Storage_16", "M1_Campaign_Transition_Silo_To_Pipeworks_01",
			"M2_Pipeworks_Drainage_01", "M2_Pipeworks_Drainage_02", "M2_Pipeworks_Drainage_03", "M2_Pipeworks_Drainage_04", "M2_Pipeworks_Drainage_05", "M2_Pipeworks_Drainage_06", "M2_Pipeworks_Drainage_07", "M2_Pipeworks_Waste_01", "M2_Pipeworks_Waste_02", "M2_Pipeworks_Waste_03",
			"M2_Pipeworks_Waste_04", "M2_Pipeworks_Break_01", "M2_Pipeworks_Organ_01", "M2_Pipeworks_Organ_02", "M2_Pipeworks_Organ_03", "M2_Pipeworks_Organ_04", "M2_Pipeworks_Organ_05", "M2_Pipeworks_Organ_06", "M2_Pipeworks_Organ_07", "M2_Pipeworks_Organ_08",
			"M3_Campaign_Transition_Pipeworks_To_Habitation_01", "M3_Habitation_Shaft_Intro", "M3_Habitation_Shaft_01", "M3_Habitation_Shaft_02", "M3_Habitation_Endless_Shaft_End", "M3_Delta_Pier_Intro_01", "M3_Delta_Pier_01", "M3_Delta_Pier_02", "M3_Delta_Pier_03", "M3_Delta_Pier_Outro_01",
			"M3_Habitation_Lab_01", "M3_Habitation_Lab_02", "M3_Habitation_Lab_03", "M3_Habitation_Lab_04", "M3_Habitation_Endless_Breakroom_01", "M3_Habitation_Endless_Shaft_Start", "M3_Habitation_Shaft_03", "M3_Habitation_Shaft_04", "M3_Habitation_Shaft_To_Pier", "M3_Habitation_Pier_Entrance_01",
			"M3_Habitation_Pier_01", "M3_Habitation_Lab_Lobby", "M3_Habitation_Endless_Breakroom_01", "M3_Habitation_Endless_Shaft_Start", "M3_Habitation_Shaft_05", "M3_Habitation_Shaft_06", "M3_Habitation_Shaft_To_Pier", "M3_Habitation_Pier_Entrance_01", "M3_Habitation_Pier_02", "M3_Habitation_Lab_Lobby",
			"M3_Habitation_Endless_Breakroom_01", "MX_Chimney_Start_01", "MX_Chimney_Frigid_01", "MX_Chimney_Frigid_02", "MX_Chimney_Frigid_03", "MX_Chimney_Frigid_04", "MX_Chimney_Frigid_05", "MX_Chimney_Gift_01", "MX_Chimney_Glacial_01", "MX_Chimney_Glacial_02",
			"MX_Chimney_Glacial_03", "MX_Chimney_Crystal_01", "MX_Chimney_Crystal_02", "MX_Chimney_Crystal_01", "MX_Chimney_Crystal_02", "MX_Chimney_Crystal_01", "MX_Chimney_Crystal_02", "MX_Chimney_Gift_02", "M3_Habitation_LadderWarp_Loop", "M3_Habitation_LadderWarp_Clean_01",
			"M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01", "M3_Habitation_LadderWarp_Clean_01",
			"M3_Habitation_LadderWarp_500m_01", "M3_Habitation_LadderWarp_Decrepit_01", "M3_Habitation_LadderWarp_Decrepit_02", "M3_Habitation_LadderWarp_Decrepit_03", "M3_Habitation_LadderWarp_Decrepit_01", "M3_Habitation_LadderWarp_Decrepit_02", "M3_Habitation_LadderWarp_Decrepit_03", "M3_Habitation_LadderWarp_1000m_01", "M3_Habitation_LadderWarp_Corrupted_01", "M3_Habitation_LadderWarp_Corrupted_02",
			"M3_Habitation_LadderWarp_Corrupted_03", "M3_Habitation_LadderWarp_Corrupted_01", "M3_Habitation_LadderWarp_Corrupted_02", "M3_Habitation_LadderWarp_Corrupted_03", "M3_Habitation_LadderWarp_1500m_01", "M3_Habitation_LadderWarp_Void_01", "M3_Habitation_LadderWarp_Void_02", "M3_Habitation_LadderWarp_Void_03", "M3_Habitation_LadderWarp_Void_04", "M3_Habitation_LadderWarp_Void_05",
			"M3_Habitation_LadderWarp_Void_06", "M3_Habitation_Lab_Ending"
		};
	}
	public static class ModeRegistry
	{
		public static readonly Dictionary<string, ModeUIConfig> ModeConfigs = new Dictionary<string, ModeUIConfig>
		{
			["DevilDaggerMode"] = new ModeUIConfig("Easy", "DevilDaggerMode", "Devil Daggers", "Shoot rebar upon opening your hands", "Play the game, or else...", DevilDaggerMode.Toggle),
			["HelpingHandMode"] = new ModeUIConfig("Easy", "HelpingHandMode", "Helping Hand", "Gives you all T1 perks", "Totally earned these perks. Definitely.", HelpingHandMode.Toggle),
			["ZenMode"] = new ModeUIConfig("Easy", "ZenMode", "Zen Mode", "No Mass, Bloodbugs, Teeth etc", "Stress-free since 1.0!", ZenMode.Toggle),
			["ZeroGravMode"] = new ModeUIConfig("Easy", "ZeroGravMode", "Zero-G", "Zero gravity", "Newton's worst nightmare", ZeroGravMode.Toggle),
			["BackwardMode"] = new ModeUIConfig("Medium", "BackwardMode", "elkcunK etihW", "Start at the top and descend", "Hope you have strong legs!", BackwardMode.Toggle),
			["CombustMode"] = new ModeUIConfig("Medium", "CombustMode", "Volatile", "Randomly explode", "Boom boom boom boom, I want you in my room~", CombustMode.Toggle),
			["MarkMode"] = new ModeUIConfig("Medium", "MarkMode", "Markiplier%", "No inventory", "Hello everybody my name is Welcome", MarkMode.Toggle),
			["ArmlessMode"] = new ModeUIConfig("Hard", "ArmlessMode", "Amputated", "Missing an arm", "Now with 50% less knuckle!", ArmlessMode.Toggle),
			["BabyMode"] = new ModeUIConfig("Hard", "BabyMode", "Baby Knuckle", "66% smaller", "Fun sized misery!", BabyMode.Toggle),
			["DisorientedMode"] = new ModeUIConfig("Hard", "DisorientedMode", "Disoriented", "Inverted camera", "ssenkciS noitoM dna daerD laitnetsixE ecudnI yaM :gninraW", DisorientedMode.Toggle),
			["GlassMode"] = new ModeUIConfig("Hard", "GlassMode", "Glass Knuckle", "One shot to everything", "There's a reason you're made of flesh", GlassMode.Toggle),
			["LeglessMode"] = new ModeUIConfig("Hard", "LeglessMode", "Paraplegic", "No jumping", "Mobility sold separately", LeglessMode.Toggle),
			["MarathonMode"] = new ModeUIConfig("Extreme", "MarathonMode", "Marathon Mode", "Every level in existence", "Hope you've got a drink and snack ready", MarathonMode.Toggle),
			["WindTunnelMode"] = new ModeUIConfig("Extreme", "WindTunnelMode", "Wind Tunnel", "Constant Downward Blizzard", "That must've been... the wind", WindTunnelMode.Toggle)
		};

		public static readonly Dictionary<string, string> InternalToDisplay = new Dictionary<string, string>
		{
			["DevilDaggerMode+CombustMode"] = "<color=#ff9500>Detonating Daggers",
			["ZenMode+BackwardMode"] = "<color=#ff9500>Backwards Buddha",
			["DevilDaggerMode+BabyMode"] = "<color=#ff4da6>Pocket Rockets",
			["HelpingHandMode+ArmlessMode"] = "<color=#f480ff>Never Skip Arm Day",
			["ZenMode+WindTunnelMode"] = "<color=#00ffff>Tranquil Tempest",
			["CombustMode+BabyMode"] = "<color=#ff490d>Coughing Bomb vs Hydrogen Baby",
			["CombustMode+GlassMode"] = "<color=#ffe6cc>Glass Cannon",
			["MarkMode+BabyMode"] = "<color=#ffe28c>Man Child",
			["BackwardMode+MarathonMode"] = "<color=#cc00ff>The Backathon",
			["DisorientedMode+MarathonMode"] = "<color=#c0c0c0>The Lost Pilgrimage",
			["ArmlessMode+LeglessMode"] = "<color=#ffff00>One Knuckle to rule them all",
			["ArmlessMode+BabyMode"] = "<color=#ff4d4d>Birth Defect",
			["BabyMode+WindTunnelMode"] = "<color=#8cffff>Freezer Baby",
			["GlassMode+MarathonMode"] = "<color=#ff00ff>The Frail Endurance",
			["MarathonMode+WindTunnelMode"] = "<color=#ff0000>Masochism",
			["DevilDaggerMode+HelpingHandMode+ZenMode+ZeroGravMode+BackwardMode+CombustMode+MarkMode+ArmlessMode+BabyMode+DisorientedMode+GlassMode+LeglessMode+MarathonMode+WindTunnelMode"] = "<color=#000000>Why"
		};
	}
	public class ModeUIConfig
	{
		public string Difficulty { get; }

		public string InternalName { get; }

		public string DisplayName { get; }

		public string Description { get; }

		public string FunDescription { get; }

		public UnityAction<bool> ToggleAction { get; }

		public bool IsEnabled { get; set; }

		public List<GameObject> Labels { get; }

		public ModeUIConfig(string difficulty, string internalName, string displayName, string description, string funDescription, UnityAction<bool> toggleAction)
		{
			Difficulty = difficulty;
			InternalName = internalName;
			DisplayName = displayName;
			Description = description;
			FunDescription = funDescription;
			ToggleAction = toggleAction;
			Labels = new List<GameObject>();
			base..ctor();
		}
	}
	public class ArmlessMode
	{
		public static bool Enabled;

		private const string ModeKey = "ArmlessMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("ArmlessMode", ref Enabled, value);
		}

		public static void Amputate(ENT_Player player)
		{
			player.hands[1].SetLocked(true);
			GameObject.Find("Interact_R").SetActive(false);
			((Component)((Component)player).transform.Find("Main Cam Root/Main Camera Shake Root/Main Camera/Inventory Camera/Inventory-Root/Right_Hand_Target")).gameObject.SetActive(false);
			CoroutineRunner.Run(DeactivateObjectsAfterDelay());
		}

		private static IEnumerator DeactivateObjectsAfterDelay()
		{
			yield return (object)new WaitForSeconds(3f);
			GameObject root = GameObject.Find("World_Root(Clone)");
			if (!Object.op_Implicit((Object)(object)root))
			{
				yield break;
			}
			List<GameObject> allObjects = GetAllChildren(root);
			foreach (GameObject obj2 in allObjects.Where((GameObject obj) => ((Object)obj).name.Contains("Prop_UpgradeConsole")))
			{
				Object.Destroy((Object)(object)obj2);
			}
		}

		private static List<GameObject> GetAllChildren(GameObject parent)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in parent.transform)
			{
				Transform val = item;
				list.Add(((Component)val).gameObject);
				list.AddRange(GetAllChildren(((Component)val).gameObject));
			}
			return list;
		}
	}
	public class BabyMode
	{
		private const float PlayerScale = 0.5f;

		private const float HoldDistance = 0.6f;

		private const float InteractDistance = 1.75f;

		private const float JumpHeight = 0.3f;

		private const float Speed = 1f;

		private const float SprintSpeed = 1.5f;

		public static bool Enabled;

		private const string ModeKey = "BabyMode";

		internal static bool IsHoldingNote;

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("BabyMode", ref Enabled, value);
		}

		public static void ApplyBabyModeToPlayer(ENT_Player player)
		{
			ApplyPlayerAttributes(player);
			AdjustWeaponsBehavior();
			player.gravity = ((!IsHoldingNote) ? (-0.2f) : (((bool)Traverse.Create((object)player).Field("falling").GetValue()) ? 0.1f : (-0.2f)));
		}

		private static void ApplyPlayerAttributes(ENT_Player player)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			((Component)player).transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
			Traverse.Create((object)player).Field("holdDistance").SetValue((object)0.6f);
			player.interactDistance = 1.75f;
			player.jumpHeight = 0.3f;
			player.speed = 1f;
			player.sprintSpeed = 1.5f;
		}

		private static void AdjustWeaponsBehavior()
		{
			string[] array = new string[5] { "Item_Hands_Rebar(Clone)", "Item_Hands_Rebar_Explosive(Clone)", "Item_Hands_RebarRope(Clone)", "Item_Hands_Rubble(Clone)", "Item_Hands_Flaregun(Clone)" };
			string[] array2 = array;
			foreach (string weaponName in array2)
			{
				try
				{
					AdjustWeaponBehavior(weaponName);
				}
				catch
				{
				}
			}
		}

		private static void AdjustWeaponBehavior(string weaponName)
		{
			HandItem_Shoot component = GameObject.Find(weaponName).GetComponent<HandItem_Shoot>();
			component.maxRecoilMagnitude = (weaponName.Contains("Flaregun") ? 1.5f : 0.513f);
			component.recoil = (weaponName.Contains("Flaregun") ? 4.5f : 3.3f);
		}
	}
	public class BackwardMode
	{
		public static bool Enabled;

		private const string ModeKey = "BackwardMode";

		private const float MarathonDelay = 2f;

		private const float NormalDelay = 0.025f;

		private const string BasePath = "Campaign-root/World_Root(Clone)";

		private const string MarathonPath = "Level Tester-root/World_Root(Clone)";

		private static readonly Action worldLoadedHandler;

		private static string CurrentPath => MarathonMode.Enabled ? "Level Tester-root/World_Root(Clone)" : "Campaign-root/World_Root(Clone)";

		static BackwardMode()
		{
			worldLoadedHandler = delegate
			{
				CoroutineRunner.Run(SetupMode());
			};
		}

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("BackwardMode", ref Enabled, value);
			ExtraModes.Logger.LogDebug((object)$"Backward Mode is now {value}");
			if (value)
			{
				WorldLoaderPatch.OnWorldLoaded = (Action)Delegate.Combine(WorldLoaderPatch.OnWorldLoaded, worldLoadedHandler);
			}
			else
			{
				WorldLoaderPatch.OnWorldLoaded = (Action)Delegate.Remove(WorldLoaderPatch.OnWorldLoaded, worldLoadedHandler);
			}
		}

		public static IEnumerator SetupMode()
		{
			ExtraModes.Logger.LogDebug((object)"Setting up Backward Mode");
			yield return WaitForModeDelay();
			SetupInitialPlayerPosition();
			DisableGameSections();
			UpdateTooltips();
			yield return WaitForModeDelay();
			SetupEndingSequence();
		}

		private static IEnumerator WaitForModeDelay()
		{
			float delay = (MarathonMode.Enabled ? 2f : 0.025f);
			yield return (object)new WaitForSeconds(delay);
		}

		private static void SetupInitialPlayerPosition()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//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_0030: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindObject("M3_Habitation_Lab_Ending(Clone)");
			Vector3 position = val.transform.position + new Vector3(0f, 24f, 0f);
			GameObject val2 = GameObject.FindGameObjectWithTag("Player");
			val2.transform.position = position;
			DisableEndingTriggers(val);
			if (!MarathonMode.Enabled)
			{
				SpawnFlashlight(position);
			}
		}

		private static void SpawnFlashlight(Vector3 position)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			GameObject val = CL_AssetManager.instance.assetDatabase.itemPrefabs.Find((GameObject item) => ((Object)item).name == "Item_Flashlight");
			Object.Instantiate<GameObject>(val, position + new Vector3(0f, -4f, 0f), Quaternion.identity);
		}

		private static void DisableEndingTriggers(GameObject ending)
		{
			((Component)ending.transform.Find("Scripting")).gameObject.SetActive(false);
			((Component)ending.transform.Find("Trigger-EvacuationOrder")).gameObject.SetActive(false);
			ExtraModes.Logger.LogDebug((object)"Player position set");
		}

		private static void DisableGameSections()
		{
			DisableHauntedPierSections();
			DisableShaftSections();
			DisableForlornGatewaySection();
			DisableInterlude1Section();
		}

		private static void DisableHauntedPierSections()
		{
			List<GameObject> list = FindObjects("M3_Habitation_Pier_Entrance_01(Clone)/M3_Habitation_Pier_Entryway_01/Level_Hull");
			foreach (GameObject item in list)
			{
				ExtraModes.Logger.LogDebug((object)$"Disabling Objects in {item}");
				SetGameObjectActive(item, "Rollup_Door_Big.002", active: false);
				SetGameObjectActive(item, "Rollup_Door_Big.003", active: false);
			}
			List<GameObject> list2 = FindObjects("M3_Habitation_Shaft_To_Pier(Clone)");
			foreach (GameObject item2 in list2)
			{
				ExtraModes.Logger.LogDebug((object)$"Disabling Objects in {item2}");
				SetGameObjectActive(item2, "Scripting", active: false);
				SetGameObjectActive(item2, "Service Elevator", active: false);
			}
		}

		private static void DisableShaftSections()
		{
			List<GameObject> list = FindObjects("M3_Habitation_Shaft_Intro(Clone)");
			foreach (GameObject item in list)
			{
				ExtraModes.Logger.LogDebug((object)$"Disabling Objects in {item}");
				SetGameObjectActive(item, "M3_Shaft_Intro/Level_Hull/Rollup_Door_Big", active: false);
				SetGameObjectActive(item, "M3_Shaft_Intro/LU_Transition_Entrance_Bay", active: true);
				SetGameObjectActive(item, "Entities", active: false);
			}
			try
			{
				GameObject.Find(CurrentPath + "/M3_Habitation_Endless_Shaft_End(Clone)/Scripting/Trigger-VentDoor").SetActive(false);
			}
			catch
			{
			}
			try
			{
				((CL_Button)GameObject.Find(CurrentPath + "/M1_Silos_Air_08(Clone)/Prop_Button_02_Switch").GetComponent<CL_ToggleButton>()).Interact();
			}
			catch
			{
			}
			try
			{
				GameObject.Find(CurrentPath + "/M1_Silos_Air_06(Clone)/Vent-Pull").gameObject.SetActive(false);
			}
			catch
			{
			}
		}

		private static void DisableForlornGatewaySection()
		{
			List<GameObject> list = FindObjects("M3_Campaign_Transition_Pipeworks_To_Habitation_01(Clone)/Sections");
			foreach (GameObject item in list)
			{
				ExtraModes.Logger.LogDebug((object)$"Disabling Objects in {item}");
				SetGameObjectActive(item, "M3_Habitation_Entryway/Level Scripting", active: false);
				SetGameObjectActive(item, "M3_Habitation_Entryway/Structure_I2_EntrywayDoor", active: false);
				SetGameObjectActive(item, "Interlude 2/M2_Campaign_Pipeworks_To_Habitation_01/Doors", active: false);
			}
			List<GameObject> list2 = FindObjects("M3_Habitation_Shaft_Intro(Clone)");
			foreach (GameObject item2 in list2)
			{
				SetGameObjectActive(item2, "Entities/Trigger-EnterShaft", active: false);
			}
		}

		private static void DisableInterlude1Section()
		{
			List<GameObject> list = FindObjects("M1_Campaign_Transition_Silo_To_Pipeworks_01(Clone)");
			foreach (GameObject item in list)
			{
				ExtraModes.Logger.LogDebug((object)$"Disabling Objects in {item}");
				SetGameObjectActive(item, "Entities (1)/Elevator_Fakeout", active: false);
				SetGameObjectActive(item, "Door_Grate_01/Door_Grate_01", active: false);
				SetGameObjectActive(item, "Prop_Button_02_Switch", active: false);
			}
		}

		private static void SetupEndingSequence()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindObject("M1_Intro_01(Clone)");
			Object.Instantiate<GameObject>(Assets.EndObj, Vector3.zero, Quaternion.identity, val.transform);
		}

		private static void UpdateTooltips()
		{
			string objectPath = (MarathonMode.Enabled ? "Level Tester-root/World_Root(Clone)/M3_Campaign_Transition_Pipeworks_To_Habitation_01(Clone)" : "Campaign-root/World_Root(Clone)/M3_Campaign_Transition_Pipeworks_To_Habitation_01(Clone)");
			string objectPath2 = (MarathonMode.Enabled ? "Level Tester-root/World_Root(Clone)/M1_Campaign_Transition_Silo_To_Pipeworks_01(Clone)" : "Campaign-root/World_Root(Clone)/M1_Campaign_Transition_Silo_To_Pipeworks_01(Clone)");
			TooltipHelper.UpdateLevelTooltip(objectPath2, "<size=40>Outerlude</size>\n<color=grey>Keyup</color>");
			TooltipHelper.UpdateLevelTooltip(objectPath, "<size=40>Outerlude</size>\n<color=grey>Descent</color>");
		}

		private static GameObject FindObject(string name)
		{
			return GameObject.Find(CurrentPath + "/" + name);
		}

		private static List<GameObject> FindObjects(string name)
		{
			string expectedPath = CurrentPath + "/" + name;
			return (from t in Object.FindObjectsOfType<Transform>(true)
				where GetFullPath(t).EndsWith(expectedPath)
				select ((Component)t).gameObject).ToList();
		}

		private static string GetFullPath(Transform t)
		{
			string text = ((Object)t).name;
			while ((Object)(object)t.parent != (Object)null)
			{
				t = t.parent;
				text = ((Object)t).name + "/" + text;
			}
			return text;
		}

		private static void SetGameObjectActive(GameObject level, string path, bool active)
		{
			GameObject gameObject = ((Component)level.transform.Find(path)).gameObject;
			if (Object.op_Implicit((Object)(object)gameObject))
			{
				gameObject.SetActive(active);
			}
		}
	}
	public class CombustMode
	{
		private static float _accumulatedTime;

		private const float Threshold = 1f;

		public static bool Enabled;

		private const string ModeKey = "CombustMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("CombustMode", ref Enabled, value);
		}

		public static void RandomlyCombust(ENT_Player player)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			_accumulatedTime += Time.deltaTime;
			if (_accumulatedTime >= 1f)
			{
				_accumulatedTime = 0f;
				if (Random.Range(0, 10) == 0)
				{
					Vector3 val = Random.insideUnitSphere * 1f;
					Vector3 val2 = ((Component)player).transform.position + new Vector3(val.x, val.y, val.z);
					GameObject val3 = Object.Instantiate<GameObject>(Assets.RebarExplosion, val2, Quaternion.identity);
					Object.Destroy((Object)(object)val3, 5f);
				}
			}
		}
	}
	public class DevilDaggerMode
	{
		public static bool Enabled;

		private static float _accumulatedTime;

		private const float ShootTimer = 0.1f;

		private const string ModeKey = "DevilDaggerMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("DevilDaggerMode", ref Enabled, value);
		}

		public static void SpawnRebar(int hand, ENT_Player player)
		{
			//IL_0070: 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_0089: 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_0099: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			_accumulatedTime += Time.deltaTime;
			if (_accumulatedTime < 0.1f)
			{
				return;
			}
			_accumulatedTime = 0f;
			Hand val = player.hands[hand];
			string fireButton = val.fireButton;
			if (InputManager.GetButton(fireButton).Pressed)
			{
				GameObject val2 = (CombustMode.Enabled ? Assets.RebarExplosive : Assets.Rebar);
				GameObject val3 = Object.Instantiate<GameObject>(val2, Vector3.Lerp(((Component)player).transform.position, ((Component)Camera.main).transform.position, 0.5f) + -((Component)player).transform.forward * 0.25f, Quaternion.LookRotation(((Component)Camera.main).transform.forward));
				val3.GetComponent<Projectile>().Initialize(((Component)Camera.main).transform.forward * 50f);
				CL_CameraControl.Shake(0.01f);
				if (player.cCon.isGrounded)
				{
					((GameEntity)player).AddForce(-((Component)Camera.main).transform.forward * 0.05f);
				}
				else
				{
					((GameEntity)player).AddForce(-((Component)Camera.main).transform.forward * 0.2f);
				}
				player.DropHang(0.1f);
			}
		}
	}
	public class DisorientedMode
	{
		public static bool Enabled;

		private const string ModeKey = "DisorientedMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("DisorientedMode", ref Enabled, value);
		}

		public static void SetCameraTransform(ENT_Player player)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			((Component)player).transform.Find("Main Cam Root").Rotate(new Vector3(0f, 0f, 180f));
		}
	}
	public class GlassMode
	{
		public static bool Enabled;

		private const string ModeKey = "GlassMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("GlassMode", ref Enabled, value);
		}

		public static void SetPlayerHp(ENT_Player player)
		{
			((GameEntity)player).maxHealth = 0.1f;
		}
	}
	public class HelpingHandMode
	{
		public static bool Enabled;

		private const string ModeKey = "HelpingHandMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("HelpingHandMode", ref Enabled, value);
		}

		public static void SetPerks(ENT_Player player)
		{
			foreach (Perk item in CL_AssetManager.instance.assetDatabase.perkAssets.Where((Perk perk) => ((Object)perk).name.Contains("Perk_T1")))
			{
				ExtraModes.Logger.LogDebug((object)("Adding " + ((Object)item).name + " to player"));
				player.AddPerk(new string[1] { item.id.ToLower() });
			}
		}
	}
	public class LeglessMode
	{
		public static bool Enabled;

		private const string ModeKey = "LeglessMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("LeglessMode", ref Enabled, value);
		}

		public static void Amputate(ENT_Player player)
		{
			Traverse.Create((object)player).Field("hasJumped").SetValue((object)true);
		}
	}
	public class MarathonMode
	{
		public static bool Enabled;

		private const string ModeKey = "MarathonMode";

		private static Event_Cold _blizzard;

		private static Event_Cold_Controller _blizzardController;

		private const string MainMenuScene = "Main-Menu";

		private const float PreloadTimer = 0.25f;

		private const string ChimneyStartPath = "Level Tester-root/World_Root(Clone)/MX_Chimney_Start_01(Clone)";

		private const float BlizzardBlendValue = 0.95f;

		private static readonly Action worldLoadedHandler;

		static MarathonMode()
		{
			worldLoadedHandler = delegate
			{
				CoroutineRunner.Run(ModifyLevelsAsync());
			};
		}

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("MarathonMode", ref Enabled, value);
			if (value)
			{
				WorldLoaderPatch.OnWorldLoaded = (Action)Delegate.Combine(WorldLoaderPatch.OnWorldLoaded, worldLoadedHandler);
			}
			else
			{
				WorldLoaderPatch.OnWorldLoaded = (Action)Delegate.Remove(WorldLoaderPatch.OnWorldLoaded, worldLoadedHandler);
			}
		}

		public static bool LoadLibraryLevels()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name != "Main-Menu")
			{
				return false;
			}
			GameObject.Find("GameManager").GetComponent<CL_GameManager>().LoadLevels(LevelsList.orderedLevels.ToArray());
			return true;
		}

		private static IEnumerator ModifyLevelsAsync()
		{
			ExtraModes.Logger.LogDebug((object)"Setting up Marathon Mode");
			yield return (object)new WaitForSeconds(0.25f);
			ModifyOtherLevels();
			ModifyEnding();
			ClearOtherLevelObjects();
			SetupBlizzardEvent();
		}

		private static void ModifyOtherLevels()
		{
			GameObject val = GameObject.Find("Level Tester-root/World_Root(Clone)/MX_Chimney_Start_01(Clone)");
			if (Object.op_Implicit((Object)(object)val))
			{
				ReplaceChimneyLevel(val);
				TooltipHelper.UpdateLevelTooltip("Level Tester-root/World_Root(Clone)/MX_Chimney_Crystal_01(Clone)", null, "The Final Stretch");
				TooltipHelper.UpdateLevelTooltip("Level Tester-root/World_Root(Clone)/M3_Habitation_LadderWarp_Loop(Clone)", "<size=40>???</size>\n<color=grey>I lied sorgy</color>");
			}
		}

		private static void ModifyEnding()
		{
			//IL_0068: 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)
			//IL_008d: 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_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)
			GameObject val = GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Habitation_Lab_Ending(Clone)");
			GameObject val2 = GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Habitation_LadderWarp_Void_06(Clone)");
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				ExtraModes.Logger.LogError((object)"Ending not found");
				return;
			}
			Transform val3 = val.transform.Find("M3_Lab_Ending/Level_Entrance");
			Transform val4 = val2.transform.Find("M3_LadderWarp_Void_06/Level_GEO_Root/LU_Transition_Exit_01");
			val4.localPosition += new Vector3(-4.5f, 0f, 0f);
			Vector3 val5 = val4.position - val3.position;
			Transform transform = val.transform;
			transform.position += val5;
		}

		private static void ReplaceChimneyLevel(GameObject chimneyStart)
		{
			//IL_000d: 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)
			GameObject chimneyStartReplacement = Assets.ChimneyStartReplacement;
			chimneyStartReplacement.transform.localScale = Vector3.one * 0.01f;
			((Component)chimneyStart.transform.Find("FX_Zone.03")).GetComponent<FX_Zone>().blend = 0.95f;
			DestroyObjectsInChimney(chimneyStart);
			Object.Instantiate<GameObject>(chimneyStartReplacement, ((Component)chimneyStart.transform.Find("MX_Chimney_Start_01")).transform);
		}

		private static void DestroyObjectsInChimney(GameObject chimneyStart)
		{
			string[] array = new string[4] { "MX_Chimney_Start_01/L_Snow.001", "MX_Chimney_Start_01/Lighting/Light-Yellow.004", "MX_Chimney_Start_01/Lighting/Light-Ambience.009", "MX_Chimney_Start_01/Level_Hull" };
			string[] array2 = array;
			foreach (string text in array2)
			{
				Transform obj = chimneyStart.transform.Find(text);
				GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static void SetupBlizzardEvent()
		{
			if (!WindTunnelMode.Enabled)
			{
				CoroutineRunner.Run(BlizzardFactory.CreateBlizzard(delegate(Event_Cold blizzard)
				{
					_blizzard = blizzard;
				}));
			}
			GameObject val = GameObject.Find("M1_Intro_01(Clone)/M1_Intro_01/Level_Hull");
			_blizzardController = val.AddComponent<Event_Cold_Controller>();
		}

		private static void ClearOtherLevelObjects()
		{
			GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Campaign_Transition_Pipeworks_To_Habitation_01(Clone)/Level Scripting/Goo Controllers").SetActive(false);
			GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Habitation_LadderWarp_Loop(Clone)/WinTrigger").SetActive(false);
			GameObject val = GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Habitation_Shaft_Intro(Clone)/Entities/Trigger-RoomEnter");
			UT_GooController[] components = val.GetComponents<UT_GooController>();
			foreach (UT_GooController val2 in components)
			{
				Object.Destroy((Object)(object)val2);
			}
		}

		internal static void UpdateColdEvent(LevelInfo currentLevel)
		{
			if (Object.op_Implicit((Object)(object)_blizzard) && Object.op_Implicit((Object)(object)_blizzardController) && !IsChimneyOrWindTunnelEnabled(currentLevel))
			{
				AdjustBlizzardEffects();
			}
		}

		private static void AdjustBlizzardEffects()
		{
			BuffContainer value = Traverse.Create((object)((Component)_blizzard).GetComponent<Event_Cold>()).Field("coldDebuff").GetValue<BuffContainer>();
			value.SetMultiplier(0f);
			_blizzardController.SetColdEventState(false);
		}

		private static bool IsChimneyOrWindTunnelEnabled(LevelInfo levelInfo)
		{
			return levelInfo.level.levelName.Contains("Chimney") || WindTunnelMode.Enabled;
		}

		internal static IEnumerator SetGiftRoomParams(M_Level level)
		{
			yield return (object)new WaitForSeconds(0.5f);
			if (level.levelName.Contains("MX_Chimney_Gift"))
			{
				ExtraModes.Logger.LogDebug((object)("Setting door vectors for " + level.levelName));
				UT_Door door1 = ((Component)((Component)level).transform.Find("Doors/Door_Reinforced_01")).GetComponent<UT_Door>();
				UT_Door door2 = ((Component)((Component)level).transform.Find("Doors/Door_Reinforced_01.01")).GetComponent<UT_Door>();
				Vector3 pos1 = Traverse.Create((object)door1).Field("startPos").GetValue<Vector3>() + new Vector3(0f, 0f, -5f);
				Traverse.Create((object)door1).Field("endPos").SetValue((object)pos1);
				Vector3 pos2 = Traverse.Create((object)door2).Field("startPos").GetValue<Vector3>() + new Vector3(0f, 0f, -5f);
				Traverse.Create((object)door2).Field("endPos").SetValue((object)pos2);
				if (BackwardMode.Enabled)
				{
					CL_ToggleButton button = ((Component)((Component)level).transform.Find("Doors/Prop_Button_Console_01/Prop_Button_02_Switch")).GetComponent<CL_ToggleButton>();
					((CL_Button)button).Interact();
				}
			}
		}
	}
	public static class MarkMode
	{
		public static bool Enabled;

		private const string ModeKey = "MarkMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("MarkMode", ref Enabled, value);
		}
	}
	public class WindTunnelMode
	{
		public static bool Enabled;

		private const string ModeKey = "WindTunnelMode";

		private static Event_Cold _blizzard;

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("WindTunnelMode", ref Enabled, value);
		}

		internal static void AddBlizzardEvent()
		{
			CoroutineRunner.Run(BlizzardFactory.CreateBlizzard(delegate(Event_Cold blizzard)
			{
				_blizzard = blizzard;
				_blizzard.StartBlizzard();
			}, 1f, 0f));
		}

		internal static void UpdateBlizzardEvent()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_blizzard))
			{
				Traverse val = Traverse.Create((object)_blizzard).Field("blizzardWindDirection");
				val.SetValue((object)Vector3.down);
				if (!Traverse.Create((object)_blizzard).Field<bool>("hasBlizzard").Value)
				{
					_blizzard.StartBlizzard();
				}
			}
		}
	}
	public static class ZenMode
	{
		public static bool Enabled;

		private const string ModeKey = "ZenMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("ZenMode", ref Enabled, value);
		}

		private static void HandleZenMode(GameObject gameObject, string logMessage)
		{
			gameObject.SetActive(false);
			ExtraModes.Logger.LogDebug((object)(logMessage + " Disabled"));
		}

		public static void ZenMass(DEN_DeathFloor deathFloor)
		{
			HandleZenMode(((Component)deathFloor).gameObject, "Mass");
		}

		public static void ZenTeeth(DEN_Teeth teeth)
		{
			teeth.Despawn();
			ExtraModes.Logger.LogDebug((object)"Teeth Disabled");
		}

		public static void ZenTurret(DEN_Turret turret)
		{
			HandleZenMode(((Component)turret).gameObject, "Turret");
		}

		internal static void ZenBloodbug(DEN_Bloodbug bloodbug)
		{
			HandleZenMode(((Component)bloodbug).gameObject, "Bloodbug");
		}

		internal static void ZenVentThing(DEN_VentThing ventThing)
		{
			HandleZenMode(((Component)ventThing).gameObject, "Vent Thing");
		}

		public static void SetPlayerHp(ENT_Player player)
		{
			((GameEntity)player).health = 5f;
		}
	}
	public class ZeroGravMode
	{
		public static bool Enabled;

		private const string ModeKey = "ZeroGravMode";

		public static void Toggle(bool value)
		{
			ModeHelper.ToggleMode("ZeroGravMode", ref Enabled, value);
		}

		public static void SetGravity(ENT_Player player)
		{
			Traverse.Create((object)player).Field("hasGravity").SetValue((object)false);
			player.dragCoefficient = 0.05f;
		}
	}
}
namespace WK_Extra_Modes.Helpers
{
	public static class BlizzardFactory
	{
		public static IEnumerator CreateBlizzard(Action<Event_Cold> onComplete, float windSpeed = 0.14f, float windChangeRate = 0.1f, float coldMultiplier = 0f)
		{
			GameObject blizzardObj = Object.Instantiate<GameObject>(Assets.EventCold);
			yield return null;
			Event_Cold blizzard = blizzardObj.GetComponent<Event_Cold>();
			BuffContainer buffContainer = Traverse.Create((object)blizzard).Field("coldDebuff").GetValue<BuffContainer>();
			buffContainer.SetMultiplier(coldMultiplier);
			blizzard.blizzardWindSpeed = windSpeed;
			blizzard.blizzardWindChangeRate = windChangeRate;
			onComplete?.Invoke(blizzard);
		}
	}
	public class CoroutineRunner : MonoBehaviour
	{
		private static CoroutineRunner _instance;

		public static void Run(IEnumerator coroutine)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = new GameObject("CoroutineRunner").AddComponent<CoroutineRunner>();
				Object.DontDestroyOnLoad((Object)(object)_instance);
			}
			((MonoBehaviour)_instance).StartCoroutine(coroutine);
		}
	}
	public class ExtremeColourAnimator : MonoBehaviour
	{
		private void Update()
		{
			//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_001e: 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)
			Color extremeColor = UI.GetExtremeColor();
			foreach (Image extremeImage in UI.ExtremeImages)
			{
				((Graphic)extremeImage).color = extremeColor;
			}
			foreach (TMP_Text extremeLabel in UI.ExtremeLabels)
			{
				((Graphic)extremeLabel).color = extremeColor;
			}
		}
	}
	public static class GameObjectHelper
	{
		public static void Disable(GameObject obj, string logMessage)
		{
			obj.SetActive(false);
			ExtraModes.Logger.LogDebug((object)(logMessage + " Disabled"));
		}

		public static void Enable(GameObject obj, string logMessage)
		{
			obj.SetActive(false);
			ExtraModes.Logger.LogDebug((object)(logMessage + " Enabled"));
		}
	}
	public static class ModeHelper
	{
		public static void ToggleMode(string modeKey, ref bool enabled, bool toggleValue)
		{
			enabled = toggleValue;
			if (ModeRegistry.ModeConfigs.TryGetValue(modeKey, out var value))
			{
				SetMode(enabled, value.Labels, value.DisplayName);
			}
			else
			{
				Debug.LogError((object)("Mode '" + modeKey + "' not found in registry!"));
			}
		}

		private static void SetMode(bool enabled, List<GameObject> labels, string modeName)
		{
			labels.ForEach(delegate(GameObject label)
			{
				if (label != null)
				{
					label.gameObject.SetActive(enabled);
				}
			});
			CL_GameManager.gamemode.allowAchievements = !enabled;
			CommandConsole.hasCheated = enabled;
			ExtraModes.Logger.LogDebug((object)(enabled ? (modeName + " Enabled!") : (modeName + " Disabled!")));
		}
	}
	public static class TooltipHelper
	{
		internal static void UpdateLevelTooltip(string objectPath, string levelToolTip, string subRegionToolTip = null, string regionToolTip = null)
		{
			GameObject val = GameObject.Find(objectPath);
			if (Object.op_Implicit((Object)(object)val))
			{
				ExtraModes.Logger.LogDebug((object)$"Updating tooltip for {val}");
				M_Level component = val.GetComponent<M_Level>();
				if (levelToolTip != null)
				{
					component.introText = levelToolTip;
				}
				if (subRegionToolTip != null)
				{
					component.subRegion.introText = subRegionToolTip;
				}
				if (regionToolTip != null)
				{
					component.region.introText = regionToolTip;
				}
			}
		}
	}
}
namespace WK_Extra_Modes.Core
{
	public class Assets
	{
		private static AssetBundle _assets;

		internal static GameObject ExtraModesMenu;

		internal static GameObject StatTracker;

		internal static GameObject Tooltip;

		internal static GameObject ExtraModesButton;

		internal static GameObject EventCold;

		internal static GameObject ChimneyStartReplacement;

		internal static GameObject EndObj;

		internal static GameObject RebarExplosion;

		internal static GameObject Rebar;

		internal static GameObject RebarExplosive;

		internal static GameObject UIEffects;

		internal static bool Load()
		{
			_assets = AssetBundle.LoadFromFile(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Assets/extra_modes_assets");
			if (!Object.op_Implicit((Object)(object)_assets))
			{
				ExtraModes.Logger.LogError((object)"Failed to load AssetBundle, aborting!");
				return false;
			}
			List<bool> source = new List<bool>(10)
			{
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/Extra Modes Menu.prefab", out ExtraModesMenu),
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/Stat Tracker.prefab", out StatTracker),
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/TooltipManager.prefab", out Tooltip),
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/Extra Modes Button.prefab", out ExtraModesButton),
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/Event_Cold.prefab", out EventCold),
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/Level_Hull.prefab", out ChimneyStartReplacement),
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/EndObj.prefab", out EndObj),
				LoadFile<GameObject>(_assets, "Assets/Neb.Assets/Extra Modes/Item_Rebar_Hit_Explosion.prefab", out RebarExplosion),
				LoadFile<GameObject>(_assets, "Assets/GameObject/Projectile_Rebar.prefab", out Rebar),
				LoadFile<GameObject>(_assets, "Assets/GameObject/Projectile_Rebar_Explosive.prefab", out RebarExplosive)
			};
			if (source.Any((bool result) => !result))
			{
				ExtraModes.Logger.LogWarning((object)"Failed to load one or more assets, aborting!");
				return false;
			}
			return true;
		}

		private static bool LoadFile<T>(AssetBundle assets, string path, out T loadedObject) where T : Object
		{
			loadedObject = assets.LoadAsset<T>(path);
			if (!Object.op_Implicit((Object)(object)loadedObject))
			{
				ExtraModes.Logger.LogError((object)("Failed to load '" + path + "'"));
				return false;
			}
			return true;
		}
	}
	public class SecretCodeListener : MonoBehaviour
	{
		private string currentInput = "";

		public string targetCode = ":3";

		private void Update()
		{
			string inputString = Input.inputString;
			for (int i = 0; i < inputString.Length; i++)
			{
				currentInput += inputString[i];
				if (currentInput.Length > targetCode.Length)
				{
					currentInput = currentInput.Substring(currentInput.Length - targetCode.Length);
				}
				if (currentInput == targetCode)
				{
					ExtraModes.Logger.LogInfo((object)"Silly activated! :3");
					UI.SillyEnabled = !UI.SillyEnabled;
					currentInput = "";
				}
			}
		}
	}
	public class StatTracker : MonoBehaviour
	{
		private static StatTracker _instance;

		private SaveData saveData;

		private TMP_Text modeValue;

		private TMP_Text scoreValue;

		private TMP_Text completedValue;

		private TMP_Text timeValue;

		private TMP_Text ascentValue;

		private UI_LerpOpen lerpComponent;

		private string[] _currentNames;

		public bool IsShowing { get; internal set; }

		private void Awake()
		{
			Transform obj = ((Component)this).transform.Find("Mode/Mode Value");
			modeValue = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
			Transform obj2 = ((Component)this).transform.Find("Stats Body/Score/Score Value");
			scoreValue = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null);
			Transform obj3 = ((Component)this).transform.Find("Stats Body/Time/Time Value");
			timeValue = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
			Transform obj4 = ((Component)this).transform.Find("Stats Body/Completed/Completed Value");
			completedValue = ((obj4 != null) ? ((Component)obj4).GetComponent<TMP_Text>() : null);
			Transform obj5 = ((Component)this).transform.Find("Stats Body/Ascent Rate/Ascent Rate Value");
			ascentValue = ((obj5 != null) ? ((Component)obj5).GetComponent<TMP_Text>() : null);
			ExtraModes.Logger.LogDebug((object)"Initialised StatTracker");
			lerpComponent = ((Component)this).GetComponent<UI_LerpOpen>();
			saveData = SaveManager.LoadData();
		}

		private void Start()
		{
			_instance = this;
		}

		private void Update()
		{
			List<ModeUIConfig> source = ModeRegistry.ModeConfigs.Values.Where(ShouldProcessConfig).ToList();
			if (source.Any())
			{
				ShowLerpIfNecessary();
				string[] array = source.Select((ModeUIConfig c) => c.InternalName).ToArray();
				if (_currentNames == null || !array.SequenceEqual(_currentNames))
				{
					_currentNames = array;
					UpdateValues(array);
				}
			}
			else if (IsShowing)
			{
				IsShowing = false;
				UI_LerpOpen obj = lerpComponent;
				if (obj != null)
				{
					obj.Hide();
				}
			}
		}

		private bool ShouldProcessConfig(ModeUIConfig config)
		{
			return config.IsEnabled && UI.IsUIOpen;
		}

		private void UpdateValues(string[] modeNames)
		{
			string key = string.Join("+", modeNames);
			if (!ModeRegistry.InternalToDisplay.TryGetValue(key, out var value))
			{
				List<string> list = new List<string>();
				foreach (string mode in modeNames)
				{
					ModeUIConfig modeUIConfig = ModeRegistry.ModeConfigs.Values.First((ModeUIConfig c) => c.InternalName == mode);
					string difficulty = modeUIConfig.Difficulty;
					if (1 == 0)
					{
					}
					string text = difficulty switch
					{
						"Easy" => "#00FF00", 
						"Medium" => "#FFAF00", 
						"Hard" => "#FF0000", 
						"Extreme" => "#B31E00", 
						_ => "#FFFFFF", 
					};
					if (1 == 0)
					{
					}
					string text2 = text;
					list.Add("<color=" + text2 + ">" + modeUIConfig.DisplayName);
				}
				value = string.Join(" <color=#ffffff>+ ", list);
			}
			ExtraModes.Logger.LogDebug((object)("Updating display for " + value));
			modeValue.text = value;
			if (!saveData.ModeRuns.TryGetValue(key, out var value2))
			{
				ExtraModes.Logger.LogDebug((object)("No run data found for " + value + ", using default values"));
				scoreValue.text = "0";
				timeValue.text = "00:00:00.00";
				completedValue.text = "No";
				ascentValue.text = "0.00m/s";
			}
			else
			{
				ExtraModes.Logger.LogDebug((object)$"Updating UI with run data - Score: {value2.Score}, Completed: {value2.Completed}, Time: {value2.TimeTaken}, Ascent: {value2.AscentRate}");
				scoreValue.text = value2.Score.ToString();
				timeValue.text = TimeSpan.FromSeconds(value2.TimeTaken).ToString("hh\\:mm\\:ss\\.ff");
				completedValue.text = (value2.Completed ? "Yes" : "No");
				ascentValue.text = $"{value2.AscentRate:F2}m/s";
			}
		}

		private void ShowLerpIfNecessary()
		{
			if (!IsShowing)
			{
				ExtraModes.Logger.LogDebug((object)"Showing lerp component");
				IsShowing = true;
				UI_LerpOpen obj = lerpComponent;
				if (obj != null)
				{
					obj.Show();
				}
			}
		}

		public void RefreshSaveData()
		{
			saveData = SaveManager.LoadData();
			ExtraModes.Logger.LogInfo((object)"Refreshed Save Data");
		}
	}
	public class Tooltip : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		private bool isShowing;

		internal string Description = "";

		internal string FunDescription = "";

		public void OnPointerEnter(PointerEventData eventData)
		{
			isShowing = true;
			UI.ToolTip.OnMouseHover.Invoke(UI.SillyEnabled ? FunDescription : Description);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			isShowing = false;
			UI.ToolTip.OnMouseLoseFocus.Invoke();
		}

		private void Update()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (isShowing)
			{
				UI.ToolTip.UpdateTip(Input.mousePosition + new Vector3(10f, -10f, 0f));
			}
		}
	}
	internal class TooltipManager : MonoBehaviour
	{
		private TMP_Text tipText;

		private RectTransform tipWindow;

		private ContentSizeFitter sizeFitter;

		public UnityAction<string> OnMouseHover;

		public UnityAction OnMouseLoseFocus;

		private void Awake()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			tipWindow = ((Component)((Component)this).transform).GetComponent<RectTransform>();
			tipText = ((Component)((Component)this).transform.Find("Description")).GetComponent<TMP_Text>();
			sizeFitter = ((Component)((Component)this).transform).GetComponent<ContentSizeFitter>();
			OnMouseHover = (UnityAction<string>)(object)Delegate.Combine((Delegate?)(object)OnMouseHover, (Delegate?)(object)new UnityAction<string>(ShowTip));
			OnMouseLoseFocus = (UnityAction)Delegate.Combine((Delegate?)(object)OnMouseLoseFocus, (Delegate?)new UnityAction(HideTip));
			((Component)((Component)this).transform).gameObject.SetActive(false);
			ExtraModes.Logger.LogDebug((object)"Initialised TooltipManager");
		}

		private void ShowTip(string tip)
		{
			tipText.text = tip;
			((Component)((Component)this).transform).gameObject.SetActive(true);
			LayoutRebuilder.ForceRebuildLayoutImmediate(tipWindow);
		}

		internal void UpdateTip(Vector3 mousePos)
		{
			//IL_0007: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			((Transform)tipWindow).position = new Vector3(mousePos.x, mousePos.y, 0f);
		}

		private void HideTip()
		{
			((Component)((Component)this).transform).gameObject.SetActive(false);
		}
	}
	public static class UI
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__32_0;

			public static UnityAction <>9__34_0;

			public static Func<Color> <>9__39_0;

			public static Func<Color> <>9__39_1;

			public static Func<Color> <>9__39_2;

			internal void <SetupCloseButton>b__32_0()
			{
				_extremePane.GetComponent<UI_LerpOpen>().Hide();
				_statTracker.GetComponent<UI_LerpOpen>().Hide();
				IsUIOpen = false;
				_statTracker.GetComponent<StatTracker>().IsShowing = false;
				_isExtremePaneVisible = false;
			}

			internal void <SetupExtraModesButton>b__34_0()
			{
				_extraModesPane.GetComponent<UI_LerpOpen>().Show();
				IsUIOpen = true;
			}

			internal Color <InitDictionaries>b__39_0()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return Color.green;
			}

			internal Color <InitDictionaries>b__39_1()
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				return new Color(1f, 0.65f, 0f);
			}

			internal Color <InitDictionaries>b__39_2()
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return Color.red;
			}
		}

		private static GameObject _extraModesButton;

		private static GameObject _extraModesPane;

		private static GameObject _statTracker;

		private static GameObject _extremePane;

		private static GameObject _modeToggleTemplate;

		private static GameObject _FX;

		private static SaveData _saveData;

		private static Dictionary<string, GameObject> _difficultyColumns;

		private static Dictionary<string, Func<Color>> _difficultyColors;

		private static readonly List<Image> _extremeImages = new List<Image>();

		private static readonly List<TMP_Text> _extremeLabels = new List<TMP_Text>();

		private static bool _isExtremePaneVisible;

		public static bool SillyEnabled = false;

		private static int _modesCompleted;

		private const string MainMenuSceneName = "Main-Menu";

		private const string IntroSceneName = "Intro";

		internal static TooltipManager ToolTip { get; private set; }

		public static bool IsUIOpen { get; private set; }

		public static List<Image> ExtremeImages => _extremeImages;

		public static List<TMP_Text> ExtremeLabels => _extremeLabels;

		public static Color GetExtremeColor()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return GetFlashingExtremeColor();
		}

		internal static void OnSceneLoad(Scene scene, LoadSceneMode mode)
		{
			if (!(((Scene)(ref scene)).name != "Main-Menu"))
			{
				_saveData = SaveManager.LoadData();
				ResetModeStatus();
				InitializeUI();
				SetupExtremeToggle();
				SetupCloseButton();
				SetupMainToggleTemplate();
				InitDictionaries();
				SetupExtraModesButton();
				AddModeToggles();
				ResetAllModeToggles();
				SetupLevels();
			}
		}

		private static void InitializeUI()
		{
			_extraModesButton = Object.Instantiate<GameObject>(Assets.ExtraModesButton, GameObject.Find("Mutators").transform);
			_extraModesPane = Object.Instantiate<GameObject>(((Component)Assets.ExtraModesMenu.transform.Find("Extra Modes Pane")).gameObject, GameObject.Find("Screens").transform);
			_extraModesPane.AddComponent<SecretCodeListener>();
			ToolTip = Object.Instantiate<GameObject>(Assets.Tooltip, GameObject.Find("Canvas").transform).AddComponent<TooltipManager>();
			_extremePane = Object.Instantiate<GameObject>(((Component)Assets.ExtraModesMenu.transform.Find("Extreme Pane")).gameObject, GameObject.Find("Screens").transform);
			_extremePane.AddComponent<ExtremeColourAnimator>();
			_statTracker = Object.Instantiate<GameObject>(Assets.StatTracker, GameObject.Find("Screens").transform);
			_statTracker.AddComponent<StatTracker>();
		}

		private static void SetupExtremeToggle()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			int chainNum = 1;
			Button extremeButton = ((Component)_extraModesPane.transform.Find("Extreme Button")).GetComponent<Button>();
			_isExtremePaneVisible = false;
			((UnityEvent)extremeButton.onClick).AddListener((UnityAction)delegate
			{
				if (_modesCompleted >= chainNum && chainNum <= 3)
				{
					Transform val = ((Component)extremeButton).transform.Find($"Chain_0{chainNum}");
					((Component)val).gameObject.SetActive(false);
					chainNum++;
				}
				else if (chainNum == 4)
				{
					((Selectable)extremeButton).interactable = true;
					UI_LerpOpen component = _extremePane.GetComponent<UI_LerpOpen>();
					if (_isExtremePaneVisible)
					{
						component.Hide();
					}
					else
					{
						component.Show();
					}
					_isExtremePaneVisible = !_isExtremePaneVisible;
				}
			});
		}

		private static void SetupCloseButton()
		{
			//IL_0035: 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_0040: Expected O, but got Unknown
			Button component = ((Component)_extraModesPane.transform.Find("Save And Close")).GetComponent<Button>();
			ButtonClickedEvent onClick = component.onClick;
			object obj = <>c.<>9__32_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					_extremePane.GetComponent<UI_LerpOpen>().Hide();
					_statTracker.GetComponent<UI_LerpOpen>().Hide();
					IsUIOpen = false;
					_statTracker.GetComponent<StatTracker>().IsShowing = false;
					_isExtremePaneVisible = false;
				};
				<>c.<>9__32_0 = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
		}

		private static void SetupMainToggleTemplate()
		{
			Transform obj = _extraModesPane.transform.Find("Extra Modes Body/Column Container/Column 01/Toggle Template");
			_modeToggleTemplate = ((obj != null) ? ((Component)obj).gameObject : null);
			if (!Object.op_Implicit((Object)(object)_modeToggleTemplate))
			{
				ExtraModes.Logger.LogError((object)"Toggle template not found!");
			}
			else
			{
				_modeToggleTemplate.AddComponent<Tooltip>();
			}
		}

		private static void SetupExtraModesButton()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			ButtonClickedEvent onClick = _extraModesButton.GetComponent<Button>().onClick;
			object obj = <>c.<>9__34_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					_extraModesPane.GetComponent<UI_LerpOpen>().Show();
					IsUIOpen = true;
				};
				<>c.<>9__34_0 = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
		}

		private static void AddModeToggles()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			foreach (ModeUIConfig value3 in ModeRegistry.ModeConfigs.Values)
			{
				if (_difficultyColumns.TryGetValue(value3.Difficulty, out var value) && _difficultyColors.TryGetValue(value3.Difficulty, out var value2))
				{
					CreateToggle(value, value3, value2());
				}
				else
				{
					Debug.LogWarning((object)("No column assigned for difficulty: " + value3.Difficulty));
				}
			}
		}

		private static void ResetModeStatus()
		{
			foreach (ModeUIConfig value in ModeRegistry.ModeConfigs.Values)
			{
				value.IsEnabled = false;
			}
		}

		private static void ResetAllModeToggles()
		{
			foreach (ModeUIConfig value in ModeRegistry.ModeConfigs.Values)
			{
				try
				{
					value.ToggleAction?.Invoke(false);
					Transform obj = _extraModesPane.transform.Find(value.DisplayName);
					Toggle val = ((obj != null) ? ((Component)obj).GetComponent<Toggle>() : null);
					if (Object.op_Implicit((Object)(object)val))
					{
						val.isOn = false;
					}
				}
				catch (Exception arg)
				{
					ExtraModes.Logger.LogError((object)$"Error resetting modes: {arg}");
				}
			}
		}

		private static Toggle CreateToggle(GameObject column, ModeUIConfig config, Color color)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(_modeToggleTemplate, column.transform);
			((Object)val).name = config.DisplayName;
			Toggle component = val.GetComponent<Toggle>();
			((UnityEvent<bool>)(object)component.onValueChanged).AddListener((UnityAction<bool>)delegate(bool isOn)
			{
				config.IsEnabled = isOn;
				config.ToggleAction?.Invoke(isOn);
			});
			ColorBlock colors = ((Selectable)component).colors;
			((ColorBlock)(ref colors)).highlightedColor = color;
			((ColorBlock)(ref colors)).selectedColor = color;
			((Selectable)component).colors = colors;
			Image[] componentsInChildren = val.GetComponentsInChildren<Image>();
			foreach (Image val2 in componentsInChildren)
			{
				if (!(((Object)((Component)val2).gameObject).name == "Star"))
				{
					((Graphic)val2).color = color;
					if (config.Difficulty == "Extreme")
					{
						_extremeImages.Add(val2);
					}
				}
			}
			Transform val3 = val.transform.Find("Background/Label Container/Label");
			TMP_Text val4 = ((val3 != null) ? ((Component)val3).GetComponent<TMP_Text>() : null);
			if (val4 != null)
			{
				val4.text = config.DisplayName;
				((Graphic)val4).color = color;
				if (config.Difficulty == "Extreme")
				{
					_extremeLabels.Add(val4);
				}
			}
			Transform val5 = val.transform.Find("Background/Label Container/Star");
			if (_saveData.ModeRuns.TryGetValue(config.InternalName, out var value) && value.Completed)
			{
				((Component)val5).gameObject.SetActive(true);
				_modesCompleted++;
			}
			Tooltip component2 = val.GetComponent<Tooltip>();
			component2.Description = config.Description;
			component2.FunDescription = config.FunDescription;
			val.SetActive(true);
			return component;
		}

		private static void InitDictionaries()
		{
			_extremeImages.Clear();
			_extremeLabels.Clear();
			Transform val = _extraModesPane.transform.Find("Extra Modes Body/Column Container");
			Transform val2 = _extremePane.transform.Find("Extreme Body/Column Container");
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				ExtraModes.Logger.LogError((object)"Column Containers not found in Panes.");
				return;
			}
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>();
			Transform obj = val.Find("Column 01");
			dictionary.Add("Easy", (obj != null) ? ((Component)obj).gameObject : null);
			Transform obj2 = val.Find("Column 02");
			dictionary.Add("Medium", (obj2 != null) ? ((Component)obj2).gameObject : null);
			Transform obj3 = val.Find("Column 03");
			dictionary.Add("Hard", (obj3 != null) ? ((Component)obj3).gameObject : null);
			Transform obj4 = val2.Find("Column 04");
			dictionary.Add("Extreme", (obj4 != null) ? ((Component)obj4).gameObject : null);
			_difficultyColumns = dictionary;
			foreach (var (text2, val4) in _difficultyColumns)
			{
				if (!Object.op_Implicit((Object)(object)val4))
				{
					ExtraModes.Logger.LogWarning((object)("Column for difficulty '" + text2 + "' not found!"));
				}
			}
			Dictionary<string, Func<Color>> dictionary2 = new Dictionary<string, Func<Color>>();
			dictionary2.Add("Easy", () => Color.green);
			dictionary2.Add("Medium", () => new Color(1f, 0.65f, 0f));
			dictionary2.Add("Hard", () => Color.red);
			dictionary2.Add("Extreme", GetFlashingExtremeColor);
			_difficultyColors = dictionary2;
		}

		private static Color GetFlashingExtremeColor()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.PingPong(Time.time * 1f, 1f);
			Color val = default(Color);
			((Color)(ref val))..ctor(0.5f, 0f, 0f);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(1f, 0.5f, 0f);
			return Color.Lerp(val, val2, num);
		}

		private static void SetupLevels()
		{
			if (CL_AssetManager.instance != null)
			{
				CL_AssetManager.instance.assetDatabase.levelPrefabs.Add(Assets.ChimneyStartReplacement);
			}
			else
			{
				ExtraModes.Logger.LogError((object)"CL_AssetManager not found!");
			}
		}
	}
}