Decompiled source of Tactics v1.12.0

Tactics.dll

Decompiled 6 hours 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 BepInEx.Logging;
using HarmonyLib;
using Landfall.TABS;
using Landfall.TABS.AI;
using Landfall.TABS.AI.Components;
using Landfall.TABS.AI.Components.Tags;
using Landfall.TABS.AI.Systems;
using Landfall.TABS.GameState;
using Microsoft.CodeAnalysis;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SmarterAI
{
	public class Bootstrap : MonoBehaviour
	{
		private static Bootstrap _instance;

		private SmartTargetingSystem _system;

		public static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("SmarterAI_Bootstrap");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<Bootstrap>();
			}
		}

		private void Update()
		{
			if (_system == null && World.Active != null)
			{
				_system = World.Active.GetOrCreateManager<SmartTargetingSystem>();
			}
		}

		public static bool InBattle()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			GameStateManager service = ServiceLocator.GetService<GameStateManager>();
			if (service != null)
			{
				return (int)service.GameState == 1;
			}
			return false;
		}
	}
	public static class MountUtils
	{
		private static readonly string[] MountNameKeys = new string[5] { "horse", "raptor", "chariot", "elephant", "mammoth" };

		public static string Normalize(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return "";
			}
			return name.ToLowerInvariant().Replace("prefabs_vb", "").Replace("unitbases_vb", "")
				.Replace("(clone)", "")
				.Trim();
		}

		public static bool IsMount(Unit unit)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return false;
			}
			string text = Normalize(((Object)unit).name);
			for (int i = 0; i < MountNameKeys.Length; i++)
			{
				if (text.Contains(MountNameKeys[i]))
				{
					return true;
				}
			}
			try
			{
				if ((Object)(object)unit.unitBlueprint != (Object)null && (Object)(object)unit.unitBlueprint.UnitBase != (Object)null)
				{
					string text2 = Normalize(((Object)unit.unitBlueprint.UnitBase).name);
					for (int j = 0; j < MountNameKeys.Length; j++)
					{
						if (text2.Contains(MountNameKeys[j]))
						{
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Unit), "Start")]
	internal static class UnitStartPatch
	{
		private static void Postfix(Unit __instance)
		{
			if (Plugin.Enabled.Value && !((Object)(object)__instance == (Object)null))
			{
				if ((Object)(object)((Component)__instance).GetComponent<SmartBrain>() == (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<SmartBrain>();
				}
				bool num = MountUtils.IsMount(__instance) || __instance.IsRider;
				float value = Plugin.TurnSpeedMultiplier.Value;
				if (!num && value > 0.01f && value != 1f)
				{
					__instance.turnSpeed *= value;
				}
			}
		}
	}
	[HarmonyPatch(typeof(UnitAPI), "SetAttackTarget")]
	internal static class SetAttackTargetPatch
	{
		private static void Prefix(UnitAPI __instance, float3 targetPos, Rigidbody mainRig, DataHandler unitData, ref TargetData targetData, ref bool canSeeTarget, bool startAttack)
		{
			if (!Plugin.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			Unit component = ((Component)__instance).GetComponent<Unit>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			SmartBrain component2 = ((Component)__instance).GetComponent<SmartBrain>();
			if ((Object)(object)component2 != (Object)null && component2.SuppressAttack)
			{
				canSeeTarget = false;
			}
			bool num = RangedHelper.IsRanged(component, __instance);
			if (num && Plugin.ExtendedFireRange.Value && targetData.TargetInAttackRange == 0)
			{
				float num2 = RangedHelper.GetAttackRange(component, __instance) * Plugin.FireRangeMult.Value;
				if (targetData.DistanceToTarget <= num2)
				{
					targetData.TargetInAttackRange = 1;
					if (component.InRangeAttackCooldown > 0f)
					{
						component.InRangeAttackCooldown = 0f;
					}
				}
			}
			if (((num && Plugin.FriendlyFireCheck.Value) & canSeeTarget) && (Object)(object)mainRig != (Object)null && RangedHelper.FriendlyBlocked(__instance, component, mainRig))
			{
				canSeeTarget = false;
			}
		}
	}
	internal static class RangedHelper
	{
		private static readonly List<Unit> UnitCache = new List<Unit>();

		private static float _nextRefresh;

		public static bool FriendlyBlocked(UnitAPI api, Unit self, Rigidbody targetRig)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			Vector3 rightWeaponPosition = api.GetRightWeaponPosition();
			Vector3 val = targetRig.position - rightWeaponPosition;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.01f)
			{
				return false;
			}
			Vector3 val2 = val / magnitude;
			float value = Plugin.FriendlyObstacleMinDistance.Value;
			float value2 = Plugin.FriendlyBlockRadius.Value;
			Team team = self.Team;
			Transform root = ((Component)self).transform.root;
			List<Unit> units = GetUnits();
			for (int i = 0; i < units.Count; i++)
			{
				Unit val3 = units[i];
				if ((Object)(object)val3 == (Object)null || (Object)(object)val3 == (Object)(object)self || val3.Team != team || (Object)(object)val3.data == (Object)null || (Object)(object)val3.data.mainRig == (Object)null || val3.data.Dead || (Object)(object)((Component)val3).transform.root == (Object)(object)root)
				{
					continue;
				}
				Vector3 position = val3.data.mainRig.position;
				float num = Vector3.Dot(position - rightWeaponPosition, val2);
				if (!(num < value) && !(num > magnitude * Plugin.BlockMaxFraction.Value))
				{
					Vector3 val4 = rightWeaponPosition + val2 * num;
					Vector3 val5 = position - val4;
					val5.y = 0f;
					if (!(Mathf.Abs(position.y - val4.y) > 2f) && ((Vector3)(ref val5)).magnitude < value2)
					{
						Plugin.Dbg("[SmarterAI] shot blocked by friendly " + ((Object)val3).name);
						return true;
					}
				}
			}
			return false;
		}

		public static List<Unit> GetUnits()
		{
			if (Time.time >= _nextRefresh)
			{
				_nextRefresh = Time.time + 0.5f;
				UnitCache.Clear();
				Unit[] array = Object.FindObjectsOfType<Unit>();
				for (int i = 0; i < array.Length; i++)
				{
					UnitCache.Add(array[i]);
				}
			}
			return UnitCache;
		}

		public static bool IsRanged(WeaponHandler wh, UnitAPI api)
		{
			if ((Object)(object)api != (Object)null && api.IsRangedUnit)
			{
				return true;
			}
			if ((Object)(object)wh != (Object)null)
			{
				if ((Object)(object)wh.rightWeapon != (Object)null && wh.rightWeapon.isRange)
				{
					return true;
				}
				if ((Object)(object)wh.leftWeapon != (Object)null && wh.leftWeapon.isRange)
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsRanged(Unit unit, UnitAPI api)
		{
			if ((Object)(object)api == (Object)null)
			{
				return false;
			}
			if (api.IsRangedUnit)
			{
				return true;
			}
			if ((Object)(object)unit != (Object)null && (Object)(object)unit.WeaponHandler != (Object)null)
			{
				return IsRanged(unit.WeaponHandler, api);
			}
			return false;
		}

		public static float GetAttackRange(Unit unit, UnitAPI api)
		{
			float num = 0f;
			WeaponHandler val = (((Object)(object)unit != (Object)null) ? unit.WeaponHandler : null);
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val.rightWeapon != (Object)null)
				{
					num = Mathf.Max(num, val.rightWeapon.maxRange);
				}
				if ((Object)(object)val.leftWeapon != (Object)null)
				{
					num = Mathf.Max(num, val.leftWeapon.maxRange);
				}
			}
			if (num <= 0.01f && (Object)(object)api != (Object)null)
			{
				num = api.GetAttackRange();
			}
			if (num <= 0.01f && (Object)(object)unit != (Object)null)
			{
				num = unit.m_AttackDistance;
			}
			return Mathf.Max(0.01f, num);
		}
	}
	[HarmonyPatch(typeof(WeaponHandler), "Attack")]
	internal static class WeaponAttackRangePatch
	{
		private static readonly Dictionary<int, float[]> OriginalRanges = new Dictionary<int, float[]>();

		private static bool IsRangedUnit(WeaponHandler wh, UnitAPI api)
		{
			return RangedHelper.IsRanged(wh, api);
		}

		private static void Prefix(WeaponHandler __instance)
		{
			if (!Plugin.Enabled.Value || !Plugin.ExtendedFireRange.Value || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			UnitAPI component = ((Component)__instance).GetComponent<UnitAPI>();
			if (!((Object)(object)component == (Object)null) && IsRangedUnit(__instance, component))
			{
				float value = Plugin.FireRangeMult.Value;
				float[] array = new float[2];
				int num = 0;
				if ((Object)(object)__instance.rightWeapon != (Object)null)
				{
					array[num++] = __instance.rightWeapon.maxRange;
					Weapon rightWeapon = __instance.rightWeapon;
					rightWeapon.maxRange *= value;
				}
				if ((Object)(object)__instance.leftWeapon != (Object)null)
				{
					array[num++] = __instance.leftWeapon.maxRange;
					Weapon leftWeapon = __instance.leftWeapon;
					leftWeapon.maxRange *= value;
				}
				OriginalRanges[((Object)__instance).GetInstanceID()] = array;
			}
		}

		private static void Postfix(WeaponHandler __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && OriginalRanges.TryGetValue(((Object)__instance).GetInstanceID(), out var value))
			{
				OriginalRanges.Remove(((Object)__instance).GetInstanceID());
				int num = 0;
				if ((Object)(object)__instance.rightWeapon != (Object)null && num < value.Length && value[num] > 0f)
				{
					__instance.rightWeapon.maxRange = value[num++];
				}
				if ((Object)(object)__instance.leftWeapon != (Object)null && num < value.Length && value[num] > 0f)
				{
					__instance.leftWeapon.maxRange = value[num++];
				}
			}
		}
	}
	[HarmonyPatch(typeof(UnitAPI), "SetLookDirection")]
	internal static class LookDirectionOverridePatch
	{
		private static void Prefix(UnitAPI __instance, ref Vector3 localDirection)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Enabled.Value && !((Object)(object)__instance == (Object)null))
			{
				SmartBrain component = ((Component)__instance).GetComponent<SmartBrain>();
				if ((Object)(object)component != (Object)null && component.TryGetDesiredDirection(out var dir))
				{
					localDirection = dir;
				}
			}
		}
	}
	[HarmonyPatch(typeof(UnitAPI), "SetMovementSpeed")]
	internal static class MovementSpeedOverridePatch
	{
		private static void Prefix(UnitAPI __instance, ref float movementSpeed)
		{
			if (Plugin.Enabled.Value && !((Object)(object)__instance == (Object)null))
			{
				SmartBrain component = ((Component)__instance).GetComponent<SmartBrain>();
				if ((Object)(object)component != (Object)null && component.TryGetDesiredSpeed(out var speed))
				{
					movementSpeed = speed;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Weapon), "Awake")]
	internal static class SpreadPatch
	{
		private static void Postfix(Weapon __instance)
		{
			if (!Plugin.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			RangeWeapon val = (RangeWeapon)(object)((__instance is RangeWeapon) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (Plugin.DisableCowardPenalty.Value)
			{
				val.extraSpreadInMelee = 0f;
				val.extraCDInMelee = 0f;
			}
			if (Plugin.SpreadEnabled.Value)
			{
				float value = Plugin.AddedSpread.Value;
				if (!(value <= 0f))
				{
					float num = Mathf.Max(0.01f, __instance.maxRange);
					float num2 = Plugin.SpreadReferenceRange.Value / num;
					float num3 = value * num2;
					float spread = val.spread;
					val.spread = Mathf.Sqrt(spread * spread + num3 * num3);
				}
			}
		}
	}
	[BepInPlugin("local.smarterai", "Tactics", "1.12.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "local.smarterai";

		public const string Name = "Tactics";

		public const string Version = "1.12.0";

		public static ManualLogSource Log;

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<bool> DebugLog;

		public static ConfigEntry<float> TurnSpeedMultiplier;

		public static ConfigEntry<bool> SmarterTargeting;

		public static ConfigEntry<float> CrowdWeight;

		public static ConfigEntry<float> RetargetInterval;

		public static ConfigEntry<float> SwitchMargin;

		public static ConfigEntry<float> RangedThreshold;

		public static ConfigEntry<bool> Spacing;

		public static ConfigEntry<float> SeparationRadius;

		public static ConfigEntry<float> SeparationWeight;

		public static ConfigEntry<float> ObstacleRadius;

		public static ConfigEntry<float> ObstacleWidth;

		public static ConfigEntry<float> ObstacleWeight;

		public static ConfigEntry<float> FlankMinDistance;

		public static ConfigEntry<float> FlankStrength;

		public static ConfigEntry<bool> ExtendedFireRange;

		public static ConfigEntry<float> FireRangeMult;

		public static ConfigEntry<bool> RangedKite;

		public static ConfigEntry<float> FleeRangeMult;

		public static ConfigEntry<float> FleeMaxDistance;

		public static ConfigEntry<float> TurnBackDelay;

		public static ConfigEntry<float> MinFleeTime;

		public static ConfigEntry<float> TurnCompleteAngle;

		public static ConfigEntry<float> MaxTurnTime;

		public static ConfigEntry<float> FleeSpeed;

		public static ConfigEntry<float> FleeExitBuffer;

		public static ConfigEntry<float> FleeDistanceFactor;

		public static ConfigEntry<bool> KiteOnlyWithoutMelee;

		public static ConfigEntry<float> AwaitShotDuration;

		public static ConfigEntry<float> MinKiteRange;

		public static ConfigEntry<bool> MapClamp;

		public static ConfigEntry<float> BoundsMargin;

		public static ConfigEntry<bool> DisableCowardPenalty;

		public static ConfigEntry<bool> SpreadEnabled;

		public static ConfigEntry<float> AddedSpread;

		public static ConfigEntry<float> SpreadReferenceRange;

		public static ConfigEntry<bool> FriendlyFireCheck;

		public static ConfigEntry<float> FriendlyObstacleMinDistance;

		public static ConfigEntry<float> FriendlyBlockRadius;

		public static ConfigEntry<float> BlockMaxFraction;

		private void Awake()
		{
			//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch.");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", false, "Verbose logging.");
			TurnSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TurnSpeedMultiplier", 5f, "Global multiplier on unit turn speed (how fast they rotate to face a new direction).");
			SmarterTargeting = ((BaseUnityPlugin)this).Config.Bind<bool>("1_Targeting", "Enabled", true, "Melee units re-pick targets preferring enemies that fewer allies already aim at.");
			CrowdWeight = ((BaseUnityPlugin)this).Config.Bind<float>("1_Targeting", "CrowdWeight", 0.25f, "Weight of 'already targeted by N allies' in target scoring. Vanilla is 0.05. Higher = spread out more.");
			RetargetInterval = ((BaseUnityPlugin)this).Config.Bind<float>("1_Targeting", "RetargetInterval", 0.6f, "Seconds between target re-picks per unit (prevents path thrashing).");
			SwitchMargin = ((BaseUnityPlugin)this).Config.Bind<float>("1_Targeting", "SwitchMargin", 2f, "New target must score this much better than the current one to switch (hysteresis).");
			RangedThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("1_Targeting", "RangedThreshold", 5f, "Attack range above which a unit counts as ranged (target re-pick only affects melee).");
			Spacing = ((BaseUnityPlugin)this).Config.Bind<bool>("2_Spacing", "Enabled", true, "Melee units keep space from nearby units (both teams), steer around blockers, and fan out when approaching.");
			SeparationRadius = ((BaseUnityPlugin)this).Config.Bind<float>("2_Spacing", "SeparationRadius", 0.4f, "Keep-away radius between units (m).");
			SeparationWeight = ((BaseUnityPlugin)this).Config.Bind<float>("2_Spacing", "SeparationWeight", 2.5f, "Strength of the separation push.");
			ObstacleRadius = ((BaseUnityPlugin)this).Config.Bind<float>("2_Spacing", "ObstacleRadius", 3f, "Units ahead closer than this are treated as path obstacles (m).");
			ObstacleWidth = ((BaseUnityPlugin)this).Config.Bind<float>("2_Spacing", "ObstacleWidth", 1.2f, "Lateral corridor half-width for obstacle detection (m).");
			ObstacleWeight = ((BaseUnityPlugin)this).Config.Bind<float>("2_Spacing", "ObstacleWeight", 4f, "Strength of obstacle avoidance steer.");
			FlankMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2_Spacing", "FlankMinDistance", 4f, "Beyond this distance to target, melee units add a lateral (flanking) offset (m).");
			FlankStrength = ((BaseUnityPlugin)this).Config.Bind<float>("2_Spacing", "FlankStrength", 0f, "Strength of the flanking offset. 0 = off (keeps units on the nav path).");
			ExtendedFireRange = ((BaseUnityPlugin)this).Config.Bind<bool>("3_RangedFire", "Enabled", true, "Ranged units may open fire at FireRangeMult x range; they still only stand still inside normal range.");
			FireRangeMult = ((BaseUnityPlugin)this).Config.Bind<float>("3_RangedFire", "FireRangeMult", 1.5f, "Fire range multiplier.");
			RangedKite = ((BaseUnityPlugin)this).Config.Bind<bool>("4_Kite", "Enabled", true, "After a ranged unit attacks while an enemy is within FleeRangeMult x range, it turns and flees until its weapon is ready again.");
			FleeRangeMult = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "FleeRangeMult", 1.2f, "Flee trigger distance as a multiplier of attack range.");
			FleeMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "FleeMaxDistance", 15f, "Absolute cap for the flee trigger distance (m), so long-range units do not flee from far-away enemies.");
			TurnBackDelay = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "TurnBackDelay", 1f, "Seconds to wait facing the enemy before resuming fire after turning back.");
			MinFleeTime = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "MinFleeTime", 0.6f, "Minimum seconds a unit keeps fleeing once it starts (makes the retreat actually visible).");
			TurnCompleteAngle = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "TurnCompleteAngle", 30f, "A unit counts as 'facing' its desired direction below this angle (degrees). Turning happens in place before moving.");
			MaxTurnTime = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "MaxTurnTime", 0.4f, "After this many seconds of turning in place, the unit starts running even if not fully turned.");
			FleeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "FleeSpeed", 1f, "Movement speed while fleeing.");
			FleeExitBuffer = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "FleeExitBuffer", 2f, "Fleeing only stops when the closest enemy is beyond trigger distance + this buffer (m).");
			FleeDistanceFactor = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "FleeDistanceFactor", 0.5f, "Flee destination = self + away-from-enemy direction * this * attack range. If that point has no ground / is blocked / off-map, the unit does NOT flee.");
			KiteOnlyWithoutMelee = ((BaseUnityPlugin)this).Config.Bind<bool>("4_Kite", "KiteOnlyWithoutMelee", true, "Only units with NO melee weapon kite; units with a melee sidearm keep fighting.");
			AwaitShotDuration = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "AwaitShotDuration", 1.5f, "Time the unit holds its firing stance (covers attack windup + shot) before it re-evaluates fleeing.");
			MinKiteRange = ((BaseUnityPlugin)this).Config.Bind<float>("4_Kite", "MinKiteRange", 6f, "Units whose weapon range is below this never kite (keeps short-range 'ranged' units like ninjas fighting in melee).");
			MapClamp = ((BaseUnityPlugin)this).Config.Bind<bool>("5_MapBounds", "Enabled", true, "Clamp movement destinations to the map circle, keeping units from pathing off the land.");
			BoundsMargin = ((BaseUnityPlugin)this).Config.Bind<float>("5_MapBounds", "BoundsMargin", 0.5f, "Extra margin inside the map edge (m).");
			DisableCowardPenalty = ((BaseUnityPlugin)this).Config.Bind<bool>("8_Coward", "Enabled", true, "Disable the vanilla 'coward' mechanic where some shooters get extra spread and longer attack cooldown when enemies are too close.");
			SpreadEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("7_Spread", "Enabled", true, "Add extra spread to ranged weapons, in quadrature: newSpread = sqrt(old^2 + AddedSpread^2). Low-spread units get a big penalty, high-spread units barely change.");
			AddedSpread = ((BaseUnityPlugin)this).Config.Bind<float>("7_Spread", "AddedSpread", 3f, "Base quadrature spread. Final added = AddedSpread * (SpreadReferenceRange / weapon range).");
			SpreadReferenceRange = ((BaseUnityPlugin)this).Config.Bind<float>("7_Spread", "SpreadReferenceRange", 10f, "Weapon range whose accuracy factor is 1 (roughly a javelin). Longer ranges get a proportionally smaller spread penalty.");
			FriendlyFireCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("6_FriendlyFire", "Enabled", true, "Ranged units treat friendly units further than FriendlyObstacleMinDistance as line-of-sight obstacles.");
			FriendlyObstacleMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("6_FriendlyFire", "FriendlyObstacleMinDistance", 1f, "Friendlies closer than this do NOT block the shot (m).");
			FriendlyBlockRadius = ((BaseUnityPlugin)this).Config.Bind<float>("6_FriendlyFire", "FriendlyBlockRadius", 0.35f, "A friendly blocks the shot only if its body passes within this distance of the firing line (m).");
			BlockMaxFraction = ((BaseUnityPlugin)this).Config.Bind<float>("6_FriendlyFire", "BlockMaxFraction", 0.6f, "Only friendlies within this fraction of the shot distance count as cover.");
			new Harmony("local.smarterai").PatchAll();
			Bootstrap.Ensure();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Tactics 1.12.0 loaded.");
		}

		public static void Dbg(string msg)
		{
			if (DebugLog != null && DebugLog.Value)
			{
				Log.LogInfo((object)msg);
			}
		}
	}
	public class SmartBrain : MonoBehaviour
	{
		private enum FleeState
		{
			None,
			Fleeing,
			TurnBack,
			AwaitingShot
		}

		private Unit _unit;

		private UnitAPI _api;

		private DataHandler _data;

		private WeaponHandler _wh;

		private FleeState _flee;

		private float _turnBackTimer;

		private float _awaitShotTimer;

		private float _fleeStartTime;

		private float _flankSide = 1f;

		private float _strafeSide = 1f;

		private bool _blockedCached;

		private float _nextBlockedCheck;

		private float _blockedSince = -1f;

		private float _nextScan;

		private Vector3 _sepCache;

		private Vector3 _avoidCache;

		private Vector3 _headingSmoothed;

		private Vector3 _fleeDest;

		private bool _fleeDestValid;

		private float _nextDestCheck;

		private static int _mapLayerMask = -2;

		private int _computedFrame = -1;

		private bool _hasDirOverride;

		private bool _hasSpeedOverride;

		private Vector3 _desiredDir;

		private float _desiredSpeed;

		private bool _isMount;

		private float _nextEnemyScan;

		private float _closestEnemyDist = float.PositiveInfinity;

		private Vector3 _closestEnemyPos;

		private bool _computeLogged;

		private static int _brainCount;

		private static int _dirOverrides;

		private static int _speedOverrides;

		private static float _nextHeartbeat;

		public bool SuppressAttack
		{
			get
			{
				if (_flee != FleeState.Fleeing)
				{
					return _flee == FleeState.TurnBack;
				}
				return true;
			}
		}

		private static int MapLayerMask
		{
			get
			{
				if (_mapLayerMask == -2)
				{
					_mapLayerMask = LayerMask.GetMask(new string[1] { "Map" });
				}
				return _mapLayerMask;
			}
		}

		private void Start()
		{
			_unit = ((Component)this).GetComponent<Unit>();
			_data = ((Component)this).GetComponentInChildren<DataHandler>();
			_api = ((Component)this).GetComponent<UnitAPI>();
			_wh = ((Component)this).GetComponentInChildren<WeaponHandler>();
			if ((Object)(object)_wh == (Object)null && (Object)(object)_unit != (Object)null)
			{
				_wh = _unit.WeaponHandler;
			}
			_isMount = MountUtils.IsMount(_unit) || ((Object)(object)_unit != (Object)null && _unit.IsRider);
			Plugin.Log.LogInfo((object)("[SmarterAI] brain attached to " + (((Object)(object)_unit != (Object)null) ? ((Object)_unit).name : ((Object)this).name) + " mount=" + _isMount + " ranged=" + IsRanged()));
			_brainCount++;
			int instanceID = ((Object)this).GetInstanceID();
			_flankSide = ((instanceID % 3 - 1 >= 0) ? 1f : (-1f));
			_strafeSide = ((instanceID % 2 == 0) ? 1f : (-1f));
		}

		private bool IsMount()
		{
			if (_isMount)
			{
				return true;
			}
			return false;
		}

		private bool IsRanged()
		{
			if ((Object)(object)_api != (Object)null && _api.IsRangedUnit)
			{
				return true;
			}
			if ((Object)(object)_wh != (Object)null)
			{
				if ((Object)(object)_wh.rightWeapon != (Object)null && _wh.rightWeapon.isRange)
				{
					return true;
				}
				if ((Object)(object)_wh.leftWeapon != (Object)null && _wh.leftWeapon.isRange)
				{
					return true;
				}
			}
			return false;
		}

		private float GetAttackRange()
		{
			return RangedHelper.GetAttackRange(_unit, _api);
		}

		private bool HasMeleeWeapon()
		{
			if ((Object)(object)_wh != (Object)null)
			{
				if ((Object)(object)_wh.rightWeapon != (Object)null && !_wh.rightWeapon.isRange)
				{
					return true;
				}
				if ((Object)(object)_wh.leftWeapon != (Object)null && !_wh.leftWeapon.isRange)
				{
					return true;
				}
			}
			return false;
		}

		private void ScanClosestEnemy(Vector3 myPos)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextEnemyScan)
			{
				return;
			}
			_nextEnemyScan = Time.time + 0.15f;
			_closestEnemyDist = float.PositiveInfinity;
			Team team = _unit.Team;
			List<Unit> units = RangedHelper.GetUnits();
			for (int i = 0; i < units.Count; i++)
			{
				Unit val = units[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)_unit) && val.Team != team && !((Object)(object)val.data == (Object)null) && !((Object)(object)val.data.mainRig == (Object)null) && !val.data.Dead)
				{
					float num = Vector3.Distance(myPos, val.data.mainRig.position);
					if (num < _closestEnemyDist)
					{
						_closestEnemyDist = num;
						_closestEnemyPos = val.data.mainRig.position;
					}
				}
			}
		}

		private float GetFleeTriggerDistance()
		{
			return Mathf.Min(GetAttackRange() * Plugin.FleeRangeMult.Value, Plugin.FleeMaxDistance.Value);
		}

		private bool WeaponReady()
		{
			Weapon val = null;
			if ((Object)(object)_wh != (Object)null)
			{
				val = _wh.rightWeapon;
				if ((Object)(object)val == (Object)null)
				{
					val = _wh.leftWeapon;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			return val.internalCounter >= val.internalCooldown;
		}

		private float FacingAngleTo(Vector3 worldDir)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_data == (Object)null || (Object)(object)_data.characterForwardObject == (Object)null)
			{
				return 0f;
			}
			Vector3 forward = _data.characterForwardObject.forward;
			forward.y = 0f;
			Vector3 val = worldDir;
			val.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f || ((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				return 0f;
			}
			return Vector3.Angle(forward, val);
		}

		private bool ComputeFleeDestination(Vector3 myPos, Vector3 enemyPos, out Vector3 dest)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0091: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: 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)
			Vector3 val = myPos - enemyPos;
			val.y = 0f;
			dest = Vector3.zero;
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				return false;
			}
			((Vector3)(ref val)).Normalize();
			dest = myPos + val * (GetAttackRange() * Plugin.FleeDistanceFactor.Value);
			if ((Object)(object)MapSettings.Instance != (Object)null)
			{
				Vector3 mapCenter = MapSettings.Instance.m_mapCenter;
				float num = MapSettings.Instance.m_mapRadius - Plugin.BoundsMargin.Value;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(dest.x - mapCenter.x, dest.z - mapCenter.z);
				if (((Vector2)(ref val2)).magnitude > num)
				{
					return false;
				}
			}
			RaycastHit[] array = Physics.RaycastAll(dest + Vector3.up * 8f, Vector3.down, 25f);
			if (array == null || array.Length == 0)
			{
				return false;
			}
			bool flag = false;
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val3 = array[i];
				if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<DataHandler>() != (Object)null) && !(((RaycastHit)(ref val3)).point.y < myPos.y - 2.5f))
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return false;
			}
			int mapLayerMask = MapLayerMask;
			if (mapLayerMask != 0)
			{
				Vector3 val4 = myPos + Vector3.up * 0.6f;
				Vector3 val5 = dest - val4;
				val5.y = 0f;
				float magnitude = ((Vector3)(ref val5)).magnitude;
				if (magnitude > 0.01f && Physics.Raycast(val4, val5 / magnitude, magnitude, mapLayerMask))
				{
					return false;
				}
			}
			return true;
		}

		private void RefreshFleeDestination(Vector3 myPos, Vector3 enemyPos)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.time < _nextDestCheck))
			{
				_nextDestCheck = Time.time + 0.25f;
				_fleeDestValid = ComputeFleeDestination(myPos, enemyPos, out _fleeDest);
			}
		}

		public bool TryGetDesiredDirection(out Vector3 dir)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Compute();
			dir = _desiredDir;
			if (_hasDirOverride)
			{
				_dirOverrides++;
			}
			return _hasDirOverride;
		}

		public bool TryGetDesiredSpeed(out float speed)
		{
			Compute();
			speed = _desiredSpeed;
			if (_hasSpeedOverride)
			{
				_speedOverrides++;
			}
			return _hasSpeedOverride;
		}

		private static void Heartbeat(SmartBrain self)
		{
			if (Time.time >= _nextHeartbeat)
			{
				_nextHeartbeat = Time.time + 5f;
				Plugin.Log.LogInfo((object)("[SmarterAI] heartbeat brains=" + _brainCount + " dirOverrides/5s=" + _dirOverrides + " speedOverrides/5s=" + _speedOverrides));
				_dirOverrides = 0;
				_speedOverrides = 0;
			}
		}

		private void Compute()
		{
			if (_computedFrame == Time.frameCount)
			{
				return;
			}
			_computedFrame = Time.frameCount;
			try
			{
				ComputeInner();
			}
			catch (Exception ex)
			{
				if (!_computeLogged)
				{
					_computeLogged = true;
					Plugin.Log.LogError((object)("[SmarterAI] SmartBrain.Compute error: " + ex));
				}
			}
		}

		private void ComputeInner()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_067c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0681: Unknown result type (might be due to invalid IL or missing references)
			//IL_069c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0739: Unknown result type (might be due to invalid IL or missing references)
			//IL_0743: Unknown result type (might be due to invalid IL or missing references)
			//IL_074c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0756: Unknown result type (might be due to invalid IL or missing references)
			//IL_0706: Unknown result type (might be due to invalid IL or missing references)
			//IL_070b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0770: Unknown result type (might be due to invalid IL or missing references)
			//IL_0777: Unknown result type (might be due to invalid IL or missing references)
			//IL_077c: Unknown result type (might be due to invalid IL or missing references)
			//IL_077e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0785: Unknown result type (might be due to invalid IL or missing references)
			//IL_078d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0793: Unknown result type (might be due to invalid IL or missing references)
			//IL_079a: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0829: Unknown result type (might be due to invalid IL or missing references)
			//IL_082e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0834: Unknown result type (might be due to invalid IL or missing references)
			//IL_0839: Unknown result type (might be due to invalid IL or missing references)
			//IL_083f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0840: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0887: Unknown result type (might be due to invalid IL or missing references)
			//IL_088c: Unknown result type (might be due to invalid IL or missing references)
			//IL_088d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0892: Unknown result type (might be due to invalid IL or missing references)
			//IL_0896: Unknown result type (might be due to invalid IL or missing references)
			//IL_089b: Unknown result type (might be due to invalid IL or missing references)
			//IL_089d: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a39: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a3b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a41: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a43: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a72: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a73: Unknown result type (might be due to invalid IL or missing references)
			//IL_05da: Unknown result type (might be due to invalid IL or missing references)
			//IL_05df: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0604: Unknown result type (might be due to invalid IL or missing references)
			//IL_0609: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aa8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ab4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ace: Unknown result type (might be due to invalid IL or missing references)
			//IL_0add: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a8b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a8d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a9c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aa1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0628: Unknown result type (might be due to invalid IL or missing references)
			//IL_062d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae7: 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_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b1f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b26: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b3b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b40: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b4c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b51: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b17: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b18: Unknown result type (might be due to invalid IL or missing references)
			//IL_094e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0953: Unknown result type (might be due to invalid IL or missing references)
			//IL_0955: Unknown result type (might be due to invalid IL or missing references)
			//IL_0956: Unknown result type (might be due to invalid IL or missing references)
			//IL_0958: Unknown result type (might be due to invalid IL or missing references)
			//IL_095d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0478: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_09aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_09af: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0986: Unknown result type (might be due to invalid IL or missing references)
			//IL_0988: Unknown result type (might be due to invalid IL or missing references)
			//IL_098c: Unknown result type (might be due to invalid IL or missing references)
			//IL_099c: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_09a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_09cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a02: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a04: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a08: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a18: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a1d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a22: Unknown result type (might be due to invalid IL or missing references)
			_hasDirOverride = false;
			_hasSpeedOverride = false;
			Heartbeat(this);
			if (!Plugin.Enabled.Value || (Object)(object)_unit == (Object)null || (Object)(object)_data == (Object)null || (Object)(object)_api == (Object)null || _data.Dead || !_api.Active || _api.IsRemotelyControlled || _api.IsPossessed || !Bootstrap.InBattle() || _isMount)
			{
				return;
			}
			Vector3 val = (((Object)(object)_data.mainRig != (Object)null) ? _data.mainRig.position : ((Component)this).transform.position);
			Rigidbody targetMainRig = _data.targetMainRig;
			Vector3 val2 = Vector3.zero;
			float num = 0f;
			if ((Object)(object)targetMainRig != (Object)null)
			{
				Vector3 val3 = targetMainRig.position - val;
				val3.y = 0f;
				num = ((Vector3)(ref val3)).magnitude;
				if (num > 0.001f)
				{
					val2 = val3 / num;
				}
			}
			bool flag = IsRanged();
			Vector3 val7;
			if (flag)
			{
				if (Plugin.RangedKite.Value && !IsMount() && GetAttackRange() >= Plugin.MinKiteRange.Value && (!Plugin.KiteOnlyWithoutMelee.Value || !HasMeleeWeapon()))
				{
					ScanClosestEnemy(val);
					float fleeTriggerDistance = GetFleeTriggerDistance();
					float num2 = fleeTriggerDistance + Plugin.FleeExitBuffer.Value;
					bool flag2 = _closestEnemyDist < float.PositiveInfinity;
					bool flag3 = flag2 && _closestEnemyDist < fleeTriggerDistance;
					bool flag4 = !flag2 || _closestEnemyDist > num2;
					if (_flee == FleeState.None && flag3)
					{
						RefreshFleeDestination(val, _closestEnemyPos);
						_nextDestCheck = 0f;
						RefreshFleeDestination(val, _closestEnemyPos);
						if (_fleeDestValid)
						{
							_flee = FleeState.Fleeing;
							_fleeStartTime = Time.time;
							Plugin.Dbg("[SmarterAI] " + ((Object)_unit).name + " starts kiting toward safe ground");
						}
					}
					if (_flee == FleeState.Fleeing)
					{
						if (flag4)
						{
							_flee = FleeState.None;
						}
						else if (WeaponReady() && Time.time - _fleeStartTime >= Plugin.MinFleeTime.Value)
						{
							_flee = FleeState.TurnBack;
							_turnBackTimer = Plugin.TurnBackDelay.Value;
						}
						else if (flag2)
						{
							RefreshFleeDestination(val, _closestEnemyPos);
							if (!_fleeDestValid)
							{
								_flee = FleeState.None;
								return;
							}
							Vector3 val4 = _fleeDest - val;
							val4.y = 0f;
							if (((Vector3)(ref val4)).sqrMagnitude > 0.04f)
							{
								Vector3 worldDir = (_desiredDir = ((Vector3)(ref val4)).normalized);
								_hasDirOverride = true;
								bool flag5 = FacingAngleTo(worldDir) <= Plugin.TurnCompleteAngle.Value;
								bool flag6 = Time.time - _fleeStartTime >= Plugin.MaxTurnTime.Value;
								_desiredSpeed = ((flag5 || flag6) ? Plugin.FleeSpeed.Value : 0f);
								_hasSpeedOverride = true;
							}
							else
							{
								_desiredSpeed = 0f;
								_hasSpeedOverride = true;
							}
							return;
						}
					}
					if (_flee == FleeState.TurnBack)
					{
						if (flag4)
						{
							_flee = FleeState.None;
						}
						else
						{
							Vector3 val5 = Vector3.zero;
							if ((Object)(object)targetMainRig != (Object)null && ((Vector3)(ref val2)).sqrMagnitude > 0.001f)
							{
								val5 = val2;
							}
							else if (flag2)
							{
								val5 = _closestEnemyPos - val;
								val5.y = 0f;
							}
							if (((Vector3)(ref val5)).sqrMagnitude > 0.001f)
							{
								_desiredDir = ((Vector3)(ref val5)).normalized;
								_hasDirOverride = true;
								_desiredSpeed = 0f;
								_hasSpeedOverride = true;
							}
							if (FacingAngleTo(_desiredDir) <= Plugin.TurnCompleteAngle.Value)
							{
								_turnBackTimer -= Time.deltaTime;
							}
							if (!(_turnBackTimer <= 0f))
							{
								return;
							}
							_flee = FleeState.AwaitingShot;
							_awaitShotTimer = Plugin.AwaitShotDuration.Value;
						}
					}
					if (_flee == FleeState.AwaitingShot)
					{
						if (flag4)
						{
							_flee = FleeState.None;
						}
						else
						{
							Vector3 val6 = Vector3.zero;
							if ((Object)(object)targetMainRig != (Object)null && ((Vector3)(ref val2)).sqrMagnitude > 0.001f)
							{
								val6 = val2;
							}
							else if (flag2)
							{
								val6 = _closestEnemyPos - val;
								val6.y = 0f;
							}
							if (((Vector3)(ref val6)).sqrMagnitude > 0.001f)
							{
								_desiredDir = ((Vector3)(ref val6)).normalized;
								_hasDirOverride = true;
								_desiredSpeed = 0f;
								_hasSpeedOverride = true;
							}
							_awaitShotTimer -= Time.deltaTime;
							if (_awaitShotTimer <= 0f)
							{
								_flee = FleeState.None;
							}
						}
					}
				}
				if (Plugin.FriendlyFireCheck.Value && (Object)(object)targetMainRig != (Object)null && num > 0.001f && (_flee == FleeState.None || _flee == FleeState.AwaitingShot))
				{
					if (Time.time >= _nextBlockedCheck)
					{
						_nextBlockedCheck = Time.time + 0.2f;
						_blockedCached = RangedHelper.FriendlyBlocked(_api, _unit, targetMainRig);
						if (_blockedCached && _blockedSince < 0f)
						{
							_blockedSince = Time.time;
						}
						if (!_blockedCached)
						{
							_blockedSince = -1f;
						}
					}
					if (_blockedCached)
					{
						if (_blockedSince > 0f && Time.time - _blockedSince > 1.5f)
						{
							_strafeSide = 0f - _strafeSide;
							_blockedSince = Time.time;
						}
						val7 = Vector3.Cross(Vector3.up, val2);
						Vector3 val8 = ((Vector3)(ref val7)).normalized * _strafeSide + val2 * 0.25f;
						val8.y = 0f;
						if (((Vector3)(ref val8)).sqrMagnitude > 0.001f)
						{
							_desiredDir = ((Vector3)(ref val8)).normalized;
							_hasDirOverride = true;
							_dirOverrides++;
							_desiredSpeed = 1.5f;
							_hasSpeedOverride = true;
						}
						return;
					}
				}
			}
			if (Plugin.MapClamp.Value && (Object)(object)MapSettings.Instance != (Object)null)
			{
				Vector3 mapCenter = MapSettings.Instance.m_mapCenter;
				float num3 = MapSettings.Instance.m_mapRadius - Plugin.BoundsMargin.Value;
				Vector2 val9 = default(Vector2);
				((Vector2)(ref val9))..ctor(val.x - mapCenter.x, val.z - mapCenter.z);
				if (((Vector2)(ref val9)).magnitude > num3)
				{
					Vector3 val10 = new Vector3(mapCenter.x, val.y, mapCenter.z) - val;
					val10.y = 0f;
					if (((Vector3)(ref val10)).sqrMagnitude > 0.001f)
					{
						_desiredDir = ((Vector3)(ref val10)).normalized;
						_hasDirOverride = true;
						_desiredSpeed = 2f;
						_hasSpeedOverride = true;
					}
					return;
				}
				if ((Object)(object)targetMainRig != (Object)null)
				{
					Vector2 val11 = default(Vector2);
					((Vector2)(ref val11))..ctor(targetMainRig.position.x - mapCenter.x, targetMainRig.position.z - mapCenter.z);
					if (((Vector2)(ref val11)).magnitude > num3)
					{
						Vector2 val12 = ((Vector2)(ref val11)).normalized * num3;
						Vector3 val13 = new Vector3(mapCenter.x + val12.x, val.y, mapCenter.z + val12.y) - val;
						val13.y = 0f;
						if (((Vector3)(ref val13)).sqrMagnitude > 0.001f)
						{
							_desiredDir = ((Vector3)(ref val13)).normalized;
							_hasDirOverride = true;
						}
						return;
					}
				}
			}
			if (!Plugin.Spacing.Value || flag || (Object)(object)targetMainRig == (Object)null || num < 0.001f || _data.distanceToTarget > 20f)
			{
				return;
			}
			float num4 = GetAttackRange() + 1f;
			if (num <= num4)
			{
				_sepCache = Vector3.zero;
				_avoidCache = Vector3.zero;
				_headingSmoothed = val2;
				return;
			}
			if (Time.time >= _nextScan)
			{
				_nextScan = Time.time + 0.1f * (0.8f + 0.4f * ((float)(((Object)this).GetInstanceID() & 0x3FF) / 1023f));
				val7 = Vector3.Cross(Vector3.up, val2);
				Vector3 normalized = ((Vector3)(ref val7)).normalized;
				Vector3 val14 = Vector3.zero;
				Vector3 val15 = Vector3.zero;
				float value = Plugin.SeparationRadius.Value;
				float value2 = Plugin.ObstacleRadius.Value;
				float value3 = Plugin.ObstacleWidth.Value;
				List<Unit> units = RangedHelper.GetUnits();
				for (int i = 0; i < units.Count; i++)
				{
					Unit val16 = units[i];
					if ((Object)(object)val16 == (Object)null || (Object)(object)val16 == (Object)(object)_unit || (Object)(object)val16.data == (Object)null || (Object)(object)val16.data.mainRig == (Object)null || val16.data.Dead)
					{
						continue;
					}
					Vector3 position = val16.data.mainRig.position;
					Vector3 val17 = val - position;
					val17.y = 0f;
					float magnitude = ((Vector3)(ref val17)).magnitude;
					if (magnitude < 0.001f)
					{
						continue;
					}
					if (magnitude < value)
					{
						val14 += val17 / magnitude * (1f - magnitude / value);
					}
					Vector3 val18 = -val17;
					float num5 = Vector3.Dot(val18, val2);
					if (num5 > 0f && num5 < value2 && num5 < num && Mathf.Abs(Vector3.Dot(val18, normalized)) < value3)
					{
						float num6 = Mathf.Sign(Vector3.Dot(normalized, val17));
						if (num6 == 0f)
						{
							num6 = _flankSide;
						}
						val15 += normalized * num6 * (1f - num5 / value2);
					}
				}
				_sepCache = val14;
				_avoidCache = val15;
			}
			if (!(((Vector3)(ref _sepCache)).sqrMagnitude > 0.0025f) && !(((Vector3)(ref _avoidCache)).sqrMagnitude > 0.0025f))
			{
				_headingSmoothed = val2;
				return;
			}
			Vector3 val19 = ((((Vector3)(ref _avoidCache)).sqrMagnitude > 0.0025f) ? (val2 * 0.35f + _avoidCache * Plugin.ObstacleWeight.Value + _sepCache * Plugin.SeparationWeight.Value) : (val2 + _sepCache * Plugin.SeparationWeight.Value));
			val19.y = 0f;
			if (!(((Vector3)(ref val19)).sqrMagnitude < 0.001f))
			{
				if (((Vector3)(ref _headingSmoothed)).sqrMagnitude < 0.001f)
				{
					_headingSmoothed = val2;
				}
				_headingSmoothed = Vector3.Slerp(_headingSmoothed, ((Vector3)(ref val19)).normalized, Mathf.Clamp01(Time.deltaTime * 7f));
				_desiredDir = ((Vector3)(ref _headingSmoothed)).normalized;
				_hasDirOverride = true;
			}
		}
	}
	public class SmartTargetingSystem : ComponentSystem
	{
		private ComponentGroup _units;

		private ComponentGroup _targets;

		private readonly Dictionary<Entity, float> _nextRetarget = new Dictionary<Entity, float>();

		private static bool _announced;

		protected override void OnCreateManager()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0057: 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_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_0089: 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_0095: 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_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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			_units = ((ComponentSystemBase)this).GetComponentGroup((ComponentType[])(object)new ComponentType[8]
			{
				ComponentType.ReadOnly<Team>(),
				ComponentType.Create<HasTargetTag>(),
				ComponentType.ReadOnly<PredictedPosition>(),
				ComponentType.ReadOnly<Range>(),
				ComponentType.ReadOnly<UnitTag>(),
				ComponentType.ReadOnly<EnemyLeastWeightTargeting>(),
				ComponentType.Subtractive<IsInPool>(),
				ComponentType.Subtractive<IsDead>()
			});
			_targets = ((ComponentSystemBase)this).GetComponentGroup((ComponentType[])(object)new ComponentType[9]
			{
				ComponentType.ReadOnly<Team>(),
				ComponentType.ReadOnly<HipPosition>(),
				ComponentType.ReadOnly<TargetPriority>(),
				ComponentType.ReadOnly<TargetThickness>(),
				ComponentType.Create<BeingTargetedBy>(),
				ComponentType.ReadOnly<UnitTag>(),
				ComponentType.Create<IsTarget>(),
				ComponentType.Subtractive<IsInPool>(),
				ComponentType.Subtractive<IsDead>()
			});
		}

		protected override void OnUpdate()
		{
			try
			{
				OnUpdateInner();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[SmarterAI] SmartTargetingSystem error: " + ex));
			}
		}

		private void OnUpdateInner()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: 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_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value || !Plugin.SmarterTargeting.Value || !Bootstrap.InBattle())
			{
				return;
			}
			if (!_announced)
			{
				_announced = true;
				Plugin.Log.LogInfo((object)"[SmarterAI] SmartTargetingSystem active in battle.");
			}
			float value = Plugin.CrowdWeight.Value;
			TeamSystem existingManager = ((ComponentSystemBase)this).World.GetExistingManager<TeamSystem>();
			float value2 = Plugin.RangedThreshold.Value;
			float value3 = Plugin.RetargetInterval.Value;
			float value4 = Plugin.SwitchMargin.Value;
			float time = Time.time;
			for (int i = 0; i <= 1; i++)
			{
				_units.SetFilter<Team>(new Team
				{
					Value = i
				});
				_targets.SetFilter<Team>(new Team
				{
					Value = 1 - i
				});
				EntityArray entityArray = _units.GetEntityArray();
				ComponentDataArray<HasTargetTag> componentDataArray = _units.GetComponentDataArray<HasTargetTag>();
				ComponentDataArray<PredictedPosition> componentDataArray2 = _units.GetComponentDataArray<PredictedPosition>();
				ComponentDataArray<Range> componentDataArray3 = _units.GetComponentDataArray<Range>();
				EntityArray entityArray2 = _targets.GetEntityArray();
				ComponentDataArray<HipPosition> componentDataArray4 = _targets.GetComponentDataArray<HipPosition>();
				ComponentDataArray<TargetPriority> componentDataArray5 = _targets.GetComponentDataArray<TargetPriority>();
				ComponentDataArray<BeingTargetedBy> componentDataArray6 = _targets.GetComponentDataArray<BeingTargetedBy>();
				if (((EntityArray)(ref entityArray)).Length == 0 || ((EntityArray)(ref entityArray2)).Length == 0)
				{
					_units.ResetFilter();
					_targets.ResetFilter();
					continue;
				}
				float[] array = new float[((EntityArray)(ref entityArray2)).Length];
				for (int j = 0; j < ((EntityArray)(ref entityArray2)).Length; j++)
				{
					array[j] = componentDataArray6[j].Value;
				}
				for (int k = 0; k < ((EntityArray)(ref entityArray)).Length; k++)
				{
					Range val = componentDataArray3[k];
					if (val.AttackRange >= value2)
					{
						continue;
					}
					if (existingManager != null)
					{
						DataHandler dataHandler = existingManager.GetDataHandler(((EntityArray)(ref entityArray))[k]);
						if ((Object)(object)dataHandler != (Object)null && (Object)(object)dataHandler.unit != (Object)null && (MountUtils.IsMount(dataHandler.unit) || dataHandler.unit.IsRider))
						{
							continue;
						}
					}
					Entity val2 = ((EntityArray)(ref entityArray))[k];
					if (_nextRetarget.TryGetValue(val2, out var value5) && time < value5)
					{
						Entity target = componentDataArray[k].Target;
						if (!(target != Entity.Null))
						{
							continue;
						}
						for (int l = 0; l < ((EntityArray)(ref entityArray2)).Length; l++)
						{
							if (((EntityArray)(ref entityArray2))[l] == target)
							{
								array[l] += 1f;
								break;
							}
						}
						continue;
					}
					_nextRetarget[val2] = time + value3 * (0.8f + 0.4f * ((float)(val2.Index & 0x3FF) / 1023f));
					float3 value6 = componentDataArray2[k].Value;
					int num = -1;
					float num2 = float.MinValue;
					float num3 = float.MinValue;
					Entity target2 = componentDataArray[k].Target;
					for (int m = 0; m < ((EntityArray)(ref entityArray2)).Length; m++)
					{
						float num4 = (0f - math.length(componentDataArray4[m].Value - value6)) / componentDataArray5[m].Value - array[m] * val.AttackRange * value;
						if (((EntityArray)(ref entityArray2))[m] == target2)
						{
							num3 = num4;
						}
						if (num4 > num2)
						{
							num2 = num4;
							num = m;
						}
					}
					if (num < 0)
					{
						continue;
					}
					if (target2 != Entity.Null && num3 != float.MinValue && num2 < num3 + value4)
					{
						for (int n = 0; n < ((EntityArray)(ref entityArray2)).Length; n++)
						{
							if (((EntityArray)(ref entityArray2))[n] == target2)
							{
								num = n;
								break;
							}
						}
					}
					Entity val3 = ((EntityArray)(ref entityArray2))[num];
					if (target2 != val3)
					{
						componentDataArray[k] = new HasTargetTag
						{
							Target = val3
						};
						((ComponentSystemBase)this).EntityManager.SetComponentData<IsTarget>(((EntityArray)(ref entityArray2))[num], new IsTarget
						{
							Targetee = val2
						});
					}
					array[num] += 1f;
				}
				_units.ResetFilter();
				_targets.ResetFilter();
			}
		}
	}
}