Decompiled source of CiCisTrinketAndBindingFramework v2.2.6

plugins/TrinketAndBindingFramework/TrinketAndBindingFramework.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NebulaetrixMutators;
using Newtonsoft.Json;
using TMPro;
using TrinketAndBindingFramework;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TrinketAndBindingFramework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TrinketAndBindingFramework")]
[assembly: AssemblyTitle("TrinketAndBindingFramework")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NebulaetrixMutators
{
	internal static class Plugin
	{
		internal static ManualLogSource Log => TrinketAndBindingFramework.Plugin.Log;
	}
	internal static class MutatorAssets
	{
		private static AssetBundle _bundle;

		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 bool Loaded { get; private set; }

		internal static bool Load()
		{
			if (Loaded)
			{
				return true;
			}
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "Assets", "more_mutators_assets");
			_bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)_bundle == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("AssetBundle missing at " + text));
				}
				return false;
			}
			return Loaded = (byte)(1u & (TryLoad("Assets/Neb.Assets/More Mutators/Event_Cold.prefab", out EventCold) ? 1u : 0u) & (TryLoad("Assets/Neb.Assets/More Mutators/Level_Hull.prefab", out ChimneyStartReplacement) ? 1u : 0u) & (TryLoad("Assets/Neb.Assets/More Mutators/EndObj.prefab", out EndObj) ? 1u : 0u) & (TryLoad("Assets/Neb.Assets/More Mutators/Item_Rebar_Hit_Explosion.prefab", out RebarExplosion) ? 1u : 0u) & (TryLoad("Assets/GameObject/Projectile_Rebar.prefab", out Rebar) ? 1u : 0u) & (TryLoad("Assets/GameObject/Projectile_Rebar_Explosive.prefab", out RebarExplosive) ? 1u : 0u)) != 0;
		}

		private static bool TryLoad(string path, out GameObject go)
		{
			go = _bundle.LoadAsset<GameObject>(path);
			if ((Object)(object)go == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("Missing bundle asset: " + path));
				}
				return false;
			}
			return true;
		}
	}
	[Serializable]
	public class MutatorRunData
	{
		public string ModeName;

		public bool Completed;

		public int Score;

		public float AscentRate;

		public float TimeTaken;
	}
	[Serializable]
	public class MutatorSaveData
	{
		public Dictionary<string, MutatorRunData> ModeRuns = new Dictionary<string, MutatorRunData>();
	}
	internal static class MutatorSaveManager
	{
		private static MutatorSaveData _cached;

		private static string SaveDir => Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "MutatorSaves");

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

		internal static MutatorSaveData LoadData()
		{
			if (_cached != null)
			{
				return _cached;
			}
			try
			{
				if (!Directory.Exists(SaveDir))
				{
					Directory.CreateDirectory(SaveDir);
				}
				if (!File.Exists(SavePath))
				{
					_cached = new MutatorSaveData();
					Write(_cached);
					return _cached;
				}
				_cached = JsonConvert.DeserializeObject<MutatorSaveData>(File.ReadAllText(SavePath)) ?? new MutatorSaveData();
				return _cached;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("Load save failed: " + ex.Message));
				}
				_cached = new MutatorSaveData();
				return _cached;
			}
		}

		internal static void SaveRun(MutatorRunData run)
		{
			try
			{
				MutatorSaveData mutatorSaveData = LoadData();
				if (!mutatorSaveData.ModeRuns.TryGetValue(run.ModeName, out var value) || run.Score > value.Score)
				{
					mutatorSaveData.ModeRuns[run.ModeName] = run;
					Write(mutatorSaveData);
					_cached = mutatorSaveData;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("SaveRun failed: " + ex.Message));
				}
			}
		}

		private static void Write(MutatorSaveData data)
		{
			try
			{
				File.WriteAllText(SavePath, JsonConvert.SerializeObject((object)data, (Formatting)1));
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("Write failed: " + ex.Message));
				}
			}
		}
	}
	public class CoroutineRunner : MonoBehaviour
	{
		private static CoroutineRunner _instance;

		public static void Run(IEnumerator co)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = new GameObject("NebMutators_CoroutineRunner").AddComponent<CoroutineRunner>();
				Object.DontDestroyOnLoad((Object)(object)_instance);
			}
			((MonoBehaviour)_instance).StartCoroutine(co);
		}
	}
	internal static class BlizzardFactory
	{
		public static IEnumerator CreateBlizzard(Action<Event_Cold> onComplete, float windSpeed = 0.14f, float windChangeRate = 0.1f, float coldMultiplier = 0f)
		{
			GameObject go = Object.Instantiate<GameObject>(MutatorAssets.EventCold);
			yield return null;
			Event_Cold component = go.GetComponent<Event_Cold>();
			Traverse.Create((object)component).Field("coldDebuff").GetValue<BuffContainer>()
				.SetMultiplier(coldMultiplier);
			component.blizzardWindSpeed = windSpeed;
			component.blizzardWindChangeRate = windChangeRate;
			onComplete?.Invoke(component);
		}
	}
	internal static class GOHelper
	{
		public static void Disable(GameObject obj)
		{
			if (!((Object)(object)obj == (Object)null))
			{
				obj.SetActive(false);
			}
		}
	}
	internal static class TooltipHelper
	{
		public static void UpdateLevelTooltip(string objectPath, string levelTip, string subRegionTip = null, string regionTip = null)
		{
			GameObject val = GameObject.Find(objectPath);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			M_Level component = val.GetComponent<M_Level>();
			if (!((Object)(object)component == (Object)null))
			{
				if (levelTip != null)
				{
					component.introText = levelTip;
				}
				if (subRegionTip != null && (Object)(object)component.subRegion != (Object)null)
				{
					component.subRegion.introText = subRegionTip;
				}
				if (regionTip != null && (Object)(object)component.region != (Object)null)
				{
					component.region.introText = regionTip;
				}
			}
		}
	}
	internal static class Toggle
	{
		public static void Set(ref bool field, bool value)
		{
			field = value;
		}
	}
	public static class ArmlessMode
	{
		public static bool Enabled;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

		public static void Amputate(ENT_Player player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				player.hands[1].SetLocked(true);
				GameObject val = GameObject.Find("Interact_R");
				if ((Object)(object)val != (Object)null)
				{
					val.SetActive(false);
				}
				Transform val2 = ((Component)player).transform.Find("Main Cam Root/Main Camera Shake Root/Main Camera/Inventory Camera/Inventory-Root/Right_Hand_Target");
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).gameObject.SetActive(false);
				}
				Hand val3 = ((player.hands.Length > 1) ? player.hands[1] : null);
				if ((Object)(object)val3?.handModel != (Object)null)
				{
					((Component)val3.handModel).gameObject.SetActive(false);
				}
				CoroutineRunner.Run(KillUpgradeConsoles());
			}
		}

		private static IEnumerator KillUpgradeConsoles()
		{
			yield return (object)new WaitForSeconds(3f);
			GameObject val = GameObject.Find("World_Root(Clone)");
			if ((Object)(object)val == (Object)null)
			{
				yield break;
			}
			foreach (GameObject item in from o in AllChildren(val)
				where ((Object)o).name.Contains("Prop_UpgradeConsole")
				select o)
			{
				Object.Destroy((Object)(object)item);
			}
		}

		private static List<GameObject> AllChildren(GameObject parent)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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(AllChildren(((Component)val).gameObject));
			}
			return list;
		}
	}
	public static 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;

		internal static bool IsHoldingNote;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

		public static void Apply(ENT_Player player)
		{
			ApplyAttributes(player);
			AdjustWeapons();
			if (!IsHoldingNote)
			{
				player.gravity = -0.2f;
			}
			else
			{
				player.gravity = (((bool)Traverse.Create((object)player).Field("falling").GetValue()) ? 0.1f : (-0.2f));
			}
		}

		private static void ApplyAttributes(ENT_Player player)
		{
			//IL_0015: 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 AdjustWeapons()
		{
			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)" };
			foreach (string text in array)
			{
				try
				{
					GameObject val = GameObject.Find(text);
					if (!((Object)(object)val == (Object)null))
					{
						HandItem_Shoot component = val.GetComponent<HandItem_Shoot>();
						if (!((Object)(object)component == (Object)null))
						{
							component.maxRecoilMagnitude = (text.Contains("Flaregun") ? 1.5f : 0.513f);
							component.recoil = (text.Contains("Flaregun") ? 4.5f : 3.3f);
						}
					}
				}
				catch
				{
				}
			}
		}
	}
	public static class BackwardMode
	{
		public static bool Enabled;

		private const float PollTimeoutSeconds = 8f;

		private static readonly Vector3 SpawnOffset = new Vector3(10.47f, 41.24f, 5.3f);

		private static readonly Action _worldLoadedHandler = delegate
		{
			CoroutineRunner.Run(Setup());
		};

		internal static M_Level ResolveTopRealLevel(BranchInfo branch)
		{
			if (branch?.levelTracker == null)
			{
				return null;
			}
			for (int num = branch.levelTracker.Count - 1; num >= 0; num--)
			{
				LevelInfo obj = branch.levelTracker[num];
				M_Level val = ((obj != null) ? obj.GetLevel() : null);
				if (!((Object)(object)val == (Object)null) && (val.levelName ?? ((Object)val).name ?? "").IndexOf("Level_Null", StringComparison.OrdinalIgnoreCase) < 0)
				{
					return val;
				}
			}
			return null;
		}

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
			if (v)
			{
				WorldLoaderHook.OnWorldLoaded = (Action)Delegate.Combine(WorldLoaderHook.OnWorldLoaded, _worldLoadedHandler);
				BackwardDebugRunner.Ensure();
				BackwardDoorKeeper.Ensure();
			}
			else
			{
				WorldLoaderHook.OnWorldLoaded = (Action)Delegate.Remove(WorldLoaderHook.OnWorldLoaded, _worldLoadedHandler);
			}
		}

		public static IEnumerator Setup()
		{
			yield return null;
			float deadline = Time.unscaledTime + 8f;
			while (Time.unscaledTime < deadline)
			{
				WorldLoader instance = WorldLoader.instance;
				BranchInfo val = ((instance != null) ? instance.GetCurrentBranch() : null);
				ENT_Player playerObject = ENT_Player.playerObject;
				if (WorldLoader.isLoaded && val?.levelTracker != null && val.levelTracker.Count > 0 && (Object)(object)playerObject != (Object)null)
				{
					break;
				}
				yield return null;
			}
			WorldLoader instance2 = WorldLoader.instance;
			BranchInfo val2 = ((instance2 != null) ? instance2.GetCurrentBranch() : null);
			ENT_Player playerObject2 = ENT_Player.playerObject;
			if (val2?.levelTracker == null || val2.levelTracker.Count == 0 || (Object)(object)playerObject2 == (Object)null)
			{
				yield break;
			}
			M_Level val3 = ResolveTopRealLevel(val2);
			if (!((Object)(object)val3 == (Object)null))
			{
				Vector3 val4 = ((Component)val3).transform.position + SpawnOffset;
				((GameEntity)playerObject2).Teleport(val4, ((Component)playerObject2).transform.rotation, false);
				LevelInfo obj = val2.levelTracker[0];
				M_Level val5 = ((obj != null) ? obj.GetLevel() : null);
				if ((Object)(object)val5 != (Object)null && (Object)(object)MutatorAssets.EndObj != (Object)null)
				{
					Object.Instantiate<GameObject>(MutatorAssets.EndObj, Vector3.zero, Quaternion.identity, ((Component)val5).transform);
				}
			}
		}
	}
	public class BackwardDoorKeeper : MonoBehaviour
	{
		private static BackwardDoorKeeper _instance;

		private const int PollFrames = 30;

		private int _frame;

		public static void Ensure()
		{
			//IL_0013: 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_001e: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("NebMutators_BackwardDoorKeeper");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<BackwardDoorKeeper>();
			}
		}

		private void Update()
		{
			if (!BackwardMode.Enabled || _frame++ % 30 != 0)
			{
				return;
			}
			UT_Door[] array = Object.FindObjectsOfType<UT_Door>();
			foreach (UT_Door val in array)
			{
				if (!((Object)(object)val == (Object)null) && !val.IsOpen())
				{
					try
					{
						val.Open();
					}
					catch
					{
					}
				}
			}
		}
	}
	public class BackwardDebugRunner : MonoBehaviour
	{
		private static BackwardDebugRunner _instance;

		public static void Ensure()
		{
			//IL_0013: 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_001e: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("NebMutators_BackwardDebug");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<BackwardDebugRunner>();
			}
		}

		private void Update()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_009b: 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)
			if (!BackwardMode.Enabled || !Input.GetKeyDown((KeyCode)290))
			{
				return;
			}
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)playerObject == (Object)null)
			{
				return;
			}
			WorldLoader instance = WorldLoader.instance;
			M_Level val = BackwardMode.ResolveTopRealLevel((instance != null) ? instance.GetCurrentBranch() : null);
			if (!((Object)(object)val == (Object)null))
			{
				Vector3 val2 = ((Component)playerObject).transform.position - ((Component)val).transform.position;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[F9] top='{val.levelName}' player={((Component)playerObject).transform.position} top.pos={((Component)val).transform.position} offset={val2}");
				}
			}
		}
	}
	public static class CombustMode
	{
		public static bool Enabled;

		private static float _accumulated;

		private const float Threshold = 1f;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

		public static void Roll(ENT_Player player)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			_accumulated += Time.deltaTime;
			if (!(_accumulated < 1f))
			{
				_accumulated = 0f;
				if (Random.Range(0, 10) == 0)
				{
					Vector3 val = ((Component)player).transform.position + Random.insideUnitSphere * 1f;
					Object.Destroy((Object)(object)Object.Instantiate<GameObject>(MutatorAssets.RebarExplosion, val, Quaternion.identity), 5f);
				}
			}
		}
	}
	public static class DevilDaggerMode
	{
		public static bool Enabled;

		private const float ShootTimer = 0.1f;

		private static float _accumulatedTime;

		private static bool _resolved;

		private static GameObject _rebarProjectilePrefab;

		private static GameObject _rebarExplosiveProjectilePrefab;

		private static float _shootSpeed;

		private static LayerMask _aimMask;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

		private static bool ResolveShoot()
		{
			//IL_0083: 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)
			if (_resolved && (Object)(object)_rebarProjectilePrefab != (Object)null)
			{
				return true;
			}
			_resolved = true;
			try
			{
				GameObject assetGameObject = CL_AssetManager.GetAssetGameObject("Item_Rebar", "");
				HandItem obj = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null)?.itemData?.handItemAsset;
				HandItem_Shoot val = (HandItem_Shoot)(object)((obj is HandItem_Shoot) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				_rebarProjectilePrefab = val.projectile;
				_shootSpeed = val.shootSpeed;
				_aimMask = val.aimMask;
				if ((Object)(object)_rebarProjectilePrefab == (Object)null)
				{
					return false;
				}
				try
				{
					GameObject assetGameObject2 = CL_AssetManager.GetAssetGameObject("Item_Rebar_Explosive", "");
					HandItem obj2 = (((Object)(object)assetGameObject2 != (Object)null) ? assetGameObject2.GetComponent<Item_Object>() : null)?.itemData?.handItemAsset;
					_rebarExplosiveProjectilePrefab = ((HandItem_Shoot)(((obj2 is HandItem_Shoot) ? obj2 : null)?)).projectile;
				}
				catch
				{
					_rebarExplosiveProjectilePrefab = null;
				}
				return true;
			}
			catch
			{
				return false;
			}
		}

		public static void SpawnRebar(int hand, ENT_Player player)
		{
			//IL_00a7: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_010a: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)Camera.main == (Object)null)
			{
				return;
			}
			_accumulatedTime += Time.deltaTime;
			if (_accumulatedTime < 0.1f)
			{
				return;
			}
			_accumulatedTime = 0f;
			if (hand < 0 || hand >= player.hands.Length)
			{
				return;
			}
			Hand val = player.hands[hand];
			if (val == null || !InputManager.GetButton(val.fireButton).Pressed || !ResolveShoot())
			{
				return;
			}
			GameObject obj = ((CombustMode.Enabled && (Object)(object)_rebarExplosiveProjectilePrefab != (Object)null) ? _rebarExplosiveProjectilePrefab : _rebarProjectilePrefab);
			Transform transform = ((Component)Camera.main).transform;
			Vector3 val2 = Vector3.Lerp(((Component)player).transform.position, transform.position, 0.5f) + -((Component)player).transform.forward * 0.25f;
			GameObject val3 = Object.Instantiate<GameObject>(obj, val2, Quaternion.LookRotation(transform.forward));
			Projectile component = val3.GetComponent<Projectile>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val3);
				return;
			}
			component.Initialize(transform.forward * 50f, (GameEntity)(object)player, (Item)null);
			CL_CameraControl.Shake(0.01f);
			if ((Object)(object)player.cCon != (Object)null && player.cCon.isGrounded)
			{
				((GameEntity)player).AddForce(-transform.forward * 0.05f, "");
			}
			else
			{
				((GameEntity)player).AddForce(-transform.forward * 0.2f, "");
			}
			player.DropHang(0.1f, 1f, false, "drop", false);
		}
	}
	public static class DisorientedMode
	{
		public static bool Enabled;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

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

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

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

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

		public static void Apply(ENT_Player player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				Traverse.Create((object)player).Field("hasJumped").SetValue((object)true);
				player.jumpHeight = 0f;
			}
		}
	}
	public static class MarathonMode
	{
		public static bool Enabled;

		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 = delegate
		{
			CoroutineRunner.Run(ModifyLevelsAsync());
		};

		public static bool IsPlaylistNeeded
		{
			get
			{
				if (!Enabled)
				{
					return BackwardMode.Enabled;
				}
				return true;
			}
		}

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
			if (v)
			{
				WorldLoaderHook.OnWorldLoaded = (Action)Delegate.Combine(WorldLoaderHook.OnWorldLoaded, _worldLoadedHandler);
			}
			else
			{
				WorldLoaderHook.OnWorldLoaded = (Action)Delegate.Remove(WorldLoaderHook.OnWorldLoaded, _worldLoadedHandler);
			}
		}

		public static bool LoadLibraryLevels()
		{
			//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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Invalid comparison between Unknown and I4
			//IL_00d1: 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 obj = GameObject.Find("GameManager");
			CL_GameManager val = ((obj != null) ? obj.GetComponent<CL_GameManager>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			List<string> orderedLevels = MutatorLevelsList.OrderedLevels;
			List<string> list = new List<string>(orderedLevels.Count);
			foreach (string item in orderedLevels)
			{
				bool flag = false;
				try
				{
					flag = CL_AssetManager.GetLevelAsset(item, "") != null;
				}
				catch
				{
					flag = false;
				}
				if (flag)
				{
					list.Add(item);
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			M_Gamemode gamemodeAsset = CL_AssetManager.GetGamemodeAsset("GM_Level_Tester", "");
			if ((Object)(object)gamemodeAsset == (Object)null)
			{
				return false;
			}
			if ((int)gamemodeAsset.modeType != 1)
			{
				gamemodeAsset.modeType = (GameType)1;
			}
			try
			{
				if (!(AccessTools.Field(typeof(CL_GameManager), "gamemodeArgs")?.GetValue(null) is List<string> list2))
				{
					return false;
				}
				if (!BackwardMode.Enabled)
				{
					ShuffleNumberedGroups(list);
				}
				list2.Clear();
				list2.AddRange(list);
				val.SetGamemode(gamemodeAsset);
				AccessTools.Field(typeof(CL_GameManager), "baseGamemode")?.SetValue(val, gamemodeAsset);
				SceneManager.LoadScene("Game-Main");
				return true;
			}
			catch (Exception arg)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)$"LoadLibraryLevels failed: {arg}");
				}
				return false;
			}
		}

		private static void ShuffleNumberedGroups(List<string> levels)
		{
			int num = 0;
			while (num < levels.Count)
			{
				string text = StripTrailingNumber(levels[num]);
				if (text == null)
				{
					num++;
					continue;
				}
				int i;
				for (i = num + 1; i < levels.Count && StripTrailingNumber(levels[i]) == text; i++)
				{
				}
				if (i - num >= 2)
				{
					for (int num2 = i - 1; num2 > num; num2--)
					{
						int index = Random.Range(num, num2 + 1);
						string value = levels[num2];
						levels[num2] = levels[index];
						levels[index] = value;
					}
				}
				num = i;
			}
		}

		private static string StripTrailingNumber(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			int num = name.LastIndexOf('_');
			if (num < 0 || num == name.Length - 1)
			{
				return null;
			}
			for (int i = num + 1; i < name.Length; i++)
			{
				if (!char.IsDigit(name[i]))
				{
					return null;
				}
			}
			return name.Substring(0, num + 1);
		}

		private static IEnumerator ModifyLevelsAsync()
		{
			yield return (object)new WaitForSeconds(0.25f);
			ModifyOtherLevels();
			ModifyEnding();
			ClearOtherLevelObjects();
		}

		private static void ModifyOtherLevels()
		{
			GameObject val = GameObject.Find("Level Tester-root/World_Root(Clone)/MX_Chimney_Start_01(Clone)");
			if (!((Object)(object)val == (Object)null))
			{
				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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0084: 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_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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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)
			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)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				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");
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null))
				{
					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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			GameObject chimneyStartReplacement = MutatorAssets.ChimneyStartReplacement;
			if (!((Object)(object)chimneyStartReplacement == (Object)null))
			{
				chimneyStartReplacement.transform.localScale = Vector3.one * 0.01f;
				Transform obj = chimneyStart.transform.Find("FX_Zone.03");
				FX_Zone val = ((obj != null) ? ((Component)obj).GetComponent<FX_Zone>() : null);
				if ((Object)(object)val != (Object)null)
				{
					val.blend = 0.95f;
				}
				DestroyObjectsInChimney(chimneyStart);
				Transform val2 = chimneyStart.transform.Find("MX_Chimney_Start_01");
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Instantiate<GameObject>(chimneyStartReplacement, ((Component)val2).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" };
			foreach (string text in array)
			{
				Transform val = chimneyStart.transform.Find(text);
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		private static void ClearOtherLevelObjects()
		{
			GameObject obj = GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Campaign_Transition_Pipeworks_To_Habitation_01(Clone)/Level Scripting/Goo Controllers");
			if (obj != null)
			{
				obj.SetActive(false);
			}
			GameObject obj2 = GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Habitation_LadderWarp_Loop(Clone)/WinTrigger");
			if (obj2 != null)
			{
				obj2.SetActive(false);
			}
			GameObject val = GameObject.Find("Level Tester-root/World_Root(Clone)/M3_Habitation_Shaft_Intro(Clone)/Entities/Trigger-RoomEnter");
			if ((Object)(object)val != (Object)null)
			{
				UT_GooController[] components = val.GetComponents<UT_GooController>();
				for (int i = 0; i < components.Length; i++)
				{
					Object.Destroy((Object)(object)components[i]);
				}
			}
		}

		internal static IEnumerator SetGiftRoomParams(M_Level level)
		{
			yield return (object)new WaitForSeconds(0.5f);
			if (!level.levelName.Contains("MX_Chimney_Gift"))
			{
				yield break;
			}
			Transform obj = ((Component)level).transform.Find("Doors/Door_Reinforced_01");
			UT_Door val = ((obj != null) ? ((Component)obj).GetComponent<UT_Door>() : null);
			Transform obj2 = ((Component)level).transform.Find("Doors/Door_Reinforced_01.01");
			UT_Door val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<UT_Door>() : null);
			if ((Object)(object)val != (Object)null)
			{
				Vector3 val3 = Traverse.Create((object)val).Field("startPos").GetValue<Vector3>() + new Vector3(0f, 0f, -5f);
				Traverse.Create((object)val).Field("endPos").SetValue((object)val3);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				Vector3 val4 = Traverse.Create((object)val2).Field("startPos").GetValue<Vector3>() + new Vector3(0f, 0f, -5f);
				Traverse.Create((object)val2).Field("endPos").SetValue((object)val4);
			}
			if (BackwardMode.Enabled)
			{
				Transform obj3 = ((Component)level).transform.Find("Doors/Prop_Button_Console_01/Prop_Button_02_Switch");
				CL_ToggleButton obj4 = ((obj3 != null) ? ((Component)obj3).GetComponent<CL_ToggleButton>() : null);
				if (obj4 != null)
				{
					((CL_Button)obj4).Interact();
				}
			}
		}
	}
	public static class MarkMode
	{
		public static bool Enabled;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}
	}
	public static class WindTunnelMode
	{
		public static bool Enabled;

		private static Event_Cold _blizzard;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

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

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

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

		public static void Teeth(DEN_Teeth teeth)
		{
			teeth.Despawn();
		}

		public static void Turret(DEN_Turret turret)
		{
			GOHelper.Disable(((Component)turret).gameObject);
		}

		internal static void Bloodbug(DEN_Bloodbug b)
		{
			GOHelper.Disable(((Component)b).gameObject);
		}

		internal static void VentThing(DEN_VentThing v)
		{
			GOHelper.Disable(((Component)v).gameObject);
		}

		public static void Apply(ENT_Player player)
		{
			((GameEntity)player).health = 5f;
		}

		public static IEnumerator KillMassWhenAvailable()
		{
			float deadline = Time.unscaledTime + 5f;
			while (Time.unscaledTime < deadline)
			{
				if ((Object)(object)DEN_DeathFloor.instance != (Object)null)
				{
					((Component)DEN_DeathFloor.instance).gameObject.SetActive(false);
					break;
				}
				yield return null;
			}
		}
	}
	public static class ZeroGravMode
	{
		public static bool Enabled;

		public static void Set(bool v)
		{
			Toggle.Set(ref Enabled, v);
		}

		public static void Apply(ENT_Player player)
		{
			Traverse.Create((object)player).Field("hasGravity").SetValue((object)false);
			player.dragCoefficient = 0.05f;
		}
	}
	internal static class MutatorLevelsList
	{
		internal static readonly List<string> OrderedLevels = new List<string>(173)
		{
			"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", "Campaign_Interlude_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",
			"Campaign_Interlude_Pipeworks_To_Habitation_03", "M3_Habitation_Entryway_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_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_Lab_01", "M3_Habitation_Lab_02",
			"M3_Habitation_Lab_03", "M3_Habitation_Lab_04", "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_Lab_05",
			"M3_Habitation_Lab_06", "M3_Habitation_Lab_07", "M3_Habitation_Lab_08", "M3_Habitation_Endless_Breakroom_01", "M3_Habitation_Endless_Shaft_Start", "M3_Habitation_Shaft_07", "M3_Habitation_Shaft_01", "M3_Habitation_Shaft_To_Pier", "M3_Habitation_Pier_Entrance_01", "M3_Habitation_Pier_03",
			"M3_Habitation_Lab_Lobby", "M3_Habitation_Endless_Shaft_Start", "M3_Habitation_Shaft_02", "M3_Habitation_Shaft_03", "M3_Habitation_Shaft_To_Pier", "M3_Habitation_Pier_Entrance_01", "M3_Habitation_Pier_04", "M3_Habitation_Lab_Lobby", "M3_Habitation_Endless_Breakroom_01", "M3_Habitation_Lab_Ending",
			"Campaign_Interlude_Habitation_To_Abyss_01", "M4_Abyss_Transit_01", "M4_Abyss_Transit_02", "M4_Abyss_Transit_03", "M4_Abyss_Transit_05", "M4_Abyss_Transit_06", "M4_Abyss_Handle_01", "M4_Abyss_Garden_01", "M4_Abyss_Garden_02", "M4_Abyss_Garden_03",
			"M4_Abyss_Garden_04", "M4_Abyss_Outro_01"
		};
	}
	[HarmonyPatch(typeof(WorldLoader))]
	internal static class WorldLoaderHook
	{
		internal static Action OnWorldLoaded;

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

		[HarmonyPatch("GenerateLevels")]
		[HarmonyPostfix]
		private static void GenerateLevelsPostfix()
		{
			OnWorldLoaded?.Invoke();
		}
	}
	[HarmonyPatch(typeof(Event_Cold))]
	internal static class EventColdPatch
	{
		[HarmonyPatch("LateUpdate")]
		[HarmonyPostfix]
		private static void LateUpdatePostfix(Event_Cold __instance)
		{
			if (WindTunnelMode.Enabled)
			{
				WindTunnelMode.Tick();
			}
		}
	}
	internal static class InventoryHelpers
	{
		public static void CheckItem(Item item)
		{
			if (item?.itemName == "Note")
			{
				BabyMode.IsHoldingNote = false;
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "ShowInventory")]
	internal static class InventoryShowBlockPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !MarkMode.Enabled;
		}
	}
	[HarmonyPatch(typeof(ENT_Player), "Jump")]
	internal static class JumpBlockPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !LeglessMode.Enabled;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItemToHand", new Type[]
	{
		typeof(Item),
		typeof(Hand)
	})]
	internal static class InventoryAddItemToHandPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref Item i)
		{
			if (i != null && i.itemName == "Note")
			{
				BabyMode.IsHoldingNote = true;
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "ClearItemFromHand")]
	internal static class InventoryClearItemPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref Item i)
		{
			InventoryHelpers.CheckItem(i);
		}
	}
	[HarmonyPatch(typeof(Inventory), "DropItemFromHand")]
	internal static class InventoryDropItemFromHandPatch
	{
		[HarmonyPrefix]
		private static void Prefix(int h, Inventory __instance)
		{
			Item currentItem = __instance.itemHands[h].currentItem;
			if (currentItem != null)
			{
				InventoryHelpers.CheckItem(currentItem);
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "DestroyItemInHand")]
	internal static class InventoryDestroyItemInHandPatch
	{
		[HarmonyPrefix]
		private static void Prefix(int h, Inventory __instance)
		{
			Item currentItem = __instance.itemHands[h].currentItem;
			if (currentItem != null)
			{
				InventoryHelpers.CheckItem(currentItem);
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItemToInventoryScreen")]
	internal static class InventoryAddToScreenPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref Item item)
		{
			InventoryHelpers.CheckItem(item);
		}
	}
	[HarmonyPatch(typeof(Inventory), "DropItemIntoWorld")]
	internal static class InventoryDropIntoWorldPatch
	{
		[HarmonyPrefix]
		private static void Prefix(ref Item item)
		{
			InventoryHelpers.CheckItem(item);
		}
	}
	[HarmonyPatch(typeof(M_Level))]
	internal static class MLevelPatch
	{
		[HarmonyPatch("OnLevelActivate")]
		[HarmonyPostfix]
		private static void OnLevelActivatePostfix(M_Level __instance)
		{
			if (MarathonMode.Enabled)
			{
				CoroutineRunner.Run(MarathonMode.SetGiftRoomParams(__instance));
			}
		}
	}
	[HarmonyPatch(typeof(UT_TriggerZone))]
	internal static class TriggerZonePatch
	{
		[HarmonyPatch("OnTriggerEnter")]
		[HarmonyPrefix]
		private static void OnTriggerEnterPrefix(UT_TriggerZone __instance)
		{
			if (!(((Object)((Component)__instance).gameObject).name != "Event-MovingSecurityZone") && (ZenMode.Enabled || BackwardMode.Enabled))
			{
				GOHelper.Disable(((Component)__instance).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(UT_PlaySoundOnStart), "PlaySound")]
	internal static class SafePlaySoundOnStartPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(UT_PlaySoundOnStart __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return false;
			}
			if (__instance.clips == null || __instance.clips.Count == 0)
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(DEN_Bloodbug), "Start")]
	internal static class DenBloodbugPatch
	{
		[HarmonyPostfix]
		private static void Postfix(DEN_Bloodbug __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.Bloodbug(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_DeathFloor), "Start")]
	internal static class DenDeathFloorPatch
	{
		[HarmonyPostfix]
		private static void Postfix(DEN_DeathFloor __instance)
		{
			if (ZenMode.Enabled || BackwardMode.Enabled)
			{
				GOHelper.Disable(((Component)__instance).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_Teeth), "Awake")]
	internal static class DenTeethPatch
	{
		[HarmonyPrefix]
		private static void Prefix(DEN_Teeth __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.Teeth(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_Turret), "Start")]
	internal static class DenTurretPatch
	{
		[HarmonyPostfix]
		private static void Postfix(DEN_Turret __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.Turret(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(DEN_VentThing), "Awake")]
	internal static class DenVentThingPatch
	{
		[HarmonyPrefix]
		private static void Prefix(DEN_VentThing __instance)
		{
			if (ZenMode.Enabled)
			{
				ZenMode.VentThing(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(CL_GameManager), "EndGameSequence")]
	internal static class EndGamePatch
	{
		[HarmonyPostfix]
		private static void Postfix(ref bool win, CL_GameManager __instance)
		{
			bool flag = false;
			foreach (KeyValuePair<string, CustomModeRegistry.Mode> item in CustomModeRegistry.All)
			{
				if (CustomModeRegistry.IsActive(item.Key))
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				float score = __instance.GetPlayerAscent() * __instance.GetPlayerAscentRate();
				SaveRun(win, score, __instance.GetGameTime(), __instance.GetPlayerAscentRate());
			}
		}

		private static void SaveRun(bool win, float score, float time, float ascentRate)
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, CustomModeRegistry.Mode> item in CustomModeRegistry.All)
			{
				if (CustomModeRegistry.IsActive(item.Key))
				{
					list.Add(item.Key);
				}
			}
			float num = (win ? (score * 5f) : score);
			MutatorSaveManager.SaveRun(new MutatorRunData
			{
				ModeName = string.Join("+", list),
				Completed = win,
				TimeTaken = time,
				Score = Mathf.RoundToInt(num),
				AscentRate = ascentRate
			});
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeScreen), "LoadGamemode")]
	internal static class LoadGamemodePatch
	{
		private static readonly FieldInfo _baseGamemodeField = AccessTools.Field(typeof(UI_GamemodeScreen), "baseGamemode");

		[HarmonyPrefix]
		private static bool Prefix(UI_GamemodeScreen __instance)
		{
			if (!MarathonMode.IsPlaylistNeeded)
			{
				return true;
			}
			object? obj = _baseGamemodeField?.GetValue(__instance);
			if ((((M_Gamemode)(((obj is M_Gamemode) ? obj : null)?)).gamemodeName ?? "").IndexOf("Campaign", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return true;
			}
			return !MarathonMode.LoadLibraryLevels();
		}
	}
	internal static class MarathonPauseGate
	{
		public const string EndingLevelName = "M4_Abyss_Outro_01";

		public static bool Decide(M_Level inst, ref bool __result)
		{
			if (!MarathonMode.IsPlaylistNeeded || (Object)(object)inst == (Object)null)
			{
				return true;
			}
			if (inst.levelName == "M4_Abyss_Outro_01")
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(M_Level), "DoesPauseGeneration")]
	internal static class MarathonDoesPauseGenerationPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(M_Level __instance, ref bool __result)
		{
			return MarathonPauseGate.Decide(__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(M_Level), "IsPausingGeneration")]
	internal static class MarathonIsPausingGenerationPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(M_Level __instance, ref bool __result)
		{
			return MarathonPauseGate.Decide(__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(M_Level), "IsLastLevel")]
	internal static class MarathonIsLastLevelPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(M_Level __instance, ref bool __result)
		{
			return MarathonPauseGate.Decide(__instance, ref __result);
		}
	}
	[HarmonyPatch(typeof(UT_Door), "Close")]
	internal static class BackwardSuppressDoorClosePatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !BackwardMode.Enabled;
		}
	}
	[HarmonyPatch(typeof(WorldLoader), "UnloadLevelRange")]
	internal static class BackwardSuppressUnloadRangePatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !BackwardMode.Enabled;
		}
	}
	[HarmonyPatch(typeof(WorldLoader), "UnloadPreviousLevels")]
	internal static class BackwardSuppressUnloadPreviousPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			return !BackwardMode.Enabled;
		}
	}
	[HarmonyPatch(typeof(ENT_Player))]
	internal static class PlayerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(ENT_Player __instance)
		{
			if (DisorientedMode.Enabled)
			{
				DisorientedMode.Apply(__instance);
			}
			if (ArmlessMode.Enabled)
			{
				ArmlessMode.Amputate(__instance);
			}
			if (ZeroGravMode.Enabled)
			{
				ZeroGravMode.Apply(__instance);
			}
			if (ZenMode.Enabled)
			{
				CoroutineRunner.Run(ZenMode.KillMassWhenAvailable());
			}
		}

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

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

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

		[HarmonyPatch("InteractCheck")]
		[HarmonyPrefix]
		private static void InteractCheckPrefix(ref int hand, ENT_Player __instance)
		{
			if (DevilDaggerMode.Enabled)
			{
				DevilDaggerMode.SpawnRebar(hand, __instance);
			}
		}
	}
}
namespace TrinketAndBindingFramework
{
	public static class AkimboMode
	{
		[HarmonyPatch(typeof(HandItem_Shoot), "GetMaxAmmo")]
		private static class MagSizePatch
		{
			[HarmonyPostfix]
			private static void Postfix(HandItem_Shoot __instance, ref int __result)
			{
				if (Enabled && IsHandgun(__instance))
				{
					__result = 30;
				}
			}
		}

		[HarmonyPatch(typeof(HandItem_Shoot), "Shoot")]
		private static class SpreadPatch
		{
			private class Original
			{
				public float initial;

				public float added;

				public float max;

				public float lose;
			}

			private static readonly Dictionary<HandItem_Shoot, Original> _originals = new Dictionary<HandItem_Shoot, Original>();

			[HarmonyPrefix]
			private static void Prefix(HandItem_Shoot __instance)
			{
				if (!IsHandgun(__instance))
				{
					return;
				}
				Original value;
				if (Enabled)
				{
					if (!_originals.ContainsKey(__instance))
					{
						_originals[__instance] = new Original
						{
							initial = __instance.initialShotInaccuracy,
							added = __instance.addedShotInaccuracy,
							max = __instance.maxShotInaccuracyMagnitude,
							lose = __instance.shotInaccuracyLoseRate
						};
					}
					__instance.initialShotInaccuracy = 0.035f;
					__instance.addedShotInaccuracy = 0.05f;
					__instance.maxShotInaccuracyMagnitude = 0.18f;
					__instance.shotInaccuracyLoseRate = 0.7f;
				}
				else if (_originals.TryGetValue(__instance, out value))
				{
					__instance.initialShotInaccuracy = value.initial;
					__instance.addedShotInaccuracy = value.added;
					__instance.maxShotInaccuracyMagnitude = value.max;
					__instance.shotInaccuracyLoseRate = value.lose;
					_originals.Remove(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Item_Object), "Start")]
		private static class SpawnedGunPatch
		{
			[HarmonyPostfix]
			private static void Postfix(Item_Object __instance)
			{
				if (Enabled && !((Object)(object)__instance == (Object)null) && __instance.itemData != null && !(__instance.itemData.prefabName != "Item_Handgun"))
				{
					StampMag(__instance.itemData);
				}
			}
		}

		[HarmonyPatch(typeof(HandItem_Shoot), "Use")]
		private static class AutoStartPatch
		{
			[HarmonyPostfix]
			private static void Postfix(HandItem_Shoot __instance)
			{
				if (Enabled && IsHandgun(__instance))
				{
					AutoFire.Begin(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(HandItem_Shoot), "StopUse")]
		private static class AutoStopPatch
		{
			[HarmonyPostfix]
			private static void Postfix(HandItem_Shoot __instance)
			{
				AutoFire.End(__instance);
			}
		}

		internal class AutoFire : MonoBehaviour
		{
			private static AutoFire _instance;

			private static readonly Dictionary<HandItem_Shoot, float> _held = new Dictionary<HandItem_Shoot, float>();

			private static readonly List<HandItem_Shoot> _scratch = new List<HandItem_Shoot>(2);

			private static readonly FieldInfo _reloadingField = AccessTools.Field(typeof(HandItem_Shoot), "reloading");

			public static void Begin(HandItem_Shoot hi)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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
				if (!((Object)(object)hi == (Object)null))
				{
					if ((Object)(object)_instance == (Object)null)
					{
						GameObject val = new GameObject("CiCi_Akimbo")
						{
							hideFlags = (HideFlags)61
						};
						Object.DontDestroyOnLoad((Object)val);
						_instance = val.AddComponent<AutoFire>();
					}
					_held[hi] = Time.time;
				}
			}

			public static void End(HandItem_Shoot hi)
			{
				if ((Object)(object)hi != (Object)null)
				{
					_held.Remove(hi);
				}
			}

			private void Update()
			{
				if (_held.Count == 0)
				{
					return;
				}
				float num = 1f / Mathf.Max(0.01f, 10f);
				_scratch.Clear();
				_scratch.AddRange(_held.Keys);
				for (int i = 0; i < _scratch.Count; i++)
				{
					HandItem_Shoot val = _scratch[i];
					if ((Object)(object)val == (Object)null || ((HandItem)val).item == null || ((Hand_Base)val).hand == null || !((Behaviour)val).isActiveAndEnabled)
					{
						_held.Remove(val);
						continue;
					}
					if (!Enabled)
					{
						_held.Remove(val);
						continue;
					}
					bool flag = false;
					try
					{
						flag = InputManager.GetButton(((Hand_Base)val).hand.fireButton).Pressed && (Object)(object)((Hand_Base)val).hand.GetHandItem() == (Object)(object)val;
					}
					catch
					{
					}
					if (!flag)
					{
						_held.Remove(val);
						continue;
					}
					bool flag2 = false;
					try
					{
						flag2 = _reloadingField != null && (bool)_reloadingField.GetValue(val);
					}
					catch
					{
					}
					if (flag2)
					{
						_held.Remove(val);
					}
					else if (val.GetAmmo() <= 0)
					{
						_held.Remove(val);
						try
						{
							val.ResetUsedState();
							val.StartShoot();
						}
						catch
						{
						}
					}
					else
					{
						if (Time.time - _held[val] < num)
						{
							continue;
						}
						_held[val] = Time.time;
						try
						{
							val.ResetUsedState();
							val.StartShoot();
						}
						catch (Exception ex)
						{
							ManualLogSource log = Plugin.Log;
							if (log != null)
							{
								log.LogWarning((object)("[Akimbo] auto shot failed: " + ex.Message));
							}
							_held.Remove(val);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(M_Gamemode), "StartFreshGamemode")]
		private static class StartKitPatch
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				if (!Enabled)
				{
					return;
				}
				Inventory instance = Inventory.instance;
				ENT_Player playerObject = ENT_Player.playerObject;
				if ((Object)(object)instance == (Object)null || (Object)(object)playerObject == (Object)null)
				{
					return;
				}
				try
				{
					GameObject assetGameObject = CL_AssetManager.GetAssetGameObject("Item_Handgun", "");
					Item_Object val = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
					GameObject assetGameObject2 = CL_AssetManager.GetAssetGameObject("Item_10mm_Ammo", "");
					Item_Object val2 = (((Object)(object)assetGameObject2 != (Object)null) ? assetGameObject2.GetComponent<Item_Object>() : null);
					if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
					{
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogWarning((object)"[Akimbo] handgun or 10mm ammo asset not found — no starting kit");
						}
						return;
					}
					for (int i = 0; i < 2 && i < playerObject.hands.Length; i++)
					{
						Item clone = val.itemData.GetClone((Item)null, false);
						StampMag(clone);
						instance.AddItemToHand(clone, i);
					}
					for (int j = 0; j < 4; j++)
					{
						instance.AddItemToInventoryScreen(new Vector3(-0.4f, 0.4f, 1f) + Random.insideUnitSphere * 0.01f, val2.itemData.GetClone((Item)null, false), true, false, true);
					}
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"[Akimbo] two handguns + {4} mags of {30}");
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log3 = Plugin.Log;
					if (log3 != null)
					{
						log3.LogWarning((object)("[Akimbo] starting kit failed: " + ex.Message));
					}
				}
			}
		}

		public const string ModeId = "cici_akimbo_mode";

		public const string Title = "Akimbo";

		public const int MagSize = 30;

		public const int SpareMags = 4;

		public const float RoundsPerSecond = 10f;

		public const float InitialSpread = 0.035f;

		public const float AddedSpread = 0.05f;

		public const float MaxSpread = 0.18f;

		public const float SpreadRecovery = 0.7f;

		public const string GunPrefab = "Item_Handgun";

		public const string AmmoPrefab = "Item_10mm_Ammo";

		public const string AmmoTag = "10mm";

		public static bool Enabled;

		public static void Register()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			CustomModeRegistry.Register("cici_akimbo_mode", "Akimbo", "Start with two automatic 10mm handguns.", CustomModeRegistry.Difficulty.Easy, delegate(bool v)
			{
				Enabled = v;
			});
			if (CustomModeRegistry._modes.TryGetValue("cici_akimbo_mode", out var value))
			{
				value.ColorOverride = TrinketPickerSectionPatch.CiCiHeaderColorPublic;
			}
			CustomModeRegistry.InjectIntoGamemode("*", "cici_akimbo_mode");
		}

		private static bool IsHandgun(HandItem_Shoot hi)
		{
			if ((Object)(object)hi != (Object)null)
			{
				return hi.ammoTag == "10mm";
			}
			return false;
		}

		internal static void StampMag(Item item)
		{
			if (item == null)
			{
				return;
			}
			try
			{
				item.SetFirstDataStringsofType("maxammo", 30.ToString());
				item.SetFirstDataStringsofType("ammo", 30.ToString());
			}
			catch
			{
			}
		}
	}
	public static class BundledMutators
	{
		private static readonly string[] Keep = new string[11]
		{
			"DevilDaggerMode", "ZenMode", "ZeroGravMode", "CombustMode", "MarkMode", "ArmlessMode", "BabyMode", "DisorientedMode", "GlassMode", "LeglessMode",
			"WindTunnelMode"
		};

		private const string Credit = "Mode by Nebulaetrix";

		private const string SourceName = "Nebulaetrix's Mutators";

		private const string SourceGuid = "com.nebulaetrix.moremutators";

		public static void Register()
		{
			if (!MutatorAssets.Load())
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)"[Mutators] asset bundle missing — Nebulaetrix's modes are not available");
				}
				return;
			}
			HashSet<string> keep = new HashSet<string>(Keep);
			CustomModeRegistry.Difficulty diff = CustomModeRegistry.Difficulty.Easy;
			CustomModeRegistry.Difficulty diff2 = CustomModeRegistry.Difficulty.Medium;
			CustomModeRegistry.Difficulty diff3 = CustomModeRegistry.Difficulty.Hard;
			CustomModeRegistry.Difficulty diff4 = CustomModeRegistry.Difficulty.Extreme;
			Reg("DevilDaggerMode", "Devil Daggers", "Shoot rebar upon opening your hands", diff, DevilDaggerMode.Set);
			Reg("ZenMode", "Zen Mode", "No Mass, Bloodbugs, Teeth etc", diff, ZenMode.Set);
			Reg("ZeroGravMode", "Zero-G", "Zero gravity", diff, ZeroGravMode.Set);
			Reg("BackwardMode", "elkcunK etihW", "Start at the top and descend", diff2, BackwardMode.Set);
			Reg("CombustMode", "Volatile", "Randomly explode", diff2, CombustMode.Set);
			Reg("MarkMode", "Markiplier%", "No inventory", diff2, MarkMode.Set);
			Reg("ArmlessMode", "Amputated", "Missing an arm", diff3, ArmlessMode.Set);
			Reg("BabyMode", "Baby Knuckle", "66% smaller", diff3, BabyMode.Set);
			Reg("DisorientedMode", "Disoriented", "Inverted camera", diff3, DisorientedMode.Set);
			Reg("GlassMode", "Glass Knuckle", "One shot to everything", diff3, GlassMode.Set);
			Reg("LeglessMode", "Paraplegic", "No jumping", diff3, LeglessMode.Set);
			Reg("MarathonMode", "Marathon Mode", "Every level in existence", diff4, MarathonMode.Set, (!keep.Contains("BackwardMode")) ? null : new string[1] { "BackwardMode" });
			Reg("WindTunnelMode", "Wind Tunnel", "Constant Downward Blizzard", diff4, WindTunnelMode.Set);
			Combo("<color=#ff9500>Detonating Daggers</color>", new string[2] { "DevilDaggerMode", "CombustMode" });
			Combo("<color=#ff9500>Backwards Buddha</color>", new string[2] { "ZenMode", "BackwardMode" });
			Combo("<color=#ff4da6>Pocket Rockets</color>", new string[2] { "DevilDaggerMode", "BabyMode" });
			Combo("<color=#00ffff>Tranquil Tempest</color>", new string[2] { "ZenMode", "WindTunnelMode" });
			Combo("<color=#ff490d>Coughing Bomb vs Hydrogen Baby</color>", new string[2] { "CombustMode", "BabyMode" });
			Combo("<color=#ffe6cc>Glass Cannon</color>", new string[2] { "CombustMode", "GlassMode" });
			Combo("<color=#ffe28c>Man Child</color>", new string[2] { "MarkMode", "BabyMode" });
			Combo("<color=#cc00ff>The Backathon</color>", new string[2] { "BackwardMode", "MarathonMode" });
			Combo("<color=#c0c0c0>The Lost Pilgrimage</color>", new string[2] { "DisorientedMode", "MarathonMode" });
			Combo("<color=#ffff00>One Knuckle to rule them all</color>", new string[2] { "ArmlessMode", "LeglessMode" });
			Combo("<color=#ff4d4d>Birth Defect</color>", new string[2] { "ArmlessMode", "BabyMode" });
			Combo("<color=#8cffff>Freezer Baby</color>", new string[2] { "BabyMode", "WindTunnelMode" });
			Combo("<color=#ff00ff>The Frail Endurance</color>", new string[2] { "GlassMode", "MarathonMode" });
			Combo("<color=#ff0000>Masochism</color>", new string[2] { "MarathonMode", "WindTunnelMode" });
			Combo("<color=#000000>Why</color>", new string[12]
			{
				"DevilDaggerMode", "ZenMode", "ZeroGravMode", "CombustMode", "MarkMode", "ArmlessMode", "BabyMode", "DisorientedMode", "GlassMode", "LeglessMode",
				"MarathonMode", "WindTunnelMode"
			});
			if (keep.Contains("BackwardMode"))
			{
				CustomModeRegistry.RegisterDisabledLock("BackwardMode");
				if (keep.Contains("MarathonMode"))
				{
					CustomModeRegistry.RegisterMutualLink("MarathonMode", "BackwardMode");
				}
			}
			if (keep.Contains("MarathonMode"))
			{
				CustomModeRegistry.RegisterGamemodeAlias("GM_Level_Tester", "Campaign");
				CustomModeRegistry.RegisterGamemodeAlias("Level Tester", "Campaign");
				MarathonPlaylist.Apply();
			}
			List<string> list = new List<string>();
			foreach (string item2 in keep)
			{
				if (CustomModeRegistry._modes.ContainsKey(item2))
				{
					list.Add(item2);
				}
			}
			CustomModeRegistry.InjectIntoGamemode("*", list.ToArray());
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"[Mutators] {keep.Count} of Nebulaetrix's modes registered (temporary bundle)");
			}
			void Combo(string label, params string[] ids)
			{
				foreach (string item in ids)
				{
					if (!keep.Contains(item))
					{
						return;
					}
				}
				CustomModeRegistry.RegisterCombo(ids, label);
			}
			void Reg(string id, string name, string desc, CustomModeRegistry.Difficulty difficulty, Action<bool> set, string[] exclusive = null)
			{
				if (keep.Contains(id))
				{
					CustomModeRegistry.Register(id, name, desc, difficulty, set, exclusive, disablesLeaderboards: true, "Mode by Nebulaetrix");
					if (CustomModeRegistry._modes.TryGetValue(id, out var value))
					{
						value.SourceMod = "Nebulaetrix's Mutators";
						value.SourceModGuid = "com.nebulaetrix.moremutators";
					}
				}
			}
		}
	}
	public static class MarathonPlaylist
	{
		[HarmonyPatch(typeof(MarathonMode), "ShuffleNumberedGroups")]
		private static class ShufflePatch
		{
			[HarmonyPrefix]
			private static bool Prefix(List<string> levels)
			{
				int num = 0;
				while (num < levels.Count)
				{
					string text = StripTrailingNumber(levels[num]);
					if (text == null)
					{
						num++;
						continue;
					}
					int i;
					for (i = num + 1; i < levels.Count && StripTrailingNumber(levels[i]) == text; i++)
					{
					}
					if (i - num >= 2 && !text.StartsWith("M5_Nest_Infested_"))
					{
						for (int num2 = i - 1; num2 > num; num2--)
						{
							int num3 = Random.Range(num, num2 + 1);
							int index = num2;
							int index2 = num3;
							string value = levels[num3];
							string value2 = levels[num2];
							levels[index] = value;
							levels[index2] = value2;
						}
					}
					num = i;
				}
				return false;
			}

			private static string StripTrailingNumber(string name)
			{
				if (string.IsNullOrEmpty(name))
				{
					return null;
				}
				int num = name.LastIndexOf('_');
				if (num < 0 || num == name.Length - 1)
				{
					return null;
				}
				for (int i = num + 1; i < name.Length; i++)
				{
					if (!char.IsDigit(name[i]))
					{
						return null;
					}
				}
				return name.Substring(0, num + 1);
			}
		}

		[HarmonyPatch(typeof(M_GenerationBranch), "GetGenerationList")]
		private static class NestBranchPatch
		{
			[HarmonyPrefix]
			private static bool Prefix(M_GenerationBranch __instance, ref List<LevelAssetHolder> __result)
			{
				if (!MarathonMode.Enabled || (Object)(object)__instance == (Object)null || __instance.regions == null)
				{
					return true;
				}
				bool flag = false;
				bool flag2 = false;
				foreach (M_Region region in __instance.regions)
				{
					if (!((Object)(object)region == (Object)null))
					{
						if (((Object)region).name.Contains("InfestedLab"))
						{
							flag = true;
						}
						else if (((Object)region).name.Contains("HotZone"))
						{
							flag2 = true;
						}
					}
				}
				if (!flag && !flag2)
				{
					return true;
				}
				List<LevelAssetHolder> list = new List<LevelAssetHolder>();
				if (flag)
				{
					Add(InfestedBlock, "Region_Nest_Campaign_Segment_InfestedLab_Regular", "Subregion_Nest_InfestedLabs");
					Add(HotZoneBlock, "Region_Nest_Campaign_Segment_HotZone", "Subregion_Nest_HotZone");
				}
				else
				{
					Add(HotZoneBlock, "Region_Nest_Campaign_Segment_HotZone", "Subregion_Nest_HotZone");
					Add(InfestedBlock, "Region_Nest_Campaign_Segment_InfestedLab_Regular", "Subregion_Nest_InfestedLabs");
				}
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)string.Format("[Mutators] Marathon: {0} door → {1} lab levels in order", flag ? "Infested" : "Hot Zone", list.Count));
				}
				__result = list;
				return false;
				void Add(string[] names, string regionName, string subregionName)
				{
					M_Region val = null;
					M_Subregion val2 = null;
					try
					{
						val = CL_AssetManager.GetRegionAsset(regionName, "");
						val2 = CL_AssetManager.GetSubregionAsset(subregionName, "");
					}
					catch
					{
					}
					foreach (string text in names)
					{
						LevelAssetHolder val3 = null;
						try
						{
							val3 = CL_AssetManager.GetLevelAsset(text, "");
						}
						catch
						{
						}
						if (val3 == null)
						{
							ManualLogSource log2 = Plugin.Log;
							if (log2 != null)
							{
								log2.LogWarning((object)("[Mutators] Marathon: level '" + text + "' not found, skipped"));
							}
						}
						else
						{
							if (!val3.setCustomRegionInfo)
							{
								if ((Object)(object)val != (Object)null)
								{
									val3.region = val;
								}
								if ((Object)(object)val2 != (Object)null)
								{
									val3.subregion = val2;
								}
							}
							list.Add(val3);
						}
					}
				}
			}
		}

		private static readonly string[] Levels = new string[143]
		{
			"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_Air_11", "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_Broken_11", "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_Silos_Storage_17", "Campaign_Interlude_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_Drainage_08", "M2_Pipeworks_Drainage_09", "M2_Pipeworks_Drainage_10", "M2_Pipeworks_Waste_01", "M2_Pipeworks_Waste_02", "M2_Pipeworks_Waste_03", "M2_Pipeworks_Waste_04", "M2_Pipeworks_Waste_05", "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", "M2_Pipeworks_Organ_09", "Campaign_Interlude_Pipeworks_To_Habitation_03", "M3_Habitation_Entryway_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_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_Lab_01", "M3_Habitation_Lab_02", "M3_Habitation_Lab_03", "M3_Habitation_Lab_04",
			"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_Lab_05", "M3_Habitation_Lab_06", "M3_Habitation_Lab_07",
			"M3_Habitation_Lab_08", "M3_Habitation_Endless_Breakroom_01", "M3_Habitation_Endless_Shaft_Start", "M3_Habitation_Shaft_07", "M3_Habitation_Shaft_01", "M3_Habitation_Shaft_To_Pier", "M3_Habitation_Pier_Entrance_01", "M3_Habitation_Pier_03", "M3_Habitation_Lab_Lobby", "M3_Habitation_Endless_Shaft_Start",
			"M3_Habitation_Shaft_02", "M3_Habitation_Shaft_03", "M3_Habitation_Shaft_To_Pier", "M3_Habitation_Pier_Entrance_01", "M3_Habitation_Pier_04", "M3_Habitation_Lab_Lobby", "M3_Habitation_Endless_Breakroom_01", "M3_Habitation_Lab_Ending", "Campaign_Interlude_Habitation_To_Abyss_01", "M4_Abyss_Transit_01",
			"M4_Abyss_Transit_02", "M4_Abyss_Transit_03", "M4_Abyss_Transit_05", "M4_Abyss_Transit_06", "M4_Abyss_Handle_01", "M4_Abyss_Garden_01", "M4_Abyss_Garden_02", "M4_Abyss_Garden_03", "M4_Abyss_Garden_04", "M4_Abyss_Outro_01",
			"Campaign_Interlude_Abyss_To_Nest_01_SafeArea", "Campaign_Interlude_Abyss_To_Nest_IntroClimb_01", "Campaign_Interlude_Abyss_To_Nest_01_Prison", "M5_Nest_Trough_Entrance_01", "M5_Nest_Trough_01", "M5_Nest_Trough_02", "M5_Nest_Trough_03", "M5_Nest_Trough_04", "M5_Nest_Trough_05", "M5_Nest_Trough_06",
			"M5_Nest_Trough_07", "M5_Nest_Trough_08", "M5_Nest_Trough_Ending_01"
		};

		private const string NoShufflePrefix = "M5_Nest_Infested_";

		private static readonly string[] InfestedBlock = new string[10] { "M5_Nest_Infested_Entrance_01", "M5_Nest_Infested_01", "M5_Nest_Infested_02", "M5_Nest_Infested_03", "M5_Nest_Infested_HunterIntro_01", "M5_Nest_Infested_04", "M5_Nest_Infested_05", "M5_Nest_Infested_Chase_01", "M5_Nest_Infested_Chase_02", "M5_Nest_Transition_Infested_To_Trough_01" };

		private static readonly string[] HotZoneBlock = new string[7] { "M5_Nest_HotZone_Intro_01", "M5_Nest_HotZone_01", "M5_Nest_HotZone_02", "M5_Nest_HotZone_03", "M5_Nest_HotZone_04", "M5_Nest_HotZone_Outro_01", "M5_Nest_Transition_HotZone_To_Trough_01" };

		public static void Apply()
		{
			List<string> orderedLevels = MutatorLevelsList.OrderedLevels;
			orderedLevels.Clear();
			orderedLevels.AddRange(Levels);
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[Mutators] Marathon playlist: {orderedLevels.Count} levels (Nest included)");
			}
		}
	}
	public static class Challenges
	{
		public class Challenge
		{
			public string Id;

			public string Title;

			public string[] Trinkets;

			public string[] Modes;

			public string How;

			public string Gamemode;

			public string LoopRoom;

			public int MinPass;

			public string Color;

			public bool IsLoop => !string.IsNullOrEmpty(LoopRoom);

			public bool IsPass => MinPass > 0;

			public Challenge(string id, string title, string how, string[] trinkets, string[] modes = null, string gamemode = null, string loopRoom = null)
			{
				Id = id;
				Title = title;
				How = how;
				Trinkets = trinkets;
				Modes = modes ?? Array.Empty<string>();
				Gamemode = gamemode;
				LoopRoom = loopRoom;
			}
		}

		[Serializable]
		private class Record
		{
			public string id;

			public bool done;

			public float seconds;

			public string date;
		}

		[Serializable]
		private class Store
		{
			public List<Record> records = new List<Record>();
		}

		[HarmonyPatch(typeof(CL_GameManager), "Win")]
		private static class WinPatch
		{
			[HarmonyPostfix]
			public static void Postfix()
			{
				try
				{
					M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
					if ((Object)(object)currentGamemode == (Object)null)
					{
						return;
					}
					SaveData saveData = StatManager.saveData;
					List<string> saved = ((saveData != null) ? saveData.GetGamemodeTrinkets(currentGamemode.GetGamemodeName(true)) : null);
					float gametime = CL_GameManager.GetGametime();
					bool flag = false;
					foreach (Challenge item in All)
					{
						if (!item.IsLoop && !item.IsPass && Satisfied(item, saved, currentGamemode))
						{
							flag |= Complete(item, gametime);
						}
					}
					if (flag)
					{
						Save();
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Challenges] win hook failed: " + ex.Message));
					}
				}
			}
		}

		[HarmonyPatch(typeof(M_Gamemode), "StartFreshGamemode")]
		private static class FreshRunPatch
		{
			[HarmonyPostfix]
			public static void Postfix()
			{
				_loopRoomSeen = false;
			}
		}

		[HarmonyPatch(typeof(M_Level), "OnEnter")]
		private static class LevelEnterPatch
		{
			[HarmonyPrefix]
			public static void Prefix(M_Level __instance, out bool __state)
			{
				__state = (Object)(object)__instance != (Object)null && __instance.HasEntered();
			}

			[HarmonyPostfix]
			public static void Postfix(M_Level __instance, bool __state)
			{
				if (__state || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				try
				{
					M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
					if ((Object)(object)currentGamemode == (Object)null)
					{
						return;
					}
					string text = __instance.levelName + "|" + ((Object)__instance).name;
					SaveData saveData = StatManager.saveData;
					List<string> saved = ((saveData != null) ? saveData.GetGamemodeTrinkets(currentGamemode.GetGamemodeName(true)) : null);
					bool flag = false;
					foreach (Challenge item in All)
					{
						if (item.IsLoop && InGamemode(currentGamemode, item.Gamemode))
						{
							if (text.IndexOf(item.LoopRoom, StringComparison.OrdinalIgnoreCase) >= 0)
							{
								_loopRoomSeen = true;
							}
							else if (_loopRoomSeen && Satisfied(item, saved, currentGamemode))
							{
								flag |= Complete(item, CL_GameManager.GetGametime());
							}
						}
					}
					if (flag)
					{
						Save();
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Challenges] loop hook failed: " + ex.Message));
					}
				}
			}
		}

		[HarmonyPatch(typeof(MenuManager), "Start")]
		private static class MenuPatch
		{
			[HarmonyPostfix]
			public static void Postfix(MenuManager __instance)
			{
				try
				{
					Build(__instance);
					Refresh();
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Challenges] menu panel failed: " + ex.Message));
					}
				}
			}
		}

		public class RowHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
		{
			public int Index;

			public Image Highlight;

			public void OnPointerEnter(PointerEventData _)
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)Highlight))
				{
					((Graphic)Highlight).color = new Color(1f, 1f, 1f, 0.12f);
				}
				ShowTip(Index);
			}

			public void OnPointerExit(PointerEventData _)
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)Highlight))
				{
					((Graphic)Highlight).color = new Color(1f, 1f, 1f, 0f);
				}
				HideTip();
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__55_0;

			internal void <Build>b__55_0()
			{
				_expanded = !_expanded;
				Refresh();
			}
		}

		private static readonly List<Challenge> _all = new List<Challenge>();

		public const string ParasiteGreen = "#18420F";

		public const string ChimneyBlue = "#8DDDF5";

		public const string FreezerTeal = "#528F82";

		private static bool _rowsDirty;

		private static Store _store;

		private static readonly string[] LegacySavePaths = new string[3]
		{
			Path.Combine(Dir, "CiCisAssortment", "cicis_challenges.json"),
			Path.Combine(Dir, "CiCisAssortment", "leos_challenges.json"),
			Path.Combine(Dir, "cicis_challenges.json")
		};

		private static bool _loopRoomSeen;

		private const string RootName = "CiCi_Challenges";

		private const float WinW = 380f;

		private const float HeaderH = 30f;

		private const float ListH = 220f;

		private const float RowH = 24f;

		private const float TipW = 320f;

		private static readonly Color BgColor = new Color(0f, 0f, 0f, 1f);

		private static readonly Color EdgeColor = new Color(1f, 1f, 1f, 0.75f);

		private static bool _expanded;

		private static RectTransform _root;

		private static RectTransform _list;

		private static RectTransform _content;

		private static RectTransform _tip;

		private static TextMeshProUGUI _header;

		private static TextMeshProUGUI _tipText;

		private static TMP_FontAsset _font;

		public static IReadOnlyList<Challenge> All => _all;

		private static string Dir => Path.GetDirectoryName(typeof(Challenges).Assembly.Location) ?? "";

		private static string FilePath => Path.Combine(Dir, "challenges.json");

		public static void Register(Challenge c)
		{
			if (c == null || string.IsNullOrEmpty(c.Id))
			{
				return;
			}
			for (int i = 0; i < _all.Count; i++)
			{
				if (_all[i].Id == c.Id)
				{
					_all[i] = c;
					_rowsDirty = true;
					return;
				}
			}
			_all.Add(c);
			_rowsDirty = true;
		}

		public static void Register(string id, string title, string how, string[] trinkets, string[] modes = null, string gamemode = null, string loopRoom = null)
		{
			Register(new Challenge(id, title, how, trinkets, modes, gamemode, loopRoom));
		}

		public static void RegisterPass(string id, string title, string how, int minPass, string[] modes, string[] trinkets = null, string color = null)
		{
			Register(new Challenge(id, title, how, trinkets ?? Array.Empty<string>(), modes, "parasite")
			{
				MinPass = minPass,
				Color = color
			});
		}

		internal static void RegisterBuiltIn()
		{
			RegisterPass("meat_freezer", "Meat Freezer", "Gamemode: <b>Parasite</b>. Gamemode settings: <b>Endless Parasite</b> + <b>SB12 Anomaly</b>.", 30, new string[2] { "cici_endless_parasite", "cici_sb12_anomaly" }, null, "#528F82");
			RegisterPass("new_home", "A New Home", "Gamemode: <b>Parasite</b>. Gamemode settings: <b>Endless Parasite</b>.", 51, new string[1] { "cici_endless_parasite" }, null, "#18420F");
		}

		internal static void OnEndlessPass(int pass, float totalSeconds)
		{
			try
			{
				M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
				if ((Object)(object)currentGamemode == (Object)null)
				{
					return;
				}
				SaveData saveData = StatManager.saveData;
				List<string> saved = ((saveData != null) ? saveData.GetGamemodeTrinkets(currentGamemode.GetGamemodeName(true)) : null);
				bool flag = false;
				foreach (Challenge item in All)
				{
					if (item.IsPass && pass >= item.MinPass && Satisfied(item, saved, currentGamemode))
					{
						flag |= Complete(item, totalSeconds);
					}
				}
				if (flag)
				{
					Save();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Challenges] pass hook failed: " + ex.Message));
				}
			}
		}

		private static Store Load()
		{
			if (_store != null)
			{
				return _store;
			}
			try
			{
				string text = (File.Exists(FilePath) ? FilePath : null);
				if (text == null)
				{
					string[] legacySavePaths = LegacySavePaths;
					foreach (string text2 in legacySavePaths)
					{
						if (File.Exists(text2))
						{
							text = text2;
							break;
						}
					}
				}
				if (text != null)
				{
					_store = JsonConvert.DeserializeObject<Store>(File.ReadAllText(text));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Challenges] load failed: " + ex.Message));
				}
			}
			return _store ?? (_store = new Store());
		}

		private static void Save()
		{
			try
			{
				File.WriteAllText(FilePath, JsonConvert.SerializeObject((object)Load(), (Formatting)1));
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Challenges] save failed: " + ex.Message));
				}
			}
		}

		private static Record Get(string id)
		{
			foreach (Record record in Load().records)
			{
				if (record.id == id)
				{
					return record;
				}
			}
			return null;
		}

		private static bool Has(List<string> saved, string id)
		{
			if (saved == null)
			{
				return false;
			}
			if (id.IndexOf('|') >= 0)
			{
				string[] array = id.Split('|');
				foreach (string id2 in array)
				{
					if (Has(saved, id2))
					{
						return true;
					}
				}
				return false;
			}
			string text = id.ToLowerInvariant();
			foreach (string item in saved)
			{
				if (string.IsNullOrEmpty(item))
				{
					continue;
				}
				string text2 = item.ToLowerInvariant();
				if (text.EndsWith("*"))
				{
					string text3 = text.Substring(0, text.Length - 1);
					if (text2.StartsWith(text3) || text2.Contains("_" + text3))
					{
						return true;
					}
				}
				else if (text2 == text || text2.EndsWith("_" + text))
				{
					return true;
				}
			}
			return false;
		}

		private static bool InGamemode(M_Gamemode gm, string name)
		{
			try
			{
				return (Object)(object)gm != (Object)null && (gm.GetGamemodeName(false) ?? "").Trim().ToLowerInvariant().Contains(name.ToLowerInvariant());
			}
			catch
			{
				return false;
			}
		}

		private static bool ModeOn(M_Gamemode gm, string id)
		{
			try
			{
				return (Object)(object)gm != (Object)null && gm.HasActiveSetting(id);
			}
			catch
			{
				return false;
			}
		}

		private static bool Satisfied(Challenge c, List<string> saved, M_Gamemode gm)
		{
			if (c.Gamemode != null && !InGamemode(gm, c.Gamemode))
			{
				return false;
			}
			string[] trinkets = c.Trinkets;
			foreach (string id in trinkets)
			{
				if (!Has(saved, id))
				{
					return false;
				}
			}
			trinkets = c.Modes;
			foreach (string id2 in trinkets)
			{
				if (!ModeOn(gm, id2))
				{
					return false;
				}
			}
			int num = 0;
			if (saved != null)
			{
				foreach (string item in saved)
				{
					if (!string.IsNullOrEmpty(item))
					{
						num++;
					}
				}
			}
			if (num != c.Trinkets.Length)
			{
				return false;
			}
			foreach (KeyValuePair<string, CustomModeRegistry.Mode> item2 in CustomModeRegistry.All)
			{
				if (Array.IndexOf(c.Modes, item2.Key) < 0 && ModeOn(gm, item2.Key))
				{
					return false;
				}
			}
			return true;
		}

		private static bool Complete(Challenge c, float secs)
		{
			Record record = Get(c.Id);
			if (record == null)
			{
				record = new Record
				{
					id = c.Id
				};
				Load().records.Add(record);
			}
			if (record.done && secs >= record.seconds)
			{
				return false;
			}
			record.done = true;
			record.seconds = secs;
			record.date = DateTime.Now.ToString("yyyy-MM-dd");
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[Challenges] completed '" + c.Title + "' in " + Fmt(secs)));
			}
			return true;
		}

		private static string Fmt(float s)
		{
			TimeSpan timeSpan = TimeSpan.FromSeconds(s);
			if (timeSpan.Hours <= 0)
			{
				return $"{timeSpan.Minutes}:{timeSpan.Seconds:00}";
			}
			return $"{timeSpan.Hours}:{timeSpan.Minutes:00}:{timeSpan.Seconds:00}";
		}

		private static RectTransform NewRect(string name, Transform parent)
		{
			//IL_0014: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform;
			((Transform)val).SetParent(parent, false);
			return val;
		}

		private static void TopRight(RectTransform rt, float x, float y, float w, float h)
		{
			//IL_0014: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(1f, 1f);
			rt.pivot = val;
			Vector2 anchorMin = (rt.anchorMax = val);
			rt.anchorMin = anchorMin;
			rt.anchoredPosition = new Vector2(x, y);
			rt.sizeDelta = new Vector2(w, h);
		}

		private static Image Box(RectTransform rt, Color fill, bool edge)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Image obj = ((Component)rt).GetComponent<Image>() ?? ((Component)rt).gameObject.AddComponent<Image>();
			((Graphic)obj).color = fill;
			if (edge)
			{
				Outline obj2 = ((Component)rt).GetComponent<Outline>() ?? ((Component)rt).gameObject.AddComponent<Outline>();
				((Shadow)obj2).effectColor = EdgeColor;
				((Shadow)obj2).effectDistance = new Vector2(1.5f, -1.5f);
			}
			return obj;
		}

		private static TextMeshProUGUI Text(RectTransform rt, float size, TextAlignmentOptions align)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = ((Component)rt).GetComponent<TextMeshProUGUI>() ?? ((Component)rt).gameObject.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_font != (Object)null)
			{
				((TMP_Text)val).font = _font;
			}
			((TMP_Text)val).fontSize = size;
			((TMP_Text)val).alignment = align;
			((TMP_Text)val).richText = true;
			((TMP_Text)val).enableWordWrapping = false;
			return val;
		}

		private static void Build(MenuManager mm)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: 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_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Expected O, but got Unknown
			if ((Object)(object)_root != (Object)null && (Object)(object)((Component)_root).gameObject != (Object)null)
			{
				return;
			}
			Canvas val = (((Object)(object)mm != (Object)null && (Object)(object)mm.menu != (Object)null) ? ((Component)mm.menu).GetComponentInParent<Canvas>() : null);
			if ((Object)(object)val == (Object)null)
			{
				val = Object.FindFirstObjectByType<Canvas>();
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			RectTransform val2 = (RectTransform)((Component)val).transform;
			object font;
			if (!((Object)(object)mm?.menu != (Object)null))
			{
				font = null;
			}
			else
			{
				TMP_Text componentInChildren = ((Component)mm.menu).GetComponentInChildren<TMP_Text>(true);
				font = ((componentInChildren != null) ? componentInChildren.font : null);
			}
			_font = (TMP_FontAsset)font;
			Transform val3 = ((Transform)val2).Find("CiCi_Challenges");
			if ((Object)(object)val3 != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val3).gameObject);
			}
			_root = NewRect("CiCi_Challenges", (Transform)(object)val2);
			TopRight(_root, -16f, -16f, 380f, 30f);
			((Transform)_root).SetAsLastSibling();
			RectTransform val4 = NewRect("Header", (Transform)(object)_root);
			TopRight(val4, 0f, 0f, 380f, 30f);
			((Graphic)Box(val4, BgColor, edge: true)).raycastTarget = true;
			RectTransform obj = NewRect("Text", (Transform)(object)val4);
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = new Vector2(10f, 0f);
			obj.offsetMax = new Vector2(-10f, 0f);
			_header = Text(obj, 18f, (TextAlignmentOptions)4097);
			((TMP_Text)_header).fontStyle = (FontStyles)1;
			((Graphic)_header).raycastTarget = false;
			Button obj2 = ((Component)val4).gameObject.AddComponent<Button>();
			((Selectable)obj2).transition = (Transition)0;
			ButtonClickedEvent onClick = obj2.onClick;
			object obj3 = <>c.<>9__55_0;
			if (obj3 == null)
			{
				UnityAction val5 = delegate
				{
					_expanded = !_expanded;
					Refresh();
				};
				<>c.<>9__55_0 = val5;
				obj3 = (object)val5;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj3);
			_list = NewRect("List", (Transform)(object)_root);
			TopRight(_list, 0f, -30f, 380f, 220f);
			((Graphic)Box(_list, BgColor, edge: true)).raycastTarget = true;
			RectTransform val6 = NewRect("Viewport", (Transform)(object)_list);
			val6.anchorMin = Vector2.zero;
			val6.anchorMax = Vector2.one;
			val6.offsetMin = new Vector2(4f, 4f);
			val6.offsetMax = new Vector2(-4f, -4f);
			((Component)val6).gameObject.AddComponent<RectMask2D>();
			((Graphic)((Component)val6).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.01f);
			_content = NewRect("Content", (Transform)(object)val6);
			_content.anchorMin = new Vector2(0f, 1f);
			_content.anchorMax = new Vector2(1f, 1f);
			_content.pivot = new Vector2(0.5f, 1f);
			_content.anchoredPosition = Vector2.zero;
			ScrollRect obj4 = ((Component)_list).gameObject.AddComponent<ScrollRect>();
			obj4.viewport = val6;
			obj4.content = _content;
			obj4.horizontal = false;
			obj4.vertical = true;
			obj4.movementType = (MovementType)2;
			obj4.scrollSensitivity = 24f;
			BuildRows();
			_tip = NewRect("Tip", (Transform)(object)_root);
			TopRight(_tip, -390f, -30f, 320f, 80f);
			((Graphic)Box(_tip, BgColor, edge: true)).raycastTarget = false;
			RectTransform obj5 = NewRect("Text", (Transform)(object)_tip);
			obj5.anchorMin = Vector2.zero;
			obj5.anchorMax = Vector2.one;
			obj5.offsetMin = new Vector2(10f, 8f);
			obj5.offsetMax = new Vector2(-10f, -8f);
			_tipText = Text(obj5, 14f, (TextAlignmentOptions)257);
			((TMP_Text)_tipText).enableWordWrapping = true;
			((Graphic)_tipText).raycastTarget = false;
			((Component)_tip).gameObject.SetActive(false);
		}

		private static void BuildRows()
		{
			//IL_0047: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_010a: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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)
			for (int num = ((Transform)_content).childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)((Transform)_content).GetChild(num)).gameObject);
			}
			_content.sizeDelta = new Vector2(0f, 24f * (float)All.Count);
			for (int i = 0; i < All.Count; i++)
			{
				RectTransform val = NewRect("Row_" + All[i].Id, (Transform)(object)_content);
				val.anchorMin = new Vector2(0f, 1f);
				val.anchorMax = new Vector2(1f, 1f);
				val.pivot = new Vector2(0.5f, 1f);
				val.anchoredPosition = new Vector2(0f, -24f * (float)i);
				val.sizeDelta = new Vector2(0f, 24f);
				Image val2 = ((Component)val).gameObject.AddComponent<Image>();
				((Graphic)val2).color = new Color(1f, 1f, 1f, 0f);
				RectTransform obj = NewRect("Text", (Transform)(object)val);
				obj.anchorMin = Vector2.zero;
				obj.anchorMax = Vector2.one;
				obj.offsetMin = new Vector2(8f, 0f);
				obj.offsetMax = new Vector2(-8f, 0f);
				((Graphic)Text(obj, 15f, (TextAlignmentOptions)4097)).raycastTarget = false;
				RowHover rowHover = ((Component)val).gameObject.AddComponent<RowHover>();
				rowHover.Index = i;
				rowHover.Highlight = val2;
			}
			_rowsDirty = false;
		}

		private static void Refresh()
		{
			if ((Object)(object)_root == (Object)null)
			{
				return;
			}
			if (_rowsDirty || ((Transform)_content).childCount != All.Count)
			{
				BuildRows();
			}
			int num = 0;
			foreach (Challenge item in All)
			{
				Record record = Get(item.Id);
				if (record != null && record.done)
				{
					num++;
				}
			}
			((TMP_Text)_header).text = string.Format("Challenges  <color=#AAAAAA>{0}/{1}</color>  {2}", num, All.Count, _expanded ? "–" : "+");
			((Component)_list).gameObject.SetActive(_expanded);
			if (!_expanded)
			{
				((Component)_tip).gameObject.SetActive(false);
				return;
			}
			for (int i = 0; i < All.Count; i++)
			{
				Challenge challenge = All[i];
				TextMeshProUGUI componentInChildren = ((Component)((Transform)_content).GetChild(i)).GetComponentInChildren<TextMeshProUGUI>();
				Record record2 = Get(challenge.Id);
				string text = ((record2 != null && record2.done) ? "<color=#6CE26C>[•]</color>" : "<color=#888888>[ ]</color>");
				string text2 = ((record2 != null && record2.done) ? ("   <color=#AAAAAA>" + Fmt(record2.seconds) + " · " + record2.date + "</color>") : "");
				string text3 = ((challenge.Color != null) ? ("<color=" + challenge.Color + ">" + challenge.Title + "</color>") : challenge.Title);
				((TMP_Text)componentInChildren).text = text + "  " + text3 + text2;
			}
		}

		private static void ShowTip(int index)
		{
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_tip == (Object)null) && index >= 0 && index < All.Count)
			{
				Challenge challenge = All[index];
				Record record = Get(challenge.Id);
				int num = challenge.Trinkets.Length + challenge.Modes.Length;
				string text = (challenge.IsPass ? $"Reach loop {challenge.MinPass}" : (challenge.IsLoop ? "Finish the first loop" : ((challenge.Gamemode != null) ? "Beat the run" : "Beat the campaign"))) + " with only " + ((num > 1) ? "these" : "this") + " active.";
				string text2 = ((record != null && record.done) ? ("\n<color=#6CE26C>Done</color> — best " + Fmt(record.seconds) + " on " + record.date) : "");
				string text3 = challenge.Color ?? "#FFFFFF";
				((TMP_Text)_tipText).text = "<b><color=" + text3 + ">" + challenge.Title + "</color></b>\n<color=" + text3 + ">" + challenge.How + "</color>\n<color=#AAAAAA>" + text + "</color>" + text2;
				((TMP_Text)_tipText).ForceMeshUpdate(false, false);
				float num2 = Mathf.Max(60f, ((TMP_Text)_tipText).preferredHeight + 16f);
				float num3 = -34f - 24f * (float)index + _content.anchoredPosition.y;
				TopRight(_tip, -390f, Mathf.Clamp(num3, -250f + num2, -30f), 320f, num2);
				((Component)_tip).gameObject.SetActive(true);
			}
		}

		private static void HideTip()
		{
			if ((Object)(object)_tip != (Object)null)
			{
				((Component)_tip).gameObject.SetActive(false);
			}
		}
	}
	public static class CustomModeRegistry
	{
		public enum Difficulty
		{
			Easy,
			Medium,
			Hard,
			Extreme
		}

		public class Mode
		{
			public string Id;

			public string DisplayName;

			public string Description;

			public Difficulty Difficulty;

			public Action<bool> OnToggle;

			public List<string> ExclusiveSettingIds;

			public bool DisablesLeaderboards;

			public string HoverCreditText;

			public Color? ColorOverride;

			internal GamemodeSetting RuntimeSetting;

			public string SourceMod;

			public string SourceModGuid;

			public HashSet<string> Gamemodes;
		}

		internal static readonly Dictionary<string, Mode> _modes = new Dictionary<string, Mode>(StringComparer.Ordinal);

		internal static readonly List<(string[] ids, string display)> _combos = new List<(string[], string)>();

		internal static readonly Dictionary<string, string> _disabledLocks = new Dictionary<string, string>(StringComparer.Ordinal);

		internal static readonly List<(string a, string b)> _mutualLinks = new List<(string, string)>();

		internal static readonly HashSet<string> _injectedGamemodes = new HashSet<string>(StringComparer.OrdinalIgnoreC