Decompiled source of Silent55ModMenu v4.5.4

BepInEx\plugins\Silent55ModMenu\Silent55ModMenu.dll

Decompiled 10 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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 BepInEx;
using BepInEx.Configuration;
using EntityStates.Croco;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.CharacterAI;
using RoR2.Projectile;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[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("Silent55ModMenu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Silent55ModMenu")]
[assembly: AssemblyTitle("Silent55ModMenu")]
[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 Silent55ModMenu
{
	[BepInPlugin("com.silent55.modmenu", "Silent55 ModMenu", "4.5.4")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private class MenuPreset
		{
			public bool god;

			public bool noCd;

			public bool maxHp;

			public bool lockOn;

			public bool projectiles;

			public bool rapid;

			public bool reload;

			public bool secondary;

			public bool special;

			public bool markers;

			public bool teleporter;

			public bool chests;

			public bool shrines;

			public bool drops;

			public bool shops;

			public bool converters;

			public bool drones;

			public bool misc;

			public bool portals;

			public bool guaranteed;

			public bool summons;

			public bool acridTargets;

			public bool acridRange;

			public float attack;

			public float move;

			public float damage;

			public float difficulty;

			public float tp;

			public float lockDistance;

			public float lockAngle;

			public float tracking;

			public float rapidInterval;

			public int jumps;
		}

		private class LoadoutEntry
		{
			public PickupIndex pickup;

			public int count;
		}

		public class RunControlRequest : MessageBase
		{
			public int action;

			public float value;

			public string requester;

			public string version;

			public override void Serialize(NetworkWriter w)
			{
				w.Write(action);
				w.Write(value);
				w.Write(requester ?? "");
				w.Write(version ?? "");
			}

			public override void Deserialize(NetworkReader r)
			{
				action = r.ReadInt32();
				value = r.ReadSingle();
				requester = r.ReadString();
				version = r.ReadString();
			}
		}

		public class RunControlResponse : MessageBase
		{
			public bool approved;

			public string message;

			public override void Serialize(NetworkWriter w)
			{
				w.Write(approved);
				w.Write(message ?? "");
			}

			public override void Deserialize(NetworkReader r)
			{
				approved = r.ReadBoolean();
				message = r.ReadString();
			}
		}

		private bool visible = true;

		private bool practiceFreeze;

		private bool practiceDisableAI;

		private bool practiceFullPause;

		private bool showMarkerDistance = true;

		private bool godMode;

		private bool noCooldown;

		private bool empoweredSummons;

		private bool guaranteedShrineChance;

		private bool acridUnlimitedTargets;

		private bool acridUnlimitedRange;

		private bool rapidFire;

		private bool rapidFireReload = true;

		private bool rapidFireSecondary = true;

		private bool rapidFireSpecial;

		private bool lockOn;

		private bool projectileTracking = true;

		private bool markers;

		private bool showChests = true;

		private bool showTeleporter = true;

		private bool showShrines = true;

		private bool showDrops = true;

		private bool maxPersonal;

		private bool showShops = true;

		private bool showConverters = true;

		private bool showDrones = true;

		private bool showMisc = true;

		private bool showPortals = true;

		private float markerMaxDistance = 1000f;

		private float jumpHeightMultiplier = 1f;

		private float attackMultiplier = 1f;

		private float moveMultiplier = 1f;

		private float damageMultiplier = 1f;

		private float difficultyRate = 1f;

		private float teleporterRate = 1f;

		private float lockDistance = 60f;

		private float lockAngle = 35f;

		private float trackingStrength = 75f;

		private float rapidFireInterval = 0.08f;

		private string itemSearch = "";

		private int spawnQuantity = 1;

		private int spawnPressureMode;

		private PickupIndex selectedPickup = PickupIndex.none;

		private int extraJumps;

		private string status = "Ready";

		private float saveQuitConfirmUntil;

		private float cleanupConfirmUntil;

		private int tab;

		private string loadoutSearch = "";

		private int loadoutQuantity = 1;

		private Vector2 loadoutScroll;

		private string presetName = "Custom Slot 1";

		private int customPresetSlot = 1;

		private int presetLoadedSlot = -1;

		private float presetOverwriteConfirmUntil;

		private int selectedRecoveryPlayer;

		private Vector2 recoveryScroll;

		private int spawnerMode;

		private int selectedEnemyMaster;

		private int enemyQuantity = 1;

		private float enemySpawnDistance = 15f;

		private string enemySearch = "";

		private Vector2 enemyScroll;

		private readonly List<GameObject> enemyMasterPrefabs = new List<GameObject>();

		private readonly List<CharacterMaster> silent55SpawnedMasters = new List<CharacterMaster>();

		private Rect window = new Rect(20f, 20f, 720f, 820f);

		private int centeredScreenW;

		private int centeredScreenH;

		private CharacterBody tracked;

		private HealthComponent trackedHealth;

		private float oldAttack;

		private float oldDamage;

		private float oldMove;

		private float oldHealth;

		private float oldRegen;

		private float oldJumpPower;

		private int originalDiseaseBounces;

		private float originalDiseaseBounceRange;

		private float originalDiseaseOrbRange;

		private bool diseaseDefaultsCaptured;

		private int oldJumps;

		private Vector3 savedPosition;

		private bool hasSavedPosition;

		private float nextScan;

		private float nextSpawnPressureApply;

		private float unlockConfirmUntil;

		private float nextPracticeUpdate;

		private float nextSafetyScan;

		private int cachedBodies;

		private int cachedProjectiles;

		private int cachedPickups;

		private bool lastPracticeFreeze;

		private bool lastPracticeDisableAI;

		private bool lastPracticeFullPause;

		private float nextPracticeCache;

		private readonly List<CharacterBody> practiceBodies = new List<CharacterBody>();

		private readonly List<BaseAI> practiceAIs = new List<BaseAI>();

		private PickupIndex lastGivenPickup = PickupIndex.none;

		private int lastGivenCount;

		private float nextPrimaryFire;

		private float nextSecondaryFire;

		private float nextSpecialFire;

		private readonly List<ChestBehavior> chests = new List<ChestBehavior>();

		private readonly List<ShrineBehavior> shrines = new List<ShrineBehavior>();

		private readonly List<PickupDropletController> drops = new List<PickupDropletController>();

		private readonly List<GenericPickupController> groundPickups = new List<GenericPickupController>();

		private readonly List<PurchaseInteraction> interactables = new List<PurchaseInteraction>();

		private readonly List<ShopTerminalBehavior> shops = new List<ShopTerminalBehavior>();

		private readonly List<SummonMasterBehavior> repairables = new List<SummonMasterBehavior>();

		private GUIStyle titleStyle;

		private GUIStyle sectionStyle;

		private GUIStyle onStyle;

		private GUIStyle offStyle;

		private GUIStyle tabStyle;

		private GUIStyle tabOnStyle;

		private GUIStyle cyanButtonStyle;

		private GUIStyle dangerButtonStyle;

		private Texture2D silent55Logo;

		private const short RequestMessageId = 28550;

		private const short ResponseMessageId = 28551;

		private const string NetworkVersion = "4.5.4";

		private NetworkClient registeredClient;

		private bool serverHandlerRegistered;

		private bool autoApproveRequests;

		private NetworkConnection pendingConnection;

		private RunControlRequest pendingRequest;

		private readonly HashSet<HoldoutZoneController> hookedZones = new HashSet<HoldoutZoneController>();

		private Run trackedRun;

		private float lastRunTime;

		private float realSessionTime;

		private float nextDifficultyRecalc;

		private int trackedStageClearCount = -1;

		private readonly Dictionary<string, List<LoadoutEntry>> opLoadouts = new Dictionary<string, List<LoadoutEntry>>();

		private readonly Dictionary<string, List<LoadoutEntry>> grantedLoadouts = new Dictionary<string, List<LoadoutEntry>>();

		private string loadedLoadoutCharacter = "";

		private readonly HashSet<string> loadoutAppliedThisRun = new HashSet<string>();

		private Run appliedRun;

		private float nextSummonScan;

		private readonly HashSet<CharacterMaster> empoweredMinions = new HashSet<CharacterMaster>();

		private HuntressTracker silentTracker;

		private CharacterBody trackerBody;

		private readonly HashSet<ProjectileController> trackedProjectiles = new HashSet<ProjectileController>();

		private MenuPreset CapturePreset()
		{
			return new MenuPreset
			{
				god = godMode,
				noCd = noCooldown,
				maxHp = maxPersonal,
				lockOn = lockOn,
				projectiles = projectileTracking,
				rapid = rapidFire,
				reload = rapidFireReload,
				secondary = rapidFireSecondary,
				special = rapidFireSpecial,
				markers = markers,
				teleporter = showTeleporter,
				chests = showChests,
				shrines = showShrines,
				drops = showDrops,
				shops = showShops,
				converters = showConverters,
				drones = showDrones,
				misc = showMisc,
				portals = showPortals,
				guaranteed = guaranteedShrineChance,
				summons = empoweredSummons,
				acridTargets = acridUnlimitedTargets,
				acridRange = acridUnlimitedRange,
				attack = attackMultiplier,
				move = moveMultiplier,
				damage = damageMultiplier,
				difficulty = difficultyRate,
				tp = teleporterRate,
				lockDistance = lockDistance,
				lockAngle = lockAngle,
				tracking = trackingStrength,
				rapidInterval = rapidFireInterval,
				jumps = extraJumps
			};
		}

		private void ApplyPreset(MenuPreset p, string name)
		{
			if (p != null)
			{
				godMode = p.god;
				noCooldown = p.noCd;
				maxPersonal = p.maxHp;
				lockOn = p.lockOn;
				projectileTracking = p.projectiles;
				rapidFire = p.rapid;
				rapidFireReload = p.reload;
				rapidFireSecondary = p.secondary;
				rapidFireSpecial = p.special;
				markers = p.markers;
				showTeleporter = p.teleporter;
				showChests = p.chests;
				showShrines = p.shrines;
				showDrops = p.drops;
				showShops = p.shops;
				showConverters = p.converters;
				showDrones = p.drones;
				showMisc = p.misc;
				showPortals = p.portals;
				guaranteedShrineChance = p.guaranteed;
				empoweredSummons = p.summons;
				acridUnlimitedTargets = p.acridTargets;
				acridUnlimitedRange = p.acridRange;
				attackMultiplier = p.attack;
				moveMultiplier = p.move;
				damageMultiplier = p.damage;
				difficultyRate = p.difficulty;
				teleporterRate = p.tp;
				lockDistance = p.lockDistance;
				lockAngle = p.lockAngle;
				trackingStrength = p.tracking;
				rapidFireInterval = p.rapidInterval;
				extraJumps = p.jumps;
				if (NetworkServer.active)
				{
					ApplyRunAction(1, difficultyRate);
					ApplyRunAction(2, teleporterRate);
					ApplyRunAction(6, guaranteedShrineChance ? 1f : 0f);
				}
				status = "Applied preset: " + name;
			}
		}

		private string SerializePreset(MenuPreset p)
		{
			return string.Join("|", new bool[23]
			{
				p.god, p.noCd, p.maxHp, p.lockOn, p.projectiles, p.rapid, p.reload, p.secondary, p.special, p.markers,
				p.teleporter, p.chests, p.shrines, p.drops, p.shops, p.converters, p.drones, p.misc, p.portals, p.guaranteed,
				p.summons, p.acridTargets, p.acridRange
			}.Select((bool x) => (!x) ? "0" : "1").Concat(new string[10]
			{
				p.attack.ToString(CultureInfo.InvariantCulture),
				p.move.ToString(CultureInfo.InvariantCulture),
				p.damage.ToString(CultureInfo.InvariantCulture),
				p.difficulty.ToString(CultureInfo.InvariantCulture),
				p.tp.ToString(CultureInfo.InvariantCulture),
				p.lockDistance.ToString(CultureInfo.InvariantCulture),
				p.lockAngle.ToString(CultureInfo.InvariantCulture),
				p.tracking.ToString(CultureInfo.InvariantCulture),
				p.rapidInterval.ToString(CultureInfo.InvariantCulture),
				p.jumps.ToString()
			}).ToArray());
		}

		private MenuPreset DeserializePreset(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return null;
			}
			string[] a = raw.Split('|');
			if (a.Length < 33)
			{
				return null;
			}
			int i = 0;
			Func<bool> func = () => a[i++] == "1";
			Func<float> func2 = () => float.Parse(a[i++], CultureInfo.InvariantCulture);
			return new MenuPreset
			{
				god = func(),
				noCd = func(),
				maxHp = func(),
				lockOn = func(),
				projectiles = func(),
				rapid = func(),
				reload = func(),
				secondary = func(),
				special = func(),
				markers = func(),
				teleporter = func(),
				chests = func(),
				shrines = func(),
				drops = func(),
				shops = func(),
				converters = func(),
				drones = func(),
				misc = func(),
				portals = func(),
				guaranteed = func(),
				summons = func(),
				acridTargets = func(),
				acridRange = func(),
				attack = func2(),
				move = func2(),
				damage = func2(),
				difficulty = func2(),
				tp = func2(),
				lockDistance = func2(),
				lockAngle = func2(),
				tracking = func2(),
				rapidInterval = func2(),
				jumps = int.Parse(a[i++])
			};
		}

		private bool CustomPresetExists(int slot)
		{
			return !string.IsNullOrWhiteSpace(((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null).Value);
		}

		private void SaveCustomPreset(int slot)
		{
			string text = (string.IsNullOrWhiteSpace(presetName) ? ("Custom Slot " + slot) : presetName.Trim());
			string value = SerializePreset(CapturePreset());
			ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Name", "Custom Slot " + slot, (ConfigDescription)null);
			ConfigEntry<string> obj = ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null);
			val.Value = text;
			obj.Value = value;
			((BaseUnityPlugin)this).Config.Save();
			presetName = text;
			presetLoadedSlot = slot;
			presetOverwriteConfirmUntil = 0f;
			status = "Saved preset: " + text;
		}

		private void ApplyCustomPreset(int slot)
		{
			string value = ((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Name", "Custom Slot " + slot, (ConfigDescription)null).Value;
			MenuPreset menuPreset = DeserializePreset(((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null).Value);
			if (menuPreset == null)
			{
				status = "Custom slot " + slot + " is empty";
			}
			else
			{
				ApplyPreset(menuPreset, value);
			}
		}

		private void ResetCustomPreset(int slot)
		{
			presetOverwriteConfirmUntil = 0f;
			presetLoadedSlot = slot;
			((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Name", "Custom Slot " + slot, (ConfigDescription)null).Value = "Custom Slot " + slot;
			((BaseUnityPlugin)this).Config.Bind<string>("Presets", "Slot" + slot + "Data", "", (ConfigDescription)null).Value = "";
			((BaseUnityPlugin)this).Config.Save();
			presetName = "Custom Slot " + slot;
			status = "Reset custom slot " + slot;
		}

		private MenuPreset BuiltInPreset(string name)
		{
			MenuPreset menuPreset = CapturePreset();
			menuPreset.god = false;
			menuPreset.noCd = false;
			menuPreset.maxHp = false;
			menuPreset.lockOn = false;
			menuPreset.projectiles = true;
			menuPreset.rapid = false;
			menuPreset.markers = true;
			menuPreset.guaranteed = false;
			menuPreset.summons = false;
			menuPreset.acridTargets = false;
			menuPreset.acridRange = false;
			menuPreset.attack = 1f;
			menuPreset.move = 1f;
			menuPreset.damage = 1f;
			menuPreset.difficulty = 1f;
			menuPreset.tp = 1f;
			menuPreset.jumps = 0;
			switch (name)
			{
			case "Practice":
				menuPreset.god = true;
				menuPreset.noCd = true;
				menuPreset.maxHp = true;
				menuPreset.lockOn = true;
				menuPreset.damage = 5f;
				menuPreset.move = 2f;
				menuPreset.jumps = 3;
				break;
			case "OP Showcase":
				menuPreset.god = true;
				menuPreset.noCd = true;
				menuPreset.maxHp = true;
				menuPreset.lockOn = true;
				menuPreset.rapid = true;
				menuPreset.reload = true;
				menuPreset.secondary = true;
				menuPreset.special = true;
				menuPreset.attack = 5f;
				menuPreset.move = 3f;
				menuPreset.damage = 100f;
				menuPreset.jumps = 5;
				menuPreset.guaranteed = true;
				break;
			case "Extreme Challenge":
				menuPreset.difficulty = 25f;
				menuPreset.tp = 1f;
				menuPreset.markers = false;
				break;
			case "Drone Commander":
				menuPreset.summons = true;
				menuPreset.guaranteed = true;
				menuPreset.move = 1.5f;
				break;
			}
			return menuPreset;
		}

		private void SafeUpdate(string n, Action a)
		{
			try
			{
				a();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Silent55 " + n + ": " + ex));
				status = n + " error; see log";
			}
		}

		private void Update()
		{
			SafeUpdate("network", InitRequestNetwork);
			SafeUpdate("run", UpdateRunControls);
			SafeUpdate("enemy limit", UpdateEnemyLimit);
			if ((Object)(object)Run.instance != (Object)(object)appliedRun)
			{
				appliedRun = Run.instance;
				loadoutAppliedThisRun.Clear();
				grantedLoadouts.Clear();
			}
			SafeUpdate("loadouts", EnsureCharacterLoadout);
			SafeUpdate("shrines", UpdateGuaranteedShrines);
			SafeUpdate("acrid", UpdateAcridEpidemic);
			SafeUpdate("rapid", UpdateRapidFire);
			SafeUpdate("lock", UpdateLockOn);
			if (NetworkServer.active && empoweredSummons && Time.unscaledTime >= nextSummonScan)
			{
				EmpowerOwnedMinions(((Object)(object)GetBody() != (Object)null) ? GetBody().master : null);
				nextSummonScan = Time.unscaledTime + 1f;
			}
			if (Input.GetKeyDown((KeyCode)288))
			{
				visible = !visible;
			}
			if (Input.GetKeyDown((KeyCode)287))
			{
				godMode = !godMode;
				status = "God Mode " + (godMode ? "enabled" : "disabled");
			}
			if (Input.GetKeyDown((KeyCode)286))
			{
				noCooldown = !noCooldown;
			}
			CharacterBody body = GetBody();
			if ((Object)(object)body != (Object)(object)tracked)
			{
				RestoreStats();
				Track(body);
			}
			SafeUpdate("practice", UpdatePracticeState);
			if (tab == 9 && visible)
			{
				SafeUpdate("safety counters", UpdateSafetyCounters);
			}
			ApplyGodMode();
			if (noCooldown && (Object)(object)body != (Object)null)
			{
				ResetSkills(body);
			}
			ApplyStats(body);
		}

		private string SaveKey()
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			if (firstLocalUser == null || firstLocalUser.userProfile == null)
			{
				return "Default";
			}
			return firstLocalUser.userProfile.name;
		}

		private string EncodeText(string v)
		{
			return Convert.ToBase64String(Encoding.UTF8.GetBytes(v ?? ""));
		}

		private string DecodeText(string v)
		{
			try
			{
				return Encoding.UTF8.GetString(Convert.FromBase64String(v ?? ""));
			}
			catch
			{
				return "";
			}
		}

		private string CaptureItems(Inventory inv)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inv == (Object)null)
			{
				return "";
			}
			List<string> list = new List<string>();
			foreach (PickupDef allPickup in PickupCatalog.allPickups)
			{
				if (allPickup != null && (int)allPickup.itemIndex != -1)
				{
					int itemCount = inv.GetItemCount(allPickup.itemIndex);
					if (itemCount > 0)
					{
						list.Add(allPickup.internalName + ":" + itemCount);
					}
				}
			}
			return string.Join(",", list.ToArray());
		}

		private string CaptureCheckpoint()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_004a: 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)
			CharacterBody body = GetBody();
			Run instance = Run.instance;
			if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null || (Object)(object)instance == (Object)null)
			{
				return "";
			}
			EquipmentIndex currentEquipmentIndex = body.inventory.currentEquipmentIndex;
			string v = (((int)currentEquipmentIndex != -1) ? ((Object)EquipmentCatalog.GetEquipmentDef(currentEquipmentIndex)).name : "");
			string[] obj = new string[14]
			{
				EncodeText(CurrentCharacterKey()),
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			Scene activeScene = SceneManager.GetActiveScene();
			obj[1] = EncodeText(((Scene)(ref activeScene)).name);
			obj[2] = EncodeText(v);
			obj[3] = EncodeText(CaptureItems(body.inventory));
			obj[4] = body.master.money.ToString();
			obj[5] = instance.GetRunStopwatch().ToString(CultureInfo.InvariantCulture);
			obj[6] = difficultyRate.ToString(CultureInfo.InvariantCulture);
			obj[7] = teleporterRate.ToString(CultureInfo.InvariantCulture);
			obj[8] = jumpHeightMultiplier.ToString(CultureInfo.InvariantCulture);
			obj[9] = moveMultiplier.ToString(CultureInfo.InvariantCulture);
			obj[10] = attackMultiplier.ToString(CultureInfo.InvariantCulture);
			obj[11] = damageMultiplier.ToString(CultureInfo.InvariantCulture);
			obj[12] = extraJumps.ToString();
			obj[13] = (((Object)(object)TeamManager.instance != (Object)null) ? TeamManager.instance.GetTeamLevel((TeamIndex)1).ToString() : "1");
			return string.Join("|", obj);
		}

		private void CreateCheckpoint()
		{
			if (!NetworkServer.active || (Object)(object)Run.instance == (Object)null)
			{
				status = "Start a host or solo run first";
				return;
			}
			string value = CaptureCheckpoint();
			if (string.IsNullOrEmpty(value))
			{
				status = "Checkpoint capture failed";
				return;
			}
			string text = SaveKey();
			string value2 = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Primary", "", (ConfigDescription)null).Value;
			if (!string.IsNullOrEmpty(value2))
			{
				((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Backup", "", (ConfigDescription)null).Value = value2;
			}
			((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Primary", "", (ConfigDescription)null).Value = value;
			((BaseUnityPlugin)this).Config.Save();
			status = "Checkpoint saved at current stage start state";
		}

		private bool RestoreCheckpoint(string raw)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Invalid comparison between Unknown and I4
			//IL_01b4: 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)
			if (string.IsNullOrEmpty(raw))
			{
				return false;
			}
			string[] array = raw.Split('|');
			if (array.Length < 14)
			{
				return false;
			}
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null || (Object)(object)Run.instance == (Object)null)
			{
				return false;
			}
			foreach (PickupDef allPickup in PickupCatalog.allPickups)
			{
				if (allPickup != null && (int)allPickup.itemIndex != -1)
				{
					int itemCount = body.inventory.GetItemCount(allPickup.itemIndex);
					if (itemCount > 0)
					{
						body.inventory.RemoveItemPermanent(allPickup.itemIndex, itemCount);
					}
				}
			}
			string[] array2 = DecodeText(array[3]).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array2)
			{
				string[] bits = text.Split(':');
				if (bits.Length == 2 && int.TryParse(bits[1], out var result))
				{
					PickupDef val = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && x.internalName == bits[0]));
					if (val != null && (int)val.itemIndex != -1)
					{
						body.inventory.GiveItemPermanent(val.itemIndex, result);
					}
				}
			}
			string text2 = DecodeText(array[2]);
			EquipmentDef val2 = null;
			for (int num = 0; num < EquipmentCatalog.equipmentCount; num++)
			{
				EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef((EquipmentIndex)num);
				if ((Object)(object)equipmentDef != (Object)null && ((Object)equipmentDef).name == text2)
				{
					val2 = equipmentDef;
					break;
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				body.inventory.SetEquipmentIndex(val2.equipmentIndex);
			}
			if (uint.TryParse(array[4], out var result2) && (Object)(object)body.master != (Object)null)
			{
				body.master.money = result2;
			}
			if (float.TryParse(array[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
			{
				Run.instance.SetRunStopwatch(result3);
			}
			if (float.TryParse(array[6], NumberStyles.Float, CultureInfo.InvariantCulture, out result3))
			{
				difficultyRate = result3;
			}
			if (float.TryParse(array[7], NumberStyles.Float, CultureInfo.InvariantCulture, out result3))
			{
				teleporterRate = result3;
			}
			if (float.TryParse(array[8], NumberStyles.Float, CultureInfo.InvariantCulture, out result3))
			{
				jumpHeightMultiplier = result3;
			}
			if (float.TryParse(array[9], NumberStyles.Float, CultureInfo.InvariantCulture, out result3))
			{
				moveMultiplier = result3;
			}
			if (float.TryParse(array[10], NumberStyles.Float, CultureInfo.InvariantCulture, out result3))
			{
				attackMultiplier = result3;
			}
			if (float.TryParse(array[11], NumberStyles.Float, CultureInfo.InvariantCulture, out result3))
			{
				damageMultiplier = result3;
			}
			if (int.TryParse(array[12], out var result4))
			{
				extraJumps = result4;
			}
			if (int.TryParse(array[13], out result4) && (Object)(object)TeamManager.instance != (Object)null)
			{
				TeamManager.instance.SetTeamLevel((TeamIndex)1, (uint)Mathf.Max(1, result4));
			}
			status = "Checkpoint restored into current run";
			return true;
		}

		private void LoadCheckpoint()
		{
			if (!NetworkServer.active || (Object)(object)Run.instance == (Object)null)
			{
				status = "Start the matching survivor and stage first";
				return;
			}
			string value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", SaveKey() + "_Primary", "", (ConfigDescription)null).Value;
			if (!RestoreCheckpoint(value))
			{
				value = ((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", SaveKey() + "_Backup", "", (ConfigDescription)null).Value;
				if (!RestoreCheckpoint(value))
				{
					status = "No usable checkpoint found";
				}
				else
				{
					status = "Primary failed; backup restored";
				}
			}
		}

		private void DeleteCheckpoint()
		{
			string text = SaveKey();
			((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Primary", "", (ConfigDescription)null).Value = "";
			((BaseUnityPlugin)this).Config.Bind<string>("Run Saves", text + "_Backup", "", (ConfigDescription)null).Value = "";
			((BaseUnityPlugin)this).Config.Save();
			status = "Saved checkpoints deleted";
		}

		private void SaveAndQuit()
		{
			if (Time.unscaledTime > saveQuitConfirmUntil)
			{
				saveQuitConfirmUntil = Time.unscaledTime + 5f;
				status = "Press Save and Quit again within 5 seconds";
				return;
			}
			CreateCheckpoint();
			if (!status.StartsWith("Checkpoint saved"))
			{
				return;
			}
			saveQuitConfirmUntil = 0f;
			status = "Saved; returning to main menu";
			Console instance = Console.instance;
			if (!((Object)(object)instance != (Object)null))
			{
				return;
			}
			MethodInfo methodInfo = ((object)instance).GetType().GetMethods().FirstOrDefault((MethodInfo x) => x.Name == "SubmitCmd" && x.GetParameters().Length >= 2);
			if (methodInfo != null)
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array = new object[parameters.Length];
				for (int num = 0; num < array.Length; num++)
				{
					array[num] = ((parameters[num].ParameterType == typeof(string)) ? "disconnect" : null);
				}
				methodInfo.Invoke(instance, array);
			}
		}

		private float SpawnPressureMultiplier()
		{
			if (spawnPressureMode != 0)
			{
				if (spawnPressureMode != 1)
				{
					if (spawnPressureMode != 2)
					{
						return 8f;
					}
					return 4f;
				}
				return 2f;
			}
			return 1f;
		}

		private void UpdateEnemyLimit()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Invalid comparison between Unknown and I4
			if (!NetworkServer.active || Time.unscaledTime < nextSpawnPressureApply)
			{
				return;
			}
			nextSpawnPressureApply = Time.unscaledTime + 0.5f;
			if (spawnPressureMode == 0)
			{
				return;
			}
			float num = SpawnPressureMultiplier();
			foreach (CombatDirector instances in CombatDirector.instancesList)
			{
				if (!((Object)(object)instances == (Object)null) && ((Behaviour)instances).enabled && (int)instances.teamIndex == 2)
				{
					instances.monsterCredit += Time.deltaTime * instances.creditMultiplier * (num - 1f);
					instances.monsterSpawnTimer = Mathf.Min(instances.monsterSpawnTimer, Mathf.Max(0.1f, 1f / num));
				}
			}
		}

		private void InitRequestNetwork()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			if (NetworkServer.active && !serverHandlerRegistered)
			{
				NetworkServer.RegisterHandler((short)28550, new NetworkMessageDelegate(OnServerRequest));
				serverHandlerRegistered = true;
			}
			NetworkClient val = (((Object)(object)NetworkManager.singleton != (Object)null) ? NetworkManager.singleton.client : null);
			if (val != null && val.isConnected && val != registeredClient)
			{
				val.RegisterHandler((short)28551, new NetworkMessageDelegate(OnClientResponse));
				registeredClient = val;
			}
		}

		private string FormatClock(float seconds)
		{
			seconds = Mathf.Max(0f, seconds);
			int num = Mathf.FloorToInt(seconds);
			return (num / 60).ToString("00") + ":" + (num % 60).ToString("00");
		}

		private void UpdateRunControls()
		{
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Expected O, but got Unknown
			if (!NetworkServer.active)
			{
				return;
			}
			Run instance = Run.instance;
			if ((Object)(object)instance != (Object)(object)trackedRun)
			{
				trackedRun = instance;
				lastRunTime = (((Object)(object)instance != (Object)null) ? instance.GetRunStopwatch() : 0f);
				realSessionTime = lastRunTime;
				trackedStageClearCount = (((Object)(object)instance != (Object)null) ? instance.stageClearCount : (-1));
				nextDifficultyRecalc = 0f;
			}
			if ((Object)(object)instance != (Object)null)
			{
				float runStopwatch = instance.GetRunStopwatch();
				float num = Mathf.Clamp(runStopwatch - lastRunTime, 0f, 0.25f);
				if (instance.stageClearCount != trackedStageClearCount)
				{
					trackedStageClearCount = instance.stageClearCount;
					lastRunTime = runStopwatch;
					num = 0f;
					nextDifficultyRecalc = 0f;
				}
				if (num > 0f)
				{
					realSessionTime += num;
					float num2 = runStopwatch + num * (Mathf.Clamp(difficultyRate, 0f, 50f) - 1f);
					instance.SetRunStopwatch(Mathf.Max(0f, num2));
				}
				lastRunTime = instance.GetRunStopwatch();
				if (Time.unscaledTime >= nextDifficultyRecalc)
				{
					nextDifficultyRecalc = Time.unscaledTime + 0.25f;
					instance.RecalculateDifficultyCoefficent();
				}
			}
			else
			{
				realSessionTime = 0f;
				trackedStageClearCount = -1;
			}
			foreach (HoldoutZoneController instances in InstanceTracker.GetInstancesList<HoldoutZoneController>())
			{
				if ((Object)(object)instances != (Object)null && hookedZones.Add(instances))
				{
					instances.calcChargeRate += new CalcChargeRateDelegate(ScaleChargeRate);
				}
			}
			hookedZones.RemoveWhere((HoldoutZoneController z) => (Object)(object)z == (Object)null);
		}

		private void SyncCombatDirectors(Run run, float extraDelta)
		{
		}

		private void UpdateGuaranteedShrines()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			ShrineChanceBehavior[] array = Object.FindObjectsOfType<ShrineChanceBehavior>();
			foreach (ShrineChanceBehavior val in array)
			{
				if (!((Object)(object)val == (Object)null) && guaranteedShrineChance)
				{
					val.failureChance = 0f;
					val.failureWeight = 0f;
				}
			}
		}

		private void ToggleOrRequestShrineChance()
		{
			if (NetworkServer.active)
			{
				guaranteedShrineChance = !guaranteedShrineChance;
				ApplyRunAction(6, guaranteedShrineChance ? 1f : 0f);
			}
			else
			{
				RequestOrApply(6, guaranteedShrineChance ? 0f : 1f);
			}
		}

		private void ScaleChargeRate(ref float rate)
		{
			if (rate > 0f)
			{
				rate *= teleporterRate;
			}
		}

		private string ActionName(int action, float value)
		{
			return action switch
			{
				1 => "Difficulty time scaling " + value.ToString("0.00") + "x", 
				2 => "Teleporter rate " + value.ToString("0.00") + "x", 
				3 => "Instant teleporter charge", 
				4 => "Default OP loadout", 
				5 => "Empowered Summons", 
				_ => "Shrine of Chance " + ((value >= 0.5f) ? "GUARANTEED" : "NORMAL"), 
			};
		}

		private void RequestOrApply(int action, float value)
		{
			if (NetworkServer.active)
			{
				ApplyRunAction(action, value);
				return;
			}
			NetworkClient val = (((Object)(object)NetworkManager.singleton != (Object)null) ? NetworkManager.singleton.client : null);
			if (val == null || !val.isConnected)
			{
				status = "Not connected to a compatible host";
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			string requester = ((firstLocalUser != null && (Object)(object)firstLocalUser.currentNetworkUser != (Object)null) ? firstLocalUser.currentNetworkUser.userName : "Client");
			val.Send((short)28550, (MessageBase)(object)new RunControlRequest
			{
				action = action,
				value = value,
				requester = requester,
				version = "4.5.4"
			});
			status = "Request sent to host: " + ActionName(action, value);
		}

		private void ApplyRunAction(int action, float value)
		{
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			switch (action)
			{
			case 1:
				difficultyRate = Mathf.Clamp(value, 0f, 50f);
				if ((Object)(object)Run.instance != (Object)null)
				{
					lastRunTime = Run.instance.GetRunStopwatch();
				}
				nextDifficultyRecalc = 0f;
				status = "Difficulty rate set to " + difficultyRate.ToString("0.00") + "x";
				break;
			case 2:
				teleporterRate = Mathf.Clamp(value, 0.25f, 10f);
				status = "Teleporter rate set to " + teleporterRate.ToString("0.00") + "x";
				break;
			case 6:
				guaranteedShrineChance = value >= 0.5f;
				UpdateGuaranteedShrines();
				status = "Shrine of Chance " + (guaranteedShrineChance ? "guaranteed" : "normal");
				break;
			case 3:
			{
				TeleporterInteraction instance = TeleporterInteraction.instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.holdoutZoneController == (Object)null)
				{
					status = "No active teleporter found";
					break;
				}
				instance.holdoutZoneController.FullyChargeHoldoutZone();
				status = "Teleporter fully charged";
				break;
			}
			}
		}

		private void OnServerRequest(NetworkMessage netMsg)
		{
			RunControlRequest runControlRequest = netMsg.ReadMessage<RunControlRequest>();
			if (runControlRequest.version != "4.5.4")
			{
				netMsg.conn.Send((short)28551, (MessageBase)(object)new RunControlResponse
				{
					approved = false,
					message = "Silent55 version mismatch. Both players need v4.5.4"
				});
			}
			else if (autoApproveRequests)
			{
				bool flag = ((runControlRequest.action == 4) ? ApplyRequestedLoadout(netMsg.conn) : ((runControlRequest.action == 5) ? ApplyRequestedSummons(netMsg.conn) : ApplyApprovedRunAction(runControlRequest.action, runControlRequest.value)));
				netMsg.conn.Send((short)28551, (MessageBase)(object)new RunControlResponse
				{
					approved = flag,
					message = (flag ? ("Host approved: " + ActionName(runControlRequest.action, runControlRequest.value)) : "Request could not be applied")
				});
			}
			else if (pendingRequest != null)
			{
				netMsg.conn.Send((short)28551, (MessageBase)(object)new RunControlResponse
				{
					approved = false,
					message = "Host is reviewing another request"
				});
			}
			else
			{
				pendingConnection = netMsg.conn;
				pendingRequest = runControlRequest;
				status = runControlRequest.requester + " requested " + ActionName(runControlRequest.action, runControlRequest.value);
			}
		}

		private bool ApplyApprovedRunAction(int action, float value)
		{
			ApplyRunAction(action, value);
			return true;
		}

		private void ResolvePending(bool approve)
		{
			if (pendingRequest != null)
			{
				string text = ActionName(pendingRequest.action, pendingRequest.value);
				bool flag = false;
				if (approve)
				{
					flag = ((pendingRequest.action == 4) ? ApplyRequestedLoadout(pendingConnection) : ((pendingRequest.action == 5) ? ApplyRequestedSummons(pendingConnection) : ApplyApprovedRunAction(pendingRequest.action, pendingRequest.value)));
				}
				if (pendingConnection != null)
				{
					pendingConnection.Send((short)28551, (MessageBase)(object)new RunControlResponse
					{
						approved = (approve && flag),
						message = ((approve && flag) ? ("Host approved: " + text) : (approve ? "Request could not be applied" : ("Host rejected: " + text)))
					});
				}
				pendingConnection = null;
				pendingRequest = null;
				if (!approve)
				{
					status = "Request rejected";
				}
			}
		}

		private void OnClientResponse(NetworkMessage netMsg)
		{
			RunControlResponse runControlResponse = netMsg.ReadMessage<RunControlResponse>();
			status = runControlResponse.message;
		}

		private string CurrentCharacterKey()
		{
			CharacterBody body = GetBody();
			if (!((Object)(object)body != (Object)null))
			{
				return "NO_CHARACTER";
			}
			return body.baseNameToken;
		}

		private string CurrentCharacterName()
		{
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null)
			{
				return "No active character";
			}
			string displayName = body.GetDisplayName();
			if (!string.IsNullOrEmpty(displayName))
			{
				return displayName;
			}
			return ((Object)((Component)body).gameObject).name;
		}

		private void EnsureCharacterLoadout()
		{
			string text = CurrentCharacterKey();
			if (!(text == "NO_CHARACTER") && !(text == loadedLoadoutCharacter))
			{
				loadedLoadoutCharacter = text;
				if (!opLoadouts.ContainsKey(text))
				{
					LoadCharacterLoadout(text);
				}
			}
		}

		private string LoadoutConfigKey(string key)
		{
			return "Loadout_" + key.Replace(".", "_").Replace(" ", "_");
		}

		private void AddDefaultItem(List<LoadoutEntry> list, int count, params string[] names)
		{
			//IL_00b2: 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)
			PickupDef def = null;
			foreach (string text in names)
			{
				string q = text.ToLowerInvariant();
				def = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && (int)x.itemIndex != -1 && ((x.internalName ?? "").ToLowerInvariant().Contains(q) || PickupName(x).ToLowerInvariant().Contains(q))));
				if (def != null)
				{
					break;
				}
			}
			if (def != null)
			{
				LoadoutEntry loadoutEntry = list.Find((LoadoutEntry e) => e.pickup == def.pickupIndex);
				if (loadoutEntry != null)
				{
					loadoutEntry.count += count;
					return;
				}
				list.Add(new LoadoutEntry
				{
					pickup = def.pickupIndex,
					count = count
				});
			}
		}

		private void AddDefaultEquipment(List<LoadoutEntry> list, params string[] names)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			PickupDef val = null;
			foreach (string text in names)
			{
				string q = text.ToLowerInvariant();
				val = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && (int)x.equipmentIndex != -1 && ((x.internalName ?? "").ToLowerInvariant().Contains(q) || PickupName(x).ToLowerInvariant().Contains(q))));
				if (val != null)
				{
					break;
				}
			}
			if (val != null)
			{
				list.Add(new LoadoutEntry
				{
					pickup = val.pickupIndex,
					count = 1
				});
			}
		}

		private List<LoadoutEntry> BuildSilent55Default(string key)
		{
			List<LoadoutEntry> list = new List<LoadoutEntry>();
			AddDefaultItem(list, 10, "syringe", "soldier's syringe");
			AddDefaultItem(list, 10, "critglasses", "lens-maker");
			AddDefaultItem(list, 10, "hoof", "paul's goat");
			AddDefaultItem(list, 5, "feather", "hopoo feather");
			AddDefaultItem(list, 10, "bear", "tougher times");
			AddDefaultItem(list, 5, "missile", "atg missile");
			AddDefaultItem(list, 3, "clover", "57 leaf");
			AddDefaultItem(list, 3, "alienhead", "alien head");
			AddDefaultItem(list, 2, "behemoth", "brilliant behemoth");
			AddDefaultItem(list, 1, "extrALife", "dio's best friend");
			AddDefaultItem(list, 5, "scythe", "harvester");
			string text = key.ToLowerInvariant();
			if (text.Contains("huntress"))
			{
				AddDefaultItem(list, 8, "ukulele");
				AddDefaultItem(list, 8, "predatory");
				AddDefaultItem(list, 6, "backupmag", "backup magazine");
			}
			else if (text.Contains("loader"))
			{
				AddDefaultItem(list, 10, "crowbar");
				AddDefaultItem(list, 10, "focuscrystal", "focus crystal");
				AddDefaultItem(list, 5, "iceRing", "runald");
				AddDefaultItem(list, 5, "fireRing", "kjaro");
			}
			else if (text.Contains("engineer"))
			{
				AddDefaultItem(list, 20, "mushroom", "bustling fungus");
				AddDefaultItem(list, 5, "nkuhana", "n'kuhana");
				AddDefaultItem(list, 5, "aegis");
			}
			else if (text.Contains("railgunner"))
			{
				AddDefaultItem(list, 20, "crowbar");
				AddDefaultItem(list, 5, "laserScope", "laser scope");
				AddDefaultItem(list, 8, "armorplate", "repulsion armor");
			}
			else if (text.Contains("bandit"))
			{
				AddDefaultItem(list, 8, "crowbar");
				AddDefaultItem(list, 8, "guillotine");
				AddDefaultItem(list, 5, "brainstalk", "brainstalks");
			}
			else if (text.Contains("merc"))
			{
				AddDefaultItem(list, 8, "predatory");
				AddDefaultItem(list, 8, "scythe");
				AddDefaultItem(list, 8, "focuscrystal", "focus crystal");
			}
			else if (text.Contains("acrid") || text.Contains("croco"))
			{
				AddDefaultEquipment(list, "dronebackup", "the back-up");
				AddDefaultItem(list, 1, "autocastequipment", "gesture of the drowned");
				AddDefaultItem(list, 10, "fuelcell", "fuel cell");
				AddDefaultItem(list, 10, "gasoline");
				AddDefaultItem(list, 10, "wisp", "will-o");
				AddDefaultItem(list, 8, "guillotine");
				AddDefaultItem(list, 10, "bleedonhit", "tri-tip");
				AddDefaultItem(list, 10, "missile", "atg missile");
				AddDefaultItem(list, 5, "clover", "57 leaf");
				AddDefaultItem(list, 3, "behemoth", "brilliant behemoth");
				AddDefaultItem(list, 10, "bossdamage", "armor-piercing rounds");
				AddDefaultItem(list, 3, "talisman", "soulbound catalyst");
			}
			else if (text.Contains("captain"))
			{
				AddDefaultItem(list, 10, "bleedOnHit", "tri-tip");
				AddDefaultItem(list, 8, "missile", "atg missile");
				AddDefaultItem(list, 5, "clover");
			}
			else if (text.Contains("treebot") || text.Contains("rex"))
			{
				AddDefaultItem(list, 10, "medkit");
				AddDefaultItem(list, 8, "seed", "leeching seed");
				AddDefaultItem(list, 5, "rejuvenation", "rejuvenation rack");
			}
			else if (text.Contains("mage") || text.Contains("artificer"))
			{
				AddDefaultItem(list, 10, "crowbar");
				AddDefaultItem(list, 8, "ignition", "ignition tank");
				AddDefaultItem(list, 6, "backupmag", "backup magazine");
			}
			else if (text.Contains("toolbot") || text.Contains("mul-t"))
			{
				AddDefaultItem(list, 10, "syringe");
				AddDefaultItem(list, 8, "missile");
				AddDefaultItem(list, 6, "fuelcell", "fuel cell");
			}
			else if (text.Contains("void"))
			{
				AddDefaultItem(list, 10, "hoof");
				AddDefaultItem(list, 8, "armorplate");
				AddDefaultItem(list, 5, "rejuvenation");
			}
			return list;
		}

		private void LoadCharacterLoadout(string key)
		{
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("OP Loadouts", LoadoutConfigKey(key), "", "Internal pickup names and quantities for this character.");
			ConfigEntry<bool> val2 = ((BaseUnityPlugin)this).Config.Bind<bool>("OP Loadouts", LoadoutConfigKey(key) + "_Initialized", false, "Whether this character loadout has been initialized.");
			List<LoadoutEntry> list = new List<LoadoutEntry>();
			if (!val2.Value)
			{
				list = BuildSilent55Default(key);
				opLoadouts[key] = list;
				val2.Value = true;
				SaveCharacterLoadout();
				status = "Loaded Silent55 default for " + CurrentCharacterName();
				return;
			}
			string value = val.Value;
			if (!string.IsNullOrEmpty(value))
			{
				string[] array = value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text in array)
				{
					string[] bits = text.Split('|');
					if (bits.Length == 2)
					{
						PickupDef val3 = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && x.internalName == bits[0]));
						if (val3 != null && int.TryParse(bits[1], out var result))
						{
							list.Add(new LoadoutEntry
							{
								pickup = val3.pickupIndex,
								count = Mathf.Clamp(result, 1, 999)
							});
						}
					}
				}
			}
			opLoadouts[key] = list;
		}

		private void SaveCharacterLoadout()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			string text = CurrentCharacterKey();
			if (text == "NO_CHARACTER")
			{
				return;
			}
			EnsureCharacterLoadout();
			List<string> list = new List<string>();
			foreach (LoadoutEntry item in opLoadouts[text])
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(item.pickup);
				if (pickupDef != null)
				{
					list.Add(pickupDef.internalName + "|" + item.count);
				}
			}
			((BaseUnityPlugin)this).Config.Bind<string>("OP Loadouts", LoadoutConfigKey(text), "", "Internal pickup names and quantities for this character.").Value = string.Join(";", list.ToArray());
			((BaseUnityPlugin)this).Config.Bind<bool>("OP Loadouts", LoadoutConfigKey(text) + "_Initialized", true, "Whether this character loadout has been initialized.").Value = true;
			((BaseUnityPlugin)this).Config.Save();
			status = "Saved OP loadout for " + CurrentCharacterName();
		}

		private void RestoreDefaultLoadout()
		{
			string text = CurrentCharacterKey();
			if (text == "NO_CHARACTER")
			{
				status = "Start a run first";
				return;
			}
			opLoadouts[text] = BuildSilent55Default(text);
			SaveCharacterLoadout();
			status = "Restored Silent55 default for " + CurrentCharacterName();
		}

		private void AddSelectedToLoadout()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(selectedPickup);
			if (!IsSpawnablePickup(pickupDef))
			{
				status = "Select an item in Spawner or OP Loadout first";
				return;
			}
			string text = CurrentCharacterKey();
			if (text == "NO_CHARACTER")
			{
				status = "Start a run first";
				return;
			}
			EnsureCharacterLoadout();
			LoadoutEntry loadoutEntry = opLoadouts[text].Find((LoadoutEntry e) => e.pickup == selectedPickup);
			if (loadoutEntry != null)
			{
				loadoutEntry.count = Mathf.Clamp(loadoutEntry.count + loadoutQuantity, 1, 999);
			}
			else
			{
				opLoadouts[text].Add(new LoadoutEntry
				{
					pickup = selectedPickup,
					count = Mathf.Clamp(loadoutQuantity, 1, 999)
				});
			}
			SaveCharacterLoadout();
		}

		private void RemoveLoadoutEntry(int index)
		{
			string key = CurrentCharacterKey();
			EnsureCharacterLoadout();
			if (opLoadouts.ContainsKey(key) && index >= 0 && index < opLoadouts[key].Count)
			{
				opLoadouts[key].RemoveAt(index);
				SaveCharacterLoadout();
			}
		}

		private void ClearCharacterLoadout()
		{
			string key = CurrentCharacterKey();
			EnsureCharacterLoadout();
			if (opLoadouts.ContainsKey(key))
			{
				opLoadouts[key].Clear();
				SaveCharacterLoadout();
				status = "Cleared OP loadout for " + CurrentCharacterName();
			}
		}

		private bool ApplyLoadoutToBody(CharacterBody body, string key, string playerKey)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Invalid comparison between Unknown and I4
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null)
			{
				return false;
			}
			if (loadoutAppliedThisRun.Contains(playerKey))
			{
				status = "OP loadout already applied to this player this run";
				return false;
			}
			if (!opLoadouts.ContainsKey(key))
			{
				LoadCharacterLoadout(key);
			}
			if (!opLoadouts.ContainsKey(key) || opLoadouts[key].Count == 0)
			{
				return false;
			}
			int num = 0;
			List<LoadoutEntry> list = new List<LoadoutEntry>();
			foreach (LoadoutEntry item in opLoadouts[key])
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(item.pickup);
				if (pickupDef != null)
				{
					if ((int)pickupDef.itemIndex != -1)
					{
						body.inventory.GiveItemPermanent(pickupDef.itemIndex, item.count);
						list.Add(new LoadoutEntry
						{
							pickup = item.pickup,
							count = item.count
						});
						num += item.count;
					}
					else if ((int)pickupDef.equipmentIndex != -1)
					{
						body.inventory.SetEquipmentIndex(pickupDef.equipmentIndex);
					}
				}
			}
			grantedLoadouts[playerKey] = list;
			loadoutAppliedThisRun.Add(playerKey);
			status = "Applied OP loadout (" + num + " stacks)";
			return true;
		}

		private void RemoveSilent55Loadout()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Invalid comparison between Unknown and I4
			//IL_009d: 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)
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			if (!grantedLoadouts.TryGetValue("local", out var value) || value.Count == 0)
			{
				status = "No recorded Silent55 loadout to remove";
				return;
			}
			int num = 0;
			foreach (LoadoutEntry item in value)
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(item.pickup);
				if (pickupDef != null && (int)pickupDef.itemIndex != -1)
				{
					int num2 = Mathf.Min(body.inventory.GetItemCount(pickupDef.itemIndex), item.count);
					if (num2 > 0)
					{
						body.inventory.RemoveItemPermanent(pickupDef.itemIndex, num2);
						num += num2;
					}
				}
			}
			grantedLoadouts.Remove("local");
			loadoutAppliedThisRun.Remove("local");
			status = "Removed " + num + " Silent55 item stacks";
		}

		private void ApplyOrRequestCharacterLoadout()
		{
			if (NetworkServer.active)
			{
				CharacterBody body = GetBody();
				if ((Object)(object)body == (Object)null)
				{
					status = "Start a run first";
				}
				else
				{
					ApplyLoadoutToBody(body, CurrentCharacterKey(), "local");
				}
			}
			else
			{
				RequestOrApply(4, 0f);
			}
		}

		private CharacterBody BodyForConnection(NetworkConnection conn)
		{
			if (conn == null)
			{
				return null;
			}
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.networkUser == (Object)null) && ((NetworkBehaviour)instance.networkUser).connectionToClient == conn && (Object)(object)instance.master != (Object)null)
				{
					return instance.master.GetBody();
				}
			}
			return null;
		}

		private bool ApplyRequestedLoadout(NetworkConnection conn)
		{
			CharacterBody val = BodyForConnection(conn);
			if ((Object)(object)val == (Object)null)
			{
				status = "Requesting player body not found";
				return false;
			}
			string baseNameToken = val.baseNameToken;
			if (!opLoadouts.ContainsKey(baseNameToken))
			{
				LoadCharacterLoadout(baseNameToken);
			}
			return ApplyLoadoutToBody(val, baseNameToken, "conn:" + conn.connectionId);
		}

		private void GiveMinionItem(Inventory inv, int count, params string[] names)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inv == (Object)null)
			{
				return;
			}
			foreach (string text in names)
			{
				string q = text.ToLowerInvariant();
				PickupDef val = PickupCatalog.allPickups.FirstOrDefault((Func<PickupDef, bool>)((PickupDef x) => x != null && (int)x.itemIndex != -1 && ((x.internalName ?? "").ToLowerInvariant().Contains(q) || PickupName(x).ToLowerInvariant().Contains(q))));
				if (val != null)
				{
					inv.GiveItemPermanent(val.itemIndex, count);
					break;
				}
			}
		}

		private bool IsOwnedMinion(CharacterMaster minion, CharacterMaster owner)
		{
			if ((Object)(object)minion != (Object)null && (Object)(object)owner != (Object)null && (Object)(object)minion.minionOwnership != (Object)null)
			{
				return (Object)(object)minion.minionOwnership.ownerMaster == (Object)(object)owner;
			}
			return false;
		}

		private int EmpowerOwnedMinions(CharacterMaster owner)
		{
			if (!NetworkServer.active || (Object)(object)owner == (Object)null)
			{
				return 0;
			}
			int num = 0;
			CharacterMaster[] array = Object.FindObjectsOfType<CharacterMaster>();
			foreach (CharacterMaster val in array)
			{
				if (IsOwnedMinion(val, owner) && !((Object)(object)val.inventory == (Object)null) && !empoweredMinions.Contains(val))
				{
					GiveMinionItem(val.inventory, 10, "syringe", "soldier's syringe");
					GiveMinionItem(val.inventory, 10, "critglasses", "lens-maker");
					GiveMinionItem(val.inventory, 10, "bleedonhit", "tri-tip");
					GiveMinionItem(val.inventory, 8, "missile", "atg missile");
					GiveMinionItem(val.inventory, 5, "clover", "57 leaf");
					GiveMinionItem(val.inventory, 3, "behemoth", "brilliant behemoth");
					GiveMinionItem(val.inventory, 10, "bossdamage", "armor-piercing rounds");
					GiveMinionItem(val.inventory, 10, "bear", "tougher times");
					empoweredMinions.Add(val);
					num++;
				}
			}
			if (num > 0)
			{
				status = "Empowered " + num + " owned summon(s)";
			}
			return num;
		}

		private void ToggleOrRequestEmpoweredSummons()
		{
			if (NetworkServer.active)
			{
				empoweredSummons = !empoweredSummons;
				if (empoweredSummons)
				{
					EmpowerOwnedMinions(((Object)(object)GetBody() != (Object)null) ? GetBody().master : null);
				}
				status = "Empowered Summons " + (empoweredSummons ? "enabled" : "disabled");
			}
			else
			{
				RequestOrApply(5, 1f);
			}
		}

		private bool ApplyRequestedSummons(NetworkConnection conn)
		{
			CharacterBody val = BodyForConnection(conn);
			if ((Object)(object)val == (Object)null || (Object)(object)val.master == (Object)null)
			{
				return false;
			}
			EmpowerOwnedMinions(val.master);
			return true;
		}

		private bool IsCurrentCharacterBandit()
		{
			return CurrentCharacterKey().ToLowerInvariant().Contains("bandit");
		}

		private bool SupportsRapidFire()
		{
			if (!IsCurrentCharacterBandit())
			{
				return IsCurrentCharacterAcrid();
			}
			return true;
		}

		private void PrepareRapidSkill(GenericSkill skill, bool refill)
		{
			if (!((Object)(object)skill == (Object)null) && refill)
			{
				skill.stock = skill.maxStock;
				skill.rechargeStopwatch = 0f;
				skill.SetBlockedCooldownSkillState(false);
			}
		}

		private void TryRapidSkill(GenericSkill skill, ref float nextTime, bool held, bool refill)
		{
			if (held && !((Object)(object)skill == (Object)null) && !(Time.unscaledTime < nextTime))
			{
				PrepareRapidSkill(skill, refill);
				if (skill.ExecuteIfReady())
				{
					nextTime = Time.unscaledTime + rapidFireInterval;
				}
				else
				{
					nextTime = Time.unscaledTime + Mathf.Min(0.03f, rapidFireInterval);
				}
			}
		}

		private void UpdateRapidFire()
		{
			if (!rapidFire || !SupportsRapidFire())
			{
				return;
			}
			CharacterBody body = GetBody();
			if (!((Object)(object)body == (Object)null) && !((Object)(object)body.inputBank == (Object)null) && !((Object)(object)body.skillLocator == (Object)null))
			{
				InputBankTest inputBank = body.inputBank;
				SkillLocator skillLocator = body.skillLocator;
				TryRapidSkill(skillLocator.primary, ref nextPrimaryFire, inputBank.skill1.down, rapidFireReload);
				if (rapidFireSecondary)
				{
					TryRapidSkill(skillLocator.secondary, ref nextSecondaryFire, inputBank.skill2.down, refill: true);
				}
				if (rapidFireSpecial)
				{
					TryRapidSkill(skillLocator.special, ref nextSpecialFire, inputBank.skill4.down, refill: true);
				}
			}
		}

		private bool IsCurrentCharacterAcrid()
		{
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null)
			{
				return false;
			}
			string text = (CurrentCharacterKey() + " " + ((Object)((Component)body).gameObject).name + " " + CurrentCharacterName()).ToLowerInvariant();
			if (!text.Contains("acrid"))
			{
				return text.Contains("croco");
			}
			return true;
		}

		private void CaptureDiseaseDefaults()
		{
			if (!diseaseDefaultsCaptured)
			{
				originalDiseaseBounces = Disease.maxBounces;
				originalDiseaseBounceRange = Disease.bounceRange;
				originalDiseaseOrbRange = Disease.orbRange;
				diseaseDefaultsCaptured = true;
			}
		}

		private void UpdateAcridEpidemic()
		{
			CaptureDiseaseDefaults();
			bool num = IsCurrentCharacterAcrid();
			Disease.maxBounces = ((num && acridUnlimitedTargets) ? 1000 : originalDiseaseBounces);
			Disease.bounceRange = ((num && acridUnlimitedRange) ? 10000f : originalDiseaseBounceRange);
			Disease.orbRange = ((num && acridUnlimitedRange) ? 10000f : originalDiseaseOrbRange);
		}

		private void RestoreAcridEpidemic()
		{
			if (diseaseDefaultsCaptured)
			{
				Disease.maxBounces = originalDiseaseBounces;
				Disease.bounceRange = originalDiseaseBounceRange;
				Disease.orbRange = originalDiseaseOrbRange;
			}
		}

		private void UpdateLockOn()
		{
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody body = GetBody();
			if (!lockOn || (Object)(object)body == (Object)null)
			{
				DisableLockTracker();
				return;
			}
			if ((Object)(object)trackerBody != (Object)(object)body || (Object)(object)silentTracker == (Object)null)
			{
				DisableLockTracker();
				trackerBody = body;
				silentTracker = ((Component)body).GetComponent<HuntressTracker>();
				if ((Object)(object)silentTracker == (Object)null)
				{
					silentTracker = ((Component)body).gameObject.AddComponent<HuntressTracker>();
				}
				((Behaviour)silentTracker).enabled = true;
			}
			silentTracker.maxTrackingDistance = lockDistance;
			silentTracker.maxTrackingAngle = lockAngle;
			HurtBox trackingTarget = silentTracker.GetTrackingTarget();
			if ((Object)(object)trackingTarget != (Object)null && (Object)(object)trackingTarget.healthComponent != (Object)null && trackingTarget.healthComponent.alive)
			{
				InputBankTest inputBank = body.inputBank;
				if ((Object)(object)inputBank != (Object)null)
				{
					Vector3 val = ((Component)trackingTarget).transform.position - inputBank.aimOrigin;
					Vector3 normalized = ((Vector3)(ref val)).normalized;
					inputBank.aimDirection = normalized;
				}
				if (projectileTracking)
				{
					SteerOwnedProjectiles(((Component)body).gameObject, ((Component)trackingTarget).transform);
				}
			}
			trackedProjectiles.RemoveWhere((ProjectileController x) => (Object)(object)x == (Object)null);
		}

		private void DisableLockTracker()
		{
			if ((Object)(object)silentTracker != (Object)null)
			{
				scientificDisableTracker();
			}
			trackerBody = null;
			trackedProjectiles.Clear();
		}

		private void scientificDisableTracker()
		{
			((Behaviour)silentTracker).enabled = false;
			silentTracker = null;
		}

		private void SteerOwnedProjectiles(GameObject owner, Transform target)
		{
			//IL_0046: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner == (Object)null || (Object)(object)target == (Object)null)
			{
				return;
			}
			foreach (ProjectileController instances in InstanceTracker.GetInstancesList<ProjectileController>())
			{
				if (!((Object)(object)instances == (Object)null) && !((Object)(object)instances.owner != (Object)(object)owner))
				{
					Vector3 val = target.position - ((Component)instances).transform.position;
					Vector3 normalized = ((Vector3)(ref val)).normalized;
					if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.001f))
					{
						float num = Mathf.Clamp01(trackingStrength * 0.01f * Time.deltaTime * 10f);
						((Component)instances).transform.rotation = Quaternion.Slerp(((Component)instances).transform.rotation, Quaternion.LookRotation(normalized), num);
						trackedProjectiles.Add(instances);
					}
				}
			}
		}

		private CharacterBody GetBody()
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			if (firstLocalUser == null)
			{
				return null;
			}
			return firstLocalUser.cachedBody;
		}

		private void Track(CharacterBody body)
		{
			tracked = body;
			if (!((Object)(object)body == (Object)null))
			{
				oldAttack = body.baseAttackSpeed;
				oldDamage = body.baseDamage;
				oldMove = body.baseMoveSpeed;
				oldHealth = body.baseMaxHealth;
				oldRegen = body.baseRegen;
				oldJumpPower = body.baseJumpPower;
				oldJumps = body.baseJumpCount;
				trackedHealth = body.healthComponent;
			}
		}

		private void ApplyGodMode()
		{
			CharacterBody body = GetBody();
			if (!((Object)(object)body == (Object)null) && !((Object)(object)body.healthComponent == (Object)null))
			{
				body.healthComponent.godMode = godMode;
				trackedHealth = body.healthComponent;
				if (godMode)
				{
					body.healthComponent.Networkhealth = body.healthComponent.fullHealth;
				}
			}
		}

		private void ResetSkills(CharacterBody body)
		{
			GenericSkill[] components = ((Component)body).GetComponents<GenericSkill>();
			foreach (GenericSkill val in components)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.skillDef == (Object)null))
				{
					val.stock = val.maxStock;
					val.rechargeStopwatch = 0f;
					val.SetBlockedCooldownSkillState(false);
				}
			}
		}

		private void ApplyStats(CharacterBody body)
		{
			if (!((Object)(object)body == (Object)null))
			{
				float num = oldAttack * attackMultiplier;
				float num2 = oldDamage * damageMultiplier;
				float num3 = oldMove * moveMultiplier;
				float num4 = oldJumpPower * jumpHeightMultiplier;
				float num5 = (maxPersonal ? (oldHealth * 20f) : oldHealth);
				float num6 = (maxPersonal ? (oldRegen * 20f + 20f) : oldRegen);
				int num7 = ((extraJumps >= 11) ? 999 : (oldJumps + extraJumps));
				bool flag = false;
				if (!Mathf.Approximately(body.baseAttackSpeed, num))
				{
					body.baseAttackSpeed = num;
					flag = true;
				}
				if (!Mathf.Approximately(body.baseDamage, num2))
				{
					body.baseDamage = num2;
					flag = true;
				}
				if (!Mathf.Approximately(body.baseMoveSpeed, num3))
				{
					body.baseMoveSpeed = num3;
					flag = true;
				}
				if (!Mathf.Approximately(body.baseJumpPower, num4))
				{
					body.baseJumpPower = num4;
					flag = true;
				}
				if (!Mathf.Approximately(body.baseMaxHealth, num5))
				{
					body.baseMaxHealth = num5;
					flag = true;
				}
				if (!Mathf.Approximately(body.baseRegen, num6))
				{
					body.baseRegen = num6;
					flag = true;
				}
				if (body.baseJumpCount != num7)
				{
					body.baseJumpCount = num7;
					flag = true;
				}
				if (flag)
				{
					body.MarkAllStatsDirty();
					body.RecalculateStats();
				}
			}
		}

		private void RestoreStats()
		{
			if (!((Object)(object)tracked == (Object)null))
			{
				tracked.baseAttackSpeed = oldAttack;
				tracked.baseDamage = oldDamage;
				tracked.baseMoveSpeed = oldMove;
				tracked.baseJumpPower = oldJumpPower;
				tracked.baseMaxHealth = oldHealth;
				tracked.baseRegen = oldRegen;
				tracked.baseJumpCount = oldJumps;
				tracked.MarkAllStatsDirty();
				tracked.RecalculateStats();
				tracked = null;
			}
		}

		private string PickupName(PickupDef def)
		{
			if (def == null)
			{
				return "Unknown";
			}
			string text = Language.GetString(def.nameToken);
			if (!string.IsNullOrEmpty(text) && !(text == def.nameToken))
			{
				return text;
			}
			return def.internalName;
		}

		private bool IsSpawnablePickup(PickupDef def)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			if (def != null)
			{
				if ((int)def.itemIndex == -1)
				{
					return (int)def.equipmentIndex != -1;
				}
				return true;
			}
			return false;
		}

		private void UpdateSafetyCounters()
		{
			if (!(Time.unscaledTime < nextSafetyScan))
			{
				nextSafetyScan = Time.unscaledTime + 2f;
				cachedBodies = CharacterBody.readOnlyInstancesList.Count;
				cachedProjectiles = InstanceTracker.GetInstancesList<ProjectileController>().Count;
				cachedPickups = InstanceTracker.GetInstancesList<PickupDropletController>().Count;
			}
		}

		private bool IsMonsterBody(CharacterBody b)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			if ((Object)(object)b != (Object)null && (Object)(object)b.teamComponent != (Object)null)
			{
				return (int)b.teamComponent.teamIndex == 2;
			}
			return false;
		}

		private void RefreshPracticeCache()
		{
			practiceBodies.Clear();
			practiceAIs.Clear();
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if (IsMonsterBody(readOnlyInstances))
				{
					practiceBodies.Add(readOnlyInstances);
				}
			}
			foreach (CharacterMaster readOnlyInstances2 in CharacterMaster.readOnlyInstancesList)
			{
				if ((Object)(object)readOnlyInstances2 == (Object)null)
				{
					continue;
				}
				CharacterBody body = readOnlyInstances2.GetBody();
				if (!IsMonsterBody(body))
				{
					continue;
				}
				BaseAI[] components = ((Component)readOnlyInstances2).GetComponents<BaseAI>();
				foreach (BaseAI val in components)
				{
					if ((Object)(object)val != (Object)null && !practiceAIs.Contains(val))
					{
						practiceAIs.Add(val);
					}
				}
			}
			nextPracticeCache = Time.unscaledTime + 2f;
		}

		private void ApplyPracticeState(bool force = false)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			bool flag = practiceFreeze || practiceFullPause;
			bool flag2 = practiceDisableAI || practiceFullPause;
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (CharacterBody practiceBody in practiceBodies)
			{
				if ((Object)(object)practiceBody == (Object)null)
				{
					continue;
				}
				if ((Object)(object)practiceBody.healthComponent != (Object)null)
				{
					if (force || practiceBody.healthComponent.isInFrozenState != flag)
					{
						practiceBody.healthComponent.isInFrozenState = flag;
					}
					num++;
				}
				if ((flag || practiceFullPause) && (Object)(object)practiceBody.inputBank != (Object)null)
				{
					practiceBody.inputBank.moveVector = Vector3.zero;
					practiceBody.inputBank.skill1.down = false;
					practiceBody.inputBank.skill2.down = false;
					practiceBody.inputBank.skill3.down = false;
					practiceBody.inputBank.skill4.down = false;
					practiceBody.inputBank.sprint.down = false;
					num2++;
				}
			}
			foreach (BaseAI practiceAI in practiceAIs)
			{
				if (!((Object)(object)practiceAI == (Object)null))
				{
					bool flag3 = !flag2;
					if (force || ((Behaviour)practiceAI).enabled != flag3)
					{
						((Behaviour)practiceAI).enabled = flag3;
					}
					num3++;
				}
			}
			status = "Practice: " + num2 + " movement inputs stopped, " + num + " frozen, " + num3 + " AI controllers";
		}

		private void UpdatePracticeState()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			bool flag = practiceFreeze || practiceDisableAI || practiceFullPause;
			bool flag2 = practiceFreeze != lastPracticeFreeze || practiceDisableAI != lastPracticeDisableAI || practiceFullPause != lastPracticeFullPause;
			if (flag || flag2)
			{
				if (Time.unscaledTime >= nextPracticeCache || practiceBodies.RemoveAll((CharacterBody x) => (Object)(object)x == (Object)null) > 0 || practiceAIs.RemoveAll((BaseAI x) => (Object)(object)x == (Object)null) > 0)
				{
					RefreshPracticeCache();
				}
				if (flag2)
				{
					ApplyPracticeState(force: true);
					lastPracticeFreeze = practiceFreeze;
					lastPracticeDisableAI = practiceDisableAI;
					lastPracticeFullPause = practiceFullPause;
				}
				if (flag && Time.unscaledTime >= nextPracticeUpdate)
				{
					nextPracticeUpdate = Time.unscaledTime + 0.1f;
					ApplyPracticeState();
				}
			}
		}

		private void ResumeEnemies()
		{
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			practiceFreeze = false;
			practiceDisableAI = false;
			practiceFullPause = false;
			RefreshPracticeCache();
			ApplyPracticeState(force: true);
			lastPracticeFreeze = false;
			lastPracticeDisableAI = false;
			lastPracticeFullPause = false;
			status = "Enemies resumed";
		}

		private void HealAllEnemies()
		{
			if (!NetworkServer.active)
			{
				status = "Host required";
				return;
			}
			int num = 0;
			CharacterBody[] array = Object.FindObjectsOfType<CharacterBody>();
			foreach (CharacterBody val in array)
			{
				if (IsMonsterBody(val) && (Object)(object)val.healthComponent != (Object)null)
				{
					val.healthComponent.Networkhealth = val.healthComponent.fullHealth;
					val.healthComponent.Networkshield = val.healthComponent.fullShield;
					num++;
				}
			}
			status = "Restored " + num + " enemies";
		}

		private void ClearAllEnemies()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				status = "Host required";
				return;
			}
			int num = 0;
			CharacterBody[] array = Object.FindObjectsOfType<CharacterBody>();
			foreach (CharacterBody val in array)
			{
				if (IsMonsterBody(val) && (Object)(object)val.healthComponent != (Object)null)
				{
					val.healthComponent.Suicide((GameObject)null, (GameObject)null, DamageTypeCombo.op_Implicit((DamageType)0));
					num++;
				}
			}
			status = "Cleared " + num + " enemies";
		}

		private void ClearHostileProjectiles()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			if (!NetworkServer.active)
			{
				status = "Host required";
				return;
			}
			int num = 0;
			ProjectileController[] array = Object.FindObjectsOfType<ProjectileController>();
			foreach (ProjectileController val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.teamFilter != (Object)null && (int)val.teamFilter.teamIndex == 2)
				{
					NetworkServer.Destroy(((Component)val).gameObject);
					num++;
				}
			}
			status = "Cleared " + num + " hostile projectiles";
		}

		private void CollectStageDrops()
		{
			//IL_0030: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			Vector3 val = body.corePosition + Vector3.up * 0.5f;
			int num = 0;
			int num2 = 0;
			PickupDropletController[] array = Object.FindObjectsOfType<PickupDropletController>();
			foreach (PickupDropletController val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)null)
				{
					continue;
				}
				PickupDef pickupDef = PickupCatalog.GetPickupDef(val2.pickupIndex);
				if (pickupDef != null)
				{
					string text = (pickupDef.internalName ?? "").ToLowerInvariant();
					if (!text.Contains("artifactkey") && !text.Contains("quest") && !text.Contains("voidcoin") && !text.Contains("lunarcoin"))
					{
						((Component)val2).transform.position = val + Random.insideUnitSphere * 0.6f;
						num++;
					}
				}
			}
			Component[] array2 = Object.FindObjectsOfType<Component>();
			foreach (Component val3 in array2)
			{
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.gameObject == (Object)null))
				{
					string text2 = ((object)val3).GetType().Name.ToLowerInvariant();
					if (text2.Contains("moneypack") || text2.Contains("goldpack") || text2.Contains("treasurepack"))
					{
						val3.transform.position = val + Random.insideUnitSphere * 0.6f;
						num2++;
					}
				}
			}
			status = "Moved " + num + " pickup(s) and " + num2 + " money pack(s) to player";
		}

		private void EmergencyCleanup()
		{
			if (!NetworkServer.active)
			{
				status = "Host required";
				return;
			}
			int num = 0;
			PickupDropletController[] array = Object.FindObjectsOfType<PickupDropletController>();
			foreach (PickupDropletController val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					NetworkServer.Destroy(((Component)val).gameObject);
					num++;
				}
			}
			ProjectileController[] array2 = Object.FindObjectsOfType<ProjectileController>();
			foreach (ProjectileController val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.owner == (Object)null)
				{
					NetworkServer.Destroy(((Component)val2).gameObject);
					num++;
				}
			}
			status = "Cleanup removed " + num + " objects";
		}

		private void RemoveSelectedPickup()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				status = "Host required";
				return;
			}
			CharacterBody body = GetBody();
			PickupDef pickupDef = PickupCatalog.GetPickupDef(selectedPickup);
			if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null || pickupDef == null || (int)pickupDef.itemIndex == -1)
			{
				status = "Select an item";
				return;
			}
			body.inventory.RemoveItemPermanent(pickupDef.itemIndex, spawnQuantity);
			status = "Removed item stacks";
		}

		private void UndoLastGive()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || lastGivenPickup == PickupIndex.none)
			{
				status = "Nothing to undo";
				return;
			}
			CharacterBody body = GetBody();
			PickupDef pickupDef = PickupCatalog.GetPickupDef(lastGivenPickup);
			if ((Object)(object)body != (Object)null && (Object)(object)body.inventory != (Object)null && pickupDef != null && (int)pickupDef.itemIndex != -1)
			{
				body.inventory.RemoveItemPermanent(pickupDef.itemIndex, lastGivenCount);
			}
			lastGivenPickup = PickupIndex.none;
			lastGivenCount = 0;
			status = "Undid item grant";
		}

		private void RefreshEnemyMasterPrefabs()
		{
			enemyMasterPrefabs.Clear();
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo[] fields = typeof(MasterCatalog).GetFields(bindingAttr);
			foreach (FieldInfo fieldInfo in fields)
			{
				object obj = null;
				try
				{
					obj = fieldInfo.GetValue(null);
				}
				catch
				{
				}
				if (!(obj is IEnumerable enumerable))
				{
					continue;
				}
				foreach (object item in enumerable)
				{
					GameObject val = (GameObject)((item is GameObject) ? item : null);
					CharacterMaster val2 = (CharacterMaster)((item is CharacterMaster) ? item : null);
					if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null)
					{
						val = ((Component)val2).gameObject;
					}
					if (!((Object)(object)val == (Object)null) && !hashSet.Contains(val) && !((Object)(object)val.GetComponent<CharacterMaster>() == (Object)null))
					{
						string text = ((Object)val).name.ToLowerInvariant();
						if (!text.Contains("player") && !text.Contains("survivor") && !text.Contains("engimaster") && !text.Contains("drone") && !text.Contains("turret"))
						{
							hashSet.Add(val);
							enemyMasterPrefabs.Add(val);
						}
					}
				}
			}
			enemyMasterPrefabs.Sort((GameObject a, GameObject b) => string.Compare(EnemyDisplayName(a), EnemyDisplayName(b), StringComparison.OrdinalIgnoreCase));
			selectedEnemyMaster = Mathf.Clamp(selectedEnemyMaster, 0, Mathf.Max(0, enemyMasterPrefabs.Count - 1));
			status = "Found " + enemyMasterPrefabs.Count + " enemy master prefabs";
		}

		private string EnemyDisplayName(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return "Unknown";
			}
			string result = ((Object)prefab).name.Replace("Master", "").Replace("Clone", "").Trim();
			CharacterMaster component = prefab.GetComponent<CharacterMaster>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.bodyPrefab != (Object)null)
			{
				CharacterBody component2 = component.bodyPrefab.GetComponent<CharacterBody>();
				if ((Object)(object)component2 != (Object)null)
				{
					string text = Language.GetString(component2.baseNameToken);
					if (!string.IsNullOrWhiteSpace(text) && text != component2.baseNameToken)
					{
						result = text;
					}
				}
			}
			return result;
		}

		private bool IsBossMaster(GameObject prefab)
		{
			string text = (((Object)(object)prefab != (Object)null) ? ((Object)prefab).name : "").ToLowerInvariant();
			if (!text.Contains("boss") && !text.Contains("titan") && !text.Contains("vagrant") && !text.Contains("worm") && !text.Contains("queen") && !text.Contains("scav") && !text.Contains("brother") && !text.Contains("voidraid"))
			{
				return text.Contains("grandparent");
			}
			return true;
		}

		private void SpawnSelectedEnemy()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			if (enemyMasterPrefabs.Count == 0)
			{
				RefreshEnemyMasterPrefabs();
			}
			if (enemyMasterPrefabs.Count == 0)
			{
				status = "No enemy master prefabs found";
				return;
			}
			selectedEnemyMaster = Mathf.Clamp(selectedEnemyMaster, 0, enemyMasterPrefabs.Count - 1);
			GameObject val = enemyMasterPrefabs[selectedEnemyMaster];
			int num = 0;
			for (int i = 0; i < Mathf.Clamp(enemyQuantity, 1, 25); i++)
			{
				float num2 = (float)i * MathF.PI * 2f / (float)Mathf.Max(1, enemyQuantity);
				Vector3 val2 = body.footPosition + new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * enemySpawnDistance;
				GameObject val3 = Object.Instantiate<GameObject>(val, val2, Quaternion.identity);
				CharacterMaster component = val3.GetComponent<CharacterMaster>();
				if ((Object)(object)component == (Object)null)
				{
					Object.Destroy((Object)(object)val3);
					continue;
				}
				component.teamIndex = (TeamIndex)2;
				NetworkServer.Spawn(val3);
				component.Respawn(val2, Quaternion.identity, false);
				silent55SpawnedMasters.Add(component);
				num++;
			}
			status = "Spawned " + num + " x " + EnemyDisplayName(val);
		}

		private void HealTrackedEnemies()
		{
			if (!NetworkServer.active)
			{
				status = "Host required";
				return;
			}
			int num = 0;
			silent55SpawnedMasters.RemoveAll((CharacterMaster x) => (Object)(object)x == (Object)null);
			foreach (CharacterMaster silent55SpawnedMaster in silent55SpawnedMasters)
			{
				CharacterBody body = silent55SpawnedMaster.GetBody();
				if (!((Object)(object)body == (Object)null) && !((Object)(object)body.healthComponent == (Object)null))
				{
					body.healthComponent.Networkhealth = body.healthComponent.fullHealth;
					body.healthComponent.Networkshield = body.healthComponent.fullShield;
					num++;
				}
			}
			status = "Healed " + num + " tracked enemies";
		}

		private void DespawnTrackedEnemies()
		{
			if (!NetworkServer.active)
			{
				status = "Host required";
				return;
			}
			int num = 0;
			CharacterMaster[] array = silent55SpawnedMasters.ToArray();
			foreach (CharacterMaster val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					CharacterBody body = val.GetBody();
					if ((Object)(object)body != (Object)null)
					{
						NetworkServer.Destroy(((Component)body).gameObject);
					}
					NetworkServer.Destroy(((Component)val).gameObject);
					num++;
				}
			}
			silent55SpawnedMasters.Clear();
			status = "Despawned " + num + " tracked enemies";
		}

		private void GiveSelectedPickup()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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)
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			CharacterBody body = GetBody();
			PickupDef pickupDef = PickupCatalog.GetPickupDef(selectedPickup);
			if ((Object)(object)body == (Object)null || (Object)(object)body.inventory == (Object)null || !IsSpawnablePickup(pickupDef))
			{
				status = "Select an item or equipment first";
			}
			else if ((int)pickupDef.itemIndex != -1)
			{
				body.inventory.GiveItemPermanent(pickupDef.itemIndex, spawnQuantity);
				lastGivenPickup = selectedPickup;
				lastGivenCount = spawnQuantity;
				status = "Gave " + spawnQuantity + " x " + PickupName(pickupDef);
			}
			else
			{
				body.inventory.SetEquipmentIndex(pickupDef.equipmentIndex);
				status = "Equipped " + PickupName(pickupDef);
			}
		}

		private void SpawnSelectedPickup()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			CharacterBody body = GetBody();
			PickupDef pickupDef = PickupCatalog.GetPickupDef(selectedPickup);
			if ((Object)(object)body == (Object)null || !IsSpawnablePickup(pickupDef))
			{
				status = "Select an item or equipment first";
				return;
			}
			int num = Mathf.Clamp(spawnQuantity, 1, 25);
			Vector3 val = default(Vector3);
			for (int i = 0; i < num; i++)
			{
				((Vector3)(ref val))..ctor(Random.Range(-4f, 4f), 18f, Random.Range(-4f, 4f));
				PickupDropletController.CreatePickupDroplet(new UniquePickup(selectedPickup), body.corePosition + Vector3.up * 2f, val);
			}
			status = "Spawned " + num + " x " + PickupName(pickupDef) + " on ground";
		}

		private void GiveLunarCoins(uint amount)
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			NetworkUser val = ((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null);
			if ((Object)(object)val == (Object)null)
			{
				status = "Start a run or enter a lobby first";
				return;
			}
			val.AwardLunarCoins(amount);
			status = "Added " + amount.ToString("N0") + " Lunar Coins";
		}

		private void GiveCredits(uint amount)
		{
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null || (Object)(object)body.master == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			uint num = uint.MaxValue - body.master.money;
			CharacterMaster master = body.master;
			master.money += ((amount > num) ? num : amount);
			status = "Added " + amount.ToString("N0") + " credits";
		}

		private void MaxPlayerXp()
		{
			if ((Object)(object)TeamManager.instance == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			TeamManager.instance.SetTeamLevel((TeamIndex)1, TeamManager.naturalLevelCap);
			status = "Player team reached max level";
		}

		private unsafe void UnlockAllContent()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			UserProfile val = ((firstLocalUser != null) ? firstLocalUser.userProfile : null);
			if (val == null)
			{
				status = "No local profile found";
				return;
			}
			if (Time.unscaledTime > unlockConfirmUntil)
			{
				unlockConfirmUntil = Time.unscaledTime + 5f;
				status = "Press Unlock All again within 5 seconds to confirm";
				return;
			}
			int num = 0;
			for (int i = 0; i < UnlockableCatalog.unlockableCount; i++)
			{
				UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef((UnlockableIndex)i);
				if ((Object)(object)unlockableDef != (Object)null && !val.HasUnlockable(unlockableDef))
				{
					val.GrantUnlockable(unlockableDef);
					num++;
				}
			}
			Enumerator enumerator = PickupCatalog.allPickupIndices.GetEnumerator();
			try
			{
				while (((Enumerator)(ref enumerator)).MoveNext())
				{
					PickupIndex current = ((Enumerator)(ref enumerator)).Current;
					if (!val.HasDiscoveredPickup(current))
					{
						val.DiscoverPickup(current);
					}
				}
			}
			finally
			{
				((IDisposable)(*(Enumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose();
			}
			val.RequestEventualSave();
			unlockConfirmUntil = 0f;
			status = "Unlocked " + num + " content entries; profile save requested";
		}

		private string RecoveryPlayerName(PlayerCharacterMasterController p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return "Unknown player";
			}
			if ((Object)(object)p.networkUser != (Object)null && !string.IsNullOrWhiteSpace(p.networkUser.userName))
			{
				return p.networkUser.userName;
			}
			return "Player";
		}

		private PlayerCharacterMasterController SelectedRecoveryPlayer()
		{
			ReadOnlyCollection<PlayerCharacterMasterController> instances = PlayerCharacterMasterController.instances;
			if (instances == null || instances.Count == 0)
			{
				return null;
			}
			selectedRecoveryPlayer = Mathf.Clamp(selectedRecoveryPlayer, 0, instances.Count - 1);
			return instances[selectedRecoveryPlayer];
		}

		private void ReviveSelectedPlayer()
		{
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			PlayerCharacterMasterController val = SelectedRecoveryPlayer();
			if ((Object)(object)val == (Object)null || (Object)(object)val.master == (Object)null)
			{
				status = "No player selected";
				return;
			}
			if (val.master.hasBody)
			{
				status = RecoveryPlayerName(val) + " is already alive";
				return;
			}
			if ((Object)(object)Stage.instance == (Object)null)
			{
				status = "No active stage";
				return;
			}
			Stage.ResetGameOverTimer(8f);
			Stage.instance.RespawnCharacter(val.master);
			status = "Revived " + RecoveryPlayerName(val);
		}

		private void ReviveAllPlayers()
		{
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			if ((Object)(object)Stage.instance == (Object)null)
			{
				status = "No active stage";
				return;
			}
			int num = 0;
			Stage.ResetGameOverTimer(8f);
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.master == (Object)null) && !instance.master.hasBody)
				{
					Stage.instance.RespawnCharacter(instance.master);
					num++;
				}
			}
			status = ((num > 0) ? ("Revived " + num + " player(s)") : "No eliminated players");
		}

		private void HealSelectedPlayer()
		{
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			PlayerCharacterMasterController val = SelectedRecoveryPlayer();
			CharacterBody val2 = (((Object)(object)val != (Object)null && (Object)(object)val.master != (Object)null) ? val.master.GetBody() : null);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val2.healthComponent == (Object)null)
			{
				status = "Selected player has no active body";
				return;
			}
			val2.healthComponent.Networkhealth = val2.healthComponent.fullHealth;
			val2.healthComponent.Networkshield = val2.healthComponent.fullShield;
			status = "Healed " + RecoveryPlayerName(val);
		}

		private void ClearSelectedPlayerDebuffs()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			PlayerCharacterMasterController val = SelectedRecoveryPlayer();
			CharacterBody val2 = (((Object)(object)val != (Object)null && (Object)(object)val.master != (Object)null) ? val.master.GetBody() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				status = "Selected player has no active body";
				return;
			}
			int num = 0;
			for (int i = 0; i < BuffCatalog.buffCount; i++)
			{
				BuffIndex val3 = (BuffIndex)i;
				BuffDef buffDef = BuffCatalog.GetBuffDef(val3);
				if ((Object)(object)buffDef != (Object)null && buffDef.isDebuff)
				{
					while (val2.HasBuff(val3))
					{
						val2.RemoveBuff(val3);
						num++;
					}
				}
			}
			status = "Removed " + num + " debuff stack(s) from " + RecoveryPlayerName(val);
		}

		private void TeleportSelectedToHost()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				status = "Host or single-player required";
				return;
			}
			CharacterBody body = GetBody();
			PlayerCharacterMasterController val = SelectedRecoveryPlayer();
			CharacterBody val2 = (((Object)(object)val != (Object)null && (Object)(object)val.master != (Object)null) ? val.master.GetBody() : null);
			if ((Object)(object)body == (Object)null || (Object)(object)val2 == (Object)null)
			{
				status = "Host or selected player body unavailable";
				return;
			}
			TeleportHelper.TeleportBody(val2, body.footPosition + ((Component)body).transform.right * 3f);
			status = "Teleported " + RecoveryPlayerName(val) + " to host";
		}

		private void Heal()
		{
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null || (Object)(object)body.healthComponent == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			body.healthComponent.Networkhealth = body.healthComponent.fullHealth;
			body.healthComponent.Networkshield = body.healthComponent.fullShield;
			status = "Health restored";
		}

		private void ClearDebuffs()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			int num = 0;
			for (int i = 0; i < BuffCatalog.buffCount; i++)
			{
				BuffIndex val = (BuffIndex)i;
				BuffDef buffDef = BuffCatalog.GetBuffDef(val);
				if ((Object)(object)buffDef != (Object)null && buffDef.isDebuff)
				{
					while (body.HasBuff(val))
					{
						body.RemoveBuff(val);
						num++;
					}
				}
			}
			status = "Removed " + num + " debuff stack(s)";
		}

		private void SavePosition()
		{
			//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)
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null)
			{
				status = "Start a run first";
				return;
			}
			savedPosition = body.corePosition;
			hasSavedPosition = true;
			status = "Position saved";
		}

		private void ReturnPosition()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			CharacterBody body = GetBody();
			if ((Object)(object)body == (Object)null || !hasSavedPosition)
			{
				status = "No saved position";
				return;
			}
			TeleportHelper.TeleportBody(body, savedPosition);
			status = "Returned to saved position";
		}

		private void Scan()
		{
			//IL_00d7: 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)
			chests.Clear();
			shrines.Clear();
			drops.Clear();
			groundPickups.Clear();
			interactables.Clear();
			shops.Clear();
			repairables.Clear();
			foreach (ChestBehavior instances in InstanceTracker.GetInstancesList<ChestBehavior>())
			{
				if ((Object)(object)instances != (Object)null && !instances.NetworkisChestOpened)
				{
					chests.Add(instances);
				}
			}
			shrines.AddRange(Object.FindObjectsOfType<ShrineBehavior>());
			drops.AddRange(Object.FindObjectsOfType<PickupDropletController>());
			foreach (GenericPickupController instances2 in InstanceTracker.GetInstancesList<GenericPickupController>())
			{
				if ((Object)(object)instances2 != (Obje