Decompiled source of SpawnBox v1.7.0

SpawnBox.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HG;
using Microsoft.CodeAnalysis;
using On.RoR2;
using On.RoR2.UI;
using RoR2;
using RoR2.CharacterAI;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SpawnBox
{
	internal enum AggressionPreset
	{
		Passive,
		Normal,
		Aggressive,
		Warpath
	}
	internal class AggressionController
	{
		private class DriverBaseline
		{
			public AISkillDriver Driver;

			public bool ShouldSprint;

			public float MoveInputScale;

			public float MaxDistance;

			public float MinUserHealthFraction;

			public float MaxUserHealthFraction;

			public float DriverUpdateTimerOverride;

			public float AimVectorMaxSpeedOverride;

			public float AimVectorDampTimeOverride;
		}

		internal static readonly string[] Labels = new string[4] { "Passive", "Normal", "Aggressive", "Warpath" };

		private readonly List<DriverBaseline> baselines = new List<DriverBaseline>();

		internal AggressionPreset CurrentPreset { get; private set; } = AggressionPreset.Normal;

		internal AggressionController(CharacterMaster master)
		{
			if ((Object)(object)master == (Object)null)
			{
				return;
			}
			BaseAI[] components = ((Component)master).GetComponents<BaseAI>();
			foreach (BaseAI val in components)
			{
				if ((Object)(object)val == (Object)null || val.skillDrivers == null)
				{
					continue;
				}
				AISkillDriver[] skillDrivers = val.skillDrivers;
				foreach (AISkillDriver val2 in skillDrivers)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						baselines.Add(new DriverBaseline
						{
							Driver = val2,
							ShouldSprint = val2.shouldSprint,
							MoveInputScale = val2.moveInputScale,
							MaxDistance = val2.maxDistance,
							MinUserHealthFraction = val2.minUserHealthFraction,
							MaxUserHealthFraction = val2.maxUserHealthFraction,
							DriverUpdateTimerOverride = val2.driverUpdateTimerOverride,
							AimVectorMaxSpeedOverride = val2.aimVectorMaxSpeedOverride,
							AimVectorDampTimeOverride = val2.aimVectorDampTimeOverride
						});
					}
				}
			}
		}

		internal void Apply(AggressionPreset preset)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Invalid comparison between Unknown and I4
			CurrentPreset = preset;
			foreach (DriverBaseline baseline in baselines)
			{
				if ((Object)(object)baseline.Driver == (Object)null)
				{
					continue;
				}
				baseline.Driver.shouldSprint = baseline.ShouldSprint;
				baseline.Driver.moveInputScale = baseline.MoveInputScale;
				baseline.Driver.maxDistance = baseline.MaxDistance;
				baseline.Driver.minUserHealthFraction = baseline.MinUserHealthFraction;
				baseline.Driver.maxUserHealthFraction = baseline.MaxUserHealthFraction;
				baseline.Driver.driverUpdateTimerOverride = baseline.DriverUpdateTimerOverride;
				baseline.Driver.aimVectorMaxSpeedOverride = baseline.AimVectorMaxSpeedOverride;
				baseline.Driver.aimVectorDampTimeOverride = baseline.AimVectorDampTimeOverride;
				bool flag = (int)baseline.Driver.movementType == 3;
				switch (preset)
				{
				case AggressionPreset.Aggressive:
					baseline.Driver.shouldSprint = true;
					baseline.Driver.moveInputScale = Mathf.Max(baseline.MoveInputScale, 1f);
					if (!flag)
					{
						baseline.Driver.maxDistance = baseline.MaxDistance * 2f;
						break;
					}
					baseline.Driver.minUserHealthFraction = 2f;
					baseline.Driver.maxUserHealthFraction = -1f;
					break;
				case AggressionPreset.Passive:
					baseline.Driver.shouldSprint = false;
					baseline.Driver.moveInputScale = Mathf.Min(baseline.MoveInputScale, 0.6f);
					if (!flag)
					{
						baseline.Driver.maxDistance = baseline.MaxDistance * 0.5f;
					}
					else
					{
						baseline.Driver.maxUserHealthFraction = Mathf.Min(baseline.MaxUserHealthFraction * 1.5f, 1f);
					}
					break;
				case AggressionPreset.Warpath:
					baseline.Driver.shouldSprint = true;
					baseline.Driver.moveInputScale = Mathf.Max(baseline.MoveInputScale, 1.75f);
					if (!flag)
					{
						baseline.Driver.maxDistance = baseline.MaxDistance * 3f;
					}
					else
					{
						baseline.Driver.minUserHealthFraction = 2f;
						baseline.Driver.maxUserHealthFraction = -1f;
					}
					baseline.Driver.driverUpdateTimerOverride = 0.1f;
					baseline.Driver.aimVectorMaxSpeedOverride = 12f;
					baseline.Driver.aimVectorDampTimeOverride = 0.1f;
					break;
				}
			}
		}
	}
	internal class SpawnedCharacterInstance
	{
		public GameObject Master;

		public string DisplayName;

		public string AffixLabel;

		public string SizeLabel;

		public AggressionController Aggression;

		public ToughnessTier ToughnessTier = ToughnessTier.Normal;
	}
	internal static class AllySpawnerTab
	{
		private class Row
		{
			public GameObject MasterPrefab;

			public string DisplayName;

			public Texture Icon;

			public string Key;

			public bool IsFavorite;
		}

		private const int IconSize = 24;

		private static readonly List<Row> allRows = new List<Row>();

		private static string search = "";

		private static string quantityText = "1";

		private static Vector2 scroll;

		private static readonly List<SpawnedCharacterInstance> spawnedObjects = new List<SpawnedCharacterInstance>();

		private static ConfigEntry<string> favoritesEntry;

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

		private static bool shareBuild = false;

		private static AggressionPreset selectedAggression = AggressionPreset.Normal;

		private static SizeTier selectedSize = SizeTier.Normal;

		private static ToughnessTier selectedToughness = ToughnessTier.Normal;

		private static int selectedEliteIndex = 0;

		private const string ExcludedMasterName = "HaulerDroneMaster";

		private static void LoadFavorites()
		{
			favoritesEntry = SpawnBoxPlugin.PluginConfig.Bind<string>("Favorites", "Allies", "", "Comma-separated list of favorited ally master names.");
			favorites.Clear();
			string[] array = favoritesEntry.Value.Split(',');
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					favorites.Add(text);
				}
			}
		}

		private static void SaveFavorites()
		{
			favoritesEntry.Value = string.Join(",", favorites);
		}

		private static void SortRows()
		{
			allRows.Sort((Row a, Row b) => (a.IsFavorite != b.IsFavorite) ? ((!a.IsFavorite) ? 1 : (-1)) : string.Compare(a.DisplayName, b.DisplayName));
		}

		public static void BuildList()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			LoadFavorites();
			allRows.Clear();
			foreach (CharacterMaster allAiMaster in MasterCatalog.allAiMasters)
			{
				if (!((Object)(object)allAiMaster == (Object)null) && !((Object)(object)allAiMaster.bodyPrefab == (Object)null) && (int)allAiMaster.teamIndex == 1 && !(((Object)((Component)allAiMaster).gameObject).name == "HaulerDroneMaster"))
				{
					CharacterBody component = allAiMaster.bodyPrefab.GetComponent<CharacterBody>();
					if (!((Object)(object)component == (Object)null) && !string.IsNullOrEmpty(component.baseNameToken))
					{
						string name = ((Object)((Component)allAiMaster).gameObject).name;
						allRows.Add(new Row
						{
							MasterPrefab = ((Component)allAiMaster).gameObject,
							DisplayName = Language.GetString(component.baseNameToken),
							Icon = component.portraitIcon,
							Key = name,
							IsFavorite = favorites.Contains(name)
						});
					}
				}
			}
			SortRows();
			SpawnBoxPlugin.Log.LogInfo((object)$"SpawnBox: {allRows.Count} allies available.");
		}

		public static void Draw()
		{
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Qty:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) });
			quantityText = GUILayout.TextField(quantityText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			GUILayout.EndHorizontal();
			GUILayout.Label("High values may impact performance.", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedEliteIndex = UiCycler.Draw("Elite:", 70f, selectedEliteIndex, EnemySpawnerTab.eliteLabels, 140f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedAggression = (AggressionPreset)UiCycler.Draw("Aggression:", 70f, (int)selectedAggression, AggressionController.Labels, 140f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedSize = (SizeTier)UiCycler.Draw("Size:", 70f, (int)selectedSize, SizeController.Labels, 140f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedToughness = (ToughnessTier)UiCycler.Draw("Toughness:", 70f, (int)selectedToughness, ToughnessController.Labels, 140f);
			GUILayout.EndHorizontal();
			shareBuild = GUILayout.Toggle(shareBuild, "Share my build with spawned allies (live)", Array.Empty<GUILayoutOption>());
			bool flag = false;
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			foreach (Row allRow in allRows)
			{
				if (!string.IsNullOrEmpty(search) && allRow.DisplayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(allRow.IsFavorite ? "Unpin" : "Pin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }))
				{
					allRow.IsFavorite = !allRow.IsFavorite;
					if (allRow.IsFavorite)
					{
						favorites.Add(allRow.Key);
					}
					else
					{
						favorites.Remove(allRow.Key);
					}
					SaveFavorites();
					flag = true;
				}
				if ((Object)(object)allRow.Icon != (Object)null)
				{
					GUILayout.Label(allRow.Icon, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(24f),
						GUILayout.Height(24f)
					});
				}
				else
				{
					GUILayout.Space(24f);
				}
				GUILayout.Label(allRow.DisplayName, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Spawn", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					SpawnMany(allRow.MasterPrefab, allRow.DisplayName, ParseQuantity());
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
			if (flag)
			{
				SortRows();
			}
		}

		private static int ParseQuantity()
		{
			if (!int.TryParse(quantityText, out var result) || result <= 0)
			{
				return 1;
			}
			return result;
		}

		private static void SpawnMany(GameObject masterPrefab, string displayName, int count)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_00e7: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0167: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			EliteDef val2 = ((selectedEliteIndex > 0 && selectedEliteIndex - 1 < EnemySpawnerTab.eliteOptions.Count) ? EnemySpawnerTab.eliteOptions[selectedEliteIndex - 1] : null);
			string affixLabel = (((Object)(object)val2 != (Object)null) ? EnemySpawnerTab.eliteLabels[selectedEliteIndex] : "");
			string sizeLabel = SizeController.DisplayLabel(selectedSize);
			for (int i = 0; i < count; i++)
			{
				float num = 360f / (float)count * (float)i;
				Vector3 val3 = Quaternion.Euler(0f, num, 0f) * (val.transform.forward * 5f);
				Vector3 position = val.transform.position + val3;
				CharacterMaster val4 = new MasterSummon
				{
					masterPrefab = masterPrefab,
					position = position,
					rotation = Quaternion.identity,
					teamIndexOverride = (TeamIndex)1,
					useAmbientLevel = true,
					inventoryToCopy = (shareBuild ? val.inventory : null),
					ignoreTeamMemberLimit = true
				}.Perform();
				if (Object.op_Implicit((Object)(object)val4) && (Object)(object)val2 != (Object)null && Object.op_Implicit((Object)(object)val4.inventory) && Object.op_Implicit((Object)(object)val2.eliteEquipmentDef))
				{
					val4.inventory.SetEquipmentIndex(val2.eliteEquipmentDef.equipmentIndex, false);
				}
				if ((Object)(object)val4 != (Object)null)
				{
					((Component)val4).gameObject.AddComponent<SetDontDestroyOnLoad>();
					AggressionController aggressionController = new AggressionController(val4);
					if (selectedAggression != AggressionPreset.Normal)
					{
						aggressionController.Apply(selectedAggression);
					}
					SizeController.Attach(val4, selectedSize);
					ToughnessController.Attach(val4, selectedToughness);
					RewardController.Attach(val4);
					spawnedObjects.Add(new SpawnedCharacterInstance
					{
						Master = ((Component)val4).gameObject,
						DisplayName = displayName,
						AffixLabel = affixLabel,
						SizeLabel = sizeLabel,
						Aggression = aggressionController,
						ToughnessTier = selectedToughness
					});
				}
			}
		}

		internal static int SpawnedCount()
		{
			int num = 0;
			foreach (SpawnedCharacterInstance spawnedObject in spawnedObjects)
			{
				if ((Object)(object)spawnedObject.Master != (Object)null)
				{
					num++;
				}
			}
			return num;
		}

		internal static IReadOnlyList<SpawnedCharacterInstance> GetSpawned()
		{
			return spawnedObjects;
		}

		internal static void DespawnAll()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (SpawnedCharacterInstance spawnedObject in spawnedObjects)
			{
				if (!((Object)(object)spawnedObject.Master == (Object)null))
				{
					CharacterMaster component = spawnedObject.Master.GetComponent<CharacterMaster>();
					if (component != null)
					{
						component.DestroyBody();
					}
					NetworkServer.Destroy(spawnedObject.Master);
				}
			}
			spawnedObjects.Clear();
		}

		internal static void DespawnOne(SpawnedCharacterInstance instance)
		{
			if (!NetworkServer.active || instance == null)
			{
				return;
			}
			if ((Object)(object)instance.Master != (Object)null)
			{
				CharacterMaster component = instance.Master.GetComponent<CharacterMaster>();
				if (component != null)
				{
					component.DestroyBody();
				}
				NetworkServer.Destroy(instance.Master);
			}
			spawnedObjects.Remove(instance);
		}

		internal static void SyncBuildToAllies(Inventory playerInventory)
		{
			if (!shareBuild || !NetworkServer.active)
			{
				return;
			}
			foreach (SpawnedCharacterInstance spawnedObject in spawnedObjects)
			{
				if (!((Object)(object)spawnedObject.Master == (Object)null))
				{
					CharacterMaster component = spawnedObject.Master.GetComponent<CharacterMaster>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.inventory == (Object)null))
					{
						component.inventory.CopyItemsFrom(playerInventory);
						component.inventory.CopyEquipmentFrom(playerInventory, false);
					}
				}
			}
		}
	}
	internal static class BuffPresets
	{
		internal class Preset
		{
			public string Name;

			public string Subtitle;

			public BuffDef[] Recipe;
		}

		internal static readonly List<Preset> All = new List<Preset>
		{
			new Preset
			{
				Name = "Ghost Protocol",
				Recipe = (BuffDef[])(object)new BuffDef[2]
				{
					Buffs.Cloak,
					Buffs.CloakSpeed
				}
			},
			new Preset
			{
				Name = "Juggernaut",
				Recipe = (BuffDef[])(object)new BuffDef[2]
				{
					Buffs.ArmorBoost,
					Buffs.ElephantArmorBoost
				}
			},
			new Preset
			{
				Name = "Berserker",
				Recipe = (BuffDef[])(object)new BuffDef[3]
				{
					Buffs.FullCrit,
					Buffs.AttackSpeedOnCrit,
					Buffs.HealingDisabled
				}
			},
			new Preset
			{
				Name = "Warlord",
				Recipe = (BuffDef[])(object)new BuffDef[2]
				{
					Buffs.Warbanner,
					Buffs.WarCryBuff
				}
			},
			new Preset
			{
				Name = "Bloodpact",
				Recipe = (BuffDef[])(object)new BuffDef[2]
				{
					Buffs.LifeSteal,
					Buffs.Energized
				}
			},
			new Preset
			{
				Name = "Death Wish",
				Recipe = (BuffDef[])(object)new BuffDef[4]
				{
					Buffs.Weak,
					Buffs.Cripple,
					Buffs.Slow80,
					Buffs.HealingDisabled
				}
			}
		};

		private static readonly List<BuffDef> activePresetBuffs = new List<BuffDef>();

		internal static void BuildSubtitles()
		{
			foreach (Preset item in All)
			{
				List<string> list = new List<string>();
				BuffDef[] recipe = item.Recipe;
				foreach (BuffDef val in recipe)
				{
					if ((Object)(object)val != (Object)null)
					{
						list.Add(BuffsTab.Prettify(((Object)val).name));
					}
					else
					{
						SpawnBoxPlugin.Log.LogWarning((object)("SpawnBox: a BuffPresets recipe entry in \"" + item.Name + "\" is null - RoR2Content.Buffs field may be unresolved."));
					}
				}
				item.Subtitle = string.Join(", ", list);
			}
		}

		internal static void Apply(Preset preset)
		{
			if (!NetworkServer.active || preset == null)
			{
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Clear();
			BuffDef[] recipe = preset.Recipe;
			foreach (BuffDef val2 in recipe)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					val.AddBuff(val2);
					activePresetBuffs.Add(val2);
					PlayerPersistence.TrackPermanent(val2);
				}
			}
		}

		internal static void Clear()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			foreach (BuffDef activePresetBuff in activePresetBuffs)
			{
				if (!((Object)(object)activePresetBuff == (Object)null))
				{
					val.RemoveBuff(activePresetBuff);
					if (val.GetBuffCount(activePresetBuff) <= 0)
					{
						PlayerPersistence.Untrack(activePresetBuff);
					}
				}
			}
			activePresetBuffs.Clear();
		}
	}
	internal static class BuffsTab
	{
		private class Row
		{
			public BuffDef Def;

			public string DisplayName;

			public Texture Icon;
		}

		private enum Section
		{
			None,
			Buffs,
			Debuffs,
			Elite,
			Presets
		}

		private const int IconSize = 24;

		internal const int TimedMaxStacks = 999;

		private const float DefaultDuration = 5f;

		private static readonly List<Row> buffRows = new List<Row>();

		private static readonly List<Row> debuffRows = new List<Row>();

		private static readonly List<Row> eliteRows = new List<Row>();

		private static readonly List<Row> curatedBuffRows = new List<Row>();

		private static readonly List<Row> curatedDebuffRows = new List<Row>();

		private static Section expandedSection = Section.None;

		private static bool showAllBuffs = false;

		private static bool showAllDebuffs = false;

		private static string search = "";

		private static string durationText = "5";

		private static Vector2 scroll;

		public static void BuildList()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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)
			buffRows.Clear();
			debuffRows.Clear();
			eliteRows.Clear();
			curatedBuffRows.Clear();
			curatedDebuffRows.Clear();
			HashSet<BuffIndex> hashSet = new HashSet<BuffIndex>(BuffCatalog.buffIndiciesRandomEligible);
			HashSet<BuffIndex> hashSet2 = new HashSet<BuffIndex>(BuffCatalog.debuffIndiciesRandomEligible);
			BuffIndex[] nonHiddenBuffIndices = BuffCatalog.nonHiddenBuffIndices;
			foreach (BuffIndex val in nonHiddenBuffIndices)
			{
				BuffDef buffDef = BuffCatalog.GetBuffDef(val);
				if ((Object)(object)buffDef == (Object)null || buffDef.isElite)
				{
					continue;
				}
				Row item = new Row
				{
					Def = buffDef,
					DisplayName = Prettify(((Object)buffDef).name),
					Icon = (Texture)(object)(((Object)(object)buffDef.iconSprite != (Object)null) ? buffDef.iconSprite.texture : null)
				};
				if (buffDef.isDebuff)
				{
					debuffRows.Add(item);
					if (hashSet2.Contains(val))
					{
						curatedDebuffRows.Add(item);
					}
				}
				else
				{
					buffRows.Add(item);
					if (hashSet.Contains(val))
					{
						curatedBuffRows.Add(item);
					}
				}
			}
			nonHiddenBuffIndices = BuffCatalog.eliteBuffIndices;
			for (int i = 0; i < nonHiddenBuffIndices.Length; i++)
			{
				BuffDef buffDef2 = BuffCatalog.GetBuffDef(nonHiddenBuffIndices[i]);
				if (!((Object)(object)buffDef2 == (Object)null))
				{
					Row item2 = new Row
					{
						Def = buffDef2,
						DisplayName = Prettify(((Object)buffDef2).name),
						Icon = (Texture)(object)(((Object)(object)buffDef2.iconSprite != (Object)null) ? buffDef2.iconSprite.texture : null)
					};
					eliteRows.Add(item2);
				}
			}
			buffRows.Sort((Row a, Row b) => string.Compare(a.DisplayName, b.DisplayName));
			debuffRows.Sort((Row a, Row b) => string.Compare(a.DisplayName, b.DisplayName));
			eliteRows.Sort((Row a, Row b) => string.Compare(a.DisplayName, b.DisplayName));
			curatedBuffRows.Sort((Row a, Row b) => string.Compare(a.DisplayName, b.DisplayName));
			curatedDebuffRows.Sort((Row a, Row b) => string.Compare(a.DisplayName, b.DisplayName));
			BuffPresets.BuildSubtitles();
			SpawnBoxPlugin.Log.LogInfo((object)($"SpawnBox: {buffRows.Count} buffs ({curatedBuffRows.Count} curated), " + $"{debuffRows.Count} debuffs ({curatedDebuffRows.Count} curated), " + $"{eliteRows.Count} elite buffs available."));
		}

		internal static string Prettify(string rawName)
		{
			if (string.IsNullOrEmpty(rawName))
			{
				return "(unnamed)";
			}
			string text = rawName;
			if (text.Length > 2 && text[0] == 'b' && text[1] == 'd' && char.IsUpper(text[2]))
			{
				text = text.Substring(2);
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length + 8);
			for (int i = 0; i < text.Length; i++)
			{
				if (i > 0 && char.IsUpper(text[i]) && !char.IsUpper(text[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(text[i]);
			}
			return stringBuilder.ToString();
		}

		private static void SetSection(Section s)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			expandedSection = ((expandedSection != s) ? s : Section.None);
			search = "";
			scroll = Vector2.zero;
		}

		public static void Draw()
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Duration (s):", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) });
			durationText = GUILayout.TextField(durationText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			GUILayout.Label("- used by the Timed button on every row.", Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.enabled = NetworkServer.active && (Object)(object)val != (Object)null;
			int currentSize = (int)PlayerPersistence.CurrentSize;
			int num = UiCycler.Draw("Your Size:", 85f, currentSize, SizeController.Labels, 120f);
			if (num != currentSize)
			{
				SizeTier sizeTier = (SizeTier)num;
				PlayerPersistence.SetSize(sizeTier);
				if ((Object)(object)val != (Object)null)
				{
					SizeController.ApplyToPlayer(val, sizeTier);
				}
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			if (GUILayout.Button((expandedSection == Section.Buffs) ? "▾ Buffs" : "▸ Buffs", Array.Empty<GUILayoutOption>()))
			{
				SetSection(Section.Buffs);
			}
			if (expandedSection == Section.Buffs)
			{
				showAllBuffs = GUILayout.Toggle(showAllBuffs, "Show all (uncurated - some may do nothing on their own)", Array.Empty<GUILayoutOption>());
				DrawSection(showAllBuffs ? buffRows : curatedBuffRows);
			}
			if (GUILayout.Button((expandedSection == Section.Debuffs) ? "▾ Debuffs" : "▸ Debuffs", Array.Empty<GUILayoutOption>()))
			{
				SetSection(Section.Debuffs);
			}
			if (expandedSection == Section.Debuffs)
			{
				showAllDebuffs = GUILayout.Toggle(showAllDebuffs, "Show all (uncurated - some may do nothing on their own)", Array.Empty<GUILayoutOption>());
				DrawSection(showAllDebuffs ? debuffRows : curatedDebuffRows);
			}
			if (GUILayout.Button((expandedSection == Section.Elite) ? "▾ Elite" : "▸ Elite", Array.Empty<GUILayoutOption>()))
			{
				SetSection(Section.Elite);
			}
			if (expandedSection == Section.Elite)
			{
				DrawSection(eliteRows);
			}
			if (GUILayout.Button((expandedSection == Section.Presets) ? "▾ Presets" : "▸ Presets", Array.Empty<GUILayoutOption>()))
			{
				SetSection(Section.Presets);
			}
			if (expandedSection == Section.Presets)
			{
				DrawPresetsSection();
			}
		}

		private static void DrawPresetsSection()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (GUILayout.Button("Clear Preset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) }))
			{
				BuffPresets.Clear();
			}
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			foreach (BuffPresets.Preset item in BuffPresets.All)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				GUILayout.Label(item.Name, Array.Empty<GUILayoutOption>());
				GUILayout.Label(item.Subtitle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					BuffPresets.Apply(item);
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
		}

		private static void DrawSection(List<Row> rows)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			int num = 0;
			foreach (Row row in rows)
			{
				if (string.IsNullOrEmpty(search) || row.DisplayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					num++;
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					if ((Object)(object)row.Icon != (Object)null)
					{
						GUILayout.Label(row.Icon, (GUILayoutOption[])(object)new GUILayoutOption[2]
						{
							GUILayout.Width(24f),
							GUILayout.Height(24f)
						});
					}
					else
					{
						GUILayout.Space(24f);
					}
					GUILayout.Label(row.DisplayName, Array.Empty<GUILayoutOption>());
					int num2 = (((Object)(object)val != (Object)null) ? val.GetBuffCount(row.Def) : 0);
					GUILayout.Label((num2 > 0) ? $"x{num2}" : "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) });
					if (GUILayout.Button("Add", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }))
					{
						AddPermanent(row.Def);
					}
					if (GUILayout.Button("Timed (" + durationText + "s)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
					{
						AddTimed(row.Def);
					}
					if (GUILayout.Button("Clear", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
					{
						ClearBuff(row.Def);
					}
					GUILayout.EndHorizontal();
				}
			}
			if (num == 0)
			{
				GUILayout.Label("No matches - try clearing Search or ticking Show all.", Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
		}

		internal static float ParseDuration()
		{
			if (!float.TryParse(durationText, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || result <= 0f)
			{
				return 5f;
			}
			return result;
		}

		private static void AddPermanent(BuffDef def)
		{
			if (NetworkServer.active && !((Object)(object)def == (Object)null))
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.AddBuff(def);
					PlayerPersistence.TrackPermanent(def);
				}
			}
		}

		private static void AddTimed(BuffDef def)
		{
			if (NetworkServer.active && !((Object)(object)def == (Object)null))
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.AddTimedBuff(def, ParseDuration(), 999);
					PlayerPersistence.TrackTimed(def);
				}
			}
		}

		private static void ClearBuff(BuffDef def)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && !((Object)(object)def == (Object)null))
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.SetBuffCount(def.buffIndex, 0);
					PlayerPersistence.Untrack(def);
				}
			}
		}
	}
	internal static class EnemySpawnerTab
	{
		private class Row
		{
			public GameObject MasterPrefab;

			public string DisplayName;

			public Texture Icon;

			public string Key;

			public bool IsFavorite;
		}

		private const int IconSize = 24;

		private static readonly List<Row> allRows = new List<Row>();

		private static string search = "";

		private static string quantityText = "1";

		private static Vector2 scroll;

		private static readonly List<SpawnedCharacterInstance> spawnedObjects = new List<SpawnedCharacterInstance>();

		private static ConfigEntry<string> favoritesEntry;

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

		internal static readonly List<EliteDef> eliteOptions = new List<EliteDef>();

		internal static string[] eliteLabels = new string[1] { "None" };

		internal static readonly string[] teamLabels = new string[2] { "Bad (enemy)", "Good (ally)" };

		private static int selectedEliteIndex = 0;

		private static bool spawnAsAlly = false;

		private static bool shareBuild = false;

		private static AggressionPreset selectedAggression = AggressionPreset.Normal;

		private static SizeTier selectedSize = SizeTier.Normal;

		private static ToughnessTier selectedToughness = ToughnessTier.Normal;

		public static void BuildEliteList()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected I4, but got Unknown
			eliteOptions.Clear();
			List<string> list = new List<string> { "None" };
			EliteDef[] eliteDefs = EliteCatalog.eliteDefs;
			foreach (EliteDef val in eliteDefs)
			{
				if (!((Object)(object)val == (Object)null) && (int)val.eliteIndex != -1)
				{
					eliteOptions.Add(val);
					list.Add((!string.IsNullOrEmpty(val.modifierToken)) ? Language.GetString(val.modifierToken) : $"Elite {(int)val.eliteIndex}");
				}
			}
			eliteLabels = list.ToArray();
			if (selectedEliteIndex >= eliteLabels.Length)
			{
				selectedEliteIndex = 0;
			}
			SpawnBoxPlugin.Log.LogInfo((object)$"SpawnBox: {eliteOptions.Count} elite affixes available.");
		}

		private static void LoadFavorites()
		{
			favoritesEntry = SpawnBoxPlugin.PluginConfig.Bind<string>("Favorites", "Enemies", "", "Comma-separated list of favorited enemy master names.");
			favorites.Clear();
			string[] array = favoritesEntry.Value.Split(',');
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					favorites.Add(text);
				}
			}
		}

		private static void SaveFavorites()
		{
			favoritesEntry.Value = string.Join(",", favorites);
		}

		private static void SortRows()
		{
			allRows.Sort((Row a, Row b) => (a.IsFavorite != b.IsFavorite) ? ((!a.IsFavorite) ? 1 : (-1)) : string.Compare(a.DisplayName, b.DisplayName));
		}

		public static void BuildList()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Invalid comparison between Unknown and I4
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Invalid comparison between Unknown and I4
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			LoadFavorites();
			allRows.Clear();
			HashSet<BodyIndex> hashSet = new HashSet<BodyIndex>();
			foreach (SurvivorDef allSurvivorDef in SurvivorCatalog.allSurvivorDefs)
			{
				if (!((Object)(object)allSurvivorDef == (Object)null) && !((Object)(object)allSurvivorDef.bodyPrefab == (Object)null))
				{
					CharacterBody component = allSurvivorDef.bodyPrefab.GetComponent<CharacterBody>();
					if ((Object)(object)component != (Object)null)
					{
						hashSet.Add(component.bodyIndex);
					}
				}
			}
			foreach (CharacterMaster allAiMaster in MasterCatalog.allAiMasters)
			{
				if (!((Object)(object)allAiMaster == (Object)null) && !((Object)(object)allAiMaster.bodyPrefab == (Object)null) && ((int)allAiMaster.teamIndex == 2 || (int)allAiMaster.teamIndex == 4))
				{
					CharacterBody component2 = allAiMaster.bodyPrefab.GetComponent<CharacterBody>();
					if (!((Object)(object)component2 == (Object)null) && !string.IsNullOrEmpty(component2.baseNameToken) && !hashSet.Contains(component2.bodyIndex))
					{
						string name = ((Object)((Component)allAiMaster).gameObject).name;
						allRows.Add(new Row
						{
							MasterPrefab = ((Component)allAiMaster).gameObject,
							DisplayName = Language.GetString(component2.baseNameToken),
							Icon = component2.portraitIcon,
							Key = name,
							IsFavorite = favorites.Contains(name)
						});
					}
				}
			}
			SortRows();
			SpawnBoxPlugin.Log.LogInfo((object)$"SpawnBox: {allRows.Count} enemies available.");
		}

		public static void Draw()
		{
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Qty:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) });
			quantityText = GUILayout.TextField(quantityText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			GUILayout.EndHorizontal();
			GUILayout.Label("High values may impact performance.", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			spawnAsAlly = UiCycler.Draw("Team:", 70f, spawnAsAlly ? 1 : 0, teamLabels, 140f) == 1;
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedEliteIndex = UiCycler.Draw("Elite:", 70f, selectedEliteIndex, eliteLabels, 140f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedAggression = (AggressionPreset)UiCycler.Draw("Aggression:", 70f, (int)selectedAggression, AggressionController.Labels, 140f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedSize = (SizeTier)UiCycler.Draw("Size:", 70f, (int)selectedSize, SizeController.Labels, 140f);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			selectedToughness = (ToughnessTier)UiCycler.Draw("Toughness:", 70f, (int)selectedToughness, ToughnessController.Labels, 140f);
			GUILayout.EndHorizontal();
			if (spawnAsAlly)
			{
				GUILayout.Label("Spawning on your team - some enemies may not behave safely off-script (report any that misbehave).", Array.Empty<GUILayoutOption>());
				shareBuild = GUILayout.Toggle(shareBuild, "Share my build with spawned allies (live)", Array.Empty<GUILayoutOption>());
			}
			bool flag = false;
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			foreach (Row allRow in allRows)
			{
				if (!string.IsNullOrEmpty(search) && allRow.DisplayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(allRow.IsFavorite ? "Unpin" : "Pin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }))
				{
					allRow.IsFavorite = !allRow.IsFavorite;
					if (allRow.IsFavorite)
					{
						favorites.Add(allRow.Key);
					}
					else
					{
						favorites.Remove(allRow.Key);
					}
					SaveFavorites();
					flag = true;
				}
				if ((Object)(object)allRow.Icon != (Object)null)
				{
					GUILayout.Label(allRow.Icon, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(24f),
						GUILayout.Height(24f)
					});
				}
				else
				{
					GUILayout.Space(24f);
				}
				GUILayout.Label(allRow.DisplayName, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Spawn", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					SpawnMany(allRow.MasterPrefab, allRow.DisplayName, ParseQuantity());
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
			if (flag)
			{
				SortRows();
			}
		}

		private static int ParseQuantity()
		{
			if (!int.TryParse(quantityText, out var result) || result <= 0)
			{
				return 1;
			}
			return result;
		}

		private static void SpawnMany(GameObject masterPrefab, string displayName, int count)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_00e7: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: 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_0178: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			EliteDef val2 = ((selectedEliteIndex > 0 && selectedEliteIndex - 1 < eliteOptions.Count) ? eliteOptions[selectedEliteIndex - 1] : null);
			string affixLabel = (((Object)(object)val2 != (Object)null) ? eliteLabels[selectedEliteIndex] : "");
			string sizeLabel = SizeController.DisplayLabel(selectedSize);
			for (int i = 0; i < count; i++)
			{
				float num = 360f / (float)count * (float)i;
				Vector3 val3 = Quaternion.Euler(0f, num, 0f) * (val.transform.forward * 5f);
				Vector3 position = val.transform.position + val3;
				CharacterMaster val4 = new MasterSummon
				{
					masterPrefab = masterPrefab,
					position = position,
					rotation = Quaternion.identity,
					teamIndexOverride = (TeamIndex)(spawnAsAlly ? 1 : 2),
					useAmbientLevel = true,
					inventoryToCopy = ((spawnAsAlly && shareBuild) ? val.inventory : null),
					ignoreTeamMemberLimit = true
				}.Perform();
				if (Object.op_Implicit((Object)(object)val4) && (Object)(object)val2 != (Object)null && Object.op_Implicit((Object)(object)val4.inventory) && Object.op_Implicit((Object)(object)val2.eliteEquipmentDef))
				{
					val4.inventory.SetEquipmentIndex(val2.eliteEquipmentDef.equipmentIndex, false);
				}
				if (Object.op_Implicit((Object)(object)val4))
				{
					if (spawnAsAlly)
					{
						((Component)val4).gameObject.AddComponent<SetDontDestroyOnLoad>();
					}
					AggressionController aggressionController = new AggressionController(val4);
					if (selectedAggression != AggressionPreset.Normal)
					{
						aggressionController.Apply(selectedAggression);
					}
					SizeController.Attach(val4, selectedSize);
					ToughnessController.Attach(val4, selectedToughness);
					RewardController.Attach(val4);
					spawnedObjects.Add(new SpawnedCharacterInstance
					{
						Master = ((Component)val4).gameObject,
						DisplayName = displayName,
						AffixLabel = affixLabel,
						SizeLabel = sizeLabel,
						Aggression = aggressionController,
						ToughnessTier = selectedToughness
					});
				}
			}
		}

		internal static int SpawnedCount()
		{
			int num = 0;
			foreach (SpawnedCharacterInstance spawnedObject in spawnedObjects)
			{
				if ((Object)(object)spawnedObject.Master != (Object)null)
				{
					num++;
				}
			}
			return num;
		}

		internal static IReadOnlyList<SpawnedCharacterInstance> GetSpawned()
		{
			return spawnedObjects;
		}

		internal static void DespawnAll()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (SpawnedCharacterInstance spawnedObject in spawnedObjects)
			{
				if (!((Object)(object)spawnedObject.Master == (Object)null))
				{
					CharacterMaster component = spawnedObject.Master.GetComponent<CharacterMaster>();
					if (component != null)
					{
						component.DestroyBody();
					}
					NetworkServer.Destroy(spawnedObject.Master);
				}
			}
			spawnedObjects.Clear();
		}

		internal static void DespawnOne(SpawnedCharacterInstance instance)
		{
			if (!NetworkServer.active || instance == null)
			{
				return;
			}
			if ((Object)(object)instance.Master != (Object)null)
			{
				CharacterMaster component = instance.Master.GetComponent<CharacterMaster>();
				if (component != null)
				{
					component.DestroyBody();
				}
				NetworkServer.Destroy(instance.Master);
			}
			spawnedObjects.Remove(instance);
		}

		internal static void SyncBuildToAllies(Inventory playerInventory)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			if (!shareBuild || !NetworkServer.active)
			{
				return;
			}
			foreach (SpawnedCharacterInstance spawnedObject in spawnedObjects)
			{
				if (!((Object)(object)spawnedObject.Master == (Object)null))
				{
					CharacterMaster component = spawnedObject.Master.GetComponent<CharacterMaster>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.inventory == (Object)null) && (int)component.teamIndex == 1)
					{
						component.inventory.CopyItemsFrom(playerInventory);
						component.inventory.CopyEquipmentFrom(playerInventory, false);
					}
				}
			}
		}
	}
	internal static class EquipmentSpawnerTab
	{
		private class Row
		{
			public EquipmentIndex Index;

			public string DisplayName;

			public Texture Icon;

			public string Key;

			public bool IsFavorite;
		}

		private const int IconSize = 24;

		private static readonly List<Row> allRows = new List<Row>();

		private static string search = "";

		private static Vector2 scroll;

		private static ConfigEntry<string> favoritesEntry;

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

		private static void LoadFavorites()
		{
			favoritesEntry = SpawnBoxPlugin.PluginConfig.Bind<string>("Favorites", "Equipment", "", "Comma-separated list of favorited equipment names.");
			favorites.Clear();
			string[] array = favoritesEntry.Value.Split(',');
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					favorites.Add(text);
				}
			}
		}

		private static void SaveFavorites()
		{
			favoritesEntry.Value = string.Join(",", favorites);
		}

		private static void SortRows()
		{
			allRows.Sort((Row a, Row b) => (a.IsFavorite != b.IsFavorite) ? ((!a.IsFavorite) ? 1 : (-1)) : string.Compare(a.DisplayName, b.DisplayName));
		}

		public unsafe static void BuildList()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0055: 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)
			LoadFavorites();
			allRows.Clear();
			AllEquipmentEnumerator enumerator = EquipmentCatalog.allEquipment.GetEnumerator();
			try
			{
				while (((AllEquipmentEnumerator)(ref enumerator)).MoveNext())
				{
					EquipmentIndex current = ((AllEquipmentEnumerator)(ref enumerator)).Current;
					EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(current);
					if (!((Object)(object)equipmentDef == (Object)null) && equipmentDef.canDrop)
					{
						string text = ((object)(*(EquipmentIndex*)(&current))/*cast due to .constrained prefix*/).ToString();
						allRows.Add(new Row
						{
							Index = current,
							DisplayName = Language.GetString(equipmentDef.nameToken),
							Icon = equipmentDef.pickupIconTexture,
							Key = text,
							IsFavorite = favorites.Contains(text)
						});
					}
				}
			}
			finally
			{
				((IDisposable)(*(AllEquipmentEnumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose();
			}
			SortRows();
			SpawnBoxPlugin.Log.LogInfo((object)$"SpawnBox: {allRows.Count} equipment available.");
		}

		public static void Draw()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			bool flag = false;
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			foreach (Row allRow in allRows)
			{
				if (!string.IsNullOrEmpty(search) && allRow.DisplayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(allRow.IsFavorite ? "Unpin" : "Pin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }))
				{
					allRow.IsFavorite = !allRow.IsFavorite;
					if (allRow.IsFavorite)
					{
						favorites.Add(allRow.Key);
					}
					else
					{
						favorites.Remove(allRow.Key);
					}
					SaveFavorites();
					flag = true;
				}
				if ((Object)(object)allRow.Icon != (Object)null)
				{
					GUILayout.Label(allRow.Icon, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(24f),
						GUILayout.Height(24f)
					});
				}
				else
				{
					GUILayout.Space(24f);
				}
				GUILayout.Label(allRow.DisplayName, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Give", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
				{
					GiveEquipment(allRow.Index);
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
			if (flag)
			{
				SortRows();
			}
		}

		private static void GiveEquipment(EquipmentIndex index)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active)
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
				Inventory val2 = (((Object)(object)val != (Object)null) ? val.inventory : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.SetEquipmentIndex(index, false);
				}
			}
		}
	}
	internal static class FollowDriver
	{
		private const float FollowMinDistance = 12f;

		internal static GameObject ResolveAnchor()
		{
			if (SettingsTab.RecallAll)
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
				if ((Object)(object)val != (Object)null)
				{
					return ((Component)val).gameObject;
				}
			}
			if (SettingsTab.DefendZone && (Object)(object)SpawnBoxPlugin.CurrentZoneTarget != (Object)null)
			{
				return SpawnBoxPlugin.CurrentZoneTarget;
			}
			return null;
		}

		internal static void Apply(CharacterMaster master, GameObject anchor)
		{
			if ((Object)(object)master == (Object)null)
			{
				return;
			}
			SpawnBoxFollowMarker spawnBoxFollowMarker = ((Component)master).GetComponent<SpawnBoxFollowMarker>();
			if ((Object)(object)anchor == (Object)null)
			{
				if ((Object)(object)spawnBoxFollowMarker != (Object)null && (Object)(object)spawnBoxFollowMarker.Driver != (Object)null)
				{
					((Behaviour)spawnBoxFollowMarker.Driver).enabled = false;
				}
				return;
			}
			if ((Object)(object)spawnBoxFollowMarker == (Object)null)
			{
				spawnBoxFollowMarker = Attach(master);
			}
			if (!((Object)(object)spawnBoxFollowMarker == (Object)null) && !((Object)(object)spawnBoxFollowMarker.Driver == (Object)null))
			{
				((Behaviour)spawnBoxFollowMarker.Driver).enabled = true;
				BaseAI[] components = ((Component)master).GetComponents<BaseAI>();
				for (int i = 0; i < components.Length; i++)
				{
					components[i].SetCustomTargetGameObject(anchor);
				}
			}
		}

		private static SpawnBoxFollowMarker Attach(CharacterMaster master)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			AISkillDriver val = ((Component)master).gameObject.AddComponent<AISkillDriver>();
			val.customName = "SpawnBoxFollow";
			val.skillSlot = (SkillSlot)(-1);
			val.movementType = (MovementType)1;
			val.moveTargetType = (TargetType)3;
			val.moveInputScale = 1f;
			val.minDistance = 12f;
			val.maxDistance = float.PositiveInfinity;
			val.shouldSprint = true;
			val.requireSkillReady = false;
			val.requireEquipmentReady = false;
			val.selectionRequiresTargetLoS = false;
			val.activationRequiresTargetLoS = false;
			val.activationRequiresAimTargetLoS = false;
			val.minUserHealthFraction = 0f;
			val.maxUserHealthFraction = float.PositiveInfinity;
			val.minTargetHealthFraction = 0f;
			val.maxTargetHealthFraction = float.PositiveInfinity;
			val.maxTimesSelected = -1;
			BaseAI[] components = ((Component)master).GetComponents<BaseAI>();
			foreach (BaseAI obj in components)
			{
				AISkillDriver[] skillDrivers = obj.skillDrivers;
				AISkillDriver[] array = (AISkillDriver[])(object)new AISkillDriver[((skillDrivers != null) ? skillDrivers.Length : 0) + 1];
				array[0] = val;
				skillDrivers?.CopyTo(array, 1);
				obj.ReplaceSkillDrivers(array);
			}
			SpawnBoxFollowMarker spawnBoxFollowMarker = ((Component)master).gameObject.AddComponent<SpawnBoxFollowMarker>();
			spawnBoxFollowMarker.Driver = val;
			return spawnBoxFollowMarker;
		}
	}
	internal class SpawnBoxFollowMarker : MonoBehaviour
	{
		public AISkillDriver Driver;
	}
	internal static class InteractableSpawnerTab
	{
		private class Row
		{
			public string Path;

			public string DisplayName;

			public Texture Icon;

			public bool IsFavorite;
		}

		internal class SpawnedInstance
		{
			public GameObject Instance;

			public string DisplayName;
		}

		private const string PathPrefix = "SpawnCards/InteractableSpawnCard/";

		private const int IconSize = 24;

		private static readonly List<Row> allRows = new List<Row>();

		private static readonly Random rng = new Random();

		private static string search = "";

		private static Vector2 scroll;

		private static ConfigEntry<string> favoritesEntry;

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

		private static readonly List<SpawnedInstance> spawnedObjects = new List<SpawnedInstance>();

		private static void LoadFavorites()
		{
			favoritesEntry = SpawnBoxPlugin.PluginConfig.Bind<string>("Favorites", "Interactables", "", "Comma-separated list of favorited interactable paths.");
			favorites.Clear();
			string[] array = favoritesEntry.Value.Split(',');
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					favorites.Add(text);
				}
			}
		}

		private static void SaveFavorites()
		{
			favoritesEntry.Value = string.Join(",", favorites);
		}

		private static void SortRows()
		{
			allRows.Sort((Row a, Row b) => (a.IsFavorite != b.IsFavorite) ? ((!a.IsFavorite) ? 1 : (-1)) : string.Compare(a.DisplayName, b.DisplayName));
		}

		public static void BuildList()
		{
			LoadFavorites();
			allRows.Clear();
			List<string> list = new List<string>();
			LegacyResourcesAPI.GetAllPaths(list);
			foreach (string item in list)
			{
				if (string.IsNullOrEmpty(item) || !item.StartsWith("SpawnCards/InteractableSpawnCard/"))
				{
					continue;
				}
				Texture icon = null;
				InteractableSpawnCard val = LegacyResourcesAPI.Load<InteractableSpawnCard>(item);
				if ((Object)(object)val != (Object)null && (Object)(object)((SpawnCard)val).prefab != (Object)null)
				{
					PingInfoProvider component = ((SpawnCard)val).prefab.GetComponent<PingInfoProvider>();
					if ((Object)(object)component != (Object)null && (Object)(object)component.pingIconOverride != (Object)null)
					{
						icon = (Texture)(object)component.pingIconOverride.texture;
					}
				}
				allRows.Add(new Row
				{
					Path = item,
					DisplayName = item.Substring("SpawnCards/InteractableSpawnCard/".Length),
					Icon = icon,
					IsFavorite = favorites.Contains(item)
				});
			}
			SortRows();
			SpawnBoxPlugin.Log.LogInfo((object)$"SpawnBox: {allRows.Count} interactables available.");
		}

		public static void Draw()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			bool flag = false;
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			foreach (Row allRow in allRows)
			{
				if (!string.IsNullOrEmpty(search) && allRow.DisplayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(allRow.IsFavorite ? "Unpin" : "Pin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }))
				{
					allRow.IsFavorite = !allRow.IsFavorite;
					if (allRow.IsFavorite)
					{
						favorites.Add(allRow.Path);
					}
					else
					{
						favorites.Remove(allRow.Path);
					}
					SaveFavorites();
					flag = true;
				}
				if ((Object)(object)allRow.Icon != (Object)null)
				{
					GUILayout.Label(allRow.Icon, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(24f),
						GUILayout.Height(24f)
					});
				}
				else
				{
					GUILayout.Space(24f);
				}
				GUILayout.Label(allRow.DisplayName, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Spawn", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					SpawnAt(allRow.Path, allRow.DisplayName);
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
			if (flag)
			{
				SortRows();
			}
		}

		private static void SpawnAt(string path, string displayName)
		{
			//IL_004e: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			if (!NetworkServer.active)
			{
				return;
			}
			InteractableSpawnCard val = LegacyResourcesAPI.Load<InteractableSpawnCard>(path);
			if (!Object.op_Implicit((Object)(object)val))
			{
				SpawnBoxPlugin.Log.LogWarning((object)("SpawnBox: could not load interactable spawn card at " + path + "."));
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val2 = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if (!((Object)(object)val2 == (Object)null))
			{
				DirectorPlacementRule val3 = new DirectorPlacementRule
				{
					placementMode = (PlacementMode)1,
					position = val2.corePosition,
					minDistance = 5f,
					maxDistance = 20f
				};
				DirectorSpawnRequest val4 = new DirectorSpawnRequest((SpawnCard)(object)val, val3, new Xoroshiro128Plus((ulong)rng.Next()));
				GameObject val5 = (Object.op_Implicit((Object)(object)DirectorCore.instance) ? DirectorCore.instance.TrySpawnObject(val4) : null);
				if (Object.op_Implicit((Object)(object)val5))
				{
					spawnedObjects.Add(new SpawnedInstance
					{
						Instance = val5,
						DisplayName = displayName
					});
				}
				else
				{
					SpawnBoxPlugin.Log.LogWarning((object)("SpawnBox: DirectorCore failed to spawn interactable at " + path + "."));
				}
			}
		}

		internal static int SpawnedCount()
		{
			int num = 0;
			foreach (SpawnedInstance spawnedObject in spawnedObjects)
			{
				if ((Object)(object)spawnedObject.Instance != (Object)null)
				{
					num++;
				}
			}
			return num;
		}

		internal static IReadOnlyList<SpawnedInstance> GetSpawned()
		{
			return spawnedObjects;
		}

		internal static void DespawnAll()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (SpawnedInstance spawnedObject in spawnedObjects)
			{
				if ((Object)(object)spawnedObject.Instance != (Object)null)
				{
					NetworkServer.Destroy(spawnedObject.Instance);
				}
			}
			spawnedObjects.Clear();
		}

		internal static void DespawnOne(SpawnedInstance instance)
		{
			if (NetworkServer.active && instance != null)
			{
				if ((Object)(object)instance.Instance != (Object)null)
				{
					NetworkServer.Destroy(instance.Instance);
				}
				spawnedObjects.Remove(instance);
			}
		}
	}
	internal static class ItemSpawnerTab
	{
		private class Row
		{
			public ItemIndex Index;

			public string DisplayName;

			public Texture Icon;

			public string Key;

			public bool IsFavorite;

			public ItemTier Tier;
		}

		private const int IconSize = 24;

		private static readonly List<Row> allRows = new List<Row>();

		private static string search = "";

		private static string quantityText = "1";

		private static string goldText = "500";

		private static Vector2 scroll;

		private static ConfigEntry<string> favoritesEntry;

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

		private static string selectedRarity = "All";

		private static void LoadFavorites()
		{
			favoritesEntry = SpawnBoxPlugin.PluginConfig.Bind<string>("Favorites", "Items", "", "Comma-separated list of favorited item names.");
			favorites.Clear();
			string[] array = favoritesEntry.Value.Split(',');
			foreach (string text in array)
			{
				if (!string.IsNullOrEmpty(text))
				{
					favorites.Add(text);
				}
			}
		}

		private static void SaveFavorites()
		{
			favoritesEntry.Value = string.Join(",", favorites);
		}

		private static void SortRows()
		{
			allRows.Sort((Row a, Row b) => (a.IsFavorite != b.IsFavorite) ? ((!a.IsFavorite) ? 1 : (-1)) : string.Compare(a.DisplayName, b.DisplayName));
		}

		public static void BuildList()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			LoadFavorites();
			allRows.Clear();
			Enumerator<ItemDef> enumerator = ItemCatalog.allItemDefs.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					ItemDef current = enumerator.Current;
					if (!((Object)(object)current == (Object)null) && !current.hidden && CategoryOf(current.tier) && current.DoesNotContainTag((ItemTag)9))
					{
						string text = ((object)current.itemIndex/*cast due to .constrained prefix*/).ToString();
						allRows.Add(new Row
						{
							Index = current.itemIndex,
							DisplayName = Language.GetString(current.nameToken),
							Icon = current.pickupIconTexture,
							Key = text,
							IsFavorite = favorites.Contains(text),
							Tier = current.tier
						});
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			SortRows();
			SpawnBoxPlugin.Log.LogInfo((object)$"SpawnBox: {allRows.Count} items available.");
		}

		private static bool CategoryOf(ItemTier tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)tier <= 4 || tier - 6 <= 3)
			{
				return true;
			}
			return false;
		}

		private static string RarityGroupOf(ItemTier tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected I4, but got Unknown
			switch ((int)tier)
			{
			case 0:
				return "Common";
			case 1:
				return "Uncommon";
			case 2:
				return "Legendary";
			case 4:
				return "Boss";
			case 3:
				return "Lunar";
			case 6:
			case 7:
			case 8:
			case 9:
				return "Void";
			default:
				return "All";
			}
		}

		public static void Draw()
		{
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Gold:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			goldText = GUILayout.TextField(goldText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			if (GUILayout.Button("Give", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
			{
				GiveGold();
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Rarity:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			if (GUILayout.Toggle(selectedRarity == "All", "All", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				selectedRarity = "All";
			}
			if (GUILayout.Toggle(selectedRarity == "Common", "Common", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				selectedRarity = "Common";
			}
			if (GUILayout.Toggle(selectedRarity == "Uncommon", "Uncommon", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				selectedRarity = "Uncommon";
			}
			if (GUILayout.Toggle(selectedRarity == "Legendary", "Legendary", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				selectedRarity = "Legendary";
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Space(54f);
			if (GUILayout.Toggle(selectedRarity == "Boss", "Boss", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				selectedRarity = "Boss";
			}
			if (GUILayout.Toggle(selectedRarity == "Lunar", "Lunar", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				selectedRarity = "Lunar";
			}
			if (GUILayout.Toggle(selectedRarity == "Void", "Void", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				selectedRarity = "Void";
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Search:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			search = GUILayout.TextField(search, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Qty:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) });
			quantityText = GUILayout.TextField(quantityText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			GUILayout.EndHorizontal();
			bool flag = false;
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			foreach (Row allRow in allRows)
			{
				if ((!string.IsNullOrEmpty(search) && allRow.DisplayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) < 0) || (selectedRarity != "All" && RarityGroupOf(allRow.Tier) != selectedRarity))
				{
					continue;
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(allRow.IsFavorite ? "Unpin" : "Pin", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(45f) }))
				{
					allRow.IsFavorite = !allRow.IsFavorite;
					if (allRow.IsFavorite)
					{
						favorites.Add(allRow.Key);
					}
					else
					{
						favorites.Remove(allRow.Key);
					}
					SaveFavorites();
					flag = true;
				}
				if ((Object)(object)allRow.Icon != (Object)null)
				{
					GUILayout.Label(allRow.Icon, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(24f),
						GUILayout.Height(24f)
					});
				}
				else
				{
					GUILayout.Space(24f);
				}
				GUILayout.Label(allRow.DisplayName, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Give", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
				{
					GiveQuantity(allRow.Index, ParseQuantity());
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
			if (flag)
			{
				SortRows();
			}
		}

		private static int ParseQuantity()
		{
			if (!int.TryParse(quantityText, out var result) || result <= 0)
			{
				return 1;
			}
			return result;
		}

		private static void GiveQuantity(ItemIndex index, int count)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active)
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
				Inventory val2 = (((Object)(object)val != (Object)null) ? val.inventory : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.GiveItemPermanent(index, count);
				}
			}
		}

		private static void GiveGold()
		{
			if (NetworkServer.active)
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
				CharacterMaster val2 = (((Object)(object)val != (Object)null) ? val.master : null);
				if (!((Object)(object)val2 == (Object)null) && uint.TryParse(goldText, out var result))
				{
					val2.GiveMoney(result);
				}
			}
		}
	}
	internal static class PlayerPersistence
	{
		private static readonly HashSet<BuffDef> permanentTouched = new HashSet<BuffDef>();

		private static readonly HashSet<BuffDef> timedTouched = new HashSet<BuffDef>();

		private static readonly Dictionary<BuffDef, int> lastKnownCounts = new Dictionary<BuffDef, int>();

		private static SizeTier persistedSize = SizeTier.Normal;

		private static CharacterBody lastKnownBody;

		private static bool reapplyPending;

		internal static SizeTier CurrentSize => persistedSize;

		internal static void TrackPermanent(BuffDef def)
		{
			if (!((Object)(object)def == (Object)null))
			{
				permanentTouched.Add(def);
			}
		}

		internal static void TrackTimed(BuffDef def)
		{
			if (!((Object)(object)def == (Object)null))
			{
				timedTouched.Add(def);
			}
		}

		internal static void Untrack(BuffDef def)
		{
			if (!((Object)(object)def == (Object)null))
			{
				permanentTouched.Remove(def);
				timedTouched.Remove(def);
				lastKnownCounts.Remove(def);
			}
		}

		internal static void SetSize(SizeTier tier)
		{
			persistedSize = tier;
		}

		internal static void Tick()
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if ((Object)(object)val == (Object)(object)lastKnownBody)
			{
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				if (reapplyPending)
				{
					reapplyPending = false;
					Reapply(val);
				}
				foreach (BuffDef item in permanentTouched)
				{
					lastKnownCounts[item] = val.GetBuffCount(item);
				}
				{
					foreach (BuffDef item2 in timedTouched)
					{
						if (!permanentTouched.Contains(item2))
						{
							lastKnownCounts[item2] = val.GetBuffCount(item2);
						}
					}
					return;
				}
			}
			lastKnownBody = val;
			if ((Object)(object)val != (Object)null)
			{
				reapplyPending = true;
			}
		}

		private static void Reapply(CharacterBody body)
		{
			if (!NetworkServer.active)
			{
				return;
			}
			foreach (BuffDef item in permanentTouched)
			{
				if (lastKnownCounts.TryGetValue(item, out var value))
				{
					for (int i = 0; i < value; i++)
					{
						body.AddBuff(item);
					}
				}
			}
			foreach (BuffDef item2 in timedTouched)
			{
				if (!permanentTouched.Contains(item2) && lastKnownCounts.TryGetValue(item2, out var value2) && value2 > 0)
				{
					body.AddTimedBuff(item2, BuffsTab.ParseDuration(), 999);
				}
			}
			if (persistedSize != SizeTier.Normal)
			{
				SizeController.ApplyToPlayer(body, persistedSize);
			}
		}

		internal static void ResetOnRunStart()
		{
			permanentTouched.Clear();
			timedTouched.Clear();
			lastKnownCounts.Clear();
			persistedSize = SizeTier.Normal;
			lastKnownBody = null;
			reapplyPending = false;
		}
	}
	[BepInPlugin("dileppy.spawnbox", "SpawnBox", "1.6.1")]
	public class SpawnBoxPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "dileppy.spawnbox";

		public const string PluginName = "SpawnBox";

		public const string PluginVersion = "1.6.1";

		internal static SpawnBoxPlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigFile PluginConfig;

		internal static GameObject CurrentZoneTarget;

		private bool windowOpen;

		private int activeTab;

		private Rect windowRect = new Rect(100f, 100f, 760f, 680f);

		private const float KeybindWindowX = 100f;

		private const float KeybindWindowY = 100f;

		private KeyCode toggleKey;

		private HoldoutZoneController trackedZone;

		private float zoneCheckTimer;

		private const float ZoneCheckInterval = 0.5f;

		private float sizeSweepTimer;

		private const float SizeSweepInterval = 0.25f;

		private bool openedFromPauseMenu;

		private RectTransform pauseMenuMainPanelToRestore;

		private void Awake()
		{
			//IL_003c: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			PluginConfig = ((BaseUnityPlugin)this).Config;
			toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ToggleKey", (KeyCode)283, "Key that opens the SpawnBox window.").Value;
			ItemCatalog.Init += new hook_Init(ItemCatalog_Init);
			MasterCatalog.Init += new hook_Init(MasterCatalog_Init);
			EquipmentCatalog.Init += new hook_Init(EquipmentCatalog_Init);
			EliteCatalog.Init += new hook_Init(EliteCatalog_Init);
			SurvivorCatalog.Init += new hook_Init(SurvivorCatalog_Init);
			BuffCatalog.Init += new hook_Init(BuffCatalog_Init);
			Inventory.onInventoryChangedGlobal += Inventory_OnChangedGlobal;
			PauseScreenController.Awake += new hook_Awake(PauseScreenController_Awake);
			CharacterBody.Start += new hook_Start(CharacterBody_Start);
			CharacterBody.RecalculateStats += new hook_RecalculateStats(CharacterBody_RecalculateStats);
			DirectorCore.TrySpawnObject += new hook_TrySpawnObject(DirectorCore_TrySpawnObject);
			SceneDirector.Start += new hook_Start(SceneDirector_Start);
			ObjectivePanelController.GetObjectiveSources += new hook_GetObjectiveSources(ObjectivePanelController_GetObjectiveSources);
			Run.onRunStartGlobal += Run_onRunStartGlobal;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"SpawnBox v1.6.1 online.");
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			ItemCatalog.Init -= new hook_Init(ItemCatalog_Init);
			MasterCatalog.Init -= new hook_Init(MasterCatalog_Init);
			EquipmentCatalog.Init -= new hook_Init(EquipmentCatalog_Init);
			EliteCatalog.Init -= new hook_Init(EliteCatalog_Init);
			SurvivorCatalog.Init -= new hook_Init(SurvivorCatalog_Init);
			BuffCatalog.Init -= new hook_Init(BuffCatalog_Init);
			Inventory.onInventoryChangedGlobal -= Inventory_OnChangedGlobal;
			PauseScreenController.Awake -= new hook_Awake(PauseScreenController_Awake);
			CharacterBody.Start -= new hook_Start(CharacterBody_Start);
			CharacterBody.RecalculateStats -= new hook_RecalculateStats(CharacterBody_RecalculateStats);
			DirectorCore.TrySpawnObject -= new hook_TrySpawnObject(DirectorCore_TrySpawnObject);
			SceneDirector.Start -= new hook_Start(SceneDirector_Start);
			ObjectivePanelController.GetObjectiveSources -= new hook_GetObjectiveSources(ObjectivePanelController_GetObjectiveSources);
			Run.onRunStartGlobal -= Run_onRunStartGlobal;
		}

		private void Inventory_OnChangedGlobal(Inventory inventory)
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			Inventory val2 = (((Object)(object)val != (Object)null) ? val.inventory : null);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)inventory != (Object)(object)val2))
			{
				AllySpawnerTab.SyncBuildToAllies(val2);
				EnemySpawnerTab.SyncBuildToAllies(val2);
				SurvivorSpawnerTab.SyncBuildToAllies(val2);
			}
		}

		private void CharacterBody_Start(orig_Start orig, CharacterBody self)
		{
			orig.Invoke(self);
			try
			{
				SpawnBoxSizeMarker spawnBoxSizeMarker = (((Object)(object)self.master != (Object)null) ? ((Component)self.master).GetComponent<SpawnBoxSizeMarker>() : null);
				if ((Object)(object)spawnBoxSizeMarker != (Object)null && spawnBoxSizeMarker.PlayerApplied)
				{
					spawnBoxSizeMarker.Scale = (spawnBoxSizeMarker.MoveSpeed = (spawnBoxSizeMarker.Damage = (spawnBoxSizeMarker.AttackSpeed = (spawnBoxSizeMarker.Health = 1f))));
					Object.Destroy((Object)(object)spawnBoxSizeMarker);
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: CharacterBody_Start stale size marker cleanup failed - {arg}");
			}
			try
			{
				if ((Object)(object)(((Object)(object)self.master != (Object)null) ? ((Component)self.master).GetComponent<SpawnBoxRewardMarker>() : null) != (Object)null)
				{
					RewardController.Configure(self);
				}
			}
			catch (Exception arg2)
			{
				Log.LogError((object)$"SpawnBox: CharacterBody_Start reward configuration failed - {arg2}");
			}
		}

		private void CharacterBody_RecalculateStats(orig_RecalculateStats orig, CharacterBody self)
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			try
			{
				SpawnBoxSizeMarker spawnBoxSizeMarker = (((Object)(object)self.master != (Object)null) ? ((Component)self.master).GetComponent<SpawnBoxSizeMarker>() : null);
				SpawnBoxToughnessMarker spawnBoxToughnessMarker = (((Object)(object)self.master != (Object)null) ? ((Component)self.master).GetComponent<SpawnBoxToughnessMarker>() : null);
				if ((Object)(object)spawnBoxSizeMarker == (Object)null && (Object)(object)spawnBoxToughnessMarker == (Object)null)
				{
					return;
				}
				float maxHealth = self.maxHealth;
				float num = (((Object)(object)self.healthComponent != (Object)null && maxHealth > 0f) ? (self.healthComponent.health / maxHealth) : 1f);
				if ((Object)(object)spawnBoxSizeMarker != (Object)null)
				{
					self.moveSpeed *= spawnBoxSizeMarker.MoveSpeed;
					self.damage *= spawnBoxSizeMarker.Damage;
					self.attackSpeed *= spawnBoxSizeMarker.AttackSpeed;
					self.maxHealth *= spawnBoxSizeMarker.Health;
					ModelLocator modelLocator = self.modelLocator;
					if ((Object)(object)modelLocator != (Object)null && (Object)(object)modelLocator.modelTransform != (Object)null)
					{
						Vector3 val = SizeController.GetTrueBaseScale(self.bodyIndex) * spawnBoxSizeMarker.Scale;
						if (modelLocator.modelTransform.localScale != val)
						{
							modelLocator.modelTransform.localScale = val;
						}
					}
				}
				if ((Object)(object)spawnBoxToughnessMarker != (Object)null)
				{
					self.damage *= spawnBoxToughnessMarker.Damage;
					self.maxHealth *= spawnBoxToughnessMarker.Health;
				}
				if ((Object)(object)self.healthComponent != (Object)null)
				{
					self.healthComponent.Networkhealth = num * self.maxHealth;
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: CharacterBody_RecalculateStats stat scaling failed - {arg}");
			}
		}

		private GameObject DirectorCore_TrySpawnObject(orig_TrySpawnObject orig, DirectorCore self, DirectorSpawnRequest directorSpawnRequest)
		{
			GameObject val = orig.Invoke(self, directorSpawnRequest);
			try
			{
				WorldTab.OnObjectSpawned(val);
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: DirectorCore_TrySpawnObject tracking failed - {arg}");
			}
			return val;
		}

		private void SceneDirector_Start(orig_Start orig, SceneDirector self)
		{
			orig.Invoke(self);
			try
			{
				WorldTab.OnSceneDirectorStartComplete();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: SceneDirector_Start suppression cleanup failed - {arg}");
			}
		}

		private void ObjectivePanelController_GetObjectiveSources(orig_GetObjectiveSources orig, ObjectivePanelController self, CharacterMaster master, List<ObjectiveSourceDescriptor> output)
		{
			orig.Invoke(self, master, output);
			try
			{
				if (WorldTab.IsExploring)
				{
					output.Clear();
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: ObjectivePanelController_GetObjectiveSources suppression failed - {arg}");
			}
		}

		private void Run_onRunStartGlobal(Run run)
		{
			try
			{
				WorldTab.ResetOnRunStart();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: WorldTab.ResetOnRunStart failed - {arg}");
			}
			try
			{
				PlayerPersistence.ResetOnRunStart();
			}
			catch (Exception arg2)
			{
				Log.LogError((object)$"SpawnBox: PlayerPersistence.ResetOnRunStart failed - {arg2}");
			}
		}

		private void PauseScreenController_Awake(orig_Awake orig, PauseScreenController self)
		{
			orig.Invoke(self);
			try
			{
				AddPauseMenuButton(self);
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: failed to add pause menu button - {arg}");
			}
		}

		private void AddPauseMenuButton(PauseScreenController controller)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			if ((Object)(object)controller.exitGameButton == (Object)null)
			{
				Log.LogWarning((object)"SpawnBox: PauseScreenController.exitGameButton was null, cannot add pause menu button.");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(controller.exitGameButton, controller.exitGameButton.transform.parent);
			((Object)obj).name = "SpawnBoxPauseButton";
			LanguageTextMeshController component = obj.GetComponent<LanguageTextMeshController>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			HGTextMeshProUGUI componentInChildren = obj.GetComponentInChildren<HGTextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = "SpawnBox";
			}
			HGButton component2 = obj.GetComponent<HGButton>();
			if ((Object)(object)component2 == (Object)null)
			{
				Log.LogWarning((object)"SpawnBox: cloned pause menu button has no HGButton component, cannot wire click.");
				return;
			}
			for (int i = 0; i < ((UnityEventBase)((Button)component2).onClick).GetPersistentEventCount(); i++)
			{
				((UnityEventBase)((Button)component2).onClick).SetPersistentListenerState(i, (UnityEventCallState)0);
			}
			((UnityEventBase)((Button)component2).onClick).RemoveAllListeners();
			((UnityEvent)((Button)component2).onClick).AddListener((UnityAction)delegate
			{
				OnPauseMenuButtonClicked(controller);
			});
		}

		private void OnPauseMenuButtonClicked(PauseScreenController controller)
		{
			try
			{
				((Component)controller.mainPanel).gameObject.SetActive(false);
				pauseMenuMainPanelToRestore = controller.mainPanel;
				openedFromPauseMenu = true;
				windowOpen = true;
				((Rect)(ref windowRect)).x = ((float)Screen.width - ((Rect)(ref windowRect)).width) / 2f;
				((Rect)(ref windowRect)).y = ((float)Screen.height - ((Rect)(ref windowRect)).height) / 2f;
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: pause menu button click failed - {arg}");
			}
		}

		private void LateUpdate()
		{
			if (openedFromPauseMenu && (Object)(object)pauseMenuMainPanelToRestore != (Object)null)
			{
				((Component)pauseMenuMainPanelToRestore).gameObject.SetActive(false);
			}
		}

		private void RestorePauseMenuIfNeeded()
		{
			if (!openedFromPauseMenu)
			{
				return;
			}
			openedFromPauseMenu = false;
			try
			{
				if ((Object)(object)pauseMenuMainPanelToRestore != (Object)null && PauseScreenController.instancesList.Count > 0)
				{
					((Component)pauseMenuMainPanelToRestore).gameObject.SetActive(true);
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"SpawnBox: failed to restore pause menu after closing - {arg}");
			}
			pauseMenuMainPanelToRestore = null;
		}

		private void UpdateZoneDefense(float deltaTime)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Invalid comparison between Unknown and I4
			if (!SettingsTab.DefendZone && !SettingsTab.RecallAll)
			{
				return;
			}
			zoneCheckTimer -= deltaTime;
			if (zoneCheckTimer > 0f)
			{
				return;
			}
			zoneCheckTimer = 0.5f;
			if (SettingsTab.DefendZone)
			{
				if ((Object)(object)trackedZone != (Object)null)
				{
					if (!trackedZone.isAnyoneCharging || (int)trackedZone.chargingTeam != 1)
					{
						trackedZone = null;
						CurrentZoneTarget = null;
					}
				}
				else
				{
					HoldoutZoneController[] array = Object.FindObjectsOfType<HoldoutZoneController>();
					foreach (HoldoutZoneController val in array)
					{
						if (!((Object)(object)val == (Object)null) && val.isAnyoneCharging && (int)val.chargingTeam == 1)
						{
							trackedZone = val;
							CurrentZoneTarget = ((Component)val).gameObject;
							break;
						}
					}
				}
			}
			else
			{
				trackedZone = null;
				CurrentZoneTarget = null;
			}
			GameObject anchor = FollowDriver.ResolveAnchor();
			ApplyAnchor(AllySpawnerTab.GetSpawned(), anchor);
			ApplyAnchor(EnemySpawnerTab.GetSpawned(), anchor);
			ApplyAnchor(SurvivorSpawnerTab.GetSpawned(), anchor);
		}

		private static void ApplyAnchor(IEnumerable<SpawnedCharacterInstance> instances, GameObject anchor)
		{
			foreach (SpawnedCharacterInstance instance in instances)
			{
				if (instance != null && !((Object)(object)instance.Master == (Object)null))
				{
					FollowDriver.Apply(instance.Master.GetComponent<CharacterMaster>(), anchor);
				}
			}
		}

		private void SweepMarkedSizes(float deltaTime)
		{
			sizeSweepTimer -= deltaTime;
			if (sizeSweepTimer > 0f)
			{
				return;
			}
			sizeSweepTimer = 0.25f;
			foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList)
			{
				if ((Object)(object)readOnlyInstances != (Object)null && (Object)(object)readOnlyInstances.master != (Object)null && (Object)(object)((Component)readOnlyInstances.master).GetComponent<SpawnBoxSizeMarker>() != (Object)null)
				{
					readOnlyInstances.RecalculateStats();
				}
			}
		}

		private void ItemCatalog_Init(orig_Init orig)
		{
			orig.Invoke();
			ItemSpawnerTab.BuildList();
		}

		private void MasterCatalog_Init(orig_Init orig)
		{
			orig.Invoke();
			AllySpawnerTab.BuildList();
			InteractableSpawnerTab.BuildList();
		}

		private void EliteCatalog_Init(orig_Init orig)
		{
			orig.Invoke();
			EnemySpawnerTab.BuildEliteList();
		}

		private void SurvivorCatalog_Init(orig_Init orig)
		{
			orig.Invoke();
			EnemySpawnerTab.BuildList();
			SurvivorSpawnerTab.BuildList();
		}

		private void EquipmentCatalog_Init(orig_Init orig)
		{
			orig.Invoke();
			EquipmentSpawnerTab.BuildList();
		}

		private void BuffCatalog_Init(orig_Init orig)
		{
			orig.Invoke();
			BuffsTab.BuildList();
		}

		private void Update()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (openedFromPauseMenu && PauseScreenController.instancesList.Count == 0)
			{
				windowOpen = false;
				openedFromPauseMenu = false;
				pauseMenuMainPanelToRestore = null;
			}
			if (Input.GetKeyDown(toggleKey))
			{
				bool flag = windowOpen;
				windowOpen = !windowOpen;
				if (windowOpen && !flag)
				{
					((Rect)(ref windowRect)).x = 100f;
					((Rect)(ref windowRect)).y = 100f;
				}
				if (!windowOpen)
				{
					RestorePauseMenuIfNeeded();
				}
			}
			if (SettingsTab.CloseRequested)
			{
				windowOpen = false;
				SettingsTab.CloseRequested = false;
				RestorePauseMenuIfNeeded();
			}
			UpdateZoneDefense(Time.deltaTime);
			SweepMarkedSizes(Time.deltaTime);
			WorldTab.TickSuppression();
			PlayerPersistence.Tick();
		}

		private void OnGUI()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (windowOpen)
			{
				windowRect = GUILayout.Window(((Object)this).GetInstanceID(), windowRect, new WindowFunction(DrawWindow), "SpawnBox", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawWindow(int id)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Toggle(activeTab == 0, "Items", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 0;
			}
			if (GUILayout.Toggle(activeTab == 1, "Equipment", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 1;
			}
			if (GUILayout.Toggle(activeTab == 2, "Allies", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 2;
			}
			if (GUILayout.Toggle(activeTab == 3, "Enemies", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 3;
			}
			if (GUILayout.Toggle(activeTab == 4, "Interactables", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 4;
			}
			if (GUILayout.Toggle(activeTab == 5, "Survivors", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 5;
			}
			if (GUILayout.Toggle(activeTab == 6, "Player", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 6;
			}
			if (GUILayout.Toggle(activeTab == 7, "World", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 7;
			}
			if (GUILayout.Toggle(activeTab == 8, "Settings", GUIStyle.op_Implicit("button"), Array.Empty<GUILayoutOption>()))
			{
				activeTab = 8;
			}
			GUILayout.EndHorizontal();
			if (activeTab == 0)
			{
				ItemSpawnerTab.Draw();
			}
			else if (activeTab == 1)
			{
				EquipmentSpawnerTab.Draw();
			}
			else if (activeTab == 2)
			{
				AllySpawnerTab.Draw();
			}
			else if (activeTab == 3)
			{
				EnemySpawnerTab.Draw();
			}
			else if (activeTab == 4)
			{
				InteractableSpawnerTab.Draw();
			}
			else if (activeTab == 5)
			{
				SurvivorSpawnerTab.Draw();
			}
			else if (activeTab == 6)
			{
				BuffsTab.Draw();
			}
			else if (activeTab == 7)
			{
				WorldTab.Draw();
			}
			else
			{
				SettingsTab.Draw();
			}
			GUI.DragWindow();
		}
	}
	internal static class RewardController
	{
		private const float ValuePerHealth = 0.12f;

		internal static void Attach(CharacterMaster master)
		{
			if (!((Object)(object)master == (Object)null))
			{
				((Component)master).gameObject.AddComponent<SpawnBoxRewardMarker>();
			}
		}

		internal static void Configure(CharacterBody body)
		{
			if (!((Object)(object)body == (Object)null) && !(body.maxHealth <= 0f) && !((Object)(object)Run.instance == (Object)null))
			{
				DeathRewards component = ((Component)body).GetComponent<DeathRewards>();
				if (!((Object)(object)component == (Object)null))
				{
					float num = body.maxHealth * 0.12f;
					float compensatedDifficultyCoefficient = Run.instance.compensatedDifficultyCoefficient;
					component.spawnValue = (int)Mathf.Max(1f, num);
					component.expReward = (uint)Mathf.Max(1f, num * compensatedDifficultyCoefficient);
					component.goldReward = (uint)Mathf.Max(1f, num * 2f * compensatedDifficultyCoefficient);
				}
			}
		}
	}
	internal class SpawnBoxRewardMarker : MonoBehaviour
	{
	}
	internal static class SettingsTab
	{
		private static bool alliesExpanded;

		private static bool enemiesExpanded;

		private static bool survivorsExpanded;

		private static bool interactablesExpanded;

		internal static bool DefendZone;

		internal static bool RecallAll;

		internal static bool CloseRequested;

		public static void Draw()
		{
			GUILayout.Label("Despawn everything SpawnBox has spawned, by category.", Array.Empty<GUILayoutOption>());
			DefendZone = GUILayout.Toggle(DefendZone, "Defend Zone (redirect Good allies to hold the current zone-hold event, teleporter or otherwise)", Array.Empty<GUILayoutOption>());
			RecallAll = GUILayout.Toggle(RecallAll, "Recall All (spawned units path to you and keep following until you switch this off)", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Close Menu", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) }))
			{
				CloseRequested = true;
			}
			GUILayout.EndHori