Decompiled source of BigBattles v1.0.0

BigBattles.dll

Decompiled 2 days 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")]
[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 NpcTypeDefinition(string displayName, string prefabName, NpcCategory category, bool supportsEquipment, float defaultHealth, float scale = 1f)
		{
			DisplayName = displayName;
			PrefabName = prefabName;
			Category = category;
			SupportsEquipment = supportsEquipment;
			DefaultHealth = defaultHealth;
			Scale = scale;
		}
	}
	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[31]
		{
			"SwordBronze", "SwordIron", "SwordSilver", "SwordBlackmetal", "SwordMistwalker", "SwordNiedhogg", "MaceBronze", "MaceIron", "MaceSilver", "MaceNeedle",
			"MaceStagbreaker", "AxeBronze", "AxeIron", "AxeBlackMetal", "AxeJotunBane", "KnifeFlint", "KnifeCopper", "KnifeChitin", "KnifeSilver", "KnifeBlackMetal",
			"KnifeSkollAndHati", "Club", "SledgeStagbreaker", "FistFenrirClaw", "SpearFlint", "SpearBronze", "SpearElderbark", "SpearWolfFang", "SpearChitin", "SpearCarapace",
			"Splitnir"
		};

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

		public void ApplyDefaults()
		{
			if (!DefaultsApplied && EquipmentData.IsReady)
			{
				DefaultsApplied = true;
				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()
		{
			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);
					break;
				case 1:
					EquipmentSlots[i] = PickFromSafeList(listForSlot, SafeChests);
					break;
				case 2:
					EquipmentSlots[i] = PickFromSafeList(listForSlot, SafeLegs);
					break;
				case 3:
					if (Side == ArmySide.A)
					{
						EquipmentSlots[i] = EquipmentData.FindIndexByName(3, "#0 Red");
					}
					else
					{
						EquipmentSlots[i] = EquipmentData.FindIndexByName(3, "#1 White");
					}
					break;
				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:
				{
					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)
		};
	}
	public class BattleController : MonoBehaviour
	{
		public enum BattleState
		{
			Idle,
			Active,
			Paused
		}

		private bool victoryAnnounced;

		public static BattleController Instance { get; private set; }

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


		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);
			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))
			{
				WarriorAI.ResetTargetTracking();
				instance.DespawnAll();
				CurrentState = BattleState.Idle;
				BattleDuration = 0f;
				victoryAnnounced = false;
				ShowMsg("Battle reset. All warriors removed.");
			}
		}

		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 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 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;

		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_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: 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_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: 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);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool flag = Time.timeScale < 0.01f;
			Color backgroundColor = 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 = backgroundColor;
			bool value = BigBattlesPlugin.EqualDamage.Value;
			Color backgroundColor2 = GUI.backgroundColor;
			if (value)
			{
				GUI.backgroundColor = new Color(0.4f, 1f, 0.5f);
			}
			if (GUILayout.Button(value ? "EQUAL DMG: ON" : "EQUAL DMG: OFF", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
			{
				BigBattlesPlugin.EqualDamage.Value = !value;
			}
			GUI.backgroundColor = backgroundColor2;
			GUILayout.EndHorizontal();
			GUILayout.Space(2f);
			int num = instance?.ArmyAAlive ?? 0;
			int num2 = instance?.ArmyBAlive ?? 0;
			string text = instance?.GetDurationString() ?? "00:00";
			string text2 = battleState.ToString().ToUpper();
			GUILayout.Label($"{text2} | {text} | A:{num} B:{num2}", 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);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Type:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			if (GUILayout.Button("<", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }))
			{
				config.SelectedNpcType--;
				if (config.SelectedNpcType < 0)
				{
					config.SelectedNpcType = NpcTypes.All.Count - 1;
				}
			}
			NpcTypeDefinition npcTypeDefinition = NpcTypes.All[config.SelectedNpcType];
			GUILayout.Label(npcTypeDefinition.DisplayName, labelStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(">", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(24f) }))
			{
				config.SelectedNpcType++;
				if (config.SelectedNpcType >= NpcTypes.All.Count)
				{
					config.SelectedNpcType = 0;
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(2f);
			if (npcTypeDefinition.SupportsEquipment && EquipmentData.IsReady)
			{
				config.ApplyDefaults();
				bool flag = IsWeaponTwoHanded(config);
				if (flag)
				{
					config.EquipmentSlots[5] = 0;
				}
				for (int i = 0; i < 6; i++)
				{
					if (i == 5 && flag)
					{
						DrawSlotRowDisabled(config, i, "(Two-Handed)");
					}
					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 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_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Expected O, but got Unknown
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Expected O, but got Unknown
			//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_046f: Expected O, but got Unknown
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_048d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: 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 = 10,
					alignment = (TextAnchor)4
				};
				val7.normal.textColor = new Color(0.5f, 0.45f, 0.35f);
				closeHintStyle = val7;
				GUIStyle val8 = new GUIStyle(buttonStyle)
				{
					fontSize = 11
				};
				val8.normal.background = slotBtnTex;
				val8.normal.textColor = new Color(0.85f, 0.8f, 0.7f);
				val8.hover.background = slotBtnHoverTex;
				val8.hover.textColor = Color.white;
				slotButtonStyle = val8;
				browseItemStyle = new GUIStyle(buttonStyle)
				{
					fontSize = 11,
					alignment = (TextAnchor)3
				};
				GUIStyle val9 = new GUIStyle(browseItemStyle);
				val9.normal.background = btnActiveTex;
				val9.normal.textColor = new Color(1f, 0.9f, 0.5f);
				browseItemActiveStyle = val9;
			}
		}

		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)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>(count);
			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 num = columns * rows;
			if (count > num)
			{
				count = num;
			}
			for (int i = 0; i < count; i++)
			{
				int num2 = i / columns;
				int num3 = i % columns;
				float num4 = ((float)num3 - (float)(columns - 1) * 0.5f) * spacing;
				float num5 = (float)(-num2) * spacing;
				Vector3 pos = center + normalized * num4 + facing * num5;
				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;
		}
	}
	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 = true;
					}
					else if (((Object)(object)cached != (Object)null && b is Player) || (a is Player && (Object)(object)cached2 != (Object)null))
					{
						__result = false;
					}
					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)
			{
				WarriorAI cached = WarriorAI.GetCached(__instance);
				if ((Object)(object)cached == (Object)null)
				{
					return true;
				}
				Character attacker = hit.GetAttacker();
				if (attacker is Player)
				{
					return false;
				}
				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)
				{
					return false;
				}
				float value = BigBattlesPlugin.BlockChance.Value;
				if (value > 0f && 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, __instance });
							}
						}
					}
					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);
					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_002b: 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)
				if (!BigBattlesPlugin.PersistentBodies.Value)
				{
					return;
				}
				Vector3 position = ((Component)__instance).transform.position;
				List<Vector3> deathPositions = WarriorManager.GetDeathPositions();
				for (int i = 0; i < deathPositions.Count; i++)
				{
					if (Vector3.Distance(position, deathPositions[i]) < 5f)
					{
						((MonoBehaviour)__instance).CancelInvoke("DestroyNow");
						__instance.m_ttl = 99999f;
						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 != (Object)null && BattleMenu.Instance.MenuCloseCooldownActive)
					{
						return false;
					}
					if ((Object)(object)PlacementSystem.Instance != (Object)null && PlacementSystem.Instance.IsActive)
					{
						return false;
					}
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Game), "OnDestroy")]
		public static class GameCleanup_Patch
		{
			private static void Prefix()
			{
				WarriorManager.Instance?.DespawnAll();
				WarriorManager.Instance?.ResetPrefabState();
				BattleMenu.Instance?.ResetConfigs();
				BigBattlesPlugin.Log("World unloading — all warriors despawned.");
			}
		}
	}
	public class PlacementSystem : MonoBehaviour
	{
		private ArmyConfig currentConfig;

		private NpcTypeDefinition currentNpcType;

		private bool randomPerWarrior;

		private GameObject groundIndicator;

		private MeshRenderer indicatorRenderer;

		private Material indicatorMatA;

		private Material indicatorMatB;

		private List<GameObject> previewMarkers = new List<GameObject>();

		private static Mesh s_cachedCylinderMesh;

		private Vector3 lastHitPoint;

		private bool hasValidHit;

		private bool wasCursorVisible;

		private CursorLockMode wasCursorLock;

		private int groundMask;

		public static PlacementSystem Instance { get; private set; }

		public bool IsActive { get; private set; }

		public ArmySide PlacingSide { get; private set; }

		public bool IndividualMode { get; private set; }

		private void Awake()
		{
			Instance = this;
			groundMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "terrain", "piece" });
		}

		public void EnterPlacementMode(ArmySide side, bool individual, ArmyConfig config, NpcTypeDefinition npcType, bool randomizePerWarrior = false)
		{
			//IL_005d: 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)
			PlacingSide = side;
			IndividualMode = individual;
			currentConfig = config;
			currentNpcType = npcType;
			randomPerWarrior = randomizePerWarrior;
			IsActive = true;
			if ((Object)(object)BattleMenu.Instance != (Object)null)
			{
				BattleMenu.Instance.ForceClose();
			}
			CreateIndicator();
			wasCursorVisible = Cursor.visible;
			wasCursorLock = Cursor.lockState;
			Cursor.visible = true;
			Cursor.lockState = (CursorLockMode)0;
			ShowMsg($"Click to place Army {side}. Right-click or Escape to cancel.");
		}

		public void ExitPlacementMode()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			IsActive = false;
			DestroyVisuals();
			Cursor.visible = wasCursorVisible;
			Cursor.lockState = wasCursorLock;
		}

		private void Update()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			if (!IsActive)
			{
				return;
			}
			if (Input.GetMouseButtonDown(1) || Input.GetKeyDown((KeyCode)27))
			{
				ExitPlacementMode();
				return;
			}
			hasValidHit = RaycastGround(out lastHitPoint);
			if (hasValidHit && (Object)(object)groundIndicator != (Object)null)
			{
				groundIndicator.SetActive(true);
				groundIndicator.transform.position = lastHitPoint + Vector3.up * 0.05f;
				((Renderer)indicatorRenderer).material = ((PlacingSide == ArmySide.A) ? indicatorMatA : indicatorMatB);
			}
			else if ((Object)(object)groundIndicator != (Object)null)
			{
				groundIndicator.SetActive(false);
			}
			if (!IndividualMode && hasValidHit)
			{
				UpdateFormationPreview();
			}
			if (Input.GetMouseButtonDown(0) && hasValidHit)
			{
				OnPlacementClick(lastHitPoint);
			}
		}

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

		private bool RaycastGround(out Vector3 hitPoint)
		{
			//IL_0002: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			hitPoint = Vector3.zero;
			Camera val = (((Object)(object)GameCamera.instance != (Object)null) ? ((Component)GameCamera.instance).GetComponent<Camera>() : Camera.main);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Ray val2 = val.ScreenPointToRay(Input.mousePosition);
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val2, ref val3, 200f, groundMask))
			{
				hitPoint = ((RaycastHit)(ref val3)).point;
				return true;
			}
			return false;
		}

		private void OnPlacementClick(Vector3 groundPos)
		{
			//IL_0091: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_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_00bd: 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)
			//IL_0068: 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_0154: Unknown result type (might be due to invalid IL or missing references)
			if (currentNpcType == null || currentConfig == null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (IndividualMode)
			{
				Vector3 spawnFacing = GetSpawnFacing(groundPos);
				Quaternion rotation = Quaternion.LookRotation(spawnFacing);
				WarriorManager.Instance?.SpawnWarrior(PlacingSide, currentNpcType, groundPos, rotation);
				if (currentNpcType.SupportsEquipment)
				{
					ApplyEquipmentToLastWarrior();
				}
				return;
			}
			Vector3 spawnFacing2 = GetSpawnFacing(groundPos);
			int spawnCount = currentConfig.SpawnCount;
			WarriorManager.Instance?.SpawnFormation(PlacingSide, currentNpcType, groundPos, spawnFacing2, spawnCount);
			if (currentNpcType.SupportsEquipment)
			{
				if (randomPerWarrior)
				{
					ApplyRandomEquipmentPerWarrior();
				}
				else
				{
					ApplyEquipmentToArmy();
				}
			}
			WarriorManager instance = WarriorManager.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				if (instance.GetArmyCount(ArmySide.A) > 0 && instance.GetArmyCount(ArmySide.B) > 0)
				{
					instance.FaceArmiesAtEachOther();
				}
				else if ((Object)(object)localPlayer != (Object)null)
				{
					instance.FaceArmyToward(PlacingSide, ((Component)localPlayer).transform.position);
				}
			}
			ExitPlacementMode();
		}

		private void ApplyEquipmentToArmy()
		{
			if (currentConfig != null && EquipmentData.IsReady)
			{
				EquipmentData.ItemEntry[] items = BuildEquipmentArray(currentConfig);
				WarriorManager.Instance?.ApplyEquipment(PlacingSide, items);
			}
		}

		private void ApplyRandomEquipmentPerWarrior()
		{
			if (!EquipmentData.IsReady)
			{
				return;
			}
			List<WarriorAI> list = WarriorManager.Instance?.GetArmy(PlacingSide);
			if (list == null)
			{
				return;
			}
			ArmyConfig armyConfig = new ArmyConfig(PlacingSide);
			foreach (WarriorAI item in list)
			{
				if (!((Object)(object)item == (Object)null))
				{
					armyConfig.RandomizeEquipment();
					EquipmentData.ItemEntry[] items = BuildEquipmentArray(armyConfig);
					WarriorManager.Instance?.ApplyEquipmentToSingle(item, items);
				}
			}
			BigBattlesPlugin.Log($"Applied random loadouts to {list.Count} warriors in Army {PlacingSide}.");
		}

		private void ApplyEquipmentToLastWarrior()
		{
			if (currentConfig == null || !EquipmentData.IsReady)
			{
				return;
			}
			List<WarriorAI> list = WarriorManager.Instance?.GetArmy(PlacingSide);
			if (list != null && list.Count != 0)
			{
				WarriorAI warriorAI = list[list.Count - 1];
				if (!((Object)(object)warriorAI == (Object)null))
				{
					EquipmentData.ItemEntry[] items = BuildEquipmentArray(currentConfig);
					WarriorManager.Instance?.ApplyEquipmentToSingle(warriorAI, items);
				}
			}
		}

		public static EquipmentData.ItemEntry[] BuildEquipmentArray(ArmyConfig config)
		{
			EquipmentData.ItemEntry[] array = new EquipmentData.ItemEntry[6];
			for (int i = 0; i < 6; i++)
			{
				List<EquipmentData.ItemEntry> listForSlot = EquipmentData.GetListForSlot(i);
				int num = config.EquipmentSlots[i];
				if (num >= 0 && num < listForSlot.Count)
				{
					array[i] = listForSlot[num];
					continue;
				}
				array[i] = new EquipmentData.ItemEntry
				{
					PrefabName = "",
					DisplayName = "",
					Variant = 0
				};
			}
			return array;
		}

		private void UpdateFormationPreview()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_014d: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Vector3 spawnFacing = GetSpawnFacing(lastHitPoint);
			int count = currentConfig?.SpawnCount ?? 40;
			int value = BigBattlesPlugin.FormationColumns.Value;
			int value2 = BigBattlesPlugin.FormationRows.Value;
			float value3 = BigBattlesPlugin.FormationSpacing.Value;
			List<Vector3> positions = FormationCalculator.GetPositions(lastHitPoint, spawnFacing, count, value, value2, value3);
			while (previewMarkers.Count < positions.Count)
			{
				AddPreviewMarker();
			}
			Color color = ((PlacingSide == ArmySide.A) ? new Color(1f, 0.3f, 0.3f, 0.3f) : new Color(0.3f, 1f, 0.3f, 0.3f));
			for (int i = 0; i < positions.Count; i++)
			{
				previewMarkers[i].transform.position = positions[i] + Vector3.up * 0.1f;
				previewMarkers[i].SetActive(true);
				MeshRenderer component = previewMarkers[i].GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).material.color = color;
				}
			}
			for (int j = positions.Count; j < previewMarkers.Count; j++)
			{
				previewMarkers[j].SetActive(false);
			}
		}

		private static Mesh GetCachedCylinderMesh()
		{
			if ((Object)(object)s_cachedCylinderMesh == (Object)null)
			{
				GameObject val = GameObject.CreatePrimitive((PrimitiveType)2);
				s_cachedCylinderMesh = val.GetComponent<MeshFilter>().sharedMesh;
				Object.Destroy((Object)(object)val);
			}
			return s_cachedCylinderMesh;
		}

		private void AddPreviewMarker()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0032: 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_0059: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("BB_PreviewMarker");
			val.AddComponent<MeshFilter>().sharedMesh = GetCachedCylinderMesh();
			val.transform.localScale = new Vector3(0.5f, 0.05f, 0.5f);
			MeshRenderer val2 = val.AddComponent<MeshRenderer>();
			((Renderer)val2).material = new Material(Shader.Find("Sprites/Default"));
			((Renderer)val2).material.color = new Color(1f, 0.3f, 0.3f, 0.3f);
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			previewMarkers.Add(val);
		}

		private void CreateIndicator()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)groundIndicator != (Object)null))
			{
				groundIndicator = new GameObject("BB_GroundIndicator");
				groundIndicator.AddComponent<MeshFilter>().sharedMesh = GetCachedCylinderMesh();
				groundIndicator.transform.localScale = new Vector3(3f, 0.02f, 3f);
				indicatorRenderer = groundIndicator.AddComponent<MeshRenderer>();
				Shader val = Shader.Find("Sprites/Default");
				indicatorMatA = new Material(val);
				indicatorMatA.color = new Color(1f, 0.3f, 0.3f, 0.4f);
				indicatorMatB = new Material(val);
				indicatorMatB.color = new Color(0.3f, 1f, 0.3f, 0.4f);
				((Renderer)indicatorRenderer).material = ((PlacingSide == ArmySide.A) ? indicatorMatA : indicatorMatB);
				((Renderer)indicatorRenderer).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)indicatorRenderer).receiveShadows = false;
			}
		}

		private void DestroyVisuals()
		{
			if ((Object)(object)groundIndicator != (Object)null)
			{
				Object.Destroy((Object)(object)groundIndicator);
				groundIndicator = null;
			}
			if ((Object)(object)indicatorMatA != (Object)null)
			{
				Object.Destroy((Object)(object)indicatorMatA);
				indicatorMatA = null;
			}
			if ((Object)(object)indicatorMatB != (Object)null)
			{
				Object.Destroy((Object)(object)indicatorMatB);
				indicatorMatB = null;
			}
			foreach (GameObject previewMarker in previewMarkers)
			{
				if ((Object)(object)previewMarker != (Object)null)
				{
					MeshRenderer component = previewMarker.GetComponent<MeshRenderer>();
					if ((Object)(object)component != (Object)null && (Object)(object)((Renderer)component).material != (Object)null)
					{
						Object.Destroy((Object)(object)((Renderer)component).material);
					}
					Object.Destroy((Object)(object)previewMarker);
				}
			}
			previewMarkers.Clear();
		}

		private void OnDestroy()
		{
			DestroyVisuals();
		}

		private Vector3 GetSpawnFacing(Vector3 groundPos)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//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_0053: 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_005f: 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_00aa: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return Vector3.forward;
			}
			Vector3 val = groundPos - ((Component)localPlayer).transform.position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude > 1f)
			{
				return -((Vector3)(ref val)).normalized;
			}
			Vector3 val2 = -((Component)localPlayer).transform.forward;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
			{
				return ((Vector3)(ref val2)).normalized;
			}
			return Vector3.forward;
		}

		private void ShowMsg(string text)
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
			}
		}
	}
	[BepInPlugin("com.mitch.bigbattles", "Big Battles", "1.0.0")]
	public class BigBattlesPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.mitch.bigbattles";

		public const string PluginName = "Big Battles";

		public const string PluginVersion = "1.0.0";

		public static ConfigEntry<KeyCode> MenuKey;

		public static ConfigEntry<int> MaxPerSide;

		public static ConfigEntry<int> FormationColumns;

		public static ConfigEntry<int> FormationRows;

		public static ConfigEntry<float> FormationSpacing;

		public static ConfigEntry<float> HumanHealth;

		public static ConfigEntry<float> HumanWalkSpeed;

		public static ConfigEntry<float> HumanRunSpeed;

		public static ConfigEntry<float> HumanScale;

		public static ConfigEntry<bool> EqualDamage;

		public static ConfigEntry<float> NormalizedDamagePerHit;

		public static ConfigEntry<float> BlockChance;

		public static ConfigEntry<bool> PersistentBodies;

		private Harmony harmony;

		public static BigBattlesPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Expected O, but got Unknown
			Instance = this;
			MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "MenuKey", (KeyCode)107, "Key to open/close the BigBattles battle panel.");
			MaxPerSide = ((BaseUnityPlugin)this).Config.Bind<int>("Army", "MaxPerSide", 80, new ConfigDescription("Maximum NPCs per army side.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 80), Array.Empty<object>()));
			FormationColumns = ((BaseUnityPlugin)this).Config.Bind<int>("Army", "FormationColumns", 8, "Number of columns in the spawn grid.");
			FormationRows = ((BaseUnityPlugin)this).Config.Bind<int>("Army", "FormationRows", 10, "Number of rows in the spawn grid.");
			FormationSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Army", "FormationSpacing", 2f, "Meters between NPCs in formation.");
			HumanHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Warriors", "HumanHealth", 1000f, "Health for human warriors.");
			HumanWalkSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Warriors", "HumanWalkSpeed", 2.5f, "Walking speed for human warriors.");
			HumanRunSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Warriors", "HumanRunSpeed", 7f, "Running speed for human warriors.");
			HumanScale = ((BaseUnityPlugin)this).Config.Bind<float>("Warriors", "HumanScale", 0.95f, new ConfigDescription("Scale of human warriors (0.95 compensates for armor bulk).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.7f, 1.2f), Array.Empty<object>()));
			EqualDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "EqualDamage", true, "When enabled, all warriors deal the same damage per hit regardless of weapon.");
			NormalizedDamagePerHit = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "NormalizedDamagePerHit", 100f, new ConfigDescription("Base DPS when EqualDamage is on. Actual per-hit damage scales with weapon speed so fast weapons do less per hit but same DPS.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 500f), Array.Empty<object>()));
			BlockChance = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "BlockChance", 0.2f, new ConfigDescription("Chance (0-1) that a warrior blocks an incoming attack with their shield. 0.20 = 20%.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.8f), Array.Empty<object>()));
			PersistentBodies = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "PersistentBodies", true, "When enabled, dead warrior bodies (ragdolls) stay on the battlefield until manually cleared.");
			harmony = new Harmony("com.mitch.bigbattles");
			try
			{
				harmony.PatchAll();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"All Harmony patches applied.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Harmony PatchAll failed: " + ex.Message));
				((BaseUnityPlugin)this).Logger.LogError((object)"Attempting individual patches...");
				ApplyPatchesSafe();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Big Battles v1.0.0 loaded!");
		}

		private void Start()
		{
			((Component)this).gameObject.AddComponent<WarriorManager>();
			((Component)this).gameObject.AddComponent<BattleController>();
			((Component)this).gameObject.AddComponent<PlacementSystem>();
			((Component)this).gameObject.AddComponent<BattleMenu>();
		}

		private void ApplyPatchesSafe()
		{
			Type[] nestedTypes = typeof(Patches).GetNestedTypes(BindingFlags.Static | BindingFlags.Public);
			Type[] array = nestedTypes;
			foreach (Type type in array)
			{
				try
				{
					harmony.CreateClassProcessor(type).Patch();
					((BaseUnityPlugin)this).Logger.LogInfo((object)("  Patched: " + type.Name));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("  SKIPPED: " + type.Name + " — " + ex.Message));
				}
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		public static void Log(string msg)
		{
			BigBattlesPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)msg);
			}
		}

		public static void LogWarn(string msg)
		{
			BigBattlesPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)msg);
			}
		}

		public static void LogErr(string msg)
		{
			BigBattlesPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)msg);
			}
		}
	}
	public class WarriorAI : BaseAI
	{
		public enum WarriorState
		{
			Idle,
			Charging,
			Fighting
		}

		private static readonly Dictionary<Character, WarriorAI> s_characterToWarrior = new Dictionary<Character, WarriorAI>();

		private Humanoid humanoid;

		private Rigidbody body;

		private Character attackTarget;

		private Vector3 chargeTarget;

		private float scanTimer;

		private float attackCooldown;

		private float visEquipTimer;

		private float pathStuckTimer;

		private Vector3 lastMovePos;

		private bool initialized;

		private Vector3 idleLookAtPos;

		private bool hasIdleLookAt;

		private static readonly Dictionary<Character, int> s_targetCounts = new Dictionary<Character, int>();

		private const float SPREAD_PENALTY = 12f;

		private const int MAX_PER_TARGET = 3;

		private const float PROXIMITY_PENALTY = 8f;

		private WarriorState stateBeforePause;

		private Character targetBeforePause;

		private int frameCounter;

		private const float AI_FULL_UPDATE_RANGE = 100f;

		private static MethodInfo s_showHandItemsMethod;

		private static bool s_reflectionCached;

		private float cachedWeaponRange = -1f;

		public WarriorState CurrentState { get; set; } = WarriorState.Idle;


		public ArmySide Side { get; private set; }

		public Character MyCharacter { get; private set; }

		public static WarriorAI GetCached(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return null;
			}
			s_characterToWarrior.TryGetValue(c, out var value);
			return value;
		}

		private static void CacheReflection()
		{
			if (!s_reflectionCached)
			{
				s_reflectionCached = true;
				s_showHandItemsMethod = typeof(Humanoid).GetMethod("ShowHandItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
		}

		protected override void Awake()
		{
			((BaseAI)this).Awake();
			humanoid = ((Component)this).GetComponent<Humanoid>();
			body = ((Component)this).GetComponent<Rigidbody>();
			MyCharacter = ((Component)this).GetComponent<Character>();
			CacheReflection();
			if ((Object)(object)MyCharacter != (Object)null)
			{
				s_characterToWarrior[MyCharacter] = this;
			}
		}

		protected virtual void OnDestroy()
		{
			UnregisterTarget();
			if ((Object)(object)MyCharacter != (Object)null)
			{
				s_characterToWarrior.Remove(MyCharacter);
			}
		}

		private void SetTarget(Character newTarget)
		{
			if (!((Object)(object)newTarget == (Object)(object)attackTarget))
			{
				UnregisterTarget();
				attackTarget = newTarget;
				RegisterTarget();
			}
		}

		private void RegisterTarget()
		{
			if (!((Object)(object)attackTarget == (Object)null))
			{
				if (s_targetCounts.ContainsKey(attackTarget))
				{
					s_targetCounts[attackTarget]++;
				}
				else
				{
					s_targetCounts[attackTarget] = 1;
				}
			}
		}

		private void UnregisterTarget()
		{
			if (!((Object)(object)attackTarget == (Object)null) && s_targetCounts.ContainsKey(attackTarget))
			{
				s_targetCounts[attackTarget]--;
				if (s_targetCounts[attackTarget] <= 0)
				{
					s_targetCounts.Remove(attackTarget);
				}
			}
		}

		private static int GetTargetCount(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return 0;
			}
			s_targetCounts.TryGetValue(c, out var value);
			return value;
		}

		public static void ResetTargetTracking()
		{
			s_targetCounts.Clear();
		}

		public void Initialize(ArmySide side, Faction faction)
		{
			//IL_0074: 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)
			Side = side;
			if ((Object)(object)humanoid == (Object)null)
			{
				humanoid = ((Component)this).GetComponent<Humanoid>();
			}
			if ((Object)(object)body == (Object)null)
			{
				body = ((Component)this).GetComponent<Rigidbody>();
			}
			if ((Object)(object)MyCharacter == (Object)null)
			{
				MyCharacter = ((Component)this).GetComponent<Character>();
			}
			if ((Object)(object)humanoid != (Object)null)
			{
				((Character)humanoid).m_faction = faction;
			}
			if ((Object)(object)body != (Object)null)
			{
				body.constraints = (RigidbodyConstraints)112;
			}
			CurrentState = WarriorState.Idle;
			initialized = true;
			scanTimer = Random.Range(0f, 1.5f);
			ResetClothSimulation();
		}

		public override bool UpdateAI(float dt)
		{
			//IL_008d: 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)
			if (!initialized)
			{
				return false;
			}
			try
			{
				if (!((BaseAI)this).UpdateAI(dt))
				{
					return false;
				}
				if ((Object)(object)base.m_character == (Object)null || base.m_character.IsDead())
				{
					return true;
				}
				frameCounter++;
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && frameCounter % 5 != 0)
				{
					float num = Vector3.Distance(((Component)this).transform.position, ((Component)localPlayer).transform.position);
					if (num > 100f)
					{
						return true;
					}
				}
				visEquipTimer -= dt;
				if (visEquipTimer <= 0f)
				{
					visEquipTimer = 2f;
					SyncVisEquipment();
				}
				switch (CurrentState)
				{
				case WarriorState.Idle:
					UpdateIdle();
					break;
				case WarriorState.Charging:
					UpdateCharging(dt);
					break;
				case WarriorState.Fighting:
					UpdateFighting(dt);
					break;
				}
			}
			catch (Exception ex)
			{
				BigBattlesPlugin.LogErr("WarriorAI.UpdateAI error: " + ex.Message);
			}
			return true;
		}

		private void UpdateIdle()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			((BaseAI)this).StopMoving();
			base.m_character.SetMoveDir(Vector3.zero);
			base.m_character.SetRun(false);
			base.m_character.SetWalk(false);
			if (hasIdleLookAt)
			{
				((BaseAI)this).LookAt(idleLookAtPos);
				Vector3 val = idleLookAtPos - ((Component)this).transform.position;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.1f)
				{
					base.m_character.SetLookDir(((Vector3)(ref val)).normalized, 0f);
				}
			}
		}

		public void SetIdleFacing(Vector3 lookAtPosition)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			idleLookAtPos = lookAtPosition;
			hasIdleLookAt = true;
		}

		private void UpdateCharging(float dt)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be du