Decompiled source of BigBattles v1.1.0

BigBattles.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("BigBattles")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6a33726e3a84ddf770b4ea8cef0c84c5d22a5665")]
[assembly: AssemblyProduct("BigBattles")]
[assembly: AssemblyTitle("BigBattles")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BigBattles
{
	public enum ArmySide
	{
		A,
		B
	}
	public enum NpcCategory
	{
		Human,
		Creature
	}
	public class NpcTypeDefinition
	{
		public string DisplayName;

		public string PrefabName;

		public NpcCategory Category;

		public bool SupportsEquipment;

		public float DefaultHealth;

		public float Scale;

		public float SpacingMultiplier;

		public float OverrideAttackRange;

		public float AttackCooldown;

		public bool ArcherMode;

		public NpcTypeDefinition(string displayName, string prefabName, NpcCategory category, bool supportsEquipment, float defaultHealth, float scale = 1f, float spacingMultiplier = 1f, float overrideAttackRange = 0f, float attackCooldown = 0f, bool archerMode = false)
		{
			DisplayName = displayName;
			PrefabName = prefabName;
			Category = category;
			SupportsEquipment = supportsEquipment;
			DefaultHealth = defaultHealth;
			Scale = scale;
			SpacingMultiplier = spacingMultiplier;
			OverrideAttackRange = overrideAttackRange;
			AttackCooldown = attackCooldown;
			ArcherMode = archerMode;
		}
	}
	public class ArmyConfig
	{
		public ArmySide Side;

		public int SelectedNpcType;

		public int[] EquipmentSlots;

		public int SpawnCount;

		public bool DefaultsApplied;

		private static readonly string[] SafeHelmets = new string[11]
		{
			"HelmetBronze", "HelmetIron", "HelmetDrake", "HelmetPadded", "HelmetCarapace", "HelmetFlametal", "HelmetMage", "HelmetFenring", "HelmetYule", "HelmetTrollLeather",
			"HelmetLeather"
		};

		private static readonly string[] SafeChests = new string[12]
		{
			"ArmorBronzeChest", "ArmorIronChest", "ArmorWolfChest", "ArmorPaddedCuirass", "ArmorCarapaceChest", "ArmorFlametalChest", "ArmorMageChest", "ArmorTrollLeatherChest", "ArmorLeatherChest", "ArmorRagsChest",
			"ArmorRootChest", "ArmorFenringChest"
		};

		private static readonly string[] SafeLegs = new string[12]
		{
			"ArmorBronzeLegs", "ArmorIronLegs", "ArmorWolfLegs", "ArmorPaddedGreaves", "ArmorCarapaceLegs", "ArmorFlametalLegs", "ArmorMageLegs", "ArmorTrollLeatherLegs", "ArmorLeatherLegs", "ArmorRagsLegs",
			"ArmorRootLegs", "ArmorFenringLegs"
		};

		private static readonly string[] SafeBows = new string[5] { "Bow", "BowFineWood", "BowHuntsman", "BowDraugrFang", "BowSpineSnap" };

		private static readonly string[] SafeMeleeWeapons = new string[25]
		{
			"SwordBronze", "SwordIron", "SwordSilver", "SwordBlackmetal", "SwordMistwalker", "SwordNiedhogg", "MaceBronze", "MaceIron", "MaceSilver", "MaceNeedle",
			"MaceStagbreaker", "AxeBronze", "AxeIron", "AxeBlackMetal", "AxeJotunBane", "KnifeFlint", "KnifeCopper", "KnifeChitin", "KnifeSilver", "KnifeBlackMetal",
			"KnifeSkollAndHati", "Club", "SledgeStagbreaker", "FistFenrirClaw", "Splitnir"
		};

		public ArmyConfig(ArmySide side)
		{
			Side = side;
			SelectedNpcType = 0;
			EquipmentSlots = new int[6];
			SpawnCount = 80;
			DefaultsApplied = false;
		}

		public void ApplyDefaults(NpcTypeDefinition npcType = null)
		{
			if (DefaultsApplied || !EquipmentData.IsReady)
			{
				return;
			}
			DefaultsApplied = true;
			if (npcType != null && npcType.ArcherMode)
			{
				if (Side == ArmySide.A)
				{
					EquipmentSlots[0] = EquipmentData.FindIndexByName(0, "Flametal");
					EquipmentSlots[1] = EquipmentData.FindIndexByName(1, "Flametal");
					EquipmentSlots[2] = EquipmentData.FindIndexByName(2, "Flametal");
					EquipmentSlots[3] = EquipmentData.FindIndexByName(3, "#0 Red");
					EquipmentSlots[4] = EquipmentData.FindIndexByName(4, "Draugr Fang");
					EquipmentSlots[5] = 0;
				}
				else
				{
					EquipmentSlots[0] = EquipmentData.FindIndexByName(0, "Drake");
					EquipmentSlots[1] = EquipmentData.FindIndexByName(1, "Wolf Hide Chest");
					EquipmentSlots[2] = EquipmentData.FindIndexByName(2, "Wolf Hide Trou");
					EquipmentSlots[3] = EquipmentData.FindIndexByName(3, "#2 Blue");
					EquipmentSlots[4] = EquipmentData.FindIndexByName(4, "Spine Snap");
					EquipmentSlots[5] = 0;
				}
			}
			else if (Side == ArmySide.A)
			{
				EquipmentSlots[0] = EquipmentData.FindIndexByName(0, "Flametal");
				EquipmentSlots[1] = EquipmentData.FindIndexByName(1, "Flametal");
				EquipmentSlots[2] = EquipmentData.FindIndexByName(2, "Flametal");
				EquipmentSlots[3] = EquipmentData.FindIndexByName(3, "#0 Red");
				EquipmentSlots[4] = EquipmentData.FindIndexByName(4, "Splitnir");
				EquipmentSlots[5] = EquipmentData.FindIndexByName(5, "Flametal");
			}
			else
			{
				EquipmentSlots[0] = EquipmentData.FindIndexByName(0, "Drake");
				EquipmentSlots[1] = EquipmentData.FindIndexByName(1, "Wolf Hide Chest");
				EquipmentSlots[2] = EquipmentData.FindIndexByName(2, "Wolf Hide Trou");
				EquipmentSlots[3] = EquipmentData.FindIndexByName(3, "#2 Blue");
				EquipmentSlots[4] = EquipmentData.FindIndexByName(4, "Nidh");
				EquipmentSlots[5] = EquipmentData.FindIndexByName(5, "Carapace");
			}
		}

		public void RandomizeEquipment(bool archerMode = false)
		{
			if (!EquipmentData.IsReady)
			{
				return;
			}
			for (int i = 0; i < 6; i++)
			{
				List<EquipmentData.ItemEntry> listForSlot = EquipmentData.GetListForSlot(i);
				if (listForSlot.Count <= 1)
				{
					continue;
				}
				switch (i)
				{
				case 0:
					EquipmentSlots[i] = PickFromSafeList(listForSlot, SafeHelmets);
					continue;
				case 1:
					EquipmentSlots[i] = PickFromSafeList(listForSlot, SafeChests);
					continue;
				case 2:
					EquipmentSlots[i] = PickFromSafeList(listForSlot, SafeLegs);
					continue;
				case 3:
					if (Side == ArmySide.A)
					{
						EquipmentSlots[i] = EquipmentData.FindIndexByName(3, "#0 Red");
					}
					else
					{
						EquipmentSlots[i] = EquipmentData.FindIndexByName(3, "#1 White");
					}
					continue;
				}
				if (i == 4 && archerMode)
				{
					EquipmentSlots[i] = PickFromSafeList(listForSlot, SafeBows);
					continue;
				}
				switch (i)
				{
				case 4:
					if (Random.value < 0.15f)
					{
						int num2 = PickFromSafeList(listForSlot, SafeBows);
						EquipmentSlots[i] = ((num2 > 0) ? num2 : PickRandomMeleeWeapon(listForSlot));
					}
					else
					{
						EquipmentSlots[i] = PickRandomMeleeWeapon(listForSlot);
					}
					break;
				case 5:
				{
					if (archerMode)
					{
						EquipmentSlots[i] = 0;
						break;
					}
					string value = "";
					List<EquipmentData.ItemEntry> listForSlot2 = EquipmentData.GetListForSlot(4);
					int num = EquipmentSlots[4];
					if (num > 0 && num < listForSlot2.Count)
					{
						value = listForSlot2[num].PrefabName;
					}
					if (Array.IndexOf(SafeBows, value) >= 0)
					{
						EquipmentSlots[i] = 0;
					}
					else
					{
						EquipmentSlots[i] = Random.Range(1, listForSlot.Count);
					}
					break;
				}
				}
			}
		}

		private static int PickFromSafeList(List<EquipmentData.ItemEntry> list, string[] safeNames)
		{
			HashSet<string> hashSet = new HashSet<string>(safeNames);
			List<int> list2 = new List<int>();
			for (int i = 1; i < list.Count; i++)
			{
				if (hashSet.Contains(list[i].PrefabName))
				{
					list2.Add(i);
				}
			}
			if (list2.Count > 0)
			{
				return list2[Random.Range(0, list2.Count)];
			}
			return Random.Range(1, list.Count);
		}

		private static int PickRandomMeleeWeapon(List<EquipmentData.ItemEntry> weapons)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_010a: Invalid comparison between Unknown and I4
			List<int> list = new List<int>();
			HashSet<string> hashSet = new HashSet<string>(SafeMeleeWeapons);
			for (int i = 1; i < weapons.Count; i++)
			{
				if (hashSet.Contains(weapons[i].PrefabName))
				{
					list.Add(i);
				}
			}
			if (list.Count > 0)
			{
				return list[Random.Range(0, list.Count)];
			}
			for (int j = 1; j < weapons.Count; j++)
			{
				string prefabName = weapons[j].PrefabName;
				if (string.IsNullOrEmpty(prefabName))
				{
					continue;
				}
				ObjectDB instance = ObjectDB.instance;
				GameObject val = ((instance != null) ? instance.GetItemPrefab(prefabName) : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				ItemDrop component = val.GetComponent<ItemDrop>();
				if (component?.m_itemData?.m_shared == null)
				{
					continue;
				}
				ItemType itemType = component.m_itemData.m_shared.m_itemType;
				if ((int)itemType == 3)
				{
					float num = component.m_itemData.m_shared.m_damages.m_damage + component.m_itemData.m_shared.m_damages.m_blunt + component.m_itemData.m_shared.m_damages.m_slash + component.m_itemData.m_shared.m_damages.m_pierce;
					if (num > 5f)
					{
						list.Add(j);
					}
				}
			}
			if (list.Count > 0)
			{
				return list[Random.Range(0, list.Count)];
			}
			return Random.Range(1, weapons.Count);
		}
	}
	public static class NpcTypes
	{
		public static readonly List<NpcTypeDefinition> All = new List<NpcTypeDefinition>
		{
			new NpcTypeDefinition("Viking Warrior", null, NpcCategory.Human, supportsEquipment: true, 200f, 0.95f),
			new NpcTypeDefinition("Viking Archer", null, NpcCategory.Human, supportsEquipment: true, 200f, 0.95f, 1.4f, 80f, 3f, archerMode: true),
			new NpcTypeDefinition("Dverger", "Dverger", NpcCategory.Creature, supportsEquipment: false, 200f, 1f, 1.3f, 80f, 3f),
			new NpcTypeDefinition("Dverger Mage", "DvergerMage", NpcCategory.Creature, supportsEquipment: false, 200f, 1f, 1.3f, 80f, 3f),
			new NpcTypeDefinition("Goblin Brute", "GoblinBrute", NpcCategory.Creature, supportsEquipment: false, 800f, 1f, 1.8f, 0f, 3.5f),
			new NpcTypeDefinition("Goblin", "Goblin", NpcCategory.Creature, supportsEquipment: false, 175f, 1f, 0.8f, 0f, 0.5f),
			new NpcTypeDefinition("Troll", "Troll", NpcCategory.Creature, supportsEquipment: false, 600f, 1f, 2.5f, 0f, 3.5f),
			new NpcTypeDefinition("Neck", "Neck", NpcCategory.Creature, supportsEquipment: false, 50f, 1f, 0.7f, 0f, 0.5f)
		};
	}
	public class BattleController : MonoBehaviour
	{
		public enum BattleState
		{
			Idle,
			Active,
			Paused
		}

		private bool victoryAnnounced;

		private bool damageTextWasEnabled = true;

		public static BattleController Instance { get; private set; }

		public BattleState CurrentState { get; private set; } = BattleState.Idle;


		public static bool DangerMode { get; set; }

		public int ArmyAAlive { get; private set; }

		public int ArmyBAlive { get; private set; }

		public float BattleDuration { get; private set; }

		private void Awake()
		{
			Instance = this;
		}

		private void Update()
		{
			if ((Object)(object)WarriorManager.Instance == (Object)null)
			{
				return;
			}
			ArmyAAlive = WarriorManager.Instance.GetAliveCount(ArmySide.A);
			ArmyBAlive = WarriorManager.Instance.GetAliveCount(ArmySide.B);
			SuppressDamageText();
			if (CurrentState != BattleState.Active)
			{
				return;
			}
			BattleDuration += Time.deltaTime;
			if (!victoryAnnounced && BattleDuration > 2f)
			{
				if (ArmyAAlive == 0 && ArmyBAlive > 0)
				{
					ShowMsg($"Army B wins! ({ArmyBAlive} survivors)");
					victoryAnnounced = true;
					FreezeAll();
					CurrentState = BattleState.Idle;
				}
				else if (ArmyBAlive == 0 && ArmyAAlive > 0)
				{
					ShowMsg($"Army A wins! ({ArmyAAlive} survivors)");
					victoryAnnounced = true;
					FreezeAll();
					CurrentState = BattleState.Idle;
				}
				else if (ArmyAAlive == 0 && ArmyBAlive == 0)
				{
					ShowMsg("Draw! Both armies wiped out!");
					victoryAnnounced = true;
					CurrentState = BattleState.Idle;
				}
				else if (BattleDuration > 300f)
				{
					ShowMsg($"Stalemate! Army A: {ArmyAAlive} vs Army B: {ArmyBAlive}");
					victoryAnnounced = true;
					FreezeAll();
					CurrentState = BattleState.Idle;
				}
			}
		}

		public void StartBattle()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			WarriorManager instance = WarriorManager.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (instance.GetAliveCount(ArmySide.A) == 0 || instance.GetAliveCount(ArmySide.B) == 0)
				{
					ShowMsg("Need warriors on both sides to start a battle!");
					return;
				}
				WarriorAI.ResetTargetTracking();
				Vector3 armyCenter = instance.GetArmyCenter(ArmySide.A);
				Vector3 armyCenter2 = instance.GetArmyCenter(ArmySide.B);
				ChargeArmySpread(instance.ArmyA, armyCenter, armyCenter2);
				ChargeArmySpread(instance.ArmyB, armyCenter2, armyCenter);
				CurrentState = BattleState.Active;
				BattleDuration = 0f;
				victoryAnnounced = false;
				ShowMsg("BATTLE COMMENCED!");
				BigBattlesPlugin.Log($"Battle started: Army A ({ArmyAAlive}) vs Army B ({ArmyBAlive})");
			}
		}

		public void PauseBattle()
		{
			if (CurrentState == BattleState.Active)
			{
				FreezeAll();
				CurrentState = BattleState.Paused;
				ShowMsg("Battle paused.");
			}
		}

		public void ResumeBattle()
		{
			if (CurrentState != BattleState.Paused)
			{
				return;
			}
			WarriorManager instance = WarriorManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			foreach (WarriorAI item in instance.ArmyA)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Character component = ((Component)item).GetComponent<Character>();
					if ((Object)(object)component != (Object)null && !component.IsDead())
					{
						item.Resume();
					}
				}
			}
			foreach (WarriorAI item2 in instance.ArmyB)
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					Character component2 = ((Component)item2).GetComponent<Character>();
					if ((Object)(object)component2 != (Object)null && !component2.IsDead())
					{
						item2.Resume();
					}
				}
			}
			CurrentState = BattleState.Active;
			ShowMsg("Battle resumed!");
		}

		public void ResetBattle()
		{
			WarriorManager instance = WarriorManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			DangerMode = false;
			WarriorAI.ResetTargetTracking();
			instance.DespawnAll();
			Ragdoll[] array = Object.FindObjectsOfType<Ragdoll>();
			foreach (Ragdoll val in array)
			{
				if ((Object)(object)val != (Object)null && val.m_ttl > 9999f)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			WarriorManager.ClearDeathPositions();
			ProjectileOnHit_FriendlyPassthrough.CleanupAllStuckArrows();
			CurrentState = BattleState.Idle;
			BattleDuration = 0f;
			victoryAnnounced = false;
			ShowMsg("Battle reset. All warriors removed.");
		}

		public void ActivateDangerMode()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			WarriorManager instance = WarriorManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			int num = instance.GetAliveCount(ArmySide.A) + instance.GetAliveCount(ArmySide.B);
			if (num == 0)
			{
				ShowMsg("No warriors to fight!");
				return;
			}
			DangerMode = true;
			WarriorAI.ResetTargetTracking();
			Vector3 position = ((Component)localPlayer).transform.position;
			foreach (WarriorAI item in instance.ArmyA)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Character myCharacter = item.MyCharacter;
					if ((Object)(object)myCharacter != (Object)null && !myCharacter.IsDead())
					{
						item.StartCharge(position);
					}
				}
			}
			foreach (WarriorAI item2 in instance.ArmyB)
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					Character myCharacter2 = item2.MyCharacter;
					if ((Object)(object)myCharacter2 != (Object)null && !myCharacter2.IsDead())
					{
						item2.StartCharge(position);
					}
				}
			}
			CurrentState = BattleState.Active;
			BattleDuration = 0f;
			victoryAnnounced = false;
			ShowMsg("DANGER! All warriors target YOU!");
			BigBattlesPlugin.Log($"Danger mode activated: {num} warriors targeting player.");
		}

		public void DeactivateDangerMode()
		{
			DangerMode = false;
			FreezeAll();
			CurrentState = BattleState.Idle;
			ShowMsg("Danger mode off. Warriors frozen.");
			BigBattlesPlugin.Log("Danger mode deactivated.");
		}

		private void ChargeArmySpread(List<WarriorAI> army, Vector3 ownCenter, Vector3 enemyCenter)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			foreach (WarriorAI item in army)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Character myCharacter = item.MyCharacter;
					if (!((Object)(object)myCharacter == (Object)null) && !myCharacter.IsDead())
					{
						Vector3 val = ((Component)item).transform.position - ownCenter;
						Vector3 enemyCenter2 = enemyCenter + val;
						enemyCenter2.y = enemyCenter.y;
						item.StartCharge(enemyCenter2);
					}
				}
			}
		}

		private void FreezeAll()
		{
			WarriorManager instance = WarriorManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			foreach (WarriorAI item in instance.ArmyA)
			{
				item?.Freeze();
			}
			foreach (WarriorAI item2 in instance.ArmyB)
			{
				item2?.Freeze();
			}
		}

		public string GetDurationString()
		{
			int num = (int)(BattleDuration / 60f);
			int num2 = (int)(BattleDuration % 60f);
			return $"{num:00}:{num2:00}";
		}

		private void SuppressDamageText()
		{
			DamageText instance = DamageText.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				WarriorManager instance2 = WarriorManager.Instance;
				bool flag = (Object)(object)instance2 != (Object)null && (instance2.ArmyA.Count > 0 || instance2.ArmyB.Count > 0);
				if (flag && ((Behaviour)instance).enabled)
				{
					damageTextWasEnabled = true;
					((Behaviour)instance).enabled = false;
				}
				else if (!flag && !((Behaviour)instance).enabled && damageTextWasEnabled)
				{
					((Behaviour)instance).enabled = true;
				}
			}
		}

		private void ShowMsg(string text)
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
			}
		}
	}
	public class BattleMenu : MonoBehaviour
	{
		private ArmyConfig configA;

		private ArmyConfig configB;

		private int browsingSlot = -1;

		private ArmySide browsingForSide;

		private Vector2 browseScroll;

		private Rect windowRect;

		private bool stylesReady;

		private GUIStyle headerStyle;

		private GUIStyle titleStyle;

		private GUIStyle sectionStyle;

		private GUIStyle labelStyle;

		private GUIStyle buttonStyle;

		private GUIStyle activeButtonStyle;

		private GUIStyle closeHintStyle;

		private GUIStyle slotButtonStyle;

		private GUIStyle browseItemStyle;

		private GUIStyle browseItemActiveStyle;

		private GUIStyle typeSelectorStyle;

		private GUIStyle dangerButtonStyle;

		private Texture2D bgTex;

		private Texture2D btnTex;

		private Texture2D btnActiveTex;

		private Texture2D btnHoverTex;

		private Texture2D glowTex;

		private Texture2D ropeBorderH;

		private Texture2D ropeBorderV;

		private Texture2D cornerTex;

		private Texture2D slotBtnTex;

		private Texture2D slotBtnHoverTex;

		private bool wasCursorVisible;

		private CursorLockMode wasCursorLock;

		private float glowPulse;

		private float menuCloseCooldown;

		private const float WIN_WIDTH = 380f;

		private const float WIN_HEIGHT_NORMAL = 860f;

		private const float WIN_HEIGHT_BROWSE = 520f;

		private const float GLOW_SIZE = 18f;

		private const float ROPE_WIDTH = 6f;

		private const float CORNER_SIZE = 16f;

		private const int SLOT_COUNT = 6;

		private static readonly int WindowID = "BigBattles_BattleMenu".GetHashCode();

		private float currentWinHeight;

		private string[] npcTypeNames;

		private static readonly HashSet<string> BowPrefabs = new HashSet<string> { "Bow", "BowFineWood", "BowHuntsman", "BowDraugrFang", "BowSpineSnap" };

		public static BattleMenu Instance { get; private set; }

		public bool IsMenuOpen { get; private set; }

		public bool MenuCloseCooldownActive => menuCloseCooldown > 0f;

		private void Awake()
		{
			//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)
			Instance = this;
			configA = new ArmyConfig(ArmySide.A);
			configB = new ArmyConfig(ArmySide.B);
			currentWinHeight = 860f;
			windowRect = new Rect(((float)Screen.width - 380f) / 2f, ((float)Screen.height - currentWinHeight) / 2f, 380f, currentWinHeight);
			npcTypeNames = new string[NpcTypes.All.Count];
			for (int i = 0; i < NpcTypes.All.Count; i++)
			{
				npcTypeNames[i] = NpcTypes.All[i].DisplayName;
			}
		}

		private void Update()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (menuCloseCooldown > 0f)
			{
				menuCloseCooldown -= Time.deltaTime;
			}
			if (IsTyping())
			{
				return;
			}
			if (Input.GetKeyDown(BigBattlesPlugin.MenuKey.Value))
			{
				SetMenuOpen(!IsMenuOpen);
			}
			if (IsMenuOpen && Input.GetKeyDown((KeyCode)27))
			{
				if (browsingSlot >= 0)
				{
					browsingSlot = -1;
				}
				else
				{
					SetMenuOpen(open: false);
				}
			}
			if (IsMenuOpen)
			{
				glowPulse = Mathf.PingPong(Time.time * 0.6f, 1f);
			}
		}

		private void LateUpdate()
		{
			if (IsMenuOpen)
			{
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
			}
		}

		private void SetMenuOpen(bool open)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if (open == IsMenuOpen)
			{
				return;
			}
			IsMenuOpen = open;
			if (open)
			{
				browsingSlot = -1;
				wasCursorVisible = Cursor.visible;
				wasCursorLock = Cursor.lockState;
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				currentWinHeight = 860f;
				windowRect = new Rect(((float)Screen.width - 380f) / 2f, ((float)Screen.height - currentWinHeight) / 2f, 380f, currentWinHeight);
			}
			else
			{
				if (Time.timeScale < 0.01f)
				{
					Time.timeScale = 1f;
				}
				Cursor.visible = wasCursorVisible;
				Cursor.lockState = wasCursorLock;
				menuCloseCooldown = 0.5f;
			}
		}

		public void ForceClose()
		{
			SetMenuOpen(open: false);
		}

		public void ResetConfigs()
		{
			configA = new ArmyConfig(ArmySide.A);
			configB = new ArmyConfig(ArmySide.B);
		}

		private static bool IsTyping()
		{
			try
			{
				if (Console.IsVisible())
				{
					return true;
				}
				if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private void OnGUI()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_010e: 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)
			if (IsMenuOpen)
			{
				InitStyles();
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				Event current = Event.current;
				if ((current.isMouse || current.isKey || current.isScrollWheel) && (!current.isMouse || !((Rect)(ref windowRect)).Contains(current.mousePosition)))
				{
					current.Use();
				}
				float num = ((browsingSlot >= 0) ? 520f : 860f);
				if (Mathf.Abs(currentWinHeight - num) > 1f)
				{
					currentWinHeight = num;
					((Rect)(ref windowRect)).height = currentWinHeight;
				}
				DrawGoldenGlow(windowRect);
				DrawRopeBorder(windowRect);
				DrawCornerKnots(windowRect);
				windowRect = GUI.Window(WindowID, windowRect, new WindowFunction(DrawPanel), "", headerStyle);
			}
		}

		private void DrawGoldenGlow(Rect rect)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Lerp(0.25f, 0.45f, glowPulse);
			GUI.color = new Color(1f, 1f, 1f, num);
			float num2 = 18f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref rect)).x - num2, ((Rect)(ref rect)).y - num2, ((Rect)(ref rect)).width + num2 * 2f, ((Rect)(ref rect)).height + num2 * 2f);
			GUI.DrawTexture(val, (Texture)(object)glowTex);
			GUI.color = Color.white;
		}

		private void DrawRopeBorder(Rect rect)
		{
			//IL_0025: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			float num = 6f;
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y - num * 0.5f, ((Rect)(ref rect)).width, num), (Texture)(object)ropeBorderH);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - num * 0.5f, ((Rect)(ref rect)).width, num), (Texture)(object)ropeBorderH);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - num * 0.5f, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height), (Texture)(object)ropeBorderV);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - num * 0.5f, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height), (Texture)(object)ropeBorderV);
		}

		private void DrawCornerKnots(Rect rect)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			float num = 16f;
			float num2 = num * 0.5f;
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - num2, ((Rect)(ref rect)).y - num2, num, num), (Texture)(object)cornerTex);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - num2, ((Rect)(ref rect)).y - num2, num, num), (Texture)(object)cornerTex);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - num2, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - num2, num, num), (Texture)(object)cornerTex);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - num2, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - num2, num, num), (Texture)(object)cornerTex);
		}

		private void DrawPanel(int windowID)
		{
			if (browsingSlot >= 0)
			{
				DrawBrowseMode(windowID);
			}
			else
			{
				DrawNormalMode(windowID);
			}
		}

		private void DrawNormalMode(int windowID)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Space(4f);
			GUILayout.Label("Big Battles", titleStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(2f);
			DrawArmySection(configA, "ARMY A (Red)", new Color(1f, 0.4f, 0.4f));
			GUILayout.Space(4f);
			DrawArmySection(configB, "ARMY B (Green)", new Color(0.4f, 1f, 0.4f));
			GUILayout.Space(4f);
			GUILayout.Label("— BATTLE CONTROLS —", sectionStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(2f);
			BattleController instance = BattleController.Instance;
			BattleController.BattleState battleState = instance?.CurrentState ?? BattleController.BattleState.Idle;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			switch (battleState)
			{
			case BattleController.BattleState.Idle:
				if (GUILayout.Button("START BATTLE", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					instance?.StartBattle();
				}
				break;
			case BattleController.BattleState.Active:
				if (GUILayout.Button("PAUSE", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					instance?.PauseBattle();
				}
				break;
			case BattleController.BattleState.Paused:
				if (GUILayout.Button("RESUME", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					instance?.ResumeBattle();
				}
				break;
			}
			if (GUILayout.Button("RESET ALL", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
			{
				instance?.ResetBattle();
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(2f);
			bool dangerMode = BattleController.DangerMode;
			int num = (WarriorManager.Instance?.GetAliveCount(ArmySide.A) ?? 0) + (WarriorManager.Instance?.GetAliveCount(ArmySide.B) ?? 0);
			Color backgroundColor = GUI.backgroundColor;
			GUI.backgroundColor = (dangerMode ? new Color(1f, 0.1f, 0.1f) : new Color(0.7f, 0.12f, 0.12f));
			GUI.enabled = num > 0;
			if (GUILayout.Button(dangerMode ? "⚠ DANGER ON ⚠" : "⚠ DANGER ⚠", dangerButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) }))
			{
				if (dangerMode)
				{
					instance?.DeactivateDangerMode();
				}
				else
				{
					instance?.ActivateDangerMode();
				}
			}
			GUI.enabled = true;
			GUI.backgroundColor = backgroundColor;
			GUILayout.Space(2f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool flag = Time.timeScale < 0.01f;
			Color backgroundColor2 = GUI.backgroundColor;
			if (flag)
			{
				GUI.backgroundColor = new Color(0.4f, 0.8f, 1f);
			}
			if (GUILayout.Button(flag ? "UNFREEZE" : "FREEZE", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
			{
				Time.timeScale = (flag ? 1f : 0f);
			}
			GUI.backgroundColor = backgroundColor2;
			bool value = BigBattlesPlugin.EqualDamage.Value;
			Color backgroundColor3 = GUI.backgroundColor;
			if (value)
			{
				GUI.backgroundColor = new Color(0.4f, 1f, 0.5f);
			}
			if (GUILayout.Button(value ? "EQUAL: ON" : "EQUAL: OFF", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
			{
				BigBattlesPlugin.EqualDamage.Value = !BigBattlesPlugin.EqualDamage.Value;
				if (BigBattlesPlugin.EqualDamage.Value)
				{
					WarriorManager.Instance?.EqualizeHealth();
				}
			}
			GUI.backgroundColor = backgroundColor3;
			GUILayout.EndHorizontal();
			GUILayout.Space(2f);
			int num2 = instance?.ArmyAAlive ?? 0;
			int num3 = instance?.ArmyBAlive ?? 0;
			string text = instance?.GetDurationString() ?? "00:00";
			string text2 = battleState.ToString().ToUpper();
			GUILayout.Label($"{text2} | {text} | A:{num2} B:{num3}", labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(4f);
			GUILayout.Label($"Press {BigBattlesPlugin.MenuKey.Value} or ESC to close", closeHintStyle, Array.Empty<GUILayoutOption>());
		}

		private void DrawArmySection(ArmyConfig config, string title, Color accent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Color contentColor = GUI.contentColor;
			GUI.contentColor = accent;
			GUILayout.Label("— " + title + " —", sectionStyle, Array.Empty<GUILayoutOption>());
			GUI.contentColor = contentColor;
			GUILayout.Space(4f);
			WarriorManager instance = WarriorManager.Instance;
			int num = instance?.GetArmyCount(config.Side) ?? 0;
			int value = BigBattlesPlugin.MaxPerSide.Value;
			GUILayout.Label($"Spawned: {num}/{value}", labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(2f);
			NpcTypeDefinition npcTypeDefinition = NpcTypes.All[config.SelectedNpcType];
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("◀", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(40f),
				GUILayout.Height(30f)
			}))
			{
				int selectedNpcType = config.SelectedNpcType;
				config.SelectedNpcType--;
				if (config.SelectedNpcType < 0)
				{
					config.SelectedNpcType = NpcTypes.All.Count - 1;
				}
				npcTypeDefinition = NpcTypes.All[config.SelectedNpcType];
				if (selectedNpcType != config.SelectedNpcType)
				{
					config.DefaultsApplied = false;
				}
			}
			GUILayout.FlexibleSpace();
			GUILayout.Label(npcTypeDefinition.DisplayName, typeSelectorStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("▶", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(40f),
				GUILayout.Height(30f)
			}))
			{
				int selectedNpcType2 = config.SelectedNpcType;
				config.SelectedNpcType++;
				if (config.SelectedNpcType >= NpcTypes.All.Count)
				{
					config.SelectedNpcType = 0;
				}
				npcTypeDefinition = NpcTypes.All[config.SelectedNpcType];
				if (selectedNpcType2 != config.SelectedNpcType)
				{
					config.DefaultsApplied = false;
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(2f);
			if (npcTypeDefinition.SupportsEquipment && EquipmentData.IsReady)
			{
				config.ApplyDefaults(npcTypeDefinition);
				bool archerMode = npcTypeDefinition.ArcherMode;
				if (archerMode)
				{
					config.EquipmentSlots[5] = 0;
					EnsureBowEquipped(config);
				}
				bool flag = IsWeaponTwoHanded(config);
				if (flag)
				{
					config.EquipmentSlots[5] = 0;
				}
				for (int i = 0; i < 6; i++)
				{
					if (i == 5 && (flag || archerMode))
					{
						DrawSlotRowDisabled(config, i, archerMode ? "(Archer)" : "(Two-Handed)");
					}
					else if (i == 4 && archerMode)
					{
						DrawSlotRowBowsOnly(config, i);
					}
					else
					{
						DrawSlotRow(config, i);
					}
				}
				GUILayout.Space(2f);
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Count: {config.SpawnCount}", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			config.SpawnCount = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)config.SpawnCount, 1f, (float)value, Array.Empty<GUILayoutOption>()));
			GUILayout.EndHorizontal();
			GUILayout.Space(2f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Place Formation", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
			{
				PlacementSystem.Instance?.EnterPlacementMode(config.Side, individual: false, config, NpcTypes.All[config.SelectedNpcType]);
			}
			if (GUILayout.Button("Place Individual", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
			{
				PlacementSystem.Instance?.EnterPlacementMode(config.Side, individual: true, config, NpcTypes.All[config.SelectedNpcType]);
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (npcTypeDefinition.SupportsEquipment && EquipmentData.IsReady && GUILayout.Button("Place Random", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
			{
				PlacementSystem.Instance?.EnterPlacementMode(config.Side, individual: false, config, NpcTypes.All[config.SelectedNpcType], randomizePerWarrior: true);
			}
			if (num > 0 && GUILayout.Button($"Remove {config.Side}", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
			{
				instance?.DespawnArmy(config.Side);
			}
			GUILayout.EndHorizontal();
		}

		private void DrawSlotRow(ArmyConfig config, int slot)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			List<EquipmentData.ItemEntry> listForSlot = EquipmentData.GetListForSlot(slot);
			int num = config.EquipmentSlots[slot];
			string text = ((num >= 0 && num < listForSlot.Count) ? listForSlot[num].DisplayName : "— None —");
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(EquipmentData.GetSlotName(slot) + ":", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			if (GUILayout.Button(text, slotButtonStyle ?? buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
			{
				browsingSlot = slot;
				browsingForSide = config.Side;
				browseScroll = Vector2.zero;
			}
			GUILayout.EndHorizontal();
		}

		private void DrawSlotRowDisabled(ArmyConfig config, int slot, string reason)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(EquipmentData.GetSlotName(slot) + ":", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			GUI.enabled = false;
			GUILayout.Button(reason, slotButtonStyle ?? buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) });
			GUI.enabled = true;
			GUILayout.EndHorizontal();
		}

		private static bool IsWeaponTwoHanded(ArmyConfig config)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Invalid comparison between Unknown and I4
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Invalid comparison between Unknown and I4
			if (!EquipmentData.IsReady)
			{
				return false;
			}
			List<EquipmentData.ItemEntry> listForSlot = EquipmentData.GetListForSlot(4);
			int num = config.EquipmentSlots[4];
			if (num <= 0 || num >= listForSlot.Count)
			{
				return false;
			}
			string prefabName = listForSlot[num].PrefabName;
			if (string.IsNullOrEmpty(prefabName))
			{
				return false;
			}
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab(prefabName) : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			if (component?.m_itemData?.m_shared == null)
			{
				return false;
			}
			ItemType itemType = component.m_itemData.m_shared.m_itemType;
			return (int)itemType == 14 || (int)itemType == 22 || (int)itemType == 4;
		}

		private static void EnsureBowEquipped(ArmyConfig config)
		{
			List<EquipmentData.ItemEntry> listForSlot = EquipmentData.GetListForSlot(4);
			int num = config.EquipmentSlots[4];
			if (num > 0 && num < listForSlot.Count && BowPrefabs.Contains(listForSlot[num].PrefabName))
			{
				return;
			}
			for (int i = 1; i < listForSlot.Count; i++)
			{
				if (BowPrefabs.Contains(listForSlot[i].PrefabName))
				{
					config.EquipmentSlots[4] = i;
					break;
				}
			}
		}

		private void DrawSlotRowBowsOnly(ArmyConfig config, int slot)
		{
			List<EquipmentData.ItemEntry> listForSlot = EquipmentData.GetListForSlot(slot);
			int num = config.EquipmentSlots[slot];
			string text = ((num >= 0 && num < listForSlot.Count) ? listForSlot[num].DisplayName : "— None —");
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Bow:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			if (GUILayout.Button("<", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(24f),
				GUILayout.Height(22f)
			}))
			{
				config.EquipmentSlots[slot] = FindAdjacentBow(listForSlot, num, -1);
			}
			GUILayout.Label(text, labelStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(">", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(24f),
				GUILayout.Height(22f)
			}))
			{
				config.EquipmentSlots[slot] = FindAdjacentBow(listForSlot, num, 1);
			}
			GUILayout.EndHorizontal();
		}

		private static int FindAdjacentBow(List<EquipmentData.ItemEntry> list, int current, int direction)
		{
			List<int> list2 = new List<int>();
			for (int i = 1; i < list.Count; i++)
			{
				if (BowPrefabs.Contains(list[i].PrefabName))
				{
					list2.Add(i);
				}
			}
			if (list2.Count == 0)
			{
				return current;
			}
			int num = list2.IndexOf(current);
			if (num < 0)
			{
				return list2[0];
			}
			num += direction;
			if (num < 0)
			{
				num = list2.Count - 1;
			}
			if (num >= list2.Count)
			{
				num = 0;
			}
			return list2[num];
		}

		private void DrawBrowseMode(int windowID)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			ArmyConfig armyConfig = ((browsingForSide == ArmySide.A) ? configA : configB);
			List<EquipmentData.ItemEntry> listForSlot = EquipmentData.GetListForSlot(browsingSlot);
			string slotName = EquipmentData.GetSlotName(browsingSlot);
			GUILayout.Space(8f);
			GUILayout.Label($"Select {slotName} for Army {browsingForSide}", titleStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(6f);
			if (GUILayout.Button("← Back", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
			{
				browsingSlot = -1;
				return;
			}
			GUILayout.Space(4f);
			browseScroll = GUILayout.BeginScrollView(browseScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			for (int i = 0; i < listForSlot.Count; i++)
			{
				GUIStyle val = ((armyConfig.EquipmentSlots[browsingSlot] == i) ? (browseItemActiveStyle ?? activeButtonStyle) : (browseItemStyle ?? buttonStyle));
				if (GUILayout.Button(listForSlot[i].DisplayName, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
				{
					armyConfig.EquipmentSlots[browsingSlot] = i;
					browsingSlot = -1;
				}
			}
			GUILayout.EndScrollView();
		}

		private void OnDestroy()
		{
			if ((Object)(object)bgTex != (Object)null)
			{
				Object.Destroy((Object)(object)bgTex);
			}
			if ((Object)(object)btnTex != (Object)null)
			{
				Object.Destroy((Object)(object)btnTex);
			}
			if ((Object)(object)btnActiveTex != (Object)null)
			{
				Object.Destroy((Object)(object)btnActiveTex);
			}
			if ((Object)(object)btnHoverTex != (Object)null)
			{
				Object.Destroy((Object)(object)btnHoverTex);
			}
			if ((Object)(object)glowTex != (Object)null)
			{
				Object.Destroy((Object)(object)glowTex);
			}
			if ((Object)(object)ropeBorderH != (Object)null)
			{
				Object.Destroy((Object)(object)ropeBorderH);
			}
			if ((Object)(object)ropeBorderV != (Object)null)
			{
				Object.Destroy((Object)(object)ropeBorderV);
			}
			if ((Object)(object)cornerTex != (Object)null)
			{
				Object.Destroy((Object)(object)cornerTex);
			}
			if ((Object)(object)slotBtnTex != (Object)null)
			{
				Object.Destroy((Object)(object)slotBtnTex);
			}
			if ((Object)(object)slotBtnHoverTex != (Object)null)
			{
				Object.Destroy((Object)(object)slotBtnHoverTex);
			}
		}

		private void InitStyles()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Expected O, but got Unknown
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Expected O, but got Unknown
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Expected O, but got Unknown
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Expected O, but got Unknown
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Expected O, but got Unknown
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Expected O, but got Unknown
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0472: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04df: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ef: Expected O, but got Unknown
			//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_0535: Expected O, but got Unknown
			//IL_053c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0541: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_055c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0571: Unknown result type (might be due to invalid IL or missing references)
			//IL_057c: Unknown result type (might be due to invalid IL or missing references)
			//IL_058e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0594: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a4: Expected O, but got Unknown
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c6: Expected O, but got Unknown
			//IL_05cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0609: Expected O, but got Unknown
			if (!stylesReady)
			{
				stylesReady = true;
				bgTex = MakeTex(2, 2, new Color(0.08f, 0.06f, 0.04f, 0.95f));
				btnTex = MakeTex(2, 2, new Color(0.18f, 0.14f, 0.1f, 0.9f));
				btnActiveTex = MakeTex(2, 2, new Color(0.35f, 0.25f, 0.12f, 0.95f));
				btnHoverTex = MakeTex(2, 2, new Color(0.25f, 0.18f, 0.1f, 0.9f));
				glowTex = MakeTex(2, 2, new Color(0.85f, 0.65f, 0.2f, 0.5f));
				ropeBorderH = MakeTex(2, 2, new Color(0.45f, 0.1f, 0.05f, 0.8f));
				ropeBorderV = MakeTex(2, 2, new Color(0.45f, 0.1f, 0.05f, 0.8f));
				cornerTex = MakeTex(2, 2, new Color(0.7f, 0.5f, 0.15f, 0.9f));
				slotBtnTex = MakeTex(2, 2, new Color(0.14f, 0.12f, 0.08f, 0.85f));
				slotBtnHoverTex = MakeTex(2, 2, new Color(0.22f, 0.18f, 0.1f, 0.9f));
				GUIStyle val = new GUIStyle(GUI.skin.window);
				val.normal.background = bgTex;
				val.normal.textColor = Color.white;
				val.onNormal.background = bgTex;
				headerStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 18,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				val2.normal.textColor = new Color(0.9f, 0.75f, 0.3f);
				titleStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				val3.normal.textColor = new Color(0.85f, 0.65f, 0.2f);
				sectionStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12
				};
				val4.normal.textColor = new Color(0.85f, 0.8f, 0.7f);
				labelStyle = val4;
				GUIStyle val5 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 12,
					fontStyle = (FontStyle)1
				};
				val5.normal.background = btnTex;
				val5.normal.textColor = new Color(0.9f, 0.85f, 0.7f);
				val5.hover.background = btnHoverTex;
				val5.hover.textColor = Color.white;
				val5.active.background = btnActiveTex;
				val5.active.textColor = Color.white;
				buttonStyle = val5;
				GUIStyle val6 = new GUIStyle(buttonStyle);
				val6.normal.background = btnActiveTex;
				val6.normal.textColor = new Color(1f, 0.9f, 0.5f);
				activeButtonStyle = val6;
				GUIStyle val7 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				val7.normal.textColor = new Color(1f, 0.9f, 0.5f);
				typeSelectorStyle = val7;
				Texture2D background = MakeTex(2, 2, new Color(0.6f, 0.05f, 0.05f, 0.95f));
				Texture2D background2 = MakeTex(2, 2, new Color(0.8f, 0.1f, 0.1f, 0.95f));
				Texture2D background3 = MakeTex(2, 2, new Color(1f, 0.15f, 0.15f, 0.95f));
				GUIStyle val8 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				val8.normal.background = background;
				val8.normal.textColor = new Color(1f, 0.3f, 0.3f);
				val8.hover.background = background2;
				val8.hover.textColor = new Color(1f, 0.5f, 0.5f);
				val8.active.background = background3;
				val8.active.textColor = Color.white;
				dangerButtonStyle = val8;
				GUIStyle val9 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 10,
					alignment = (TextAnchor)4
				};
				val9.normal.textColor = new Color(0.5f, 0.45f, 0.35f);
				closeHintStyle = val9;
				GUIStyle val10 = new GUIStyle(buttonStyle)
				{
					fontSize = 11
				};
				val10.normal.background = slotBtnTex;
				val10.normal.textColor = new Color(0.85f, 0.8f, 0.7f);
				val10.hover.background = slotBtnHoverTex;
				val10.hover.textColor = Color.white;
				slotButtonStyle = val10;
				browseItemStyle = new GUIStyle(buttonStyle)
				{
					fontSize = 11,
					alignment = (TextAnchor)3
				};
				GUIStyle val11 = new GUIStyle(browseItemStyle);
				val11.normal.background = btnActiveTex;
				val11.normal.textColor = new Color(1f, 0.9f, 0.5f);
				browseItemActiveStyle = val11;
			}
		}

		private static Texture2D MakeTex(int w, int h, Color col)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Color[] array = (Color[])(object)new Color[w * h];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = col;
			}
			Texture2D val = new Texture2D(w, h);
			val.SetPixels(array);
			val.Apply();
			return val;
		}
	}
	public static class EquipmentData
	{
		public struct ItemEntry
		{
			public string PrefabName;

			public string DisplayName;

			public int Variant;
		}

		private static List<ItemEntry> helmets;

		private static List<ItemEntry> chests;

		private static List<ItemEntry> legs;

		private static List<ItemEntry> capes;

		private static List<ItemEntry> weapons;

		private static List<ItemEntry> shields;

		private static bool initialized;

		private static readonly List<ItemEntry> Empty = new List<ItemEntry>
		{
			new ItemEntry
			{
				PrefabName = "",
				DisplayName = "— None —",
				Variant = 0
			}
		};

		private static readonly HashSet<string> BlacklistedPrefabs = new HashSet<string>
		{
			"PickaxeAntler", "PickaxeIron", "PickaxeBronze", "PickaxeStone", "PickaxeBlackMetal", "Hammer", "Hoe", "Cultivator", "FishingRod", "AxeStone",
			"AxeFlint", "AxeBronze", "AxeIron", "AxeBlackMetal", "AxeJotunBane", "Tankard", "TankardAnniversary", "TankardOdin", "TankardDvergr", "HelmetDverger",
			"SwordCheat", "AxeTest", "Torch", "TorchMist"
		};

		private static readonly string[] BlacklistedNameFragments = new string[10] { "Chicken", "Turnip", "Carrot", "Mushroom", "Sausage", "Bread", "Fish", "Serpent stew", "Blood pudding", "Lox pie" };

		private static readonly Dictionary<string, string[]> CapeVariants = new Dictionary<string, string[]>
		{
			{
				"CapeLinen",
				new string[10] { "#0 Red", "#1 White", "#2 Blue", "#3 Yellow", "#4 Green", "#5 Black", "#6 Purple", "#7 White Alt", "#8 Teal", "#9 Brown" }
			},
			{
				"CapeLox",
				new string[3] { "#0 Default", "#1 Dark", "#2 White" }
			}
		};

		public static List<ItemEntry> Helmets
		{
			get
			{
				EnsureInit();
				return helmets ?? Empty;
			}
		}

		public static List<ItemEntry> Chests
		{
			get
			{
				EnsureInit();
				return chests ?? Empty;
			}
		}

		public static List<ItemEntry> Legs
		{
			get
			{
				EnsureInit();
				return legs ?? Empty;
			}
		}

		public static List<ItemEntry> Capes
		{
			get
			{
				EnsureInit();
				return capes ?? Empty;
			}
		}

		public static List<ItemEntry> Weapons
		{
			get
			{
				EnsureInit();
				return weapons ?? Empty;
			}
		}

		public static List<ItemEntry> Shields
		{
			get
			{
				EnsureInit();
				return shields ?? Empty;
			}
		}

		public static bool IsReady
		{
			get
			{
				if (!initialized)
				{
					EnsureInit();
				}
				return initialized;
			}
		}

		public static List<ItemEntry> GetListForSlot(int slot)
		{
			return slot switch
			{
				0 => Helmets, 
				1 => Chests, 
				2 => Legs, 
				3 => Capes, 
				4 => Weapons, 
				5 => Shields, 
				_ => Empty, 
			};
		}

		public static string GetSlotName(int slot)
		{
			return slot switch
			{
				0 => "Head", 
				1 => "Chest", 
				2 => "Legs", 
				3 => "Cape", 
				4 => "Weapon", 
				5 => "Offhand", 
				_ => "???", 
			};
		}

		private static void EnsureInit()
		{
			if (!initialized && !((Object)(object)ObjectDB.instance == (Object)null) && ObjectDB.instance.m_items != null && ObjectDB.instance.m_items.Count != 0)
			{
				BigBattlesPlugin.Log("EquipmentData: Scanning ObjectDB for equipment items...");
				helmets = ScanItems((ItemType)6);
				chests = ScanItems((ItemType)7);
				legs = ScanItems((ItemType)11);
				capes = ScanCapes();
				ItemType[] array = new ItemType[4];
				RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
				weapons = ScanItems((ItemType[])(object)array);
				shields = ScanItems((ItemType)5);
				ItemEntry itemEntry = default(ItemEntry);
				itemEntry.PrefabName = "";
				itemEntry.DisplayName = "— None —";
				itemEntry.Variant = 0;
				ItemEntry item = itemEntry;
				helmets.Insert(0, item);
				chests.Insert(0, item);
				legs.Insert(0, item);
				capes.Insert(0, item);
				weapons.Insert(0, item);
				shields.Insert(0, item);
				initialized = true;
				BigBattlesPlugin.Log($"EquipmentData ready: {helmets.Count} helmets, {chests.Count} chests, " + $"{legs.Count} legs, {capes.Count} capes, {weapons.Count} weapons, " + $"{shields.Count} shields");
			}
		}

		private static List<ItemEntry> ScanItems(params ItemType[] types)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ItemType> hashSet = new HashSet<ItemType>(types);
			HashSet<string> hashSet2 = new HashSet<string>();
			List<ItemEntry> list = new List<ItemEntry>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null || !hashSet.Contains(component.m_itemData.m_shared.m_itemType) || !hashSet2.Add(((Object)item).name) || BlacklistedPrefabs.Contains(((Object)item).name))
				{
					continue;
				}
				string localizedName = GetLocalizedName(item, component);
				if (localizedName.StartsWith("$"))
				{
					continue;
				}
				bool flag = false;
				for (int i = 0; i < BlacklistedNameFragments.Length; i++)
				{
					if (localizedName.IndexOf(BlacklistedNameFragments[i], StringComparison.OrdinalIgnoreCase) >= 0)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list.Add(new ItemEntry
					{
						PrefabName = ((Object)item).name,
						DisplayName = localizedName,
						Variant = 0
					});
				}
			}
			list.Sort((ItemEntry a, ItemEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
			return list;
		}

		private static List<ItemEntry> ScanCapes()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Invalid comparison between Unknown and I4
			HashSet<string> hashSet = new HashSet<string>();
			List<ItemEntry> list = new List<ItemEntry>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null || (int)component.m_itemData.m_shared.m_itemType != 17 || !hashSet.Add(((Object)item).name) || BlacklistedPrefabs.Contains(((Object)item).name))
				{
					continue;
				}
				string localizedName = GetLocalizedName(item, component);
				if (localizedName.StartsWith("$"))
				{
					continue;
				}
				if (CapeVariants.TryGetValue(((Object)item).name, out var value))
				{
					for (int i = 0; i < value.Length; i++)
					{
						list.Add(new ItemEntry
						{
							PrefabName = ((Object)item).name,
							DisplayName = localizedName + " (" + value[i] + ")",
							Variant = i
						});
					}
				}
				else
				{
					list.Add(new ItemEntry
					{
						PrefabName = ((Object)item).name,
						DisplayName = localizedName,
						Variant = 0
					});
				}
			}
			list.Sort((ItemEntry a, ItemEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
			return list;
		}

		private static string GetLocalizedName(GameObject go, ItemDrop itemDrop)
		{
			string name = itemDrop.m_itemData.m_shared.m_name;
			string text = name;
			try
			{
				if (Localization.instance != null)
				{
					text = Localization.instance.Localize(name);
				}
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(text))
			{
				text = ((Object)go).name;
			}
			if (text.StartsWith("$"))
			{
				text = ((Object)go).name;
			}
			return text;
		}

		public static int FindIndexByName(int slot, string nameContains)
		{
			List<ItemEntry> listForSlot = GetListForSlot(slot);
			for (int i = 0; i < listForSlot.Count; i++)
			{
				if (listForSlot[i].DisplayName.IndexOf(nameContains, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return i;
				}
			}
			return 0;
		}

		public static void Reset()
		{
			initialized = false;
			helmets = null;
			chests = null;
			legs = null;
			capes = null;
			weapons = null;
			shields = null;
		}
	}
	public static class FormationCalculator
	{
		public static List<Vector3> GetPositions(Vector3 center, Vector3 facing, int count, int columns = 8, int rows = 5, float spacing = 2f, float spacingMultiplier = 1f)
		{
			//IL_003d: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_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)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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)
			List<Vector3> list = new List<Vector3>(count);
			float num = spacing * spacingMultiplier;
			facing.y = 0f;
			if (((Vector3)(ref facing)).sqrMagnitude < 0.01f)
			{
				facing = Vector3.forward;
			}
			((Vector3)(ref facing)).Normalize();
			Vector3 val = Vector3.Cross(Vector3.up, facing);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			int num2 = columns * rows;
			if (count > num2)
			{
				count = num2;
			}
			for (int i = 0; i < count; i++)
			{
				int num3 = i / columns;
				int num4 = i % columns;
				float num5 = ((float)num4 - (float)(columns - 1) * 0.5f) * num;
				float num6 = (float)(-num3) * num;
				Vector3 pos = center + normalized * num5 + facing * num6;
				pos = SnapToGround(pos);
				list.Add(pos);
			}
			return list;
		}

		public static Vector3 SnapToGround(Vector3 pos)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			float y = default(float);
			if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(pos, ref y))
			{
				pos.y = y;
			}
			return pos;
		}
	}
	[HarmonyPatch(typeof(Projectile), "IsValidTarget")]
	public static class ProjectileIsValidTarget_Patch
	{
		private static readonly FieldInfo s_ownerField = AccessTools.Field(typeof(Projectile), "m_owner");

		private static bool Prefix(Projectile __instance, ref bool __result, IDestructible destr)
		{
			object? obj = s_ownerField?.GetValue(__instance);
			Character val = (Character)((obj is Character) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			WarriorAI cached = WarriorAI.GetCached(val);
			if ((Object)(object)cached == (Object)null)
			{
				return true;
			}
			Character val2 = (Character)(object)((destr is Character) ? destr : null);
			if ((Object)(object)val2 == (Object)null)
			{
				MonoBehaviour val3 = (MonoBehaviour)(object)((destr is MonoBehaviour) ? destr : null);
				if ((Object)(object)val3 != (Object)null)
				{
					val2 = ((Component)val3).GetComponentInParent<Character>();
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return true;
			}
			if (!((Object)(object)WarriorAI.GetCached(val2) != (Object)null) && !(val2 is Player))
			{
				return true;
			}
			if ((Object)(object)val2 == (Object)(object)val || val2.IsDead())
			{
				__result = false;
				return false;
			}
			__result = BaseAI.IsEnemy(val, val2);
			return false;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "GetAttackDrawPercentage")]
	public static class WarriorBowFullDraw_Patch
	{
		private static bool Prefix(Humanoid __instance, ref float __result)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			if ((Object)(object)__instance == (Object)null || (Object)(object)WarriorAI.GetCached((Character)(object)__instance) == (Object)null)
			{
				return true;
			}
			ItemData currentWeapon = __instance.GetCurrentWeapon();
			if (currentWeapon == null || (int)(currentWeapon.m_shared?.m_itemType).GetValueOrDefault() != 4)
			{
				return true;
			}
			WarriorAI cached = WarriorAI.GetCached((Character)(object)__instance);
			__result = (((Object)(object)cached != (Object)null) ? cached.NextDrawPercent : 1f);
			return false;
		}
	}
	[HarmonyPatch(typeof(Projectile), "Setup")]
	public static class ProjectileSetup_TagWarriorArrows
	{
		private static readonly FieldInfo s_gravityField = AccessTools.Field(typeof(Projectile), "m_gravity");

		private static readonly FieldInfo s_velField = AccessTools.Field(typeof(Projectile), "m_vel");

		private static void Postfix(Projectile __instance, Character owner)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00cd: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner == (Object)null)
			{
				return;
			}
			WarriorAI cached = WarriorAI.GetCached(owner);
			if ((Object)(object)cached == (Object)null)
			{
				return;
			}
			((Component)__instance).gameObject.AddComponent<WarriorArrowTag>();
			if (s_gravityField != null)
			{
				s_gravityField.SetValue(__instance, 5f);
			}
			Character targetCreature = ((BaseAI)cached).GetTargetCreature();
			if ((Object)(object)targetCreature == (Object)null || s_velField == null)
			{
				return;
			}
			Vector3 val = (Vector3)s_velField.GetValue(__instance);
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 5f)
			{
				return;
			}
			Vector3 centerPoint = targetCreature.GetCenterPoint();
			Vector3 position = ((Component)__instance).transform.position;
			Vector3 val2 = centerPoint - position;
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(val2.x, 0f, val2.z);
			float magnitude2 = ((Vector3)(ref val3)).magnitude;
			float y = val2.y;
			if (magnitude2 < 3f)
			{
				s_velField.SetValue(__instance, ((Vector3)(ref val2)).normalized * magnitude);
				return;
			}
			Vector3 velocity = targetCreature.GetVelocity();
			if (((Vector3)(ref velocity)).sqrMagnitude > 0.5f && magnitude2 > 10f)
			{
				float num = magnitude2 / magnitude;
				Vector3 val4 = centerPoint + velocity * num;
				val2 = val4 - position;
				((Vector3)(ref val3))..ctor(val2.x, 0f, val2.z);
				magnitude2 = ((Vector3)(ref val3)).magnitude;
				y = val2.y;
			}
			float num2 = magnitude * magnitude;
			float num3 = num2 * num2;
			float num4 = 5f;
			float num5 = num3 - num4 * (num4 * magnitude2 * magnitude2 + 2f * y * num2);
			float num6;
			if (num5 < 0f)
			{
				num6 = 0.43633232f;
			}
			else
			{
				num6 = Mathf.Atan2(num2 - Mathf.Sqrt(num5), num4 * magnitude2);
				num6 = Mathf.Clamp(num6, -0.1f, 0.43633232f);
			}
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			float num7 = Mathf.Cos(num6);
			float num8 = Mathf.Sin(num6);
			Vector3 val5 = new Vector3(normalized.x * num7, num8, normalized.z * num7);
			Vector3 normalized2 = ((Vector3)(ref val5)).normalized;
			s_velField.SetValue(__instance, normalized2 * magnitude);
		}
	}
	public class WarriorArrowTag : MonoBehaviour
	{
	}
	public class StuckArrowBehaviour : MonoBehaviour
	{
		private float _orphanTimer;

		private bool _isOrphaned;

		private void LateUpdate()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)this).transform.parent == (Object)null && !_isOrphaned)
			{
				_isOrphaned = true;
				_orphanTimer = 0f;
			}
			if (!_isOrphaned)
			{
				return;
			}
			_orphanTimer += Time.deltaTime;
			Ragdoll[] array = Object.FindObjectsOfType<Ragdoll>();
			foreach (Ragdoll val in array)
			{
				if ((Object)(object)val != (Object)null && Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position) < 5f)
				{
					((Component)this).transform.SetParent(((Component)val).transform, true);
					_isOrphaned = false;
					return;
				}
			}
			if (_orphanTimer > 1f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnHit")]
	public static class ProjectileOnHit_FriendlyPassthrough
	{
		private static readonly FieldInfo s_ownerField = AccessTools.Field(typeof(Projectile), "m_owner");

		public static readonly List<GameObject> AllStuckArrows = new List<GameObject>();

		private const int MAX_ARROWS_PER_CHARACTER = 10;

		private static bool Prefix(Projectile __instance, Collider collider, Vector3 hitPoint)
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			object? obj = s_ownerField?.GetValue(__instance);
			Character val = (Character)((obj is Character) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			WarriorAI cached = WarriorAI.GetCached(val);
			if ((Object)(object)cached == (Object)null)
			{
				return true;
			}
			Character val2 = ((collider != null) ? ((Component)collider).GetComponentInParent<Character>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				if ((Object)(object)val2 == (Object)(object)val)
				{
					Collider component = ((Component)__instance).GetComponent<Collider>();
					if ((Object)(object)component != (Object)null && (Object)(object)collider != (Object)null)
					{
						Physics.IgnoreCollision(component, collider, true);
					}
					return false;
				}
				WarriorAI cached2 = WarriorAI.GetCached(val2);
				if ((Object)(object)cached2 != (Object)null && cached2.Side == cached.Side)
				{
					Collider component2 = ((Component)__instance).GetComponent<Collider>();
					if ((Object)(object)component2 != (Object)null && (Object)(object)collider != (Object)null)
					{
						Physics.IgnoreCollision(component2, collider, true);
					}
					return false;
				}
				if ((Object)(object)cached2 != (Object)null || val2 is Player)
				{
					EmbedArrowInTarget(__instance, val2, hitPoint);
				}
			}
			return true;
		}

		private static void EmbedArrowInTarget(Projectile projectile, Character target, Vector3 hitPoint)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform val = null;
				FieldInfo fieldInfo = AccessTools.Field(typeof(Projectile), "m_visual");
				if (fieldInfo != null)
				{
					object? value = fieldInfo.GetValue(projectile);
					GameObject val2 = (GameObject)((value is GameObject) ? value : null);
					if ((Object)(object)val2 != (Object)null)
					{
						val = val2.transform;
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					MeshRenderer componentInChildren = ((Component)projectile).GetComponentInChildren<MeshRenderer>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						val = ((Component)componentInChildren).transform;
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Transform val3 = FindNearestBone(target, hitPoint);
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = ((Component)target).transform;
				}
				GameObject val4 = Object.Instantiate<GameObject>(((Component)val).gameObject);
				((Object)val4).name = "BB_StuckArrow";
				val4.transform.SetParent(val3, true);
				val4.transform.position = hitPoint;
				val4.transform.rotation = ((Component)projectile).transform.rotation;
				Rigidbody component = val4.GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				Collider[] componentsInChildren = val4.GetComponentsInChildren<Collider>();
				foreach (Collider val5 in componentsInChildren)
				{
					Object.Destroy((Object)(object)val5);
				}
				val4.AddComponent<StuckArrowBehaviour>();
				AllStuckArrows.Add(val4);
				int num = 0;
				for (int num2 = AllStuckArrows.Count - 1; num2 >= 0; num2--)
				{
					if ((Object)(object)AllStuckArrows[num2] == (Object)null)
					{
						AllStuckArrows.RemoveAt(num2);
					}
					else if (AllStuckArrows[num2].transform.IsChildOf(((Component)target).transform))
					{
						num++;
						if (num > 10)
						{
							Object.Destroy((Object)(object)AllStuckArrows[num2]);
							AllStuckArrows.RemoveAt(num2);
						}
					}
				}
			}
			catch (Exception ex)
			{
				BigBattlesPlugin.LogErr("EmbedArrowInTarget error: " + ex.Message);
			}
		}

		private static Transform FindNearestBone(Character character, Vector3 worldPoint)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			SkinnedMeshRenderer componentInChildren = ((Component)character).GetComponentInChildren<SkinnedMeshRenderer>();
			if ((Object)(object)componentInChildren == (Object)null || componentInChildren.bones == null || componentInChildren.bones.Length == 0)
			{
				return ((Component)character).transform;
			}
			Transform val = null;
			float num = float.MaxValue;
			Transform[] bones = componentInChildren.bones;
			foreach (Transform val2 in bones)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					float num2 = Vector3.SqrMagnitude(val2.position - worldPoint);
					if (num2 < num)
					{
						num = num2;
						val = val2;
					}
				}
			}
			return val ?? ((Component)character).transform;
		}

		public static void CleanupAllStuckArrows()
		{
			for (int num = AllStuckArrows.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)AllStuckArrows[num] != (Object)null)
				{
					Object.Destroy((Object)(object)AllStuckArrows[num]);
				}
			}
			AllStuckArrows.Clear();
		}
	}
	[HarmonyPatch(typeof(BaseAI), "DoProjectileHitNoise")]
	public static class DoProjectileHitNoise_NullGuard
	{
		private static bool Prefix(Character attacker)
		{
			return (Object)(object)attacker != (Object)null;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "OnRagdollCreated")]
	public static class OnRagdollCreated_TransferArrows
	{
		private static void Postfix(Humanoid __instance, Ragdoll ragdoll)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)ragdoll == (Object)null || (Object)(object)WarriorAI.GetCached((Character)(object)__instance) == (Object)null)
			{
				return;
			}
			try
			{
				SkinnedMeshRenderer componentInChildren = ((Component)__instance).GetComponentInChildren<SkinnedMeshRenderer>();
				SkinnedMeshRenderer componentInChildren2 = ((Component)ragdoll).GetComponentInChildren<SkinnedMeshRenderer>();
				if (((componentInChildren != null) ? componentInChildren.bones : null) == null || ((componentInChildren2 != null) ? componentInChildren2.bones : null) == null)
				{
					return;
				}
				Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>();
				Transform[] bones = componentInChildren2.bones;
				foreach (Transform val in bones)
				{
					if ((Object)(object)val != (Object)null && !dictionary.ContainsKey(((Object)val).name))
					{
						dictionary[((Object)val).name] = val;
					}
				}
				float num = 1f;
				float x = ((Component)__instance).transform.lossyScale.x;
				float x2 = ((Component)ragdoll).transform.lossyScale.x;
				if (x > 0.01f && x2 > 0.01f)
				{
					num = x2 / x;
				}
				int num2 = 0;
				Transform[] bones2 = componentInChildren.bones;
				foreach (Transform val2 in bones2)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					for (int num3 = val2.childCount - 1; num3 >= 0; num3--)
					{
						Transform child = val2.GetChild(num3);
						if (!((Object)(object)child == (Object)null) && ((Object)child).name.StartsWith("BB_StuckArrow") && dictionary.TryGetValue(((Object)val2).name, out var value))
						{
							GameObject val3 = Object.Instantiate<GameObject>(((Component)child).gameObject, value);
							val3.transform.localPosition = child.localPosition * num;
							val3.transform.localRotation = child.localRotation;
							((Object)val3).name = "BB_StuckArrow_Ragdoll";
							StuckArrowBehaviour component = val3.GetComponent<StuckArrowBehaviour>();
							if ((Object)(object)component != (Object)null)
							{
								Object.Destroy((Object)(object)component);
							}
							ProjectileOnHit_FriendlyPassthrough.AllStuckArrows.Add(val3);
							num2++;
						}
					}
				}
				for (int num4 = ((Component)__instance).transform.childCount - 1; num4 >= 0; num4--)
				{
					Transform child2 = ((Component)__instance).transform.GetChild(num4);
					if (!((Object)(object)child2 == (Object)null) && ((Object)child2).name.StartsWith("BB_StuckArrow"))
					{
						child2.SetParent(((Component)ragdoll).transform, true);
						StuckArrowBehaviour component2 = ((Component)child2).GetComponent<StuckArrowBehaviour>();
						if ((Object)(object)component2 != (Object)null)
						{
							Object.Destroy((Object)(object)component2);
						}
						num2++;
					}
				}
				if (num2 > 0)
				{
					BigBattlesPlugin.Log($"Transferred {num2} stuck arrows to ragdoll.");
				}
			}
			catch (Exception ex)
			{
				BigBattlesPlugin.LogErr("Arrow ragdoll transfer error: " + ex.Message);
			}
		}
	}
	public static class Patches
	{
		[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
		{
			typeof(Character),
			typeof(Character)
		})]
		public static class IsEnemy_Patch
		{
			private static void Postfix(Character a, Character b, ref bool __result)
			{
				WarriorAI cached = WarriorAI.GetCached(a);
				WarriorAI cached2 = WarriorAI.GetCached(b);
				if (!((Object)(object)cached == (Object)null) || !((Object)(object)cached2 == (Object)null))
				{
					if ((Object)(object)cached != (Object)null && (Object)(object)cached2 != (Object)null && cached.Side == cached2.Side)
					{
						__result = false;
					}
					else if ((Object)(object)cached != (Object)null && (Object)(object)cached2 != (Object)null && cached.Side != cached2.Side)
					{
						__result = !BattleController.DangerMode;
					}
					else if (((Object)(object)cached != (Object)null && b is Player) || (a is Player && (Object)(object)cached2 != (Object)null))
					{
						__result = true;
					}
					else if (((Object)(object)cached != (Object)null && (Object)(object)cached2 == (Object)null && !(b is Player)) || ((Object)(object)cached2 != (Object)null && (Object)(object)cached == (Object)null && !(a is Player)))
					{
						__result = false;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Character), "Damage")]
		public static class Damage_Patch
		{
			private static bool Prefix(Character __instance, HitData hit)
			{
				//IL_0268: Unknown result type (might be due to invalid IL or missing references)
				//IL_026d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0288: Unknown result type (might be due to invalid IL or missing references)
				//IL_028d: Unknown result type (might be due to invalid IL or missing references)
				WarriorAI cached = WarriorAI.GetCached(__instance);
				if ((Object)(object)cached == (Object)null)
				{
					return true;
				}
				Character attacker = hit.GetAttacker();
				if ((Object)(object)attacker != (Object)null)
				{
					WarriorAI cached2 = WarriorAI.GetCached(attacker);
					if ((Object)(object)cached2 != (Object)null && cached2.Side == cached.Side)
					{
						return false;
					}
				}
				if ((Object)(object)attacker == (Object)null)
				{
					return false;
				}
				if ((Object)(object)WarriorAI.GetCached(attacker) == (Object)null && !(attacker is Player))
				{
					return false;
				}
				float value = BigBattlesPlugin.BlockChance.Value;
				if (value > 0f && hit.m_damage.m_damage < 999f && Random.value < value)
				{
					try
					{
						Humanoid component = ((Component)__instance).GetComponent<Humanoid>();
						if ((Object)(object)component != (Object)null)
						{
							MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "BlockAttack", (Type[])null, (Type[])null);
							if (methodInfo != null)
							{
								methodInfo.Invoke(component, new object[2] { hit, attacker });
							}
						}
					}
					catch
					{
					}
					return false;
				}
				if (BigBattlesPlugin.EqualDamage.Value)
				{
					float value2 = BigBattlesPlugin.NormalizedDamagePerHit.Value;
					float health = __instance.GetHealth();
					float num = health - value2;
					if (num <= 0f)
					{
						hit.m_damage.m_damage = health + 1f;
						hit.m_damage.m_blunt = 0f;
						hit.m_damage.m_slash = 0f;
						hit.m_damage.m_pierce = 0f;
						hit.m_damage.m_chop = 0f;
						hit.m_damage.m_pickaxe = 0f;
						hit.m_damage.m_fire = 0f;
						hit.m_damage.m_frost = 0f;
						hit.m_damage.m_lightning = 0f;
						hit.m_damage.m_poison = 0f;
						hit.m_damage.m_spirit = 0f;
						return true;
					}
					__instance.SetHealth(num);
					try
					{
						Humanoid component2 = ((Component)__instance).GetComponent<Humanoid>();
						if (((Character)(component2?)).m_hitEffects != null && hit.m_point != Vector3.zero)
						{
							((Character)component2).m_hitEffects.Create(hit.m_point, Quaternion.identity, ((Component)__instance).transform, 1f, -1);
						}
					}
					catch
					{
					}
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "GetSkillFactor")]
		public static class WarriorSkillProficiency_Patch
		{
			private static bool Prefix(Character __instance, ref float __result)
			{
				if ((Object)(object)WarriorAI.GetCached(__instance) != (Object)null)
				{
					__result = 1f;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "RaiseSkill")]
		public static class WarriorNoSkillRaise_Patch
		{
			private static bool Prefix(Character __instance)
			{
				if ((Object)(object)WarriorAI.GetCached(__instance) != (Object)null)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "HaveEitr")]
		public static class WarriorInfiniteEitr_Patch
		{
			private static bool Prefix(Character __instance, ref bool __result)
			{
				if ((Object)(object)WarriorAI.GetCached(__instance) != (Object)null)
				{
					__result = true;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "UseEitr")]
		public static class WarriorNoEitrCost_Patch
		{
			private static bool Prefix(Character __instance)
			{
				if ((Object)(object)WarriorAI.GetCached(__instance) != (Object)null)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "UseStamina")]
		public static class WarriorNoStaminaCost_Patch
		{
			private static bool Prefix(Character __instance)
			{
				if ((Object)(object)WarriorAI.GetCached(__instance) != (Object)null)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "HaveStamina")]
		public static class WarriorInfiniteStamina_Patch
		{
			private static bool Prefix(Character __instance, ref bool __result)
			{
				if ((Object)(object)WarriorAI.GetCached(__instance) != (Object)null)
				{
					__result = true;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(CharacterDrop), "OnDeath")]
		public static class NoLootDrop_Patch
		{
			private static bool Prefix(CharacterDrop __instance)
			{
				Character component = ((Component)__instance).GetComponent<Character>();
				if ((Object)(object)component != (Object)null && (Object)(object)WarriorAI.GetCached(component) != (Object)null)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "OnDeath")]
		public static class WarriorDeathPosition_Patch
		{
			private static void Prefix(Character __instance)
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)WarriorAI.GetCached(__instance) != (Object)null)
				{
					WarriorManager.RecordDeathPosition(((Component)__instance).transform.position);
				}
			}
		}

		[HarmonyPatch(typeof(Ragdoll), "Awake")]
		public static class RagdollPersist_Patch
		{
			private static void Postfix(Ragdoll __instance)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				if (!BigBattlesPlugin.PersistentBodies.Value)
				{
					return;
				}
				Vector3 position = ((Component)__instance).transform.position;
				List<Vector3> deathPositions = WarriorManager.GetDeathPositions();
				bool flag = false;
				for (int i = 0; i < deathPositions.Count; i++)
				{
					if (Vector3.Distance(position, deathPositions[i]) < 5f)
					{
						((MonoBehaviour)__instance).CancelInvoke("DestroyNow");
						__instance.m_ttl = 99999f;
						flag = true;
						break;
					}
				}
			}
		}

		[HarmonyPatch(typeof(TimedDestruction), "Awake")]
		public static class BloodSlowFade_Patch
		{
			private static void Postfix(TimedDestruction __instance)
			{
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				//IL_016c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0171: Unknown result type (might be due to invalid IL or missing references)
				//IL_0176: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: 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)
				if (!BigBattlesPlugin.PersistentBodies.Value || (Object)(object)WarriorManager.Instance == (Object)null || (WarriorManager.Instance.ArmyA.Count == 0 && WarriorManager.Instance.ArmyB.Count == 0))
				{
					return;
				}
				Vector3 position = ((Component)__instance).transform.position;
				bool flag = false;
				foreach (WarriorAI item in WarriorManager.Instance.ArmyA)
				{
					if ((Object)(object)item != (Object)null && Vector3.SqrMagnitude(position - ((Component)item).transform.position) < 225f)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					foreach (WarriorAI item2 in WarriorManager.Instance.ArmyB)
					{
						if ((Object)(object)item2 != (Object)null && Vector3.SqrMagnitude(position - ((Component)item2).transform.position) < 225f)
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					List<Vector3> deathPositions = WarriorManager.GetDeathPositions();
					for (int i = 0; i < deathPositions.Count; i++)
					{
						if (Vector3.SqrMagnitude(position - deathPositions[i]) < 225f)
						{
							flag = true;
							break;
						}
					}
				}
				if (flag)
				{
					__instance.m_timeout = 300f;
				}
			}
		}

		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		public static class GameCameraUpdate_Patch
		{
			private static bool Prefix()
			{
				if ((Object)(object)BattleMenu.Instance != (Object)null && BattleMenu.Instance.IsMenuOpen)
				{
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Player), "TakeInput")]
		public static class PlayerTakeInput_Patch
		{
			private static bool Prefix(ref bool __result)
			{
				if ((Object)(object)BattleMenu.Instance != (Object)null && BattleMenu.Instance.IsMenuOpen)
				{
					__result = false;
					return false;
				}
				if ((Object)(object)PlacementSystem.Instance != (Object)null && PlacementSystem.Instance.IsActive)
				{
					__result = false;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		public static class BlockAttackWhenMenuOpen_Patch
		{
			private static bool Prefix(Humanoid __instance)
			{
				if (__instance is Player)
				{
					if ((Object)(object)BattleMenu.Instance != (Object)null && BattleMenu.Instance.IsMenuOpen)
					{
						return false;
					}
					if ((Object)(object)BattleMenu.Instance != (