using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DM; using HarmonyLib; using Landfall.TABS; using Landfall.TABS.AI.Components; using Landfall.TABS.AI.Components.Events; using Landfall.TABS.AI.Components.Modifiers; using Landfall.TABS.AI.Components.Pathfinding; using Landfall.TABS.AI.Components.Tags; using Landfall.TABS.AI.Systems; using Landfall.TABS.GameMode; using Landfall.TABS.GameState; using Landfall.TABS.UnitEditor; using Landfall.TABS.Workshop; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Pathfinding; using StayCombatFix.FleeDebug; using StayCombatFix.UnitMarker; using TFBGames; using Unity.Entities; using Unity.Mathematics; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Stay & Combat Fixes")] [assembly: AssemblyDescription("Stay aura, lay-down combat, water physics, mirror shield, barrel death, gas grenade, and faction creator fixes for TABS")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Pretz")] [assembly: AssemblyProduct("StayCombatFix")] [assembly: AssemblyCopyright("Pretz")] [assembly: ComVisible(false)] [assembly: Guid("b2c3d4e5-f6a7-8901-bcde-f12345678901")] [assembly: AssemblyFileVersion("3.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("3.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 StayCombatFix { internal sealed class BarrelDeathPlan { internal Transform Root; internal float DelaySeconds; internal GameObject[] BarrelVisuals; internal Rigidbody[] BarrelRigidbodies; internal Transform[] BarrelAnchors; internal Vector3 SnapshotPosition; internal bool HasSnapshotPosition; internal Explosion CachedBarrelExplosion; internal GameObject CachedExplosionPrefab; internal Explosion FallbackExplosionTemplate; internal Unit OwnerUnit; } internal static class BarrelRollerDeathLogic { private struct PendingBarrelDeath { internal int RootId; internal BarrelDeathPlan Plan; internal float ExplodeAt; internal Vector3 ExplodePosition; internal bool HasExplodePosition; } [CompilerGenerated] private sealed class d__46 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__46(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (PendingDeaths.Count > 0) { float time = Time.time; int num = 0; int num2 = PendingDeaths.Count - 1; while (num2 >= 0 && num < 8) { PendingBarrelDeath pendingBarrelDeath = PendingDeaths[num2]; if (!(time < pendingBarrelDeath.ExplodeAt)) { if ((Object)(object)pendingBarrelDeath.Plan?.Root == (Object)null) { PendingDeaths.RemoveAt(num2); PendingDeathRootIds.Remove(pendingBarrelDeath.RootId); } else { PendingDeaths.RemoveAt(num2); PendingDeathRootIds.Remove(pendingBarrelDeath.RootId); ExecuteDeathExplosion(pendingBarrelDeath.RootId, pendingBarrelDeath.Plan, pendingBarrelDeath.ExplodePosition, pendingBarrelDeath.HasExplodePosition); num++; } } num2--; } <>2__current = null; <>1__state = 1; return true; } _queueRunner = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal const int BarrelRollerUnitId = 846602731; private const float MinimumDelaySeconds = 0.45f; private const float MaxBarrelDistanceFromUnit = 80f; private static MonoBehaviour _runner; private static ManualLogSource _log; private static readonly Dictionary RecentBarrelExplosionTimeByRoot = new Dictionary(); private static readonly Dictionary AllowedBarrelExplosionTimeByRoot = new Dictionary(); private static readonly Dictionary ActiveBarrelRollerRoots = new Dictionary(); private static readonly HashSet KnownBarrelRollerRootIds = new HashSet(); private static readonly HashSet NotBarrelRollerRootIds = new HashSet(); private static readonly List PendingDeaths = new List(32); private static readonly HashSet PendingDeathRootIds = new HashSet(); private const float RecentBarrelExplosionWindowSeconds = 2.5f; private const float DuplicateAbilityExplosionWindowSeconds = 0.75f; private const float AbilityDeathSkipExplosionAgeSeconds = 0.5f; private const float AbilityExplosionOwnerSearchRadius = 20f; private const float DeathExplosionDamage = 15f; private const int MaxExplosionsPerFrame = 8; private static GameObject _sharedBarrelDeathExplosionPrefab; private static Explosion _sharedBarrelDeathExplosionTemplate; private static Coroutine _queueRunner; private static bool _executingDeathExplosion; internal static void Initialize(MonoBehaviour runner, ManualLogSource log) { _runner = runner; _log = log; } internal static void ResetBattleCaches() { RecentBarrelExplosionTimeByRoot.Clear(); AllowedBarrelExplosionTimeByRoot.Clear(); ActiveBarrelRollerRoots.Clear(); KnownBarrelRollerRootIds.Clear(); NotBarrelRollerRootIds.Clear(); PendingDeaths.Clear(); PendingDeathRootIds.Clear(); _executingDeathExplosion = false; _queueRunner = null; } private static void EvictRootCache(int rootId) { KnownBarrelRollerRootIds.Remove(rootId); NotBarrelRollerRootIds.Remove(rootId); ActiveBarrelRollerRoots.Remove(rootId); RecentBarrelExplosionTimeByRoot.Remove(rootId); AllowedBarrelExplosionTimeByRoot.Remove(rootId); PendingDeathRootIds.Remove(rootId); for (int num = PendingDeaths.Count - 1; num >= 0; num--) { if (PendingDeaths[num].RootId == rootId) { PendingDeaths.RemoveAt(num); } } } private static bool IsCachedBarrelRollerRoot(Transform root, int rootId) { if (!KnownBarrelRollerRootIds.Contains(rootId)) { return false; } if (!ActiveBarrelRollerRoots.TryGetValue(rootId, out var value) || (Object)(object)value == (Object)null) { EvictRootCache(rootId); return false; } if ((Object)(object)value != (Object)(object)root) { EvictRootCache(rootId); return false; } RememberBarrelRollerRoot(root); return true; } internal static void MarkRecentBarrelExplosion(Transform ownerRoot) { if (!((Object)(object)ownerRoot == (Object)null)) { RecentBarrelExplosionTimeByRoot[((Object)ownerRoot).GetInstanceID()] = Time.time; CancelPendingDeathExplosion(ownerRoot); } } internal static void PrepareBarrelOwnedExplosionForDetonation(Explosion explosion) { if (!((Object)(object)explosion == (Object)null) && MightBeBarrelRollerExplosion(explosion)) { Transform val = ResolveBarrelRollerOwnerRoot(((Component)explosion).transform); if (!((Object)(object)val == (Object)null) && IsBarrelRollerOwnedExplosion(explosion, val)) { StripDeathExplosionStatusEffects(((Component)((Component)explosion).transform.root).gameObject); } } } internal static bool TryBlockDuplicateBarrelExplosion(Explosion explosion) { if ((Object)(object)explosion == (Object)null || _executingDeathExplosion || !MightBeBarrelRollerExplosion(explosion)) { return false; } Transform val = ResolveBarrelRollerOwnerRoot(((Component)explosion).transform); if ((Object)(object)val == (Object)null || !IsBarrelRollerOwnedExplosion(explosion, val)) { return false; } int instanceID = ((Object)val).GetInstanceID(); float time = Time.time; if (AllowedBarrelExplosionTimeByRoot.TryGetValue(instanceID, out var value) && time - value <= 0.75f) { return true; } AllowedBarrelExplosionTimeByRoot[instanceID] = time; MarkRecentBarrelExplosion(val); return false; } private static bool MightBeBarrelRollerExplosion(Explosion explosion) { if ((Object)(object)explosion == (Object)null) { return false; } Transform transform = ((Component)explosion).transform; if ((Object)(object)transform == (Object)null) { return false; } if (IsRollingBarrelGearTransform(transform)) { return true; } if (ContainsBarrelExplosionName(((Object)((Component)transform).gameObject).name) || ContainsBarrelExplosionName(((Object)transform.root).name)) { return true; } int instanceID = ((Object)transform.root).GetInstanceID(); return KnownBarrelRollerRootIds.Contains(instanceID); } internal static void NotifyBarrelAbilityExplosionFromSpawn(Transform scope, GameObject prefab) { if (!((Object)(object)scope == (Object)null) && !((Object)(object)prefab == (Object)null) && !_executingDeathExplosion && ContainsBarrelExplosionName(((Object)prefab).name)) { Transform root = scope.root; if (IsBarrelRollerRoot(root)) { MarkRecentBarrelExplosion(root); } } } private static void CancelPendingDeathExplosion(Transform ownerRoot) { if ((Object)(object)ownerRoot == (Object)null) { return; } int instanceID = ((Object)ownerRoot).GetInstanceID(); PendingDeathRootIds.Remove(instanceID); for (int num = PendingDeaths.Count - 1; num >= 0; num--) { if (PendingDeaths[num].RootId == instanceID) { PendingDeaths.RemoveAt(num); } } } private static Transform ResolveBarrelRollerOwnerRoot(Transform explosionTransform) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)explosionTransform == (Object)null) { return null; } TeamHolder val = ((Component)explosionTransform).GetComponent() ?? ((Component)explosionTransform).GetComponentInParent(); if ((Object)(object)val?.spawner != (Object)null) { Transform root = val.spawner.transform.root; if (IsBarrelRollerRoot(root)) { return root; } } if (ContainsBarrelExplosionName(((Object)((Component)explosionTransform).gameObject).name) || ContainsBarrelExplosionName(((Object)explosionTransform.root).name)) { Transform val2 = FindBarrelRollerRootNear(explosionTransform.position); if ((Object)(object)val2 != (Object)null) { return val2; } } Transform root2 = explosionTransform.root; if (IsSpawnedBarrelExplosionPrefabRoot(root2)) { return null; } if (IsBarrelRollerRoot(root2)) { return root2; } return null; } private static bool IsSpawnedBarrelExplosionPrefabRoot(Transform root) { if ((Object)(object)root == (Object)null) { return false; } if ((Object)(object)((Component)root).GetComponentInChildren(true) != (Object)null) { return false; } return ContainsBarrelExplosionName(((Object)root).name); } private static Transform FindBarrelRollerRootNear(Vector3 position) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) Transform result = null; float num = 400f; foreach (KeyValuePair activeBarrelRollerRoot in ActiveBarrelRollerRoots) { if (!KnownBarrelRollerRootIds.Contains(activeBarrelRollerRoot.Key)) { continue; } Transform value = activeBarrelRollerRoot.Value; if (!((Object)(object)value == (Object)null) && !IsSpawnedBarrelExplosionPrefabRoot(value)) { Vector3 val = value.position - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude > num)) { num = sqrMagnitude; result = value; } } } return result; } private static void RememberBarrelRollerRoot(Transform root) { if (!((Object)(object)root == (Object)null)) { ActiveBarrelRollerRoots[((Object)root).GetInstanceID()] = root; } } private static bool IsBarrelRollerOwnedExplosion(Explosion explosion, Transform ownerRoot) { if ((Object)(object)explosion == (Object)null || (Object)(object)ownerRoot == (Object)null) { return false; } if (ContainsBarrelExplosionName(((Object)((Component)explosion).gameObject).name) || ContainsBarrelExplosionName(((Object)((Component)explosion).transform.root).name)) { return true; } if (!BelongsToRoot(((Component)explosion).transform, ownerRoot)) { return false; } if (IsRollingBarrelGearTransform(((Component)explosion).transform)) { return true; } return IsUnderBarrelRollerAbilityMount(((Component)explosion).transform, ownerRoot); } private static bool ContainsBarrelExplosionName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } if (objectName.IndexOf("ExplosionBombBarrel", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (objectName.IndexOf("BarrelE_Explosion", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } internal static bool IsBarrelRollerRoot(Transform root) { if ((Object)(object)root == (Object)null) { return false; } if (IsSpawnedBarrelExplosionPrefabRoot(root)) { return false; } int instanceID = ((Object)root).GetInstanceID(); if (IsCachedBarrelRollerRoot(root, instanceID)) { return true; } if (NotBarrelRollerRootIds.Contains(instanceID)) { return false; } Unit component = ((Component)root).GetComponent(); if (!IsBarrelAbilityUnit(root, component)) { NotBarrelRollerRootIds.Add(instanceID); return false; } KnownBarrelRollerRootIds.Add(instanceID); RememberBarrelRollerRoot(root); return true; } private static bool ShouldSkipDeathForAbilityKill(Transform root) { if ((Object)(object)root == (Object)null || !IsBarrelRollerRoot(root)) { return false; } if (TryGetRecentBarrelExplosionAge(root, out var ageSeconds)) { return ageSeconds <= 0.5f; } return false; } private static bool TryGetRecentBarrelExplosionAge(Transform root, out float ageSeconds) { ageSeconds = float.MaxValue; if ((Object)(object)root == (Object)null) { return false; } if (!RecentBarrelExplosionTimeByRoot.TryGetValue(((Object)root).GetInstanceID(), out var value)) { return false; } ageSeconds = Time.time - value; return ageSeconds <= 2.5f; } internal static bool ShouldSuppressDeathExplosion(Transform root) { if ((Object)(object)root == (Object)null || !IsBarrelRollerRoot(root)) { return false; } return HasRecentBarrelExplosion(root); } internal static void EnsureScheduledFromDead(DataHandler data) { if (!((Object)(object)data == (Object)null) && data.Dead) { TryScheduleFromScope(((Component)data).transform, "DataHandler.Dead"); } } private static void TryScheduleFromScope(Transform scope, string source) { if ((Object)(object)scope == (Object)null) { return; } Transform root = scope.root; if (!IsBarrelRollerRoot(root)) { return; } if (!TryBuildPlan(root, out var plan)) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Barrel death plan failed (" + source + ") on " + ((Object)root).name)); } } else { TrySchedule(plan, source); } } private static void TrySchedule(BarrelDeathPlan plan, string source) { //IL_00c5: 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_007e: 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_0090: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)plan?.Root == (Object)null || (Object)(object)_runner == (Object)null) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Barrel death skip schedule (" + source + "): runner or root missing")); } return; } int instanceID = ((Object)plan.Root).GetInstanceID(); if (!ShouldSkipDeathForAbilityKill(plan.Root) && PendingDeathRootIds.Add(instanceID)) { Vector3 position; bool flag = TryResolveExplosionPosition(plan, out position); if (!flag && plan.HasSnapshotPosition && IsFinite(plan.SnapshotPosition)) { position = plan.SnapshotPosition; flag = true; } PendingDeaths.Add(new PendingBarrelDeath { RootId = instanceID, Plan = plan, ExplodeAt = Time.time + plan.DelaySeconds, ExplodePosition = position, HasExplodePosition = flag }); if (_queueRunner == null) { _queueRunner = _runner.StartCoroutine(ProcessDeathQueue()); } } } [IteratorStateMachine(typeof(d__46))] private static IEnumerator ProcessDeathQueue() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__46(0); } private static void ExecuteDeathExplosion(int rootId, BarrelDeathPlan plan, Vector3 scheduledPosition, bool hasScheduledPosition) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) Transform val = plan?.Root; if ((Object)(object)val != (Object)null && ShouldSuppressDeathExplosion(val)) { CancelPendingDeathExplosion(val); return; } if (!TryResolveDeathExplosionPosition(plan, scheduledPosition, hasScheduledPosition, out var position)) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)$"Barrel death execute failed: no position (rootId={rootId})"); } return; } HideBarrelGear(plan); RefreshOwnerUnit(plan); _executingDeathExplosion = true; try { TriggerSingleBarrelExplosion(plan, position); } catch (Exception ex) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogError((object)$"Barrel death execute failed (rootId={rootId}): {ex.Message}"); } } finally { _executingDeathExplosion = false; } } private static bool TryResolveDeathExplosionPosition(BarrelDeathPlan plan, Vector3 scheduledPosition, bool hasScheduledPosition, out Vector3 position) { //IL_0001: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) position = default(Vector3); if (plan == null) { return false; } if ((Object)(object)plan.Root != (Object)null && TryResolveExplosionPosition(plan, out position)) { return true; } if (hasScheduledPosition && IsFinite(scheduledPosition)) { position = scheduledPosition; return true; } if (plan.HasSnapshotPosition && IsFinite(plan.SnapshotPosition)) { position = plan.SnapshotPosition; return true; } return false; } private static bool TryBuildPlan(Transform root, out BarrelDeathPlan plan) { //IL_00fb: 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) plan = null; if ((Object)(object)root == (Object)null || !IsBarrelRollerRoot(root)) { return false; } float delayFromConditionalEvents = GetDelayFromConditionalEvents(((Component)root).GetComponentsInChildren(true)); Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); CollectBarrelHoldableData(root, componentsInChildren, out var barrelRigidbodies, out var barrelAnchors, out var barrelVisuals); PickExplosionAssets(((Component)root).GetComponentsInChildren(true), out var cachedExplosion, out var fallbackTemplate); GameObject val = FindExplosionPrefab(root); if ((Object)(object)val == (Object)null && (Object)(object)cachedExplosion != (Object)null) { val = FindExplosionPrefabFromTemplate(cachedExplosion); } if ((Object)(object)val != (Object)null) { RememberSharedDeathExplosionAssets(val, cachedExplosion ?? fallbackTemplate); } else if ((Object)(object)_sharedBarrelDeathExplosionPrefab != (Object)null) { val = _sharedBarrelDeathExplosionPrefab; } if ((Object)(object)cachedExplosion == (Object)null && (Object)(object)fallbackTemplate == (Object)null && (Object)(object)_sharedBarrelDeathExplosionTemplate != (Object)null) { fallbackTemplate = _sharedBarrelDeathExplosionTemplate; } Vector3 position; bool hasSnapshotPosition = TryCaptureBarrelSnapshot(barrelRigidbodies, barrelAnchors, root, out position); plan = new BarrelDeathPlan { Root = root, DelaySeconds = delayFromConditionalEvents, BarrelVisuals = barrelVisuals, BarrelRigidbodies = barrelRigidbodies, BarrelAnchors = barrelAnchors, SnapshotPosition = position, HasSnapshotPosition = hasSnapshotPosition, CachedBarrelExplosion = cachedExplosion, CachedExplosionPrefab = val, FallbackExplosionTemplate = (cachedExplosion ?? fallbackTemplate), OwnerUnit = ((Component)root).GetComponent() }; return true; } private static float GetDelayFromConditionalEvents(ConditionalEvent[] conditionalEvents) { float num = 0.45f; if (conditionalEvents == null) { return num; } for (int i = 0; i < conditionalEvents.Length; i++) { ConditionalEventInstance[] array = conditionalEvents[i]?.events; if (array == null) { continue; } foreach (ConditionalEventInstance val in array) { if (HasUnitDeathCondition(val)) { float delay = val.delay; if (delay > num) { num = delay; } } } } return num; } private static void CollectBarrelHoldableData(Transform root, Holdable[] holdables, out Rigidbody[] barrelRigidbodies, out Transform[] barrelAnchors, out GameObject[] barrelVisuals) { List list = new List(); List list2 = new List(); List list3 = new List(); HashSet hashSet = new HashSet(); HashSet hashSet2 = new HashSet(); HashSet hashSet3 = new HashSet(); if (holdables != null) { foreach (Holdable holdable in holdables) { if (IsBarrelHoldable(holdable)) { AddBarrelHoldable(holdable, list, list2, list3, hashSet, hashSet2, hashSet3); } } } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (((Object)val).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0) { if (hashSet2.Add(((Object)val).GetInstanceID())) { list2.Add(val); } if (hashSet3.Add(((Object)((Component)val).gameObject).GetInstanceID())) { list3.Add(((Component)val).gameObject); } Rigidbody componentInChildren = ((Component)val).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null && hashSet.Add(((Object)componentInChildren).GetInstanceID())) { list.Add(componentInChildren); } } } barrelRigidbodies = list.ToArray(); barrelAnchors = list2.ToArray(); barrelVisuals = list3.ToArray(); } private static void AddBarrelHoldable(Holdable holdable, List rigidbodies, List anchors, List visuals, HashSet seenBodies, HashSet seenAnchors, HashSet seenVisuals) { Transform val = (((Object)(object)holdable.rig != (Object)null) ? ((Component)holdable.rig).transform : ((Component)holdable).transform); if ((Object)(object)val != (Object)null && seenAnchors.Add(((Object)val).GetInstanceID())) { anchors.Add(val); } Rigidbody val2 = holdable.rig ?? ((Component)holdable).GetComponentInChildren(); if ((Object)(object)val2 != (Object)null && seenBodies.Add(((Object)val2).GetInstanceID())) { rigidbodies.Add(val2); } if (seenVisuals.Add(((Object)((Component)holdable).gameObject).GetInstanceID())) { visuals.Add(((Component)holdable).gameObject); } } private static void PickExplosionAssets(Explosion[] explosions, out Explosion cachedExplosion, out Explosion fallbackTemplate) { cachedExplosion = null; fallbackTemplate = null; float num = float.MinValue; if (explosions == null) { return; } foreach (Explosion val in explosions) { if ((Object)(object)val == (Object)null) { continue; } if (fallbackTemplate == null) { fallbackTemplate = val; } if (IsBarrelDeathExplosionSource(((Component)val).transform, ((Component)val).transform.root)) { float num2 = ScoreBarrelExplosion(val); if (!(num2 <= num)) { num = num2; cachedExplosion = val; } } } } private static GameObject FindExplosionPrefab(Transform root) { GameObject preferred = null; GameObject val = null; GameObject any = null; RemoveAfterSeconds[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (RemoveAfterSeconds val2 in componentsInChildren) { GameObject val3 = val2?.objectToSpawn; if ((Object)(object)val3 == (Object)null) { continue; } if (any == null) { any = val3; } if (val2.spawnObjectOnMainRig) { if (val == null) { val = val3; } } else { preferred = val3; } } if ((Object)(object)preferred != (Object)null) { return preferred; } KillAfterSeconds[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (KillAfterSeconds val4 in componentsInChildren2) { GameObject val5 = val4?.objectToSpawn; if (!((Object)(object)val5 == (Object)null)) { if (any == null) { any = val5; } if (!val4.spawnObjectOnMainRig) { return val5; } if (val == null) { val = val5; } } } CollectSpawnPrefabs(root, ref preferred, ref any); return preferred ?? val ?? any; } private static void CollectSpawnPrefabs(Transform root, ref GameObject preferred, ref GameObject any) { SpawnObject[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (SpawnObject val in componentsInChildren) { GameObject objectToSpawn = val.objectToSpawn; if (!((Object)(object)objectToSpawn == (Object)null)) { if (any == null) { any = objectToSpawn; } if (IsRollingBarrelGearTransform(((Component)val).transform)) { preferred = objectToSpawn; } } } CollisionEvent[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (CollisionEvent val2 in componentsInChildren2) { GameObject objectToSpawn2 = val2.objectToSpawn; if (!((Object)(object)objectToSpawn2 == (Object)null)) { if (any == null) { any = objectToSpawn2; } if (IsRollingBarrelGearTransform(((Component)val2).transform)) { preferred = objectToSpawn2; } } } } internal static bool IsBarrelDeathDelayEvent(Component component) { if ((Object)(object)component == (Object)null) { return false; } ConditionalEvent componentInParent = component.GetComponentInParent(); if (componentInParent?.events == null) { return IsRollingBarrelGearTransform(component.transform); } for (int i = 0; i < componentInParent.events.Length; i++) { if (HasUnitDeathCondition(componentInParent.events[i])) { return true; } } return false; } private static GameObject FindExplosionPrefabFromTemplate(Explosion template) { if ((Object)(object)template == (Object)null) { return null; } Transform val = ((Component)template).transform; while ((Object)(object)val != (Object)null) { RemoveAfterSeconds component = ((Component)val).GetComponent(); if ((Object)(object)component?.objectToSpawn != (Object)null) { return component.objectToSpawn; } val = val.parent; } return null; } private static bool IsBarrelAbilityMountTransform(Transform transform) { if ((Object)(object)transform == (Object)null) { return false; } string name = ((Object)transform).name; if (name.IndexOf("Wings_Leg_Barrel", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (name.IndexOf("Leg_Barrel", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return name.IndexOf("BarrelRoller", StringComparison.OrdinalIgnoreCase) >= 0; } private static bool IsBarrelRollerAbilityTransform(Transform transform) { return IsBarrelAbilityMountTransform(transform); } private static bool IsUnderBarrelAbilityMount(Transform transform, Transform ownerRoot) { Transform val = transform; while ((Object)(object)val != (Object)null && (!((Object)(object)ownerRoot != (Object)null) || !((Object)(object)val == (Object)(object)ownerRoot))) { if (IsBarrelAbilityMountTransform(val)) { return true; } val = val.parent; } return false; } private static bool IsUnderBarrelRollerAbilityMount(Transform transform, Transform ownerRoot) { return IsUnderBarrelAbilityMount(transform, ownerRoot); } private static bool IsBarrelAbilityUnit(Transform root, Unit unit) { return MatchesBarrelRollerBlueprint(unit); } private static bool HasBarrelAbilityGear(Transform root) { if ((Object)(object)root == (Object)null) { return false; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (IsBarrelAbilityMountTransform(componentsInChildren[i])) { return true; } } Holdable[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { if (IsBarrelHoldable(componentsInChildren2[i])) { return true; } } Explosion[] componentsInChildren3 = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { if (IsBarrelDeathExplosionSource(((Component)componentsInChildren3[i]).transform, root)) { return true; } } DelayEvent[] componentsInChildren4 = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren4.Length; i++) { if (IsBarrelDeathDelayEvent((Component)(object)componentsInChildren4[i])) { return true; } } return false; } private static bool IsBarrelDeathExplosionSource(Transform transform, Transform root) { if ((Object)(object)transform == (Object)null) { return false; } if (ContainsBarrelExplosionName(((Object)((Component)transform).gameObject).name)) { return true; } if (IsRollingBarrelGearTransform(transform)) { return true; } return IsUnderBarrelAbilityMount(transform, root); } private static bool MatchesBarrelRollerBlueprint(Unit unit) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) object obj; if (unit == null) { obj = null; } else { UnitBlueprint unitBlueprint = unit.unitBlueprint; obj = ((unitBlueprint != null) ? unitBlueprint.Entity : null); } if (obj == null) { return false; } if (unit.unitBlueprint.Entity.GUID.m_ID == 846602731) { return true; } string name = unit.unitBlueprint.Entity.Name; if (string.IsNullOrEmpty(name)) { return false; } if (name.IndexOf("BOXER", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (name.IndexOf("BARRELROLLER", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } private static bool HasUnitDeathCondition(ConditionalEventInstance instance) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 EventCondition[] array = instance?.conditions; if (array == null) { return false; } foreach (EventCondition obj in array) { if (obj != null && (int)obj.conditionType == 5) { return true; } } return false; } private static bool TryResolveExplosionPosition(BarrelDeathPlan plan, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); if ((Object)(object)plan?.Root == (Object)null) { return false; } if (TryGetTrackedRigidbodyPosition(plan.BarrelRigidbodies, plan.Root, out position)) { return true; } if (TryGetLiveScanPosition(plan.Root, plan.BarrelVisuals, out position)) { return true; } if (TryGetAnchorPosition(plan.BarrelAnchors, plan.Root, out position)) { return true; } if (plan.HasSnapshotPosition && IsUsableExplosionPosition(plan.Root, plan.SnapshotPosition)) { position = plan.SnapshotPosition; return true; } DataHandler componentInChildren = ((Component)plan.Root).GetComponentInChildren(); if ((Object)(object)componentInChildren?.mainRig != (Object)null && IsUsableExplosionPosition(plan.Root, componentInChildren.mainRig.position)) { position = componentInChildren.mainRig.position; return true; } if (IsUsableExplosionPosition(plan.Root, plan.Root.position)) { position = plan.Root.position; return true; } return false; } private static bool TryCaptureBarrelSnapshot(Rigidbody[] barrelRigidbodies, Transform[] barrelAnchors, Transform root, out Vector3 position) { if (TryGetTrackedRigidbodyPosition(barrelRigidbodies, root, out position)) { return true; } return TryGetAnchorPosition(barrelAnchors, root, out position); } private static bool TryGetAnchorPosition(Transform[] anchors, Transform root, out Vector3 position) { //IL_0001: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); if (anchors == null) { return false; } foreach (Transform val in anchors) { if (!((Object)(object)val == (Object)null)) { position = GetTransformCenter(val); if (IsUsableExplosionPosition(root, position)) { return true; } } } position = default(Vector3); return false; } private static bool TryGetTrackedRigidbodyPosition(Rigidbody[] trackedRigidbodies, Transform root, out Vector3 position) { //IL_0001: 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_0050: 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) position = default(Vector3); Rigidbody val = null; float num = float.MinValue; if (trackedRigidbodies != null) { foreach (Rigidbody val2 in trackedRigidbodies) { if (IsAliveRigidbody(val2)) { float num2 = ScoreBarrelRigidbody(val2); if (num2 > num) { num = num2; val = val2; } } } } if ((Object)(object)val == (Object)null) { return false; } position = val.worldCenterOfMass; return IsUsableExplosionPosition(root, position); } private static bool TryGetLiveScanPosition(Transform root, GameObject[] barrelVisuals, out Vector3 position) { //IL_0001: 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_001f: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_013e: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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) position = default(Vector3); Rigidbody val = FindBarrelRigidbody(root, null); if ((Object)(object)val != (Object)null) { position = val.worldCenterOfMass; return IsUsableExplosionPosition(root, position); } Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Holdable val2 in componentsInChildren) { if (!IsBarrelHoldable(val2)) { continue; } Transform val3 = (((Object)(object)val2.rig != (Object)null) ? ((Component)val2.rig).transform : ((Component)val2).transform); if (!((Object)(object)val3 == (Object)null)) { position = GetTransformCenter(val3); if (IsUsableExplosionPosition(root, position)) { return true; } } } Transform[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (Transform val4 in componentsInChildren2) { if (((Object)val4).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0) { position = GetTransformCenter(val4); if (IsUsableExplosionPosition(root, position)) { return true; } } } if (barrelVisuals != null) { foreach (GameObject val5 in barrelVisuals) { if (!((Object)(object)val5 == (Object)null) && val5.activeInHierarchy) { position = GetTransformCenter(val5.transform); if (IsUsableExplosionPosition(root, position)) { return true; } } } } position = default(Vector3); return false; } private static bool IsUsableExplosionPosition(Transform root, Vector3 position) { //IL_000b: 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_0025: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) if ((Object)(object)root == (Object)null) { return false; } if (float.IsNaN(position.x) || float.IsNaN(position.y) || float.IsNaN(position.z)) { return false; } if (((Vector3)(ref position)).sqrMagnitude < 0.25f) { return false; } Vector3 position2 = root.position; DataHandler componentInChildren = ((Component)root).GetComponentInChildren(); if ((Object)(object)componentInChildren?.mainRig != (Object)null) { position2 = componentInChildren.mainRig.position; } Vector3 val = position - position2; return ((Vector3)(ref val)).sqrMagnitude <= 6400f; } private static bool IsAliveRigidbody(Rigidbody rigidbody) { return (Object)(object)rigidbody != (Object)null; } private static bool BelongsToRoot(Transform transform, Transform root) { if ((Object)(object)transform == (Object)null || (Object)(object)root == (Object)null) { return false; } return (Object)(object)transform.root == (Object)(object)root; } private static Rigidbody FindBarrelRigidbody(Transform root, Rigidbody[] trackedRigidbodies) { Rigidbody result = null; float num = float.MinValue; if (trackedRigidbodies != null) { foreach (Rigidbody val in trackedRigidbodies) { if (IsAliveRigidbody(val)) { float num2 = ScoreBarrelRigidbody(val); if (num2 > num) { num = num2; result = val; } } } } Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Holdable val2 in componentsInChildren) { if (!IsBarrelHoldable(val2)) { continue; } Rigidbody val3 = val2.rig ?? ((Component)val2).GetComponentInChildren(); if (!((Object)(object)val3 == (Object)null) && BelongsToRoot(((Component)val3).transform, root)) { float num3 = ScoreBarrelRigidbody(val3) + 50f; if (num3 > num) { num = num3; result = val3; } } } Rigidbody[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (Rigidbody val4 in componentsInChildren2) { if (BelongsToRoot(((Component)val4).transform, root) && IsRollingBarrelGearTransform(((Component)val4).transform)) { float num4 = ScoreBarrelRigidbody(val4); if (num4 > num) { num = num4; result = val4; } } } return result; } private static bool IsBarrelHoldable(Holdable holdable) { if ((Object)(object)holdable == (Object)null) { return false; } if (IsAbilityMountName(((Object)holdable).name)) { return false; } if (IsBarrelName(((Object)holdable).name)) { return true; } return IsRollingBarrelGearTransform(((Component)holdable).transform); } private static bool IsAbilityMountName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } if (objectName.IndexOf("BarrelRoller", StringComparison.OrdinalIgnoreCase) < 0) { return objectName.IndexOf("Wings_Leg_Barrel", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } internal static bool IsRollingBarrelGearTransform(Transform transform) { Transform val = transform; while ((Object)(object)val != (Object)null) { if (IsAbilityMountName(((Object)val).name)) { return false; } if (((Object)val).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (IsBarrelName(((Object)val).name)) { return true; } if ((Object)(object)val.parent == (Object)null) { break; } val = val.parent; } return false; } private static float ScoreBarrelRigidbody(Rigidbody rigidbody) { float num = rigidbody.mass; string name = ((Object)((Component)rigidbody).transform).name; if (name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0) { num += 200f; } if (IsBarrelName(name)) { num += 100f; } return num; } private static Vector3 GetTransformCenter(Transform transform) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)transform == (Object)null) { return Vector3.zero; } Renderer[] componentsInChildren = ((Component)transform).GetComponentsInChildren(true); if (componentsInChildren.Length != 0) { Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return ((Bounds)(ref bounds)).center; } Rigidbody componentInChildren = ((Component)transform).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { return componentInChildren.worldCenterOfMass; } return transform.position; } private static bool IsBarrelName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } if (objectName.IndexOf("Barrel", StringComparison.OrdinalIgnoreCase) < 0) { return false; } if (objectName.IndexOf("DoubleBarrel", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (objectName.IndexOf("GunBarrel", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } return true; } private static Unit RefreshOwnerUnit(BarrelDeathPlan plan) { if (plan == null) { return null; } if ((Object)(object)plan.OwnerUnit != (Object)null) { return plan.OwnerUnit; } if ((Object)(object)plan.Root == (Object)null) { return null; } plan.OwnerUnit = ((Component)plan.Root).GetComponent(); return plan.OwnerUnit; } private static void RememberSharedDeathExplosionAssets(GameObject prefab, Explosion template) { if ((Object)(object)prefab != (Object)null && (Object)(object)_sharedBarrelDeathExplosionPrefab == (Object)null) { _sharedBarrelDeathExplosionPrefab = prefab; } if ((Object)(object)template != (Object)null && (Object)(object)_sharedBarrelDeathExplosionTemplate == (Object)null) { _sharedBarrelDeathExplosionTemplate = template; } } private static void TriggerSingleBarrelExplosion(BarrelDeathPlan plan, Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (!IsFinite(position)) { return; } Unit ownerUnit = RefreshOwnerUnit(plan); Explosion template = plan.FallbackExplosionTemplate ?? plan.CachedBarrelExplosion ?? _sharedBarrelDeathExplosionTemplate; if ((Object)(object)plan.CachedExplosionPrefab != (Object)null) { GameObject obj = Object.Instantiate(plan.CachedExplosionPrefab, position, Quaternion.identity); PrepareDeathExplosionObject(obj, template); FinalizeDeathExplosionInstance(obj, ownerUnit); obj.SetActive(true); TriggerExplosionOnObject(obj, template); } else if ((Object)(object)_sharedBarrelDeathExplosionPrefab != (Object)null) { GameObject obj2 = Object.Instantiate(_sharedBarrelDeathExplosionPrefab, position, Quaternion.identity); PrepareDeathExplosionObject(obj2, template); FinalizeDeathExplosionInstance(obj2, ownerUnit); obj2.SetActive(true); TriggerExplosionOnObject(obj2, template); } else if ((Object)(object)plan.CachedBarrelExplosion != (Object)null) { GameObject obj3 = Object.Instantiate(((Component)plan.CachedBarrelExplosion).gameObject, position, ((Component)plan.CachedBarrelExplosion).transform.rotation); PrepareDeathExplosionObject(obj3, template); FinalizeDeathExplosionInstance(obj3, ownerUnit); obj3.SetActive(true); TriggerExplosionOnObject(obj3, template); Object.Destroy((Object)(object)obj3, 12f); } else if (!TryCreateFallbackExplosion(position, template, ownerUnit)) { ManualLogSource log = _log; if (log != null) { log.LogWarning((object)"Barrel death fallback explode failed: no viable explosion path"); } } } private static void AttachTeamHolder(GameObject instance, Unit ownerUnit) { if (!((Object)(object)instance == (Object)null) && !((Object)(object)ownerUnit == (Object)null)) { TeamHolder.AddTeamHolder(instance, ownerUnit, (TeamHolder)null); } } private static void FinalizeDeathExplosionInstance(GameObject instance, Unit ownerUnit) { if (!((Object)(object)instance == (Object)null) && !((Object)(object)ownerUnit == (Object)null)) { AttachTeamHolder(instance, ownerUnit); ApplyOwnerLevel(instance, ownerUnit); } } private static void StripDeathExplosionStatusEffects(GameObject instance) { if (!((Object)(object)instance == (Object)null)) { Explosion[] componentsInChildren = instance.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].addEffectFromParent = false; } ExplosionEffect[] componentsInChildren2 = instance.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.Destroy((Object)(object)componentsInChildren2[i]); } AddTargetableEffect[] componentsInChildren3 = instance.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.Destroy((Object)(object)componentsInChildren3[i]); } } } private static void ApplyOwnerLevel(GameObject instance, Unit ownerUnit) { Level val = FindOwnerLevel(ownerUnit); if (!((Object)(object)val == (Object)null)) { Level obj = instance.GetComponent() ?? instance.AddComponent(); obj.levelMultiplier = val.levelMultiplier; obj.level = val.level; obj.ignoreTeam = val.ignoreTeam; TargetableEffect[] componentsInChildren = instance.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].damageMultiplier = val.levelMultiplier; } } } private static Level FindOwnerLevel(Unit ownerUnit) { if ((Object)(object)ownerUnit == (Object)null) { return null; } Level component = ((Component)ownerUnit).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } return ((Component)ownerUnit).GetComponentInChildren(true); } private static void HideBarrelGear(BarrelDeathPlan plan) { if (plan != null) { HideBarrelGearLive(plan.Root, plan.BarrelVisuals, plan.BarrelRigidbodies); } } private static void HideBarrelGearLive(Transform root, GameObject[] cachedVisuals, Rigidbody[] cachedRigidbodies) { if (cachedVisuals != null) { for (int i = 0; i < cachedVisuals.Length; i++) { HideGameObjectTree(cachedVisuals[i]); } } if (cachedRigidbodies != null) { for (int j = 0; j < cachedRigidbodies.Length; j++) { HideRigidbodyGear(cachedRigidbodies[j]); } } if ((Object)(object)root == (Object)null) { return; } Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Holdable val in componentsInChildren) { if (IsBarrelHoldable(val)) { HideGameObjectTree(((Component)val).gameObject); if ((Object)(object)val.rig != (Object)null) { HideRigidbodyGear(val.rig); } } } Transform[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren2) { if (IsRollingBarrelGearTransform(val2) || ((Object)val2).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0) { HideGameObjectTree(((Component)val2).gameObject); } } } private static void HideRigidbodyGear(Rigidbody rigidbody) { if (!((Object)(object)rigidbody == (Object)null)) { HideGameObjectTree(((Component)rigidbody).gameObject); } } private static void HideGameObjectTree(GameObject target) { if ((Object)(object)target == (Object)null) { return; } Renderer[] componentsInChildren = target.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)null) { val.enabled = false; } } Collider[] componentsInChildren2 = target.GetComponentsInChildren(true); foreach (Collider val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } target.SetActive(false); } private static bool HasRecentBarrelExplosion(Transform root) { if ((Object)(object)root == (Object)null) { return false; } if (!RecentBarrelExplosionTimeByRoot.TryGetValue(((Object)root).GetInstanceID(), out var value)) { return false; } return Time.time - value <= 2.5f; } private static float ScoreBarrelExplosion(Explosion explosion) { float num = (((Object)(object)explosion != (Object)null) ? (explosion.radius + explosion.damage * 0.01f) : 0f); if ((((explosion != null) ? ((Object)((Component)explosion).transform).name : null) ?? string.Empty).IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0) { num += 100f; } return num; } private static void PrepareDeathExplosionObject(GameObject instance, Explosion template) { if ((Object)(object)instance == (Object)null) { return; } instance.SetActive(false); StripDeathExplosionStatusEffects(instance); Explosion[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (Explosion val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.automatic = false; ApplyDeathExplosionStats(val, template); } } } private static bool TryCreateFallbackExplosion(Vector3 position, Explosion template, Unit ownerUnit) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!IsFinite(position) || ((Vector3)(ref position)).sqrMagnitude < 0.25f) { return false; } GameObject val = new GameObject("StayCombatFix_BarrelExplosion"); try { val.transform.position = position; FinalizeDeathExplosionInstance(val, ownerUnit); Explosion obj = val.AddComponent(); ApplyDeathExplosionStats(obj, template); obj.automatic = false; obj.Explode(); Object.Destroy((Object)(object)val, 10f); return true; } catch (Exception ex) { ManualLogSource log = _log; if (log != null) { log.LogError((object)("Barrel death fallback explode failed: " + ex.Message)); } Object.Destroy((Object)(object)val); return false; } } private static bool IsFinite(Vector3 value) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsNaN(value.y)) { return !float.IsNaN(value.z); } return false; } private static void TriggerExplosionOnObject(GameObject instance, Explosion template) { if ((Object)(object)instance == (Object)null) { return; } Explosion[] componentsInChildren = instance.GetComponentsInChildren(true); Explosion val = null; float num = float.MinValue; foreach (Explosion val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { float num2 = val2.radius + val2.damage * 0.01f; if (!(num2 <= num)) { num = num2; val = val2; } } } if (!((Object)(object)val == (Object)null)) { ApplyDeathExplosionStats(val, template); val.automatic = false; val.Explode(); } } private unsafe static void ApplyDeathExplosionStats(Explosion explosion, Explosion template) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0099->IL0099: Incompatible stack types: O vs I4 //IL_0093->IL0099: Incompatible stack types: I4 vs O //IL_0093->IL0099: Incompatible stack types: O vs I4 if (!((Object)(object)explosion == (Object)null)) { float radius = (((Object)(object)template != (Object)null) ? template.radius : 4f); float force = (((Object)(object)template != (Object)null) ? template.force : 350f); float minMassCap = (((Object)(object)template != (Object)null) ? template.minMassCap : 25f); explosion.damage = 15f; explosion.percentDamage = 0f; explosion.radius = radius; explosion.force = force; explosion.minMassCap = minMassCap; explosion.layerMask = LayerMask.op_Implicit(-1); object obj = explosion; int num; if ((Object)(object)template != (Object)null) { obj = template.forceDirection; num = (int)obj; } else { num = 0; obj = num; num = (int)obj; } System.Runtime.CompilerServices.Unsafe.Write(&((Explosion)num).forceDirection, (ForceDirection)obj); explosion.ignoreTeamMates = (Object)(object)template != (Object)null && template.ignoreTeamMates; explosion.ignoreRoot = true; } } } internal static class BarrelRollerDeathPatches { public static bool ConditionalEvent_OnUnitDead_Prefix(ConditionalEvent __instance) { Transform val = ((__instance != null) ? ((Component)__instance).transform.root : null); if ((Object)(object)val == (Object)null) { return true; } return !BarrelRollerDeathLogic.IsBarrelRollerRoot(val); } public static bool Explosion_Explode_Prefix(Explosion __instance) { BarrelRollerDeathLogic.PrepareBarrelOwnedExplosionForDetonation(__instance); return !BarrelRollerDeathLogic.TryBlockDuplicateBarrelExplosion(__instance); } public static void KillAfterSeconds_Spawn_Postfix(KillAfterSeconds __instance) { BarrelRollerDeathLogic.NotifyBarrelAbilityExplosionFromSpawn((__instance != null) ? ((Component)__instance).transform : null, __instance?.objectToSpawn); } public static void RemoveAfterSeconds_TriggerRemoval_Postfix(MonoBehaviour __instance) { if (!((Object)(object)__instance == (Object)null) && !(((object)__instance).GetType().Name != "RemoveAfterSeconds")) { GameObject value = Traverse.Create((object)__instance).Field("objectToSpawn").Value; BarrelRollerDeathLogic.NotifyBarrelAbilityExplosionFromSpawn(((Component)__instance).transform, value); } } public static bool DelayEvent_Go_Prefix(DelayEvent __instance) { Transform val = ((__instance != null) ? ((Component)__instance).transform.root : null); if ((Object)(object)val == (Object)null || !BarrelRollerDeathLogic.IsBarrelRollerRoot(val)) { return true; } if (!BarrelRollerDeathLogic.IsBarrelDeathDelayEvent((Component)(object)__instance)) { return true; } DataHandler componentInChildren = ((Component)val).GetComponentInChildren(); if ((Object)(object)componentInChildren == (Object)null || !componentInChildren.Dead) { return true; } return false; } public static void GameStateManager_EnterPlacementState_Postfix() { BarrelRollerDeathLogic.ResetBattleCaches(); } } internal static class BattleCreatorSaveWhitelistFix { private static readonly FieldInfo BannedUnitsField = AccessTools.Field(AccessTools.TypeByName("BattleCreatorSaveUI"), "BannedUnits"); private static readonly FieldInfo AllowedFactionsField = AccessTools.Field(AccessTools.TypeByName("BattleCreatorSaveUI"), "AllowedFactions"); private static readonly MethodInfo GetAllowedUnitIdsMethod = AccessTools.Method(AccessTools.TypeByName("BattleCreatorSaveUI"), "GetAllowedUnitIDs", (Type[])null, (Type[])null); private static readonly MethodInfo UpdateUnitFilterMethod = AccessTools.Method(AccessTools.TypeByName("BattleCreatorSaveUI"), "UpdateUnitFilter", (Type[])null, (Type[])null); private static readonly FieldInfo FactionButtonPlacementUiField = AccessTools.Field(AccessTools.TypeByName("FactionButton"), "m_placementUI"); private static readonly FieldInfo FactionButtonIsDraggingField = AccessTools.Field(AccessTools.TypeByName("FactionButton"), "isDragging"); private static readonly Type UnitWhitelistUiType = AccessTools.TypeByName("UnitWhitelistUI"); internal static bool OnUnitClicked(object saveUi, DatabaseID unit) { //IL_0067: 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_007e: 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_0087: Unknown result type (might be due to invalid IL or missing references) if (saveUi == null || BannedUnitsField == null) { return true; } if (!(BannedUnitsField.GetValue(saveUi) is List list)) { return true; } List allUnits = CollectAllUnitIds(AllowedFactionsField?.GetValue(saveUi) as Faction[]); DatabaseID[] allowedUnitIds = GetAllowedUnitIds(saveUi); if (IsFullyUnrestricted(list, allowedUnitIds, allUnits)) { BanAllExceptUnit(list, allUnits, unit); RefreshFilter(saveUi); return false; } if (IsSoloUnit(allowedUnitIds, unit)) { list.Clear(); RefreshFilter(saveUi); return false; } if (list.Contains(unit)) { list.Remove(unit); } else { list.Add(unit); } RefreshFilter(saveUi); return false; } internal static void OnFactionPointerUp(object factionButton, object eventData) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (factionButton == null || FactionButtonPlacementUiField == null || UnitWhitelistUiType == null || eventData == null || (FactionButtonIsDraggingField != null && (bool)FactionButtonIsDraggingField.GetValue(factionButton))) { return; } FieldInfo fieldInfo = AccessTools.Field(eventData.GetType(), "button"); if (fieldInfo != null && (int)fieldInfo.GetValue(eventData) != 0) { return; } object value = FactionButtonPlacementUiField.GetValue(factionButton); if (value == null || !UnitWhitelistUiType.IsInstanceOfType(value)) { return; } PropertyInfo propertyInfo = AccessTools.Property(factionButton.GetType(), "WasAlreadySelected"); if (propertyInfo == null || !(bool)propertyInfo.GetValue(factionButton)) { return; } PropertyInfo propertyInfo2 = AccessTools.Property(factionButton.GetType(), "m_factionID"); if (!(propertyInfo2 == null)) { DatabaseID factionId = (DatabaseID)propertyInfo2.GetValue(factionButton); object obj = AccessTools.Field(UnitWhitelistUiType, "m_SaveUI")?.GetValue(value); if (obj != null) { SoloFaction(obj, factionId); } } } private static void SoloFaction(object saveUi, DatabaseID factionId) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!(BannedUnitsField?.GetValue(saveUi) is List list)) { return; } List allUnits = CollectAllUnitIds(AllowedFactionsField?.GetValue(saveUi) as Faction[]); DatabaseID[] allowedUnitIds = GetAllowedUnitIds(saveUi); Faction faction = ContentDatabase.Instance().GetFaction(factionId); if (!((Object)(object)faction == (Object)null)) { if (IsFullyUnrestricted(list, allowedUnitIds, allUnits)) { BanAllExceptFaction(list, allUnits, faction); RefreshFilter(saveUi); } else if (IsSoloFaction(allowedUnitIds, allUnits, faction)) { list.Clear(); RefreshFilter(saveUi); } } } private static void BanAllExceptUnit(List bannedUnits, List allUnits, DatabaseID keepUnit) { //IL_000c: 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_001c: Unknown result type (might be due to invalid IL or missing references) bannedUnits.Clear(); for (int i = 0; i < allUnits.Count; i++) { if (allUnits[i] != keepUnit) { bannedUnits.Add(allUnits[i]); } } } private static void BanAllExceptFaction(List bannedUnits, List allUnits, Faction faction) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) bannedUnits.Clear(); for (int i = 0; i < allUnits.Count; i++) { if (!faction.DoesIncludeUnit(allUnits[i])) { bannedUnits.Add(allUnits[i]); } } } private static List CollectAllUnitIds(Faction[] allowedFactions) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if (allowedFactions == null) { return list; } foreach (Faction val in allowedFactions) { if (((val != null) ? val.Units : null) == null) { continue; } for (int j = 0; j < val.Units.Length; j++) { UnitBlueprint val2 = val.Units[j]; if (!((Object)(object)val2 == (Object)null) && val2.Entity != null) { DatabaseID gUID = val2.Entity.GUID; if (!list.Contains(gUID)) { list.Add(gUID); } } } } return list; } private static DatabaseID[] GetAllowedUnitIds(object saveUi) { if (GetAllowedUnitIdsMethod == null) { return (DatabaseID[])(object)new DatabaseID[0]; } return (DatabaseID[])(((object)(GetAllowedUnitIdsMethod.Invoke(saveUi, null) as DatabaseID[])) ?? ((object)new DatabaseID[0])); } private static bool IsFullyUnrestricted(List bannedUnits, DatabaseID[] allowedUnits, List allUnits) { if (bannedUnits.Count == 0 && allowedUnits.Length == allUnits.Count) { return allUnits.Count > 0; } return false; } private static bool IsSoloUnit(DatabaseID[] allowedUnits, DatabaseID unit) { //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) if (allowedUnits.Length == 1) { return allowedUnits[0] == unit; } return false; } private static bool IsSoloFaction(DatabaseID[] allowedUnits, List allUnits, Faction faction) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (allUnits.Count == 0 || (Object)(object)faction == (Object)null) { return false; } for (int i = 0; i < allUnits.Count; i++) { DatabaseID val = allUnits[i]; bool num = faction.DoesIncludeUnit(val); bool flag = ContainsUnit(allowedUnits, val); if (num != flag) { return false; } } return true; } private static bool ContainsUnit(DatabaseID[] allowedUnits, DatabaseID id) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < allowedUnits.Length; i++) { if (allowedUnits[i] == id) { return true; } } return false; } private static void RefreshFilter(object saveUi) { UpdateUnitFilterMethod?.Invoke(saveUi, null); } } internal static class BattleCreatorSaveWhitelistPatches { public static bool OnUnitClicked_Prefix(object __instance, DatabaseID unit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return BattleCreatorSaveWhitelistFix.OnUnitClicked(__instance, unit); } public static void OnFactionPointerUp_Postfix(object __instance, object eventData) { BattleCreatorSaveWhitelistFix.OnFactionPointerUp(__instance, eventData); } } internal static class ConfigCleanup { private static readonly ConfigDefinition[] OrphanedMonolithKeys = (ConfigDefinition[])(object)new ConfigDefinition[42] { new ConfigDefinition("Mirror.Shield", "Enabled"), new ConfigDefinition("Mirror.Shield", "Improved"), new ConfigDefinition("Mirror.Shield", "BreakSoundEnabled"), new ConfigDefinition("Mirror.Shield", "BreakSoundMode"), new ConfigDefinition("Mirror.Shield", "VanillaBreakSoundRef"), new ConfigDefinition("Mirror.Shield", "CustomBreakSoundFile"), new ConfigDefinition("Mirror.Shield", "BreakSoundVolume"), new ConfigDefinition("Possession.FirstPerson", "FreeAim"), new ConfigDefinition("Combat.HeadshotFeedback", "Enabled"), new ConfigDefinition("Combat.HeadshotFeedback", "FirstHeadDamageMultiplier"), new ConfigDefinition("Combat.HeadshotFeedback", "RepeatHeadDamageMultiplier"), new ConfigDefinition("Combat.HeadshotFeedback", "FirstStaggerDamageThreshold"), new ConfigDefinition("Combat.HeadshotFeedback", "RepeatStaggerDamageThreshold"), new ConfigDefinition("Combat.HeadshotFeedback", "BaseStunSeconds"), new ConfigDefinition("Combat.HeadshotFeedback", "DamageStep"), new ConfigDefinition("Combat.HeadshotFeedback", "StunSecondsPer50Damage"), new ConfigDefinition("Combat.LimbDamage", "Enabled"), new ConfigDefinition("Combat.LimbDamage", "LimbMultiplier"), new ConfigDefinition("CustomVoices", "Enabled"), new ConfigDefinition("CustomVoices", "PreviewVolume"), new ConfigDefinition("CustomVoices", "BattleVolume"), new ConfigDefinition("CustomVoices", "MaxDurationSeconds"), new ConfigDefinition("UnitEditor", "CustomTargetingTypes"), new ConfigDefinition("UnitEditor", "NearRangeAttackRangeFraction"), new ConfigDefinition("UnitEditor", "MaxSearchRangeMultiplier"), new ConfigDefinition("UnitEditor", "ShortRangeAttackThreshold"), new ConfigDefinition("UnitEditor", "ShortRangeNearFraction"), new ConfigDefinition("UnitEditor", "ShortRangeApproachMultiplier"), new ConfigDefinition("UnitEditor", "LongRangeNearFraction"), new ConfigDefinition("UnitEditor", "LongRangeApproachMultiplier"), new ConfigDefinition("UnitEditor", "RangedEnemiesShortNearFraction"), new ConfigDefinition("UnitEditor", "RangedEnemiesLongNearFraction"), new ConfigDefinition("UnitEditor", "MostExpensiveEnemyRetargetInterval"), new ConfigDefinition("UnitEditor", "CustomEnemyTargetingRetargetInterval"), new ConfigDefinition("UnitEditor", "CustomFootsteps"), new ConfigDefinition("UnitEditor", "MoveWhileTurningEnabled"), new ConfigDefinition("UnitEditor", "CustomFootstepsDebug"), new ConfigDefinition("UnitEditor", "FootstepPitchMin"), new ConfigDefinition("UnitEditor", "FootstepPitchMax"), new ConfigDefinition("Movement", "FixNeverStopDirectChargeInRange"), new ConfigDefinition("TeamLine", "Enabled"), new ConfigDefinition("WinConditions", "Enabled") }; internal static void RemoveOrphanedMonolithKeys(ConfigFile config) { ConfigDefinition[] orphanedMonolithKeys = OrphanedMonolithKeys; foreach (ConfigDefinition val in orphanedMonolithKeys) { config.Remove(val); } } } internal static class CustomUnitRangedMovementFix { private const float FallbackWaitingDistance = 100f; private static float? _cachedVanillaWaitingDistance; private static bool _loggedResolution; private static string _waitingDistanceSource = "default fallback"; internal static void EnsureRangedHoldDistance(UnitBlueprint blueprint) { //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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!UnitMarkerConfig.FixRangedEdgeHold || (Object)(object)blueprint == (Object)null || !blueprint.IsCustomUnit) { return; } List movementComponents = blueprint.MovementComponents; if (movementComponents == null || movementComponents.Count == 0) { return; } float num = ResolveWaitingDistance(blueprint); bool flag = false; for (int i = 0; i < movementComponents.Count; i++) { if (movementComponents[i] is KeepRangedDistance val && !(val.WaitingDistance > 0f)) { val.WaitingDistance = num; movementComponents[i] = (IMovementComponent)(object)val; flag = true; } } if (flag && !_loggedResolution) { _loggedResolution = true; Plugin.LogInfo($"Custom unit ranged edge hold: WaitingDistance={num:0.##} " + "(source=" + DescribeWaitingDistanceSource() + ")"); } } public static void DeserializedUnit_Postfix(ref UnitBlueprint __result) { EnsureRangedHoldDistance(__result); } public static void Spawn_Prefix(UnitBlueprint __instance) { EnsureRangedHoldDistance(__instance); } private static float ResolveWaitingDistance(UnitBlueprint blueprint) { float? num = TryGetVanillaWaitingDistance(); if (num.HasValue) { _waitingDistanceSource = "vanilla template"; return num.Value; } float num2 = TryGetWaitingDistanceFromWeapons(blueprint); if (num2 > 0f) { _waitingDistanceSource = "weapon range fallback"; return num2; } _waitingDistanceSource = "default fallback"; return 100f; } private static float? TryGetVanillaWaitingDistance() { if (_cachedVanillaWaitingDistance.HasValue) { return _cachedVanillaWaitingDistance.Value; } ContentDatabase val = ContentDatabase.Instance(); if (val == null) { return null; } foreach (UnitBlueprint item in val.GetAllUnitBlueprints() ?? Enumerable.Empty()) { if (!((Object)(object)item == (Object)null) && !item.IsCustomUnit && TryGetKeepRangedDistance(item.MovementComponents, out var waitingDistance)) { _cachedVanillaWaitingDistance = waitingDistance; return waitingDistance; } } return null; } private static bool TryGetKeepRangedDistance(IReadOnlyList movementComponents, out float waitingDistance) { //IL_0021: 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_0027: 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) waitingDistance = 0f; if (movementComponents == null) { return false; } for (int i = 0; i < movementComponents.Count; i++) { if (movementComponents[i] is KeepRangedDistance val && !(val.WaitingDistance <= 0f)) { waitingDistance = val.WaitingDistance; return true; } } return false; } private static float TryGetWaitingDistanceFromWeapons(UnitBlueprint blueprint) { float num = 0f; if ((Object)(object)blueprint.RightWeapon != (Object)null) { RangeWeapon component = blueprint.RightWeapon.GetComponent(); if ((Object)(object)component != (Object)null) { num = Mathf.Max(num, ((Weapon)component).maxRange); } } if ((Object)(object)blueprint.LeftWeapon != (Object)null) { RangeWeapon component2 = blueprint.LeftWeapon.GetComponent(); if ((Object)(object)component2 != (Object)null) { num = Mathf.Max(num, ((Weapon)component2).maxRange); } } if (num <= 0f) { return 0f; } return num + 0.3f; } private static string DescribeWaitingDistanceSource() { return _waitingDistanceSource; } } internal static class EcsComponentHelper { private static readonly PropertyInfo WorldActiveProperty = AccessTools.Property(typeof(World), "Active"); private static readonly MethodInfo GetExistingManagerMethod = AccessTools.Method(typeof(World), "GetExistingManager", (Type[])null, (Type[])null); private static readonly PropertyInfo ComponentSystemEntityManagerProperty = AccessTools.Property(typeof(ComponentSystemBase), "EntityManager"); internal static readonly Type GameObjectEntityType = AccessTools.TypeByName("GameObjectEntity") ?? AccessTools.TypeByName("Unity.Entities.Hybrid.GameObjectEntity, Unity.Entities.Hybrid"); internal static bool IsAvailable { get { if (WorldActiveProperty != null && GetExistingManagerMethod != null) { return ComponentSystemEntityManagerProperty != null; } return false; } } internal static World GetActiveWorld() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return (World)(WorldActiveProperty?.GetValue(null, null)); } internal static EntityManager GetEntityManager() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown World activeWorld = GetActiveWorld(); if (activeWorld == null || GetExistingManagerMethod == null) { return null; } Type type = AccessTools.TypeByName("Landfall.TABS.AI.Systems.UnitECSToMonoSyncSystem, Assembly-CSharp"); if (type == null) { return null; } object? obj = GetExistingManagerMethod.MakeGenericMethod(type).Invoke(activeWorld, null); ComponentSystemBase val = (ComponentSystemBase)((obj is ComponentSystemBase) ? obj : null); if (val == null) { return null; } return (EntityManager)ComponentSystemEntityManagerProperty.GetValue(val, null); } internal static TManager GetExistingManager() where TManager : class { World activeWorld = GetActiveWorld(); if (activeWorld == null || GetExistingManagerMethod == null) { return null; } return (TManager)GetExistingManagerMethod.MakeGenericMethod(typeof(TManager)).Invoke(activeWorld, null); } internal static bool TryGetComponentData(EntityManager entityManager, Entity entity, out T data) where T : struct, IComponentData { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) data = default(T); if (!entityManager.IsCreated || !entityManager.Exists(entity) || !entityManager.HasComponent(entity)) { return false; } data = entityManager.GetComponentData(entity); return true; } internal static bool TryGetEntityManager(Component component, out Entity entity, out EntityManager entityManager) { //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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown entity = Entity.Null; entityManager = null; if ((Object)(object)component == (Object)null || GameObjectEntityType == null) { return false; } Component component2 = component.GetComponent(GameObjectEntityType); if ((Object)(object)component2 == (Object)null) { return false; } PropertyInfo propertyInfo = AccessTools.Property(GameObjectEntityType, "Entity"); PropertyInfo propertyInfo2 = AccessTools.Property(GameObjectEntityType, "EntityManager"); if (propertyInfo == null || propertyInfo2 == null) { return false; } entity = (Entity)propertyInfo.GetValue(component2, null); entityManager = (EntityManager)propertyInfo2.GetValue(component2, null); return entityManager.IsCreated; } internal static T GetArrayItem(object array, int index) { PropertyInfo? property = array.GetType().GetProperty("Item", new Type[1] { typeof(int) }); if (property == null) { throw new MissingMemberException(array.GetType().FullName, "Item[int]"); } return (T)property.GetValue(array, new object[1] { index }); } } internal sealed class FactionCreatorCostHoverState : MonoBehaviour { private bool _captured; private Transform _costParent; private int _costSiblingIndex; private Vector2 _anchorMin; private Vector2 _anchorMax; private Vector2 _pivot; private Vector2 _anchoredPosition; private Vector3 _localScale; internal void CaptureCostLayout(RectTransform costRect) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_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_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) if (!_captured && !((Object)(object)costRect == (Object)null)) { _costParent = ((Transform)costRect).parent; _costSiblingIndex = ((Transform)costRect).GetSiblingIndex(); _anchorMin = costRect.anchorMin; _anchorMax = costRect.anchorMax; _pivot = costRect.pivot; _anchoredPosition = costRect.anchoredPosition; _localScale = ((Transform)costRect).localScale; _captured = true; } } internal void RestoreCostLayout(RectTransform costRect) { //IL_002d: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (_captured && !((Object)(object)costRect == (Object)null)) { ((Transform)costRect).SetParent(_costParent, false); ((Transform)costRect).SetSiblingIndex(_costSiblingIndex); costRect.anchorMin = _anchorMin; costRect.anchorMax = _anchorMax; costRect.pivot = _pivot; costRect.anchoredPosition = _anchoredPosition; ((Transform)costRect).localScale = _localScale; } } internal static FactionCreatorCostHoverState GetOrCreate(UnitButtonBase button) { return ((Component)button).gameObject.GetComponent() ?? ((Component)button).gameObject.AddComponent(); } } internal sealed class FactionCreatorDragScrollSession : MonoBehaviour { private ScrollRect _scrollRect; private Camera _eventCamera; private FactionCreatorUnitDragReorder _drag; internal void Begin(ScrollRect scrollRect, Camera eventCamera, FactionCreatorUnitDragReorder drag) { _scrollRect = scrollRect; _eventCamera = eventCamera; _drag = drag; } private void Update() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_scrollRect == (Object)null) && !((Object)(object)_drag == (Object)null)) { FactionCreatorReorderLogic.UpdateDragScroll(_scrollRect, _drag.CurrentScreenPosition, _eventCamera); } } } internal static class FactionCreatorDropGap { private const string GapObjectName = "StayCombatFix_DropGap"; internal static RectTransform Create(RectTransform listParent, RectTransform unitButton, bool horizontal) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_006a: 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) GameObject val = new GameObject("StayCombatFix_DropGap", new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent(); ((Transform)component).SetParent((Transform)(object)listParent, false); ((Transform)component).localScale = Vector3.one; LayoutElement obj = val.AddComponent(); float num = LayoutUtility.GetPreferredWidth(unitButton); float num2 = LayoutUtility.GetPreferredHeight(unitButton); Rect rect; if (num <= 1f) { rect = unitButton.rect; num = ((Rect)(ref rect)).width; } if (num2 <= 1f) { rect = unitButton.rect; num2 = ((Rect)(ref rect)).height; } obj.preferredWidth = num; obj.preferredHeight = num2; obj.minWidth = num; obj.minHeight = num2; obj.flexibleWidth = 0f; obj.flexibleHeight = 0f; CreateCircleHighlight(component, unitButton, num, num2); return component; } internal static void Destroy(RectTransform gap) { if ((Object)(object)gap != (Object)null) { Object.Destroy((Object)(object)((Component)gap).gameObject); } } private static void CreateCircleHighlight(RectTransform gapRect, RectTransform unitButton, float width, float height) { //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_0052: 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_007c: 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_0093: 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_00f5: Unknown result type (might be due to invalid IL or missing references) UnitButtonBase component = ((Component)unitButton).GetComponent(); Image val = component?.NameSelect; float num = Mathf.Min(width, height); GameObject val2 = new GameObject("Highlight", new Type[1] { typeof(RectTransform) }); RectTransform component2 = val2.GetComponent(); ((Transform)component2).SetParent((Transform)(object)gapRect, false); component2.anchorMin = new Vector2(0.5f, 0.5f); component2.anchorMax = new Vector2(0.5f, 0.5f); component2.pivot = new Vector2(0.5f, 0.5f); component2.sizeDelta = new Vector2(num, num); component2.anchoredPosition = Vector2.zero; Image val3 = val2.AddComponent(); ((Graphic)val3).raycastTarget = false; val3.preserveAspect = true; ((Graphic)val3).color = new Color(1f, 1f, 1f, 0.38f); if ((Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null) { val3.sprite = val.sprite; val3.type = val.type; } else if ((Object)(object)component?.IconImage != (Object)null && (Object)(object)component.IconImage.sprite != (Object)null) { val3.sprite = component.IconImage.sprite; } } } internal static class FactionCreatorPatches { public static void AddNewUnit_Postfix(FactionCreatorManager __instance) { if (!((Object)(object)__instance?.FactionListParent == (Object)null) && __instance.FactionListParent.childCount != 0) { FactionCreatorReorderLogic.AttachDragHandle(((Component)__instance.FactionListParent.GetChild(__instance.FactionListParent.childCount - 1)).GetComponent(), __instance); } } public static void LoadFaction_Postfix(FactionCreatorManager __instance) { FactionCreatorReorderLogic.RefreshAllDragHandles(__instance); } public static void SaveNewFaction_Prefix(FactionCreatorManager __instance) { FactionCreatorReorderLogic.SyncAddedUnitsFromHierarchy(__instance); } public static void GetFactionUnits_Prefix(FactionCreatorManager __instance) { FactionCreatorReorderLogic.SyncAddedUnitsFromHierarchy(__instance); } public static bool UnitButtonFactionCreator_OnClick_Prefix(UnitButtonFactionCreator __instance) { FactionCreatorUnitDragReorder component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { return !component.ConsumeClickSuppression(); } return true; } public static void UnitButtonBase_OnPointerEnter_Postfix(UnitButtonBase __instance) { FactionCreatorUnitCostHover.ShowOnHover(__instance); } public static void UnitButtonBase_OnPointerExit_Postfix(UnitButtonBase __instance) { FactionCreatorUnitCostHover.HideOnHover(__instance); } public static void UnitButtonBase_OnSelect_Postfix(UnitButtonBase __instance) { FactionCreatorUnitCostHover.ShowOnHover(__instance); } public static void UnitButtonBase_OnDeselect_Postfix(UnitButtonBase __instance) { FactionCreatorUnitCostHover.HideOnHover(__instance); } } internal static class FactionCreatorReorderLogic { private static readonly FieldInfo AddedUnitsField = AccessTools.Field(typeof(FactionCreatorManager), "addedUnits"); private static FieldInfo _spawnedButtonField; internal static void AttachDragHandle(UnitButtonBase button, FactionCreatorManager manager) { if (!((Object)(object)button == (Object)null) && !((Object)(object)manager == (Object)null) && !((Object)(object)((Component)button).GetComponent() != (Object)null)) { ((Component)button).gameObject.AddComponent().Initialize(manager, button); } } internal static void RefreshAllDragHandles(FactionCreatorManager manager) { if ((Object)(object)manager?.FactionListParent == (Object)null) { return; } for (int i = 0; i < manager.FactionListParent.childCount; i++) { UnitButtonBase component = ((Component)manager.FactionListParent.GetChild(i)).GetComponent(); if ((Object)(object)component != (Object)null) { AttachDragHandle(component, manager); } } } internal static int GetUnitIndex(FactionCreatorManager manager, UnitButtonBase button) { IList addedUnits = GetAddedUnits(manager); if (addedUnits == null || (Object)(object)button == (Object)null) { return -1; } for (int i = 0; i < addedUnits.Count; i++) { if ((Object)(object)GetSpawnedButton(addedUnits[i]) == (Object)(object)button) { return i; } } return -1; } internal static void SyncAddedUnitsFromHierarchy(FactionCreatorManager manager) { IList addedUnits = GetAddedUnits(manager); Transform val = manager?.FactionListParent; if (addedUnits == null || (Object)(object)val == (Object)null || addedUnits.Count == 0) { return; } Dictionary dictionary = new Dictionary(); for (int i = 0; i < addedUnits.Count; i++) { UnitButtonBase spawnedButton = GetSpawnedButton(addedUnits[i]); if ((Object)(object)spawnedButton != (Object)null && !dictionary.ContainsKey(spawnedButton)) { dictionary[spawnedButton] = addedUnits[i]; } } List list = new List(); for (int j = 0; j < val.childCount; j++) { UnitButtonBase component = ((Component)val.GetChild(j)).GetComponent(); if ((Object)(object)component != (Object)null && dictionary.TryGetValue(component, out var value)) { list.Add(value); } } if (list.Count == addedUnits.Count) { addedUnits.Clear(); for (int k = 0; k < list.Count; k++) { addedUnits.Add(list[k]); } } } internal static ScrollRect FindListScrollRect(FactionCreatorManager manager) { if (!((Object)(object)manager?.FactionListParent != (Object)null)) { return null; } return ((Component)manager.FactionListParent).GetComponentInParent(); } internal static bool IsHorizontalLayout(RectTransform listParent) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)listParent != (Object)null) { Rect rect = listParent.rect; float width = ((Rect)(ref rect)).width; rect = listParent.rect; return width >= ((Rect)(ref rect)).height; } return false; } internal static void UpdateDragScroll(ScrollRect scrollRect, Vector2 screenPosition, Camera eventCamera) { //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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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) if ((Object)(object)scrollRect == (Object)null) { return; } RectTransform val = (RectTransform)(((Object)(object)scrollRect.viewport != (Object)null) ? ((object)scrollRect.viewport) : ((object)/*isinst with value type is only supported in some contexts*/)); Vector2 val2 = default(Vector2); if ((Object)(object)val == (Object)null || !RectTransformUtility.ScreenPointToLocalPointInRectangle(val, screenPosition, eventCamera, ref val2)) { return; } Rect rect = val.rect; float unscaledDeltaTime = Time.unscaledDeltaTime; if (scrollRect.horizontal) { float num = val2.x - ((Rect)(ref rect)).xMin; float num2 = ((Rect)(ref rect)).xMax - val2.x; float num3 = 0f; if (num < 72f) { num3 = (0f - Mathf.InverseLerp(72f, 0f, num)) * 2.5f * unscaledDeltaTime; } else if (num2 < 72f) { num3 = Mathf.InverseLerp(72f, 0f, num2) * 2.5f * unscaledDeltaTime; } if (Mathf.Abs(num3) > 0.0001f) { scrollRect.horizontalNormalizedPosition = Mathf.Clamp01(scrollRect.horizontalNormalizedPosition + num3); } } if (scrollRect.vertical) { float num4 = val2.y - ((Rect)(ref rect)).yMin; float num5 = ((Rect)(ref rect)).yMax - val2.y; float num6 = 0f; if (num4 < 72f) { num6 = (0f - Mathf.InverseLerp(72f, 0f, num4)) * 2.5f * unscaledDeltaTime; } else if (num5 < 72f) { num6 = Mathf.InverseLerp(72f, 0f, num5) * 2.5f * unscaledDeltaTime; } if (Mathf.Abs(num6) > 0.0001f) { scrollRect.verticalNormalizedPosition = Mathf.Clamp01(scrollRect.verticalNormalizedPosition + num6); } } } internal static int GetInsertionIndex(FactionCreatorManager manager, Vector2 screenPosition, Camera camera, Transform ignore, int currentIndex = -1) { //IL_0026: 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_004a: 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_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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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) Transform obj = manager?.FactionListParent; RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if ((Object)(object)val == (Object)null || ((Transform)val).childCount == 0) { return 0; } Vector2 val2 = default(Vector2); if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(val, screenPosition, camera, ref val2)) { return Mathf.Clamp(currentIndex, 0, ((Transform)val).childCount); } bool flag = IsHorizontalLayout(val); float num = (flag ? val2.x : val2.y); int num2 = 0; for (int i = 0; i < ((Transform)val).childCount; i++) { Transform child = ((Transform)val).GetChild(i); RectTransform val3 = (RectTransform)(object)((child is RectTransform) ? child : null); if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)ignore)) { Rect rect = val3.rect; Vector3 val4 = ((Transform)val).InverseTransformPoint(((Transform)val3).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))); float num3 = (flag ? val4.x : val4.y); if (num > num3) { num2 = i + 1; } } } num2 = Mathf.Clamp(num2, 0, ((Transform)val).childCount); if (currentIndex < 0) { return num2; } if (num2 == currentIndex) { return currentIndex; } if (Mathf.Abs(num2 - currentIndex) > 1) { num2 = currentIndex + ((num2 > currentIndex) ? 1 : (-1)); } return num2; } private static IList GetAddedUnits(FactionCreatorManager manager) { return AddedUnitsField?.GetValue(manager) as IList; } private static UnitButtonBase GetSpawnedButton(object wrapper) { object? obj = (_spawnedButtonField ?? (_spawnedButtonField = AccessTools.Field(AccessTools.Inner(typeof(FactionCreatorManager), "SpawnedWrapper"), "spawnedButton")))?.GetValue(wrapper); return (UnitButtonBase)((obj is UnitButtonBase) ? obj : null); } } internal static class FactionCreatorUnitCostHover { private static readonly FieldInfo UnitCostField = AccessTools.Field(typeof(UnitButtonBase), "UnitCost"); private static readonly FieldInfo TargetIconColorField = AccessTools.Field(typeof(UnitButtonBase), "targetIconColor"); private static readonly MethodInfo GetUnitMethod = AccessTools.Method(typeof(UnitButtonBase), "GetUnit", (Type[])null, (Type[])null); private static readonly PropertyInfo IsCustomUnitProperty = AccessTools.Property(AccessTools.TypeByName("Landfall.TABS.UnitBlueprint"), "IsCustomUnit"); private static readonly MethodInfo GetUnitCostMethod = AccessTools.Method(AccessTools.TypeByName("Landfall.TABS.UnitBlueprint"), "GetUnitCost", new Type[1] { typeof(bool) }, (Type[])null); private static PropertyInfo _costTextProperty; private static readonly Color DimIconColor = new Color(0.32f, 0.32f, 0.32f, 1f); internal static bool IsFactionEditorUnitButton(UnitButtonBase button) { if ((Object)(object)button == (Object)null) { return false; } if (button is UnitButtonFactionCreator) { return true; } if (((object)button).GetType().Name == "FactionCreatorUnitBrowserUnitButton") { return true; } if (!((Object)(object)((Component)button).GetComponentInParent() != (Object)null)) { return (Object)(object)((Component)button).GetComponentInParent() != (Object)null; } return true; } internal static void ShowOnHover(UnitButtonBase button) { if (!IsFactionEditorUnitButton(button)) { return; } object obj = GetUnitMethod?.Invoke(button, null); if (obj != null && IsCustomUnit(obj)) { string unitCostText = GetUnitCostText(obj); if (unitCostText != null) { DimIcon(button); ShowCostOverlay(button, unitCostText); } } } internal static void HideOnHover(UnitButtonBase button) { if (IsFactionEditorUnitButton(button)) { object obj = GetUnitMethod?.Invoke(button, null); if (obj != null && IsCustomUnit(obj)) { RestoreIcon(button); HideCostOverlay(button); } } } private static bool IsCustomUnit(object unit) { if (IsCustomUnitProperty != null) { return (bool)IsCustomUnitProperty.GetValue(unit); } return false; } private static string GetUnitCostText(object unit) { if (GetUnitCostMethod == null) { return null; } return GetUnitCostMethod.Invoke(unit, new object[1] { true })?.ToString(); } private static void DimIcon(UnitButtonBase button) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) TargetIconColorField?.SetValue(button, 1f); Image iconImage = button.IconImage; if ((Object)(object)iconImage != (Object)null) { ((Graphic)iconImage).color = DimIconColor; } } private static void RestoreIcon(UnitButtonBase button) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) TargetIconColorField?.SetValue(button, 0f); Image iconImage = button.IconImage; if ((Object)(object)iconImage != (Object)null) { ((Graphic)iconImage).color = Color.white; } } private static void ShowCostOverlay(UnitButtonBase button, string costText) { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_0151: 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) //IL_0166: Unknown result type (might be due to invalid IL or missing references) object? obj = UnitCostField?.GetValue(button); Behaviour val = (Behaviour)((obj is Behaviour) ? obj : null); if ((Object)(object)val == (Object)null) { return; } Transform transform = ((Component)val).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); RectTransform val3 = (((Object)(object)button.IconImage != (Object)null) ? ((Graphic)button.IconImage).rectTransform : null); if (!((Object)(object)val2 == (Object)null)) { FactionCreatorCostHoverState.GetOrCreate(button).CaptureCostLayout(val2); if ((Object)(object)val3 != (Object)null) { ((Transform)val2).SetParent(((Transform)val3).parent, false); val2.anchorMin = val3.anchorMin; val2.anchorMax = val3.anchorMax; val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = val3.anchoredPosition; val2.sizeDelta = val3.sizeDelta; } else { val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = Vector2.zero; } ((Transform)val2).SetAsLastSibling(); SetText((Component)(object)val, costText); val.enabled = true; ((Component)val).gameObject.SetActive(true); PropertyInfo property = ((object)val).GetType().GetProperty("color"); if (property != null) { Color val4 = (Color)property.GetValue(val, null); val4 = Color.white; val4.a = 1f; property.SetValue(val, val4, null); } } } private static void HideCostOverlay(UnitButtonBase button) { object? obj = UnitCostField?.GetValue(button); Behaviour val = (Behaviour)((obj is Behaviour) ? obj : null); if (!((Object)(object)val == (Object)null)) { val.enabled = false; Transform transform = ((Component)val).transform; RectTransform costRect = (RectTransform)(object)((transform is RectTransform) ? transform : null); ((Component)button).GetComponent()?.RestoreCostLayout(costRect); } } private static void SetText(Component textComponent, string value) { if (!((Object)(object)textComponent == (Object)null)) { if ((object)_costTextProperty == null) { _costTextProperty = ((object)textComponent).GetType().GetProperty("text"); } _costTextProperty?.SetValue(textComponent, value, null); } } } internal sealed class FactionCreatorUnitDragReorder : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler { private static readonly Vector3[] WorldCorners = (Vector3[])(object)new Vector3[4]; private FactionCreatorManager _manager; private UnitButtonBase _button; private RectTransform _rectTransform; private RectTransform _canvasRect; private Canvas _canvas; private Camera _eventCamera; private Transform _listParent; private RectTransform _listParentRect; private RectTransform _dropGap; private ScrollRect _scrollRect; private FactionCreatorDragScrollSession _scrollSession; private bool _horizontalLayout; private int _targetIndex; private int _fromIndex; private bool _moved; private bool _suppressClick; private CanvasGroup _canvasGroup; private Vector2 _currentScreenPosition; internal Vector2 CurrentScreenPosition => _currentScreenPosition; internal void Initialize(FactionCreatorManager manager, UnitButtonBase button) { _manager = manager; _button = button; ref RectTransform rectTransform = ref _rectTransform; Transform transform = ((Component)this).transform; rectTransform = (RectTransform)(object)((transform is RectTransform) ? transform : null); _canvas = ((Component)this).GetComponentInParent(); _canvasRect = (RectTransform)(((Object)(object)_canvas != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); } internal bool ConsumeClickSuppression() { if (!_suppressClick) { return false; } _suppressClick = false; return true; } public void OnBeginDrag(PointerEventData eventData) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_manager == (Object)null) && !((Object)(object)_button == (Object)null) && !((Object)(object)_rectTransform == (Object)null) && !((Object)(object)_canvasRect == (Object)null) && (int)eventData.button == 0 && FactionCreatorReorderLogic.GetUnitIndex(_manager, _button) >= 0) { _fromIndex = ((Component)_button).transform.GetSiblingIndex(); _targetIndex = _fromIndex; _moved = false; _listParent = _manager.FactionListParent; ref RectTransform listParentRect = ref _listParentRect; Transform listParent = _listParent; listParentRect = (RectTransform)(object)((listParent is RectTransform) ? listParent : null); _horizontalLayout = FactionCreatorReorderLogic.IsHorizontalLayout(_listParentRect); _scrollRect = FactionCreatorReorderLogic.FindListScrollRect(_manager); object obj = eventData.pressEventCamera; if (obj == null) { Canvas canvas = _canvas; obj = ((canvas != null) ? canvas.worldCamera : null); } _eventCamera = (Camera)obj; _canvasGroup = ((Component)this).gameObject.GetComponent(); if ((Object)(object)_canvasGroup == (Object)null) { _canvasGroup = ((Component)this).gameObject.AddComponent(); } _dropGap = FactionCreatorDropGap.Create(_listParentRect, _rectTransform, _horizontalLayout); ((Transform)_dropGap).SetSiblingIndex(_fromIndex); ((Component)this).transform.SetParent((Transform)(object)_canvasRect, true); _canvasGroup.blocksRaycasts = false; _canvasGroup.alpha = 0.85f; ((Component)this).transform.SetAsLastSibling(); _currentScreenPosition = eventData.position; if ((Object)(object)_scrollRect != (Object)null) { _scrollSession = ((Component)this).gameObject.AddComponent(); _scrollSession.Begin(_scrollRect, _eventCamera, this); } SnapCenterToCursor(eventData); UpdateDropTarget(_currentScreenPosition); } } public void OnDrag(PointerEventData eventData) { //IL_0010: 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_002d: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_manager == (Object)null)) { Vector2 delta = eventData.delta; if (((Vector2)(ref delta)).sqrMagnitude > 0.01f) { _moved = true; } _currentScreenPosition = eventData.position; SnapCenterToCursor(eventData); UpdateDropTarget(_currentScreenPosition); } } public void OnEndDrag(PointerEventData eventData) { if (!((Object)(object)_manager == (Object)null) && !((Object)(object)_listParent == (Object)null)) { if ((Object)(object)_scrollSession != (Object)null) { Object.Destroy((Object)(object)_scrollSession); _scrollSession = null; } FactionCreatorDropGap.Destroy(_dropGap); _dropGap = null; ((Component)this).transform.SetParent(_listParent, false); ((Component)this).transform.SetSiblingIndex(_targetIndex); if (_moved) { FactionCreatorReorderLogic.SyncAddedUnitsFromHierarchy(_manager); _suppressClick = true; } if ((Object)(object)_canvasGroup != (Object)null) { _canvasGroup.blocksRaycasts = true; _canvasGroup.alpha = 1f; } if ((Object)(object)_listParentRect != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(_listParentRect); } } } private void UpdateDropTarget(Vector2 screenPosition) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) int insertionIndex = FactionCreatorReorderLogic.GetInsertionIndex(_manager, screenPosition, _eventCamera, (Transform)(object)_dropGap, _targetIndex); if (insertionIndex == _targetIndex) { return; } _targetIndex = insertionIndex; if ((Object)(object)_dropGap != (Object)null) { ((Transform)_dropGap).SetSiblingIndex(_targetIndex); if ((Object)(object)_listParentRect != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(_listParentRect); } } } private void SnapCenterToCursor(PointerEventData eventData) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_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_003d: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) _rectTransform.GetWorldCorners(WorldCorners); Vector3 val = (WorldCorners[0] + WorldCorners[2]) * 0.5f; Vector3 val2 = default(Vector3); if (RectTransformUtility.ScreenPointToWorldPointInRectangle(_canvasRect, eventData.position, ((Object)(object)_canvas != (Object)null && (int)_canvas.renderMode == 0) ? null : _eventCamera, ref val2)) { RectTransform rectTransform = _rectTransform; ((Transform)rectTransform).position = ((Transform)rectTransform).position + (val2 - val); } } } internal static class FactionUnitsLoadFix { private static Func _parseFactionJson; internal static void AddUserFaction_Prefix(Faction faction) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)faction == (Object)null || !faction.IsCustom || faction.Units.Length != 0) { return; } string factionFilePath = GetFactionFilePath(faction); if (factionFilePath == null || !File.Exists(factionFilePath)) { return; } if (_parseFactionJson == null) { _parseFactionJson = CreateFactionJsonParser(); } SerializedFaction val; try { val = _parseFactionJson(File.ReadAllText(factionFilePath)); } catch { return; } if (val?.units == null || val.units.Length == 0) { return; } ContentDatabase val2 = ContentDatabase.Instance(); if (val2 == null) { return; } List list = new List(); DatabaseID[] units = val.units; foreach (DatabaseID val3 in units) { UnitBlueprint unitBlueprint = val2.GetUnitBlueprint(val3); if ((Object)(object)unitBlueprint != (Object)null) { list.Add(unitBlueprint); } } if (list.Count != 0) { faction.Units = list.ToArray(); } } private static string GetFactionFilePath(Faction faction) { //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) if (((faction != null) ? faction.Entity : null) == null) { return null; } DatabaseID gUID = faction.Entity.GUID; string text = ((object)(DatabaseID)(ref gUID)).ToString(); if (faction.IsModFaction) { string modInstallationDirectory = GetModInstallationDirectory(); if (string.IsNullOrEmpty(modInstallationDirectory)) { return null; } string[] files = Directory.GetFiles(modInstallationDirectory, text + ".TABSFaction", SearchOption.AllDirectories); if (files.Length == 0) { return null; } return files[0]; } string localFactionRootPath = GetLocalFactionRootPath(); if (string.IsNullOrEmpty(localFactionRootPath)) { return null; } return Path.Combine(Path.Combine(localFactionRootPath, text), text + ".TABSFaction"); } private static string GetLocalFactionRootPath() { Type type = AccessTools.TypeByName("CustomContentFilePaths"); if (type != null && AccessTools.Property(type, "FilePathFaction")?.GetValue(null) is string text && !string.IsNullOrEmpty(text)) { return text; } Type type2 = AccessTools.TypeByName("GamePaths"); if (type2 != null && AccessTools.Field(type2, "DataPath")?.GetValue(null) is string text2 && !string.IsNullOrEmpty(text2)) { return Path.Combine(text2, "CustomContent/CustomFactions/"); } return Path.Combine(Application.dataPath, "CustomContent/CustomFactions/"); } private static string GetModInstallationDirectory() { Type type = AccessTools.TypeByName("PluginSettings"); if (type != null && AccessTools.Field(type, "INSTALLATION_DIRECTORY")?.GetValue(null) is string text && !string.IsNullOrEmpty(text)) { return text; } Type type2 = AccessTools.TypeByName("DataStorage"); if (type2 != null && AccessTools.Field(type2, "INSTALLATION_DIRECTORY")?.GetValue(null) is string text2 && !string.IsNullOrEmpty(text2)) { return text2; } return null; } private static Func CreateFactionJsonParser() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly obj in assemblies) { Type type = obj.GetType("UnityEngine.JsonUtility"); if (type == null) { continue; } MethodInfo methodInfo = AccessTools.FirstMethod(type, (Func)((MethodInfo m) => m.Name == "FromJson" && m.IsGenericMethodDefinition && m.GetParameters().Length == 1)); if (!(methodInfo == null)) { MethodInfo generic = methodInfo.MakeGenericMethod(typeof(SerializedFaction)); return (string json) => (SerializedFaction)generic.Invoke(null, new object[1] { json }); } } return (string json) => JsonConvert.DeserializeObject(json); } } internal static class FleeConfig { internal static bool FleeDistanceEnabled = true; internal static void Bind(ConfigFile config) { FleeDistanceEnabled = config.Bind("Flee", "FleeDistanceEnabled", true, "Enable flee distance runtime AI and pathfinding for units with the FleeDistance movement modifier.").Value; } } public static class FleeDistanceInterop { public static bool IsAiEnabled => FleeConfig.FleeDistanceEnabled; public static bool IsFleeManaged(Entity entity) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (IsAiEnabled) { return FleeDistanceAiState.IsFleeManaged(entity); } return false; } public static bool ShouldFlee(EntityManager entityManager, Entity entity) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (IsAiEnabled) { return FleeDistanceAiState.ShouldFlee(entityManager, entity); } return false; } } internal static class BattleStateHelper { private static int _checkFrame = -1; private static bool _cachedBattleActive; private static int _fleeAiCheckFrame = -1; private static bool _cachedShouldRunFleeAi; internal static bool IsBattleActive() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 if (Time.frameCount == _checkFrame) { return _cachedBattleActive; } _checkFrame = Time.frameCount; GameStateManager service = ServiceLocator.GetService(); _cachedBattleActive = service != null && (int)service.GameState == 1; return _cachedBattleActive; } internal static bool ShouldRunFleeAi() { if (Time.frameCount == _fleeAiCheckFrame) { return _cachedShouldRunFleeAi; } _fleeAiCheckFrame = Time.frameCount; if (!IsBattleActive()) { _cachedShouldRunFleeAi = false; return false; } if (TABSSceneManager.IsInUnitCreatorScene()) { _cachedShouldRunFleeAi = false; return false; } GameModeService service = ServiceLocator.GetService(); if (((service != null) ? service.CurrentGameMode : null) is UnitCreatorGameMode) { _cachedShouldRunFleeAi = false; return false; } _cachedShouldRunFleeAi = true; return true; } internal static void InvalidateCache() { _checkFrame = -1; _fleeAiCheckFrame = -1; } } internal static class FleeBattleContext { private static int _frame = -1; private static EntityManager _entityManager; private static IReadOnlyList _fleeEntries; private static readonly List ActiveFleeEntries = new List(); internal static int ActiveFleeCount { get; private set; } internal static bool IsHighLoad => ActiveFleeCount >= 10; internal static bool TryGetCurrentFrame(out EntityManager entityManager, out IReadOnlyList fleeEntries, out IReadOnlyList activeFleeEntries) { entityManager = _entityManager; fleeEntries = _fleeEntries; activeFleeEntries = ActiveFleeEntries; if (_frame == Time.frameCount && entityManager.IsCreated) { return fleeEntries != null; } return false; } internal static bool EnsureFrame(out EntityManager entityManager, out IReadOnlyList fleeEntries, out IReadOnlyList activeFleeEntries) { if (TryGetCurrentFrame(out entityManager, out fleeEntries, out activeFleeEntries)) { return true; } if (!EcsComponentHelper.IsAvailable) { entityManager = null; fleeEntries = null; activeFleeEntries = ActiveFleeEntries; return false; } TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { entityManager = null; fleeEntries = null; activeFleeEntries = ActiveFleeEntries; return false; } List allUnits = existingManager.GetAllUnits(); if (allUnits == null || allUnits.Count == 0) { entityManager = null; fleeEntries = null; activeFleeEntries = ActiveFleeEntries; return false; } entityManager = null; Entity entity; for (int i = 0; i < allUnits.Count && !EcsComponentHelper.TryGetEntityManager((Component)(object)allUnits[i], out entity, out entityManager); i++) { } if (!entityManager.IsCreated) { fleeEntries = null; activeFleeEntries = ActiveFleeEntries; return false; } fleeEntries = FleeUnitRegistry.GetEntries(entityManager, allUnits); FleeTeamSnapshot.RefreshIfNeeded(entityManager, existingManager); BeginFrame(entityManager, fleeEntries); activeFleeEntries = ActiveFleeEntries; return true; } internal static void BeginFrame(EntityManager entityManager, IReadOnlyList fleeEntries) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) _frame = Time.frameCount; _entityManager = entityManager; _fleeEntries = fleeEntries; ActiveFleeEntries.Clear(); ActiveFleeCount = 0; FleeShouldFleeCache.BeginFrame(); if (!entityManager.IsCreated || fleeEntries == null) { return; } for (int i = 0; i < fleeEntries.Count; i++) { FleeUnitEntry item = fleeEntries[i]; if (FleeDistanceAiState.IsFleeManaged(item.Entity) || FleeShouldFleeCache.ShouldFlee(entityManager, item.Entity)) { ActiveFleeEntries.Add(item); } } ActiveFleeCount = ActiveFleeEntries.Count; } internal static IReadOnlyList GetActiveEntries() { return ActiveFleeEntries; } } internal static class FleeCombatTargetHelper { private const float RangedAttackRangeThreshold = 5f; internal static bool IsRangedFleeEntity(EntityManager entityManager, Entity entity) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0029: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated || !entityManager.Exists(entity)) { return false; } if (entityManager.HasComponent(entity)) { return true; } if (entityManager.HasComponent(entity)) { return entityManager.GetComponentData(entity).AttackRange >= 5f; } return false; } internal static void EnsureFleeThreatTarget(EntityManager entityManager, Entity entity) { //IL_0009: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0036: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_006e: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (entityManager.IsCreated && entityManager.Exists(entity) && entityManager.HasComponent(entity)) { HasTargetTag componentData = entityManager.GetComponentData(entity); if ((!(componentData.Target != Entity.Null) || !entityManager.Exists(componentData.Target) || !FleeThreatResolver.TryIsLivingTarget(entityManager, componentData.Target)) && FleeThreatResolver.TryGetClosestLivingEnemyDistance(entityManager, entity, out var _, out var enemyEntity) && !(enemyEntity == Entity.Null)) { entityManager.SetComponentData(entity, new HasTargetTag { Target = enemyEntity }); } } } } internal static class FleeDistanceAiPatches { internal static void Register(Harmony harmony, ref int applied) { if (!FleeConfig.FleeDistanceEnabled) { return; } try { applied += RegisterFleeAttackGuardPatches(harmony); applied += RegisterFleeMovementGuardPatches(harmony); applied += PatchMethod(harmony, AccessTools.Method(typeof(CalculateNavPathSystem), "OnUpdate", (Type[])null, (Type[])null), typeof(FleeDistanceAiPatches), "CalculateNavPathSystem_OnUpdate_Prefix"); MethodInfo methodInfo = AccessTools.Method(typeof(CalculateNavPathSystem), "OnPathComplete", (Type[])null, (Type[])null); if (methodInfo != null) { applied += PatchMethod(harmony, methodInfo, typeof(FleeDistanceAiPatches), "CalculateNavPathSystem_OnPathComplete_Prefix"); } Type type = AccessTools.TypeByName("EzECS.Barriers.PreLateUpdateBarrier, Assembly-CSharp"); if (type != null) { applied += PatchMethod(harmony, AccessTools.Method(type, "OnUpdate", (Type[])null, (Type[])null), typeof(FleeDistanceAiPatches), null, "PreLateUpdateBarrier_OnUpdate_Postfix"); } applied += PatchMethod(harmony, AccessTools.Method(typeof(UnitECSToMonoSyncSystem), "OnUpdate", (Type[])null, (Type[])null), typeof(FleeDistanceAiPatches), null, "UnitECSToMonoSyncSystem_OnUpdate_Postfix"); Plugin.LogInfo("Flee AI: pathfinding patches registered"); } catch (Exception ex) { Plugin.LogWarning("Flee AI patch registration failed: " + ex.Message); } } internal static void PreLateUpdateBarrier_OnUpdate_Postfix() { if (!FleeConfig.FleeDistanceEnabled || !BattleStateHelper.ShouldRunFleeAi() || !EcsComponentHelper.IsAvailable) { return; } FleePathClearanceContext.IsActive = true; try { TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return; } List allUnits = existingManager.GetAllUnits(); if (allUnits == null || allUnits.Count == 0) { return; } EntityManager entityManager = null; Entity entity; for (int i = 0; i < allUnits.Count && !EcsComponentHelper.TryGetEntityManager((Component)(object)allUnits[i], out entity, out entityManager); i++) { } if (entityManager.IsCreated) { FleeDistanceAiState.Prune(entityManager); IReadOnlyList entries = FleeUnitRegistry.GetEntries(entityManager, allUnits); if (FleeTeamSnapshot.RefreshIfNeeded(entityManager, existingManager)) { FleeShouldFleeCache.RefreshStickyFromSnapshot(entityManager, entries); } FleeBattleContext.BeginFrame(entityManager, entries); IReadOnlyList activeEntries = FleeBattleContext.GetActiveEntries(); ProcessExitFleeManagedUnits(entityManager, activeEntries); DriveFleeUnits(entityManager, activeEntries); } } finally { FleePathClearanceContext.IsActive = false; } } public static void CalculateNavPathSystem_OnUpdate_Prefix(object __instance) { if (BattleStateHelper.ShouldRunFleeAi()) { EntityManager entityManagerFromSystem = GetEntityManagerFromSystem(__instance); if (entityManagerFromSystem.IsCreated) { FreezeVanillaRepathForManagedUnits(entityManagerFromSystem); } } } public static bool CalculateNavPathSystem_OnPathComplete_Prefix(Path path, CalculateNavPathSystem __instance) { //IL_004a: 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) if (!BattleStateHelper.ShouldRunFleeAi()) { return true; } EntityManager entityManagerFromSystem = GetEntityManagerFromSystem(__instance); if (!entityManagerFromSystem.IsCreated) { return true; } if (!(Traverse.Create((object)__instance).Field("m_pathIDs").GetValue() is Dictionary dictionary) || !dictionary.TryGetValue(path.pathID, out var value)) { return true; } if (FleeDistanceAiState.IsFleeManaged(value) && FleeDistanceAiState.ShouldFlee(entityManagerFromSystem, value)) { return false; } return true; } private static void ProcessExitFleeManagedUnits(EntityManager entityManager, IReadOnlyList fleeUnits) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < fleeUnits.Count; i++) { Entity entity = fleeUnits[i].Entity; if (FleeDistanceAiState.IsFleeManaged(entity) && !FleeDistanceAiState.ShouldFlee(entityManager, entity)) { FleeDistancePathHelper.RestoreVanillaRepath(entityManager, entity); FleeDistanceAiState.OnExitFlee(entity); } } } private static void DriveFleeUnits(EntityManager entityManager, IReadOnlyList activeFleeUnits) { //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_002c: 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_0040: 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_0049: 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_0057: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_0091: 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_00a0: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_00f6: 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) for (int i = 0; i < activeFleeUnits.Count; i++) { Unit unit = activeFleeUnits[i].Unit; Entity entity = activeFleeUnits[i].Entity; if ((Object)(object)unit == (Object)null || !FleeDistanceAiState.ShouldFlee(entityManager, entity)) { continue; } bool num = FleeDistanceAiState.GetMode(entity) == FleeAiMode.Idle; FleeDistanceAiState.OnEnterFlee(entity); if (num) { FleeCombatTargetHelper.EnsureFleeThreatTarget(entityManager, entity); FleeDistancePathHelper.DisableVanillaRepath(entityManager, entity); FleeDistancePathHelper.TryWriteEmergencyFleePath(entityManager, entity); } switch (FleeDistanceAiState.GetMode(entity)) { case FleeAiMode.SeekingInitial: FleeDistancePathHelper.TickInitialPathSearch(entityManager, entity); RestoreFleeLocomotionIfBlocked(entityManager, entity); break; case FleeAiMode.OnPath: { FleeDistancePathHelper.DisableVanillaRepath(entityManager, entity); FleeDistancePathHelper.ApplyCustomPathMovement(entityManager, entity); RestoreFleeLocomotionIfBlocked(entityManager, entity); float distanceToPathEnd = FleeDistancePathHelper.GetDistanceToPathEnd(entityManager, entity); FleeDistanceAiState.UpdatePathProgress(entityManager, entity, distanceToPathEnd); if (FleeDistanceAiState.ShouldRecoverFromStall(entityManager, entity)) { FleeDistanceAiState.RecordStallRecovery(entity); FleeDistancePathHelper.RestoreVanillaRepath(entityManager, entity); FleeDistanceAiState.CancelSearchSession(entity); FleeDistanceAiState.ResetToSeekingInitialForCornerEscape(entity); FleeDistanceDebugLog.LogTransition(entity, "corner escape: path stalled, re-searching 360"); FleeDistancePathHelper.TickInitialPathSearch(entityManager, entity); RestoreFleeLocomotionIfBlocked(entityManager, entity); } else if (distanceToPathEnd <= 4f) { if (!FleeDistancePathHelper.TryApplyPendingNextPath(entityManager, entity)) { FleeDistancePathHelper.TickInitialPathSearch(entityManager, entity); RestoreFleeLocomotionIfBlocked(entityManager, entity); } } else if (distanceToPathEnd <= 8f) { FleeDistancePathHelper.TickBackgroundNextPathSearch(entityManager, entity); } break; } } } } private static void RestoreFleeLocomotionIfBlocked(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) if (!FleeDistanceAiState.ShouldFlee(entityManager, entity)) { return; } switch (FleeDistanceAiState.GetMode(entity)) { case FleeAiMode.SeekingInitial: case FleeAiMode.AwaitingSwap: FleeDistancePathHelper.RestoreThreatAwayLocomotion(entityManager, entity); break; case FleeAiMode.OnPath: if (entityManager.HasComponent(entity) && !(math.lengthsq(entityManager.GetComponentData(entity).Value) >= 0.01f)) { FleeDistancePathHelper.RestoreForwardVelocity(entityManager, entity); } break; } } internal static void UnitECSToMonoSyncSystem_OnUpdate_Postfix() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!FleeConfig.FleeDistanceEnabled || !BattleStateHelper.ShouldRunFleeAi() || !EcsComponentHelper.IsAvailable || !FleeBattleContext.EnsureFrame(out var entityManager, out var _, out var activeFleeEntries)) { return; } for (int i = 0; i < activeFleeEntries.Count; i++) { Entity entity = activeFleeEntries[i].Entity; Unit unit = activeFleeEntries[i].Unit; if (FleeDistanceAiState.IsCustomPathActive(entity)) { FleeDistancePathHelper.ApplyCustomPathMovement(entityManager, entity); } else { FleeDistancePathHelper.RestoreThreatAwayLocomotion(entityManager, entity); } FleeMonoLocomotionHelper.ApplyFleeLocomotionToMono(entityManager, entity, unit); } } public static bool FleeWithinDistanceJob_Execute_Prefix(int index) { return !FleeMovementJobGuard.ShouldSkipFleeWithinDistance(index); } public static bool KeepPreferredDistanceJob_Execute_Prefix(int index) { return !FleeMovementJobGuard.ShouldSkipKeepPreferredDistance(index); } public static bool KeepRangedDistanceJob_Execute_Prefix(int index) { return !FleeMovementJobGuard.ShouldSkipKeepRangedDistance(index); } public static void FleeWithinDistanceSystem_OnUpdate_Prefix(object __instance) { FleeMovementJobGuard.CaptureFleeWithinEntities(Traverse.Create(__instance).Field("m_filter").GetValue()); } public static void KeepPreferredDistanceSystem_OnUpdate_Prefix(object __instance) { FleeMovementJobGuard.CaptureKeepPreferredEntities(Traverse.Create(__instance).Field("m_filter").GetValue()); } public static void KeepRangedDistanceSystem_OnUpdate_Prefix(object __instance) { FleeMovementJobGuard.CaptureKeepRangedEntities(Traverse.Create(__instance).Field("m_filter").GetValue()); } public static void UnitAPI_SetAttackTarget_Prefix(object __instance, ref bool startAttack) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (BattleStateHelper.ShouldRunFleeAi()) { Unit value = Traverse.Create(__instance).Field("m_unit").GetValue(); if (!((Object)(object)value == (Object)null) && EcsComponentHelper.TryGetEntityManager((Component)(object)value, out var entity, out var entityManager) && FleePostFleeAttackCooldown.ShouldBlockAttacks(entityManager, entity)) { startAttack = false; } } } public static void UnitAPI_SetLookDirection_Prefix(object __instance, ref Vector3 localDirection) { //IL_001d: 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) if (FleeConfig.FleeDistanceEnabled && BattleStateHelper.ShouldRunFleeAi() && MovementStyleUnitContext.TryGetEntityFromUnitApi(__instance, out var entity, out var entityManager) && entityManager.HasComponent(entity)) { FleeMonoLocomotionHelper.TryRedirectLookDirectionWhileFleeing(entityManager, entity, ref localDirection); } } public static void UnitAPI_SetMovementSpeed_Prefix(object __instance, ref float movementSpeed) { //IL_001d: 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) if (FleeConfig.FleeDistanceEnabled && BattleStateHelper.ShouldRunFleeAi() && MovementStyleUnitContext.TryGetEntityFromUnitApi(__instance, out var entity, out var entityManager) && entityManager.HasComponent(entity)) { FleeMonoLocomotionHelper.TryEnsureForwardMovementWhileFleeing(entityManager, entity, ref movementSpeed); } } public static bool Unit_Attack_Prefix(Unit __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!BattleStateHelper.ShouldRunFleeAi()) { return true; } if (!EcsComponentHelper.TryGetEntityManager((Component)(object)__instance, out var entity, out var entityManager)) { return true; } if (FleePostFleeAttackCooldown.ShouldBlockAttacks(entityManager, entity)) { return false; } return true; } private static int RegisterFleeAttackGuardPatches(Harmony harmony) { int num = 0; Type type = AccessTools.TypeByName("Landfall.TABS.AI.UnitAPI, Assembly-CSharp"); if (type != null) { num += PatchMethod(harmony, AccessTools.Method(type, "SetAttackTarget", (Type[])null, (Type[])null), typeof(FleeDistanceAiPatches), "UnitAPI_SetAttackTarget_Prefix"); num += PatchMethod(harmony, AccessTools.Method(type, "SetLookDirection", new Type[2] { typeof(Vector3), typeof(bool) }, (Type[])null), typeof(FleeDistanceAiPatches), "UnitAPI_SetLookDirection_Prefix"); num += PatchMethod(harmony, AccessTools.Method(type, "SetMovementSpeed", new Type[2] { typeof(float), typeof(bool) }, (Type[])null), typeof(FleeDistanceAiPatches), "UnitAPI_SetMovementSpeed_Prefix"); } return num + PatchMethod(harmony, AccessTools.Method(typeof(Unit), "Attack", new Type[3] { typeof(Vector3), typeof(Rigidbody), typeof(Vector3) }, (Type[])null), typeof(FleeDistanceAiPatches), "Unit_Attack_Prefix"); } private static int RegisterFleeMovementGuardPatches(Harmony harmony) { return 0 + PatchMovementSystemGuards(harmony, "Landfall.TABS.AI.Systems.Modifiers.FleeWithinDistanceSystem, Assembly-CSharp", "FleeWithinDistanceSystem_OnUpdate_Prefix", "FleeWithinDistanceJob_Execute_Prefix") + PatchMovementSystemGuards(harmony, "Landfall.TABS.AI.Systems.Modifiers.KeepPreferredDistanceSystem, Assembly-CSharp", "KeepPreferredDistanceSystem_OnUpdate_Prefix", "KeepPreferredDistanceJob_Execute_Prefix") + PatchMovementSystemGuards(harmony, "Landfall.TABS.AI.Systems.Modifiers.KeepRangedDistanceSystem, Assembly-CSharp", "KeepRangedDistanceSystem_OnUpdate_Prefix", "KeepRangedDistanceJob_Execute_Prefix"); } private static int PatchMovementSystemGuards(Harmony harmony, string systemTypeName, string onUpdatePrefixName, string executePrefixName) { int num = 0; Type type = AccessTools.TypeByName(systemTypeName); if (type == null) { Plugin.LogWarning("Flee AI: movement system not found (" + systemTypeName + ")"); return 0; } num += PatchMethod(harmony, AccessTools.Method(type, "OnUpdate", (Type[])null, (Type[])null), typeof(FleeDistanceAiPatches), onUpdatePrefixName); Type nestedType = type.GetNestedType("Job", BindingFlags.Public | BindingFlags.NonPublic); MethodInfo original = ((nestedType != null) ? AccessTools.Method(nestedType, "Execute", (Type[])null, (Type[])null) : null); return num + PatchMethod(harmony, original, typeof(FleeDistanceAiPatches), executePrefixName); } private static void FreezeVanillaRepathForManagedUnits(EntityManager entityManager) { //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_0041: 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_0055: Unknown result type (might be due to invalid IL or missing references) if (!FleeBattleContext.TryGetCurrentFrame(out var _, out var fleeEntries, out var _)) { TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return; } List allUnits = existingManager.GetAllUnits(); if (allUnits == null) { return; } fleeEntries = FleeUnitRegistry.GetEntries(entityManager, allUnits); } for (int i = 0; i < fleeEntries.Count; i++) { Entity entity = fleeEntries[i].Entity; if (FleeDistanceAiState.IsFleeManaged(entity) && FleeDistanceAiState.ShouldFlee(entityManager, entity)) { FleeDistancePathHelper.DisableVanillaRepath(entityManager, entity); } } } private static EntityManager GetEntityManagerFromSystem(object system) { if (system == null) { return null; } object value = Traverse.Create(system).Property("EntityManager", (object[])null).GetValue(); EntityManager val = (EntityManager)((value is EntityManager) ? value : null); if (val == null) { return null; } return val; } private static int PatchMethod(Harmony harmony, MethodBase original, Type patchClass, string prefix = null, string postfix = null) { //IL_0052: 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) if (original == null) { Plugin.LogWarning("Flee AI: patch target missing (" + patchClass.Name + "." + (prefix ?? postfix) + ")"); return 0; } try { object obj = harmony; obj = original; obj = (object)((prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(patchClass, prefix, (Type[])null)); obj = (object)((postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(patchClass, postfix, (Type[])null)); ((Harmony)obj).Patch((MethodBase)obj, (HarmonyMethod)obj, (HarmonyMethod)obj, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return 1; } catch (Exception ex) { Plugin.LogWarning("Flee AI: failed to patch " + original.DeclaringType?.Name + "." + original.Name + ": " + ex.Message); return 0; } } } internal enum FleeAiMode { Idle, SeekingInitial, OnPath, AwaitingSwap } internal enum FleePathSearchKind { Initial, NextPath } internal struct FleeStoredPath { internal float3 End; internal float Length; internal float Score; internal float3[] Points; } internal struct FleePathSearchSession { internal bool Active; internal FleePathSearchKind Kind; internal float3 Origin; internal float3 AwayDirection; internal bool UseFullCircle; internal bool CornerEscape; internal int AngleIndex; internal int CandidateOffset; internal int Generation; internal bool HasBestPath; internal FleeStoredPath BestPath; internal float BestScore; internal bool HasRelaxedBestPath; internal FleeStoredPath RelaxedBestPath; internal float RelaxedBestScore; internal bool HasPrimaryThreat; internal FleeNearbyThreat PrimaryThreat; } internal static class FleeDistanceAiState { private struct State { internal FleeAiMode Mode; internal float3 ActivePathEnd; internal float ActivePathLength; internal FleeStoredPath PendingNextPath; internal bool HasPendingNextPath; internal FleePathSearchSession SearchSession; internal int CandidateOffset; internal bool UseFullCircleSearch; internal float LastSearchTime; internal bool WasFleeing; internal bool CornerEscapeActive; internal int ConsecutiveFailedConeSearches; internal bool LastSearchWasConeFailure; internal float LastPathProgressDistance; internal float LastPathProgressTime; internal float LastStallRecoveryTime; internal float3 LastStallRecoveryPathEnd; internal bool HasLastStallRecoveryPathEnd; } internal const float DisabledRepathRate = 999f; internal const float VanillaRepathRate = 0.5f; private static readonly Dictionary States = new Dictionary(); private static readonly List PruneScratch = new List(); internal static bool IsFleeManaged(Entity entity) { //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_0012: 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) if (entity != Entity.Null && States.ContainsKey(entity)) { return States[entity].Mode != FleeAiMode.Idle; } return false; } internal static bool IsCustomPathActive(Entity entity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetMode(entity) == FleeAiMode.OnPath; } internal static bool ShouldFlee(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return FleeShouldFleeCache.ShouldFlee(entityManager, entity); } internal static FleeAiMode GetMode(Entity entity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value)) { return FleeAiMode.Idle; } return value.Mode; } internal static bool TryGetActivePathEnd(Entity entity, out float3 pathEnd) { //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_0010: 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) pathEnd = float3.zero; if (!States.TryGetValue(entity, out var value) || value.Mode == FleeAiMode.Idle) { return false; } pathEnd = value.ActivePathEnd; return true; } internal static bool TryGetPendingNextPath(Entity entity, out FleeStoredPath path) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) path = default(FleeStoredPath); if (!States.TryGetValue(entity, out var value) || !value.HasPendingNextPath) { return false; } path = value.PendingNextPath; return true; } internal static bool HasPendingNextPath(Entity entity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (States.TryGetValue(entity, out var value)) { return value.HasPendingNextPath; } return false; } internal static bool HasActiveSearchSession(Entity entity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (States.TryGetValue(entity, out var value)) { return value.SearchSession.Active; } return false; } internal static bool TryGetSearchSession(Entity entity, out FleePathSearchSession session) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) session = default(FleePathSearchSession); if (!States.TryGetValue(entity, out var value) || !value.SearchSession.Active) { return false; } session = value.SearchSession; return true; } internal static bool ShouldUseFullCircle(Entity entity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (States.TryGetValue(entity, out var value)) { return value.UseFullCircleSearch; } return false; } internal static bool IsCornerEscapeActive(Entity entity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (States.TryGetValue(entity, out var value)) { return value.CornerEscapeActive; } return false; } internal static bool ShouldUseCornerEscape(EntityManager entityManager, Entity entity) { //IL_0009: 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_002a: 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_0067: 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) if (!entityManager.IsCreated || !entityManager.Exists(entity)) { return false; } float maxDistance = 4f; if (!FleeThreatResolver.HasThreatWithinDistance(entityManager, entity, maxDistance)) { return false; } if (!States.TryGetValue(entity, out var value)) { return false; } if (value.Mode == FleeAiMode.OnPath && IsPathProgressStalled(entityManager, entity)) { return true; } if (value.Mode == FleeAiMode.SeekingInitial && (value.ConsecutiveFailedConeSearches >= 2 || value.LastSearchWasConeFailure)) { return true; } if (!FleeThreatResolver.TryGetGroundPosition(entityManager, entity, out var ground)) { return false; } if (FleePathClearanceContext.IsActive && FleePathClearance.IsPocketTrapped(ground)) { return true; } return false; } internal static bool ShouldRecoverFromStall(EntityManager entityManager, Entity entity) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated || !entityManager.Exists(entity)) { return false; } if (!IsPathProgressStalled(entityManager, entity)) { return false; } if (!FleeThreatResolver.HasThreatWithinDistance(entityManager, entity, 4f)) { return false; } if (!States.TryGetValue(entity, out var value) || value.Mode != FleeAiMode.OnPath) { return false; } float time = Time.time; if (value.LastStallRecoveryTime > 0f && time - value.LastStallRecoveryTime < 2f) { return false; } if (value.HasLastStallRecoveryPathEnd && math.distancesq(value.ActivePathEnd, value.LastStallRecoveryPathEnd) < 0.01f) { return false; } return true; } internal static void RecordStallRecovery(Entity entity) { //IL_0005: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (States.TryGetValue(entity, out var value)) { value.LastStallRecoveryTime = Time.time; value.LastStallRecoveryPathEnd = value.ActivePathEnd; value.HasLastStallRecoveryPathEnd = true; States[entity] = value; } } internal static bool IsFleeUnitRunning(EntityManager entityManager, Entity entity) { //IL_0009: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated || !entityManager.Exists(entity) || !entityManager.HasComponent(entity)) { return false; } return math.lengthsq(entityManager.GetComponentData(entity).Value) >= 0.01f; } internal static void UpdatePathProgress(EntityManager entityManager, Entity entity, float distanceToEnd) { //IL_0005: 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_0035: 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_008b: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value) || value.Mode != FleeAiMode.OnPath) { return; } float time = Time.time; if (!IsFleeUnitRunning(entityManager, entity)) { value.LastPathProgressTime = time; States[entity] = value; return; } if (value.LastPathProgressTime <= 0f) { value.LastPathProgressDistance = distanceToEnd; value.LastPathProgressTime = time; States[entity] = value; return; } if (value.LastPathProgressDistance - distanceToEnd >= 1f) { value.LastPathProgressDistance = distanceToEnd; value.LastPathProgressTime = time; } States[entity] = value; } internal static bool IsPathProgressStalled(EntityManager entityManager, Entity entity) { //IL_0005: 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) if (!States.TryGetValue(entity, out var value) || value.Mode != FleeAiMode.OnPath) { return false; } if (!IsFleeUnitRunning(entityManager, entity)) { return false; } if (value.LastPathProgressTime <= 0f) { return false; } return Time.time - value.LastPathProgressTime >= 0.5f; } internal static void ResetToSeekingInitialForCornerEscape(Entity entity) { //IL_0005: 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_001f: 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) if (States.TryGetValue(entity, out var value)) { value.Mode = FleeAiMode.SeekingInitial; value.ActivePathEnd = float3.zero; value.ActivePathLength = 0f; value.HasPendingNextPath = false; value.SearchSession = default(FleePathSearchSession); value.LastPathProgressDistance = 0f; value.LastPathProgressTime = 0f; States[entity] = value; } } internal static void ResetPathProgress(Entity entity) { //IL_0005: 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) if (States.TryGetValue(entity, out var value)) { value.LastPathProgressDistance = 0f; value.LastPathProgressTime = 0f; States[entity] = value; } } internal static void ResetStallRecoveryTracking(Entity entity) { //IL_0005: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (States.TryGetValue(entity, out var value)) { value.HasLastStallRecoveryPathEnd = false; value.LastStallRecoveryPathEnd = float3.zero; States[entity] = value; } } internal static int GetCandidateOffset(Entity entity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value)) { return 0; } return value.CandidateOffset; } internal static void Prune(EntityManager entityManager) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated) { return; } PruneScratch.Clear(); foreach (KeyValuePair state in States) { if (!entityManager.Exists(state.Key)) { PruneScratch.Add(state.Key); } } for (int i = 0; i < PruneScratch.Count; i++) { States.Remove(PruneScratch[i]); } FleePostFleeAttackCooldown.Prune(entityManager); FleeShouldFleeCache.Prune(entityManager); } internal static void Clear(Entity entity) { //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_0012: Unknown result type (might be due to invalid IL or missing references) if (entity != Entity.Null) { States.Remove(entity); } } internal static void OnEnterFlee(Entity entity) { //IL_0005: 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_0090: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value)) { value = default(State); } if (value.Mode == FleeAiMode.Idle) { value.Mode = FleeAiMode.SeekingInitial; value.CandidateOffset = 0; value.UseFullCircleSearch = false; value.CornerEscapeActive = false; value.ConsecutiveFailedConeSearches = 0; value.LastSearchWasConeFailure = false; value.HasPendingNextPath = false; value.SearchSession = default(FleePathSearchSession); value.LastPathProgressDistance = 0f; value.LastPathProgressTime = 0f; value.LastStallRecoveryTime = 0f; value.HasLastStallRecoveryPathEnd = false; FleeDistanceDebugLog.LogTransition(entity, "entered flee range -> SeekingInitial"); } value.WasFleeing = true; States[entity] = value; } internal static void OnExitFlee(Entity entity) { //IL_0005: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (States.ContainsKey(entity)) { FleeDistanceDebugLog.LogTransition(entity, "left flee range"); } FleePostFleeAttackCooldown.RecordExit(entity); FleeDistanceDebugLog.ClearEntity(entity); Clear(entity); } internal static bool CanStartSearch(Entity entity, float minIntervalSeconds) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value)) { return false; } if (value.SearchSession.Active) { return false; } return Time.time - value.LastSearchTime >= minIntervalSeconds; } internal static bool BeginPathSearch(Entity entity, FleePathSearchKind kind, float3 origin, float3 awayDirection, bool useFullCircle, int candidateOffset, bool cornerEscape, bool hasPrimaryThreat, FleeNearbyThreat primaryThreat) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value)) { State state = default(State); state.Mode = ((kind == FleePathSearchKind.Initial) ? FleeAiMode.SeekingInitial : FleeAiMode.OnPath); value = state; } if (cornerEscape) { value.CornerEscapeActive = true; value.UseFullCircleSearch = true; useFullCircle = true; FleeDistanceDebugLog.LogTransition(entity, "corner escape active"); } value.SearchSession = new FleePathSearchSession { Active = true, Kind = kind, Origin = origin, AwayDirection = awayDirection, UseFullCircle = useFullCircle, CornerEscape = cornerEscape, AngleIndex = 0, CandidateOffset = candidateOffset, Generation = (int)(Time.time * 1000f), HasBestPath = false, BestScore = float.MinValue, HasRelaxedBestPath = false, RelaxedBestScore = float.MinValue, HasPrimaryThreat = hasPrimaryThreat, PrimaryThreat = primaryThreat }; value.LastSearchTime = Time.time; States[entity] = value; FleeDistanceDebugLog.LogThrottled(entity, cornerEscape ? $"corner escape path search started ({kind})" : $"path search started ({kind})"); return true; } internal static bool TryUpdateSearchBestPath(Entity entity, in FleeStoredPath path) { //IL_0005: 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) if (!States.TryGetValue(entity, out var value) || !value.SearchSession.Active) { return false; } if (path.Score <= value.SearchSession.BestScore) { return false; } value.SearchSession.BestPath = path; value.SearchSession.BestScore = path.Score; value.SearchSession.HasBestPath = true; States[entity] = value; return true; } internal static bool TryUpdateSearchRelaxedBestPath(Entity entity, in FleeStoredPath path) { //IL_0005: 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) if (!States.TryGetValue(entity, out var value) || !value.SearchSession.Active) { return false; } if (path.Score <= value.SearchSession.RelaxedBestScore) { return false; } value.SearchSession.RelaxedBestPath = path; value.SearchSession.RelaxedBestScore = path.Score; value.SearchSession.HasRelaxedBestPath = true; States[entity] = value; return true; } internal static bool TryAdvanceSearchAngle(Entity entity, int angleCount, out bool sessionComplete, out FleePathSearchSession session) { //IL_000f: 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) sessionComplete = false; session = default(FleePathSearchSession); if (!States.TryGetValue(entity, out var value) || !value.SearchSession.Active) { return false; } value.SearchSession.AngleIndex++; if (value.SearchSession.AngleIndex >= angleCount) { sessionComplete = true; session = value.SearchSession; value.SearchSession = default(FleePathSearchSession); } States[entity] = value; return true; } internal static void CancelSearchSession(Entity entity) { //IL_0005: 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 (States.TryGetValue(entity, out var value)) { value.SearchSession = default(FleePathSearchSession); States[entity] = value; } } internal static void FinalizeCompletedSearch(Entity entity, in FleePathSearchSession session, bool foundPath) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value)) { return; } bool cornerEscape = session.CornerEscape; value.LastSearchTime = Time.time; value.SearchSession = default(FleePathSearchSession); if (!foundPath) { if (!session.UseFullCircle && !session.CornerEscape) { value.ConsecutiveFailedConeSearches++; value.LastSearchWasConeFailure = true; } if (!session.CornerEscape) { value.CandidateOffset++; if (value.CandidateOffset >= 3 && !value.UseFullCircleSearch) { value.UseFullCircleSearch = true; } } } else { value.ConsecutiveFailedConeSearches = 0; value.LastSearchWasConeFailure = false; value.CandidateOffset = 0; value.UseFullCircleSearch = false; value.CornerEscapeActive = false; } if (!foundPath && cornerEscape) { value.CornerEscapeActive = false; } States[entity] = value; } internal static bool TryAcceptInitialPath(Entity entity, in FleeStoredPath path, bool cornerEscape) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_0097: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(entity, out var value)) { return false; } value.Mode = FleeAiMode.OnPath; value.ActivePathEnd = path.End; value.ActivePathLength = path.Length; value.HasPendingNextPath = false; value.CandidateOffset = 0; value.UseFullCircleSearch = false; value.CornerEscapeActive = false; value.ConsecutiveFailedConeSearches = 0; value.LastSearchWasConeFailure = false; value.SearchSession = default(FleePathSearchSession); value.LastPathProgressDistance = 0f; value.LastPathProgressTime = 0f; if (value.HasLastStallRecoveryPathEnd && math.distancesq(path.End, value.LastStallRecoveryPathEnd) >= 0.01f) { value.HasLastStallRecoveryPathEnd = false; value.LastStallRecoveryPathEnd = float3.zero; } States[entity] = value; if (cornerEscape) { FleeDistanceDebugLog.LogTransition(entity, $"corner escape path committed -> OnPath ({path.Length:F1} WM)"); } else { FleeDistanceDebugLog.LogTransition(entity, $"path committed -> OnPath ({path.Length:F1} WM)"); } return true; } internal static bool TryStorePendingNextPath(Entity entity, in FleeStoredPath path) { //IL_0005: 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) if (!States.TryGetValue(entity, out var value)) { return false; } if (value.HasPendingNextPath && path.Score <= value.PendingNextPath.Score) { return false; } value.PendingNextPath = path; value.HasPendingNextPath = true; States[entity] = value; return true; } internal static bool TryConsumePendingNextPath(Entity entity, out FleeStoredPath path) { //IL_000c: 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_0034: 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) path = default(FleeStoredPath); if (!States.TryGetValue(entity, out var value) || !value.HasPendingNextPath) { return false; } path = value.PendingNextPath; value.ActivePathEnd = path.End; value.ActivePathLength = path.Length; value.HasPendingNextPath = false; value.Mode = FleeAiMode.OnPath; value.CandidateOffset = 0; value.UseFullCircleSearch = false; States[entity] = value; return true; } } internal static class FleeDistancePathHelper { internal const float MinFirstSegmentDot = 0.3f; internal const float TargetProbeDistance = 13.5f; internal const float SearchRetryInterval = 0.2f; internal const float EmergencyFleeDistance = 10f; private static readonly float[] FullCircleCandidateAnglesDeg = new float[12] { 0f, 30f, -30f, 60f, -60f, 90f, -90f, 120f, -120f, 150f, -150f, 180f }; private static readonly float[] HighLoadConeCandidateAnglesDeg = new float[5] { 0f, 60f, -60f, 120f, -120f }; private static readonly List NearbyThreatScratch = new List(16); private static float _cachedConeDegrees = float.NaN; private static float[] _cachedConeCandidateAngles; private static AstarPath _astarPath; private static Seeker _seeker; private static bool _hasLargeUnitNavmesh; internal static bool TryGetSelfPosition(EntityManager entityManager, Entity entity, out float3 position) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_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_003e: Unknown result type (might be due to invalid IL or missing references) position = float3.zero; if (entityManager.HasComponent(entity)) { position = entityManager.GetComponentData(entity).Value; return true; } if (entityManager.HasComponent(entity)) { position = entityManager.GetComponentData(entity).Value; return true; } return false; } internal static float GetDistanceToPathEnd(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) if (!TryGetSelfPosition(entityManager, entity, out var position) || !FleeDistanceAiState.TryGetActivePathEnd(entity, out var pathEnd)) { return float.MaxValue; } float3 val = pathEnd - position; val.y = 0f; return math.length(val); } internal static void EnsureAstarReady() { if ((Object)(object)_astarPath == (Object)null) { _astarPath = Object.FindObjectOfType(); } if ((Object)(object)_seeker == (Object)null) { _seeker = Object.FindObjectOfType(); } if ((Object)(object)_astarPath != (Object)null) { _hasLargeUnitNavmesh = (Object)(object)AstarData.active != (Object)null && AstarData.active.data.graphs.Length > 1; } } internal static void TickInitialPathSearch(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0023: 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_0026: Unknown result type (might be due to invalid IL or missing references) if (FleeDistanceAiState.ShouldFlee(entityManager, entity) && TryGetSelfPosition(entityManager, entity, out var position) && FleeThreatResolver.TryGetClosestEnemyThreat(entityManager, entity, out var _, out var awayDirection)) { TickPathSearch(entityManager, entity, FleePathSearchKind.Initial, position, awayDirection); } } internal static void TickBackgroundNextPathSearch(EntityManager entityManager, Entity entity) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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) //IL_0034: 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) if (!FleeBattleContext.IsHighLoad && !FleeDistanceAiState.HasActiveSearchSession(entity) && !FleeDistanceAiState.HasPendingNextPath(entity) && FleeDistanceAiState.TryGetActivePathEnd(entity, out var pathEnd) && FleeThreatResolver.TryGetClosestEnemyThreat(entityManager, entity, out var _, out var awayDirection)) { TickPathSearch(entityManager, entity, FleePathSearchKind.NextPath, pathEnd, awayDirection); } } internal static bool TryApplyPendingNextPath(EntityManager entityManager, Entity entity) { //IL_0000: 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) if (!FleeDistanceAiState.TryConsumePendingNextPath(entity, out var path)) { return false; } WriteStoredPath(entityManager, entity, in path); return true; } internal static void WriteStoredPath(EntityManager entityManager, Entity entity, in FleeStoredPath storedPath) { //IL_0001: 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_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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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) if (!entityManager.HasComponent(entity)) { entityManager.AddBuffer(entity); } DynamicBuffer buffer = entityManager.GetBuffer(entity); buffer.Clear(); if (storedPath.Points != null && storedPath.Points.Length != 0) { for (int i = 0; i < storedPath.Points.Length; i++) { buffer.Add(new PathPoint { Value = storedPath.Points[i] }); } entityManager.SetComponentData(entity, new CurrentWaypoint { Value = 0 }); entityManager.SetComponentData(entity, new PathDistance { Distance = storedPath.Length }); } } internal static void DisableVanillaRepath(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0020: 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_002d: Unknown result type (might be due to invalid IL or missing references) if (entityManager.HasComponent(entity)) { PathSettings componentData = entityManager.GetComponentData(entity); componentData.RepathRate = 999f; componentData.CurrentRate = componentData.RepathRate; entityManager.SetComponentData(entity, componentData); } } internal static void RestoreVanillaRepath(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0020: 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_002d: Unknown result type (might be due to invalid IL or missing references) if (entityManager.HasComponent(entity)) { PathSettings componentData = entityManager.GetComponentData(entity); componentData.RepathRate = 0.5f; componentData.CurrentRate = componentData.RepathRate; entityManager.SetComponentData(entity, componentData); } } internal static void RestoreForwardVelocity(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0023: 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_002e: 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) if (entityManager.HasComponent(entity)) { Velocity componentData = entityManager.GetComponentData(entity); componentData.Value = new float3(0f, 0f, 1f); entityManager.SetComponentData(entity, componentData); } } internal static void RestoreThreatAwayLocomotion(EntityManager entityManager, Entity entity) { //IL_0001: 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_003d: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_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) //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_002f: 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_0036: Unknown result type (might be due to invalid IL or missing references) if (FleeThreatResolver.TryGetClosestEnemyThreat(entityManager, entity, out var _, out var awayDirection)) { if (entityManager.HasComponent(entity)) { Direction componentData = entityManager.GetComponentData(entity); componentData.LastValue = componentData.Value; componentData.Value = awayDirection; entityManager.SetComponentData(entity, componentData); } RestoreForwardVelocity(entityManager, entity); } } internal static void RestoreDirectionAlongPath(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_001e: 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_0024: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0093: 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_00a0: 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_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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00ef: 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_010c: 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_0113: 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_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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.HasComponent(entity) || !entityManager.HasComponent(entity) || !entityManager.HasComponent(entity)) { return; } DynamicBuffer buffer; try { buffer = entityManager.GetBuffer(entity); } catch { return; } if (buffer.Length == 0) { return; } CurrentWaypoint componentData = entityManager.GetComponentData(entity); if (componentData.Value >= buffer.Length - 1) { return; } HipPosition componentData2 = entityManager.GetComponentData(entity); float3 value = buffer[componentData.Value].Value; float3 value2 = buffer[componentData.Value + 1].Value; float3 val = ProjectPointOntoLine(value, value2, componentData2.Value); float num = math.length(value2 - value); if (math.length(val - value) > num) { componentData.Value++; } if (componentData.Value < buffer.Length - 1) { value2 = buffer[componentData.Value + 1].Value; float3 val2 = value2 - componentData2.Value; val2.y = 0f; if (!(math.lengthsq(val2) < 0.0001f)) { val2 = math.normalize(val2); Direction componentData3 = entityManager.GetComponentData(entity); componentData3.LastValue = componentData3.Value; componentData3.Value = val2; entityManager.SetComponentData(entity, componentData); entityManager.SetComponentData(entity, componentData3); } } } internal static void ApplyCustomPathMovement(EntityManager entityManager, Entity entity) { //IL_0001: 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) RestoreDirectionAlongPath(entityManager, entity); RestoreForwardVelocity(entityManager, entity); } private static float3 ProjectPointOntoLine(float3 a, float3 b, float3 p) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //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_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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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) float3 val = b - a; float3 val2 = p - a; float num = math.dot(val, val); if (num < 0.0001f) { return a; } float num2 = math.dot(val2, val) / num; return a + val * num2; } internal static bool TryReadCurrentPathPoints(EntityManager entityManager, Entity entity, out float3[] points) { //IL_0004: 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_0010: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) points = null; if (!entityManager.HasComponent(entity)) { return false; } DynamicBuffer buffer = entityManager.GetBuffer(entity); if (buffer.Length == 0) { return false; } points = (float3[])(object)new float3[buffer.Length]; for (int i = 0; i < buffer.Length; i++) { points[i] = buffer[i].Value; } return true; } private static void TickPathSearch(EntityManager entityManager, Entity entity, FleePathSearchKind kind, float3 origin, float3 awayDirection) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0060: 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_0070: 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) if (FleeDistanceAiState.TryGetSearchSession(entity, out var session)) { AdvanceSearchCandidate(entityManager, entity, ref session); } else { if (!FleePathSearchBudget.TryBeginNewSession() || !FleeDistanceAiState.CanStartSearch(entity, 0.2f)) { return; } bool flag = FleeDistanceAiState.ShouldUseCornerEscape(entityManager, entity); if (TryResolveAwayDirection(entityManager, entity, flag, out awayDirection)) { bool useFullCircle = flag || FleeDistanceAiState.ShouldUseFullCircle(entity); int candidateOffset = FleeDistanceAiState.GetCandidateOffset(entity); FleeNearbyThreat threat; bool hasPrimaryThreat = FleeThreatResolver.TryGetPrimaryFleeThreat(entityManager, entity, out threat); FleeDistanceAiState.BeginPathSearch(entity, kind, origin, awayDirection, useFullCircle, candidateOffset, flag, hasPrimaryThreat, threat); if (FleeDistanceAiState.TryGetSearchSession(entity, out session)) { AdvanceSearchCandidate(entityManager, entity, ref session); } } } } private static bool TryResolveAwayDirection(EntityManager entityManager, Entity entity, bool cornerEscape, out float3 awayDirection) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (cornerEscape && FleeThreatResolver.TryGetCompositeAwayDirection(entityManager, entity, 4f, NearbyThreatScratch, out awayDirection)) { return true; } float3 threatGround; return FleeThreatResolver.TryGetClosestEnemyThreat(entityManager, entity, out threatGround, out awayDirection); } private static void AdvanceSearchCandidate(EntityManager entityManager, Entity entity, ref FleePathSearchSession session) { //IL_0048: 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_005a: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_00d2: 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_0138: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00f2: 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) //IL_00a6: 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_012f: Unknown result type (might be due to invalid IL or missing references) if (!FleePathSearchBudget.TryConsume()) { return; } float[] array = (session.UseFullCircle ? FullCircleCandidateAnglesDeg : GetConeCandidateAngles()); if (session.AngleIndex >= array.Length) { CompleteSearch(entityManager, entity, ref session); return; } int num = (session.AngleIndex + session.CandidateOffset) % array.Length; float num2 = array[num]; float3 val = RotateFlat(session.AwayDirection, math.radians(num2)); float3 snapped = session.Origin + val * 13.5f; List nearbyThreats = null; if (session.HasPrimaryThreat) { if (FleeThreatResolver.DestinationMovesCloserToThreat(session.Origin, snapped, in session.PrimaryThreat)) { if (FleeDistanceAiState.TryAdvanceSearchAngle(entity, array.Length, out var sessionComplete, out var session2) && sessionComplete) { CompleteSearch(entityManager, entity, ref session2); } return; } NearbyThreatScratch.Clear(); NearbyThreatScratch.Add(session.PrimaryThreat); nearbyThreats = NearbyThreatScratch; } if (TrySnapToNavmesh(entityManager, entity, snapped, out snapped) && FleePathClearance.IsViableFleePosition(snapped) && TryBuildPathCandidate(entityManager, entity, session.Origin, snapped, val, session.AwayDirection, session.CornerEscape, nearbyThreats, out var storedPath)) { if (IsPathLengthValid(storedPath.Length)) { FleeDistanceAiState.TryUpdateSearchBestPath(entity, in storedPath); } else if (IsRelaxedPathLengthValid(storedPath.Length)) { FleeDistanceAiState.TryUpdateSearchRelaxedBestPath(entity, in storedPath); } } if (FleeDistanceAiState.TryAdvanceSearchAngle(entity, array.Length, out var sessionComplete2, out var session3) && sessionComplete2) { CompleteSearch(entityManager, entity, ref session3); } } private static void CompleteSearch(EntityManager entityManager, Entity entity, ref FleePathSearchSession session) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0083: 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) FleePathSearchKind kind = session.Kind; bool flag = session.HasBestPath; FleeStoredPath path = session.BestPath; if (!flag && session.HasRelaxedBestPath) { flag = true; path = session.RelaxedBestPath; FleeDistanceDebugLog.LogThrottled(entity, "using relaxed path fallback"); } if (!flag && kind == FleePathSearchKind.Initial && TryBuildEmergencyPath(entityManager, entity, session.Origin, session.AwayDirection, out path)) { flag = true; FleeDistanceDebugLog.LogTransition(entity, "using emergency flee path"); } if (!flag) { FleeDistanceDebugLog.LogThrottled(entity, "path search failed, retrying"); } FleeDistanceAiState.FinalizeCompletedSearch(entity, in session, flag); if (flag) { bool cornerEscape = session.CornerEscape; if (kind == FleePathSearchKind.Initial) { WriteStoredPath(entityManager, entity, in path); FleeDistanceAiState.TryAcceptInitialPath(entity, in path, cornerEscape); } else { FleeDistanceAiState.TryStorePendingNextPath(entity, in path); } } } private static float[] GetConeCandidateAngles() { if (FleeBattleContext.IsHighLoad) { return HighLoadConeCandidateAnglesDeg; } float num = 240f; if (_cachedConeCandidateAngles != null && math.abs(num - _cachedConeDegrees) < 0.001f) { return _cachedConeCandidateAngles; } _cachedConeDegrees = num; float num2 = num * 0.5f; _cachedConeCandidateAngles = new float[7] { 0f, num2 * 0.33f, (0f - num2) * 0.33f, num2 * 0.67f, (0f - num2) * 0.67f, num2, 0f - num2 }; return _cachedConeCandidateAngles; } private static bool TryBuildPathCandidate(EntityManager entityManager, Entity entity, float3 origin, float3 destination, float3 candidateDirection, float3 awayDirection, bool cornerEscape, List nearbyThreats, out FleeStoredPath storedPath) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) //IL_002a: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: 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_017f: 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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) storedPath = default(FleeStoredPath); EnsureAstarReady(); if ((Object)(object)_astarPath == (Object)null) { return false; } if (nearbyThreats != null && nearbyThreats.Count > 0 && FleeThreatResolver.DestinationMovesCloserToAnyThreat(origin, destination, nearbyThreats)) { return false; } ABPath val = ABPath.Construct(new Vector3(origin.x, origin.y, origin.z), new Vector3(destination.x, destination.y, destination.z), (OnPathDelegate)null); ApplyNavmeshConstraint(entityManager, entity, val); AstarPath.StartPath((Path)(object)val, true); ((Path)val).BlockUntilCalculated(); if (!IsPathSuccessful((Path)(object)val) || ((Path)val).vectorPath == null || ((Path)val).vectorPath.Count < 2) { return false; } int graphMask = GetGraphMask(entityManager, entity); bool seekerAppliedModifiers = TryApplySeekerModifiers((Path)(object)val); List list = FleePathSimplify.PrepareForStorage(((Path)val).vectorPath, seekerAppliedModifiers, graphMask); if (list == null || list.Count < 2) { return false; } if (!FleePathClearance.IsPathEdgeSafe(list)) { return false; } float3 val2 = (cornerEscape ? awayDirection : candidateDirection); if (!ValidateFirstSegment(list, val2)) { return false; } float3 val3 = default(float3); ((float3)(ref val3))..ctor(list[list.Count - 1].x, list[list.Count - 1].y, list[list.Count - 1].z); if (!FleePathClearance.IsViableFleePosition(val3)) { return false; } if (nearbyThreats != null && nearbyThreats.Count > 0 && FleeThreatResolver.DestinationMovesCloserToAnyThreat(origin, val3, nearbyThreats)) { return false; } float num = MeasureVectorPathLength(list); float alignmentWithAway = math.dot(math.normalizesafe(new float3(val2.x, 0f, val2.z), default(float3)), math.normalizesafe(new float3(awayDirection.x, 0f, awayDirection.z), default(float3))); float num2 = FleePathClearance.ScoreDestination(val3, alignmentWithAway); num2 += math.clamp(num / 15f, 0f, 1f) * 0.25f; if (!FleePathClearance.UseHighLoadFastMode) { num2 += FleePathClearance.MeasurePathMinClearance(list) / 3f * 0.4f; } if (nearbyThreats != null && nearbyThreats.Count > 0) { num2 += FleeThreatResolver.ScoreDestinationAgainstThreats(origin, val3, nearbyThreats); } storedPath = new FleeStoredPath { End = val3, Length = num, Score = num2, Points = ToPointArray(list) }; return true; } private static bool TryApplySeekerModifiers(Path path) { if ((Object)(object)_seeker == (Object)null) { return false; } _seeker.RunModifiers((ModifierPass)2, path); if (path.vectorPath != null) { return path.vectorPath.Count >= 2; } return false; } private static int GetGraphMask(EntityManager entityManager, Entity entity) { //IL_0003: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected I4, but got Unknown int result = 1; if (!entityManager.HasComponent(entity)) { return result; } int num = (int)entityManager.GetComponentData(entity).Value; if (!_hasLargeUnitNavmesh) { num = 0; } return 1 << num; } internal static void TryWriteEmergencyFleePath(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (FleeDistanceAiState.ShouldFlee(entityManager, entity) && TryGetSelfPosition(entityManager, entity, out var position) && FleeThreatResolver.TryGetClosestEnemyThreat(entityManager, entity, out var _, out var awayDirection) && TryBuildEmergencyPath(entityManager, entity, position, awayDirection, out var storedPath)) { WriteStoredPath(entityManager, entity, in storedPath); } } private static bool TryBuildEmergencyPath(EntityManager entityManager, Entity entity, float3 origin, float3 awayDirection, out FleeStoredPath storedPath) { //IL_0008: 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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_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_004e: 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_0051: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00af: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00e1: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) storedPath = default(FleeStoredPath); float3 val = math.normalizesafe(new float3(awayDirection.x, 0f, awayDirection.z), default(float3)); if (math.lengthsq(val) < 0.0001f) { return false; } float3 snapped = origin + val * 10f; if (!TrySnapToNavmesh(entityManager, entity, snapped, out snapped)) { return false; } if (!FleePathClearance.IsViableFleePosition(snapped)) { return false; } if (!FleePathClearance.IsPathEdgeSafe(new List { new Vector3(origin.x, origin.y, origin.z), new Vector3(snapped.x, snapped.y, snapped.z) })) { return false; } float3 val2 = snapped - origin; val2.y = 0f; float num = math.length(val2); if (num < 0.5f) { return false; } storedPath = new FleeStoredPath { End = snapped, Length = num, Score = 0f, Points = (float3[])(object)new float3[2] { origin, snapped } }; return true; } internal static bool IsPathLengthValid(float length) { if (length >= 12f) { return length <= 15f; } return false; } internal static bool IsRelaxedPathLengthValid(float length) { float num = math.max(6f, 6f); return length >= num; } internal static float MeasureVectorPathLength(List vectorPath) { //IL_0021: 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) if (vectorPath == null || vectorPath.Count < 2) { return 0f; } float num = 0f; for (int i = 1; i < vectorPath.Count; i++) { num += Vector3.Distance(vectorPath[i - 1], vectorPath[i]); } return num; } private static bool ValidateFirstSegment(List vectorPath, float3 candidateDirection) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) if (vectorPath.Count < 2) { return false; } Vector3 val = vectorPath[1] - vectorPath[0]; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { return false; } Vector3 val2 = new Vector3(candidateDirection.x, 0f, candidateDirection.z); Vector3 normalized = ((Vector3)(ref val2)).normalized; ((Vector3)(ref val)).Normalize(); return Vector3.Dot(val, normalized) >= 0.3f; } private static bool IsPathSuccessful(Path path) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected I4, but got Unknown int num = (int)path.CompleteState; if (num != 2) { return num == 3; } return true; } private static void ApplyNavmeshConstraint(EntityManager entityManager, Entity entity, ABPath path) { //IL_0008: 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) NNConstraint none = NNConstraint.None; none.graphMask = GraphMask.op_Implicit(GetGraphMask(entityManager, entity)); ((Path)path).nnConstraint = none; } private static bool TrySnapToNavmesh(EntityManager entityManager, Entity entity, float3 position, out float3 snapped) { //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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_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_0061: 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_006c: 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) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) snapped = position; EnsureAstarReady(); if ((Object)(object)_astarPath == (Object)null) { return false; } NNConstraint none = NNConstraint.None; none.graphMask = GraphMask.op_Implicit(GetGraphMask(entityManager, entity)); NNInfo nearest = AstarPath.active.GetNearest(new Vector3(position.x, position.y, position.z), none); if (nearest.node == null) { return false; } snapped = new float3(nearest.position.x, nearest.position.y, nearest.position.z); return true; } private static float3 RotateFlat(float3 direction, float radians) { //IL_000e: 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_0024: 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_0035: Unknown result type (might be due to invalid IL or missing references) float num = math.cos(radians); float num2 = math.sin(radians); return new float3(direction.x * num - direction.z * num2, 0f, direction.x * num2 + direction.z * num); } private static float3[] ToPointArray(List vectorPath) { //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_001a: 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_0026: 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_0031: Unknown result type (might be due to invalid IL or missing references) float3[] array = (float3[])(object)new float3[vectorPath.Count]; for (int i = 0; i < vectorPath.Count; i++) { Vector3 val = vectorPath[i]; array[i] = new float3(val.x, val.y, val.z); } return array; } } internal static class FleeDistanceTuning { internal const bool DebugEnabled = false; internal const bool ClearanceRoutingEnabled = true; internal const bool SkipBackgroundPathSearchUnderLoad = true; internal const float PathMinLength = 12f; internal const float PathMaxLength = 15f; internal const float SwapDistance = 4f; internal const float SearchConeDegrees = 240f; internal const float FleeExitHysteresis = 0.5f; internal const float CornerEscapeEnemyDistance = 4f; internal const float CornerEscapeStallSeconds = 0.5f; internal const float CornerEscapeMinProgress = 1f; internal const float MinEdgeClearance = 0.35f; internal const float MaxStepHeight = 0.65f; internal const float StallRecoveryCooldown = 2f; internal const float PostFleeAttackCooldown = 1f; internal const float ThreatSnapshotInterval = 0.25f; internal const int MaxPathSearchesPerFrame = 4; internal const int MaxNewPathSearchSessionsPerFrame = 2; internal const int IdleThreatCheckIntervalFrames = 6; internal const int HighLoadFleeUnitThreshold = 10; internal const float BackgroundNextPathLeadDistance = 8f; } internal static class FleeEcsJobHelper { private static int _entityManagerFrame = -1; private static EntityManager _entityManager; internal static Entity GetEntity(object jobInstance, int index) { //IL_0003: 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_0060: 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) if (jobInstance == null) { return Entity.Null; } object value = Traverse.Create(jobInstance).Field("Entities").GetValue(); if (value == null) { return Entity.Null; } PropertyInfo property = value.GetType().GetProperty("Item", BindingFlags.Instance | BindingFlags.Public); if (property == null) { return Entity.Null; } return (Entity)property.GetValue(value, new object[1] { index }); } internal static EntityManager GetBattleEntityManager() { if (Time.frameCount == _entityManagerFrame) { return _entityManager; } _entityManagerFrame = Time.frameCount; _entityManager = null; if (!BattleStateHelper.ShouldRunFleeAi() || !EcsComponentHelper.IsAvailable) { return null; } TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return null; } List allUnits = existingManager.GetAllUnits(); if (allUnits == null) { return null; } for (int i = 0; i < allUnits.Count; i++) { if (EcsComponentHelper.TryGetEntityManager((Component)(object)allUnits[i], out var _, out var entityManager)) { _entityManager = entityManager; break; } } return _entityManager; } } internal static class FleeMovementJobGuard { private static object _fleeWithinEntities; private static object _keepPreferredEntities; private static object _keepRangedEntities; internal static void CaptureFleeWithinEntities(object filter) { _fleeWithinEntities = GetFilterEntities(filter); } internal static void CaptureKeepPreferredEntities(object filter) { _keepPreferredEntities = GetFilterEntities(filter); } internal static void CaptureKeepRangedEntities(object filter) { _keepRangedEntities = GetFilterEntities(filter); } internal static bool ShouldSkipFleeWithinDistance(int index) { //IL_0014: 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) if (!TryGetEntity(_fleeWithinEntities, index, out var entity, out var entityManager)) { return false; } if (!entityManager.HasComponent(entity)) { return false; } return FleeDistanceAiState.ShouldFlee(entityManager, entity); } internal static bool ShouldSkipKeepPreferredDistance(int index) { //IL_0014: 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) if (!TryGetEntity(_keepPreferredEntities, index, out var entity, out var entityManager)) { return false; } if (!entityManager.HasComponent(entity)) { return false; } return FleeDistanceAiState.ShouldFlee(entityManager, entity); } internal static bool ShouldSkipKeepRangedDistance(int index) { //IL_0014: 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) if (!TryGetEntity(_keepRangedEntities, index, out var entity, out var entityManager)) { return false; } if (!entityManager.HasComponent(entity)) { return false; } return FleeDistanceAiState.ShouldFlee(entityManager, entity); } private static object GetFilterEntities(object filter) { if (filter == null) { return null; } return Traverse.Create(filter).Field("Entities").GetValue(); } private static bool TryGetEntity(object entities, int index, out Entity entity, out EntityManager entityManager) { //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_006a: 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_0075: 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_0089: Unknown result type (might be due to invalid IL or missing references) entity = Entity.Null; entityManager = null; if (!FleeConfig.FleeDistanceEnabled || !BattleStateHelper.ShouldRunFleeAi()) { return false; } if (entities == null) { return false; } entityManager = FleeEcsJobHelper.GetBattleEntityManager(); if (!entityManager.IsCreated) { return false; } PropertyInfo property = entities.GetType().GetProperty("Item", BindingFlags.Instance | BindingFlags.Public); if (property == null) { return false; } entity = (Entity)property.GetValue(entities, new object[1] { index }); if (entity != Entity.Null) { return entityManager.Exists(entity); } return false; } } internal static class FleeMonoLocomotionHelper { internal const float MinFleeMovementSpeed = 1f; internal static bool TryGetAwayLookDirection(EntityManager entityManager, Entity entity, out Vector3 lookDirection) { //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_000c: 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_0021: 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_002d: 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) lookDirection = Vector3.forward; if (!FleeThreatResolver.TryGetClosestEnemyThreat(entityManager, entity, out var _, out var awayDirection)) { return false; } lookDirection = new Vector3(awayDirection.x, awayDirection.y, awayDirection.z); if (((Vector3)(ref lookDirection)).sqrMagnitude < 0.0001f) { return false; } ((Vector3)(ref lookDirection)).Normalize(); return true; } internal static bool TryGetFleeLookDirection(EntityManager entityManager, Entity entity, out Vector3 lookDirection) { //IL_0000: 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_0009: Unknown result type (might be due to invalid IL or missing references) if (FleeDistanceAiState.IsCustomPathActive(entity) && TryGetPathFollowingLookDirection(entityManager, entity, out lookDirection)) { return true; } return TryGetAwayLookDirection(entityManager, entity, out lookDirection); } private static bool TryGetPathFollowingLookDirection(EntityManager entityManager, Entity entity, out Vector3 lookDirection) { //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_000c: 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_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) //IL_0027: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) lookDirection = Vector3.forward; if (!entityManager.HasComponent(entity) || !entityManager.HasComponent(entity)) { return false; } DynamicBuffer buffer; try { buffer = entityManager.GetBuffer(entity); } catch { return false; } if (buffer.Length < 2) { return false; } CurrentWaypoint componentData = entityManager.GetComponentData(entity); if (componentData.Value >= buffer.Length - 1) { return false; } HipPosition componentData2 = entityManager.GetComponentData(entity); float3 val = buffer[componentData.Value + 1].Value - componentData2.Value; val.y = 0f; if (math.lengthsq(val) < 0.0001f) { return false; } val = math.normalize(val); lookDirection = new Vector3(val.x, val.y, val.z); return true; } internal static void ApplyFleeLocomotionToMono(EntityManager entityManager, Entity entity, Unit unit) { //IL_0020: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_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_004e: 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: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_0096: 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_00a2: 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) if ((Object)(object)unit == (Object)null || (Object)(object)unit.api == (Object)null || !entityManager.IsCreated || !entityManager.Exists(entity) || !entityManager.HasComponent(entity) || !entityManager.HasComponent(entity)) { return; } Direction componentData = entityManager.GetComponentData(entity); Velocity componentData2 = entityManager.GetComponentData(entity); Vector3 lookDirection = default(Vector3); ((Vector3)(ref lookDirection))..ctor(componentData.Value.x, componentData.Value.y, componentData.Value.z); if (((Vector3)(ref lookDirection)).sqrMagnitude < 0.0001f) { if (!TryGetFleeLookDirection(entityManager, entity, out lookDirection)) { return; } } else { ((Vector3)(ref lookDirection)).Normalize(); } float num = componentData2.Value.z; if (math.lengthsq(componentData2.Value) < 0.01f || num <= 0.01f) { num = 1f; } unit.api.SetLookDirection(lookDirection, true); unit.api.SetMovementSpeed(num, true); } internal static bool TryRedirectLookDirectionWhileFleeing(EntityManager entityManager, Entity entity, ref Vector3 localDirection) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!FleeDistanceAiState.ShouldFlee(entityManager, entity)) { return false; } if (!TryGetFleeLookDirection(entityManager, entity, out var lookDirection)) { return false; } localDirection = lookDirection; return true; } internal static bool TryEnsureForwardMovementWhileFleeing(EntityManager entityManager, Entity entity, ref float movementSpeed) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (!FleeDistanceAiState.ShouldFlee(entityManager, entity)) { return false; } if (movementSpeed > 0.01f) { return false; } movementSpeed = 1f; return true; } } internal static class FleePathClearance { internal const int MinOpenEscapeDirections = 3; private const float RaycastHeight = 1f; internal const float MaxRayDistance = 12f; internal const float ClearanceScanMaxDistance = 3f; private const int RayCount = 8; private const float DropCheckDepth = 4f; private const float ScoringProbeStep = 0.5f; private const float PocketWallProbeDistance = 1.25f; private const float CacheQuantize = 0.5f; private const float WaterProbeRadius = 0.4f; private const float WaterSampleHeight = 0.3f; private static int _mapLayerMask = -1; private static int _waterLayerMask = -1; private static int _cacheFrame = -1; private static readonly Dictionary ClearanceCache = new Dictionary(); private static readonly Dictionary WaterPointCache = new Dictionary(); private static readonly Dictionary PocketCache = new Dictionary(); private const int MaxPathClearanceSamples = 3; internal static bool UseHighLoadFastMode => FleeBattleContext.IsHighLoad; internal static bool Enabled => true; internal static float MinEdgeClearance => 0.35f; internal static float MaxStepHeight => 0.65f; internal static bool IsNearDropEdge(float3 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (Enabled && FleePathClearanceContext.IsActive) { return HasSignificantDrop(position); } return false; } internal static bool IsDropEdgeAt(float3 from, float3 flatDir, float horizontalDistance) { //IL_0010: 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_0021: 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_002e: 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_0034: 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_0046: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0075: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return false; } float3 val = math.normalizesafe(new float3(flatDir.x, 0f, flatDir.z), default(float3)); if (math.lengthsq(val) < 0.0001f) { return false; } Vector3 probePosition = default(Vector3); ((Vector3)(ref probePosition))..ctor(from.x + val.x * horizontalDistance, from.y, from.z + val.z * horizontalDistance); return IsDropAtProbe(from.y, probePosition); } internal static float MeasureDropEdgeClearance(float3 position) { //IL_0019: 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_0067: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return 3f; } BeginCacheFrame(); long key = QuantizeKey(position); if (ClearanceCache.TryGetValue(key, out var value)) { return value; } float num = 3f; float3 flatDir = default(float3); for (int i = 0; i < 8; i++) { float num2 = (float)i * 45f * ((float)Math.PI / 180f); ((float3)(ref flatDir))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2)); num = Mathf.Min(num, MeasureDirectionDropClearance(position, flatDir)); } ClearanceCache[key] = num; return num; } internal static bool IsDropEdgeUnsafe(float3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return HasSignificantDrop(position); } internal static bool IsMapEdge(float3 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (Enabled && FleePathClearanceContext.IsActive) { return MeasureDropEdgeClearance(position) < MinEdgeClearance; } return false; } internal static bool HasSignificantDrop(float3 position) { //IL_0015: 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) if (!Enabled || !FleePathClearanceContext.IsActive) { return false; } EnsureMapMask(); return !Physics.Raycast(ToRayOrigin(position), Vector3.down, 4f, _mapLayerMask); } internal static bool IsPocketTrapped(float3 position) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return false; } if (UseHighLoadFastMode) { return false; } BeginCacheFrame(); long key = QuantizeKey(position); if (PocketCache.TryGetValue(key, out var value)) { return value; } bool flag = !IsOpenEscape(position); PocketCache[key] = flag; return flag; } internal static bool IsOpenEscape(float3 position, int minOpenDirections = 3) { //IL_0015: 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_0049: 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) if (!Enabled || !FleePathClearanceContext.IsActive) { return true; } EnsureMapMask(); Vector3 val = ToRayOrigin(position); int num = 0; Vector3 val2 = default(Vector3); for (int i = 0; i < 8; i++) { float num2 = (float)i * 45f * ((float)Math.PI / 180f); ((Vector3)(ref val2))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2)); if (!Physics.Raycast(val, val2, 1.25f, _mapLayerMask)) { num++; } } return num >= minOpenDirections; } internal static bool IsViableFleePosition(float3 position) { //IL_0010: 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_0022: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return true; } if (IsDropEdgeUnsafe(position) || IsWaterAt(position)) { return false; } return !IsPocketTrapped(position); } internal static float MeasurePathMinClearance(List points) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive || points == null || points.Count == 0) { return 3f; } if (UseHighLoadFastMode) { return 3f; } float num = 3f; int num2 = ((points.Count <= 3) ? points.Count : 3); for (int i = 0; i < num2; i++) { int sampleIndex = GetSampleIndex(points.Count, i, num2); Vector3 val = points[sampleIndex]; num = Mathf.Min(num, MeasureDropEdgeClearance(new float3(val.x, val.y, val.z))); } return num; } internal static bool IsPathEdgeSafe(List points) { //IL_0042: 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_004a: 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_0056: 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_006a: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive || points == null || points.Count == 0) { return true; } int num = ((points.Count <= 3) ? points.Count : 3); float3 position = default(float3); for (int i = 0; i < num; i++) { int sampleIndex = GetSampleIndex(points.Count, i, num); Vector3 val = points[sampleIndex]; ((float3)(ref position))..ctor(val.x, val.y, val.z); if (HasSignificantDrop(position) || IsWaterAt(position)) { return false; } } return true; } internal static float ScoreDestination(float3 position, float alignmentWithAway) { //IL_004b: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return alignmentWithAway; } if (UseHighLoadFastMode) { float num = (IsWaterAt(position) ? (-2f) : 0f); float num2 = (HasSignificantDrop(position) ? (-2f) : 0f); return alignmentWithAway + num + num2; } float num3 = MeasureDropEdgeClearance(position); float num4 = Mathf.Clamp01(num3 / 3f); float num5 = (IsMapEdge(position) ? (-2f) : 0f); float num6 = (IsPocketTrapped(position) ? (-1.5f) : 0f); float num7 = ((num3 < MinEdgeClearance * 2f) ? (-1f) : 0f); float num8 = (IsWaterAt(position) ? (-2f) : 0f); return alignmentWithAway + num4 * 0.55f + num5 + num6 + num7 + num8; } private static float MeasureDirectionDropClearance(float3 from, float3 flatDir) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) for (float num = 0.5f; num <= 3f; num += 0.5f) { if (IsHazardAt(from, flatDir, num)) { return Mathf.Max(0f, num - 0.5f); } } return 3f; } private static bool IsHazardAt(float3 from, float3 flatDir, float horizontalDistance) { //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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!IsDropEdgeAt(from, flatDir, horizontalDistance)) { return IsWaterEdgeAt(from, flatDir, horizontalDistance); } return true; } private static bool IsWaterEdgeAt(float3 from, float3 flatDir, float horizontalDistance) { //IL_0010: 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_0021: 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_002e: 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_0034: 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_0046: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0075: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return false; } float3 val = math.normalizesafe(new float3(flatDir.x, 0f, flatDir.z), default(float3)); if (math.lengthsq(val) < 0.0001f) { return false; } Vector3 probePosition = default(Vector3); ((Vector3)(ref probePosition))..ctor(from.x + val.x * horizontalDistance, from.y, from.z + val.z * horizontalDistance); return IsWaterAtProbe(from.y, probePosition); } private static bool IsWaterAt(float3 position) { //IL_0015: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return false; } BeginCacheFrame(); long key = QuantizeKey(position); if (WaterPointCache.TryGetValue(key, out var value)) { return value; } EnsureWaterMask(); if (_waterLayerMask == 0) { WaterPointCache[key] = false; return false; } bool flag = Physics.CheckSphere(new Vector3(position.x, position.y + 0.3f, position.z), 0.4f, _waterLayerMask, (QueryTriggerInteraction)2); WaterPointCache[key] = flag; return flag; } private static bool IsWaterAtProbe(float referenceGroundY, Vector3 probePosition) { //IL_001e: 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_0031: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !FleePathClearanceContext.IsActive) { return false; } EnsureWaterMask(); if (_waterLayerMask == 0) { return false; } return Physics.CheckSphere(new Vector3(probePosition.x, referenceGroundY + 0.3f, probePosition.z), 0.4f, _waterLayerMask, (QueryTriggerInteraction)2); } private static bool IsDropAtProbe(float referenceGroundY, Vector3 probePosition) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_001d: 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_003f: Unknown result type (might be due to invalid IL or missing references) EnsureMapMask(); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(new Vector3(probePosition.x, probePosition.y + 1f, probePosition.z), Vector3.down, ref val, 4f, _mapLayerMask)) { return true; } return Mathf.Abs(referenceGroundY - ((RaycastHit)(ref val)).point.y) > MaxStepHeight; } private static void BeginCacheFrame() { int frameCount = Time.frameCount; if (frameCount != _cacheFrame) { ClearanceCache.Clear(); WaterPointCache.Clear(); PocketCache.Clear(); _cacheFrame = frameCount; } } private static int GetSampleIndex(int count, int sample, int sampleCount) { if (count <= 1 || sampleCount <= 1) { return 0; } if (sample <= 0) { return 0; } if (sample >= sampleCount - 1) { return count - 1; } return Mathf.RoundToInt((float)(count - 1) * ((float)sample / (float)(sampleCount - 1))); } private static long QuantizeKey(float3 position) { //IL_0000: 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) int num = Mathf.RoundToInt(position.x / 0.5f); int num2 = Mathf.RoundToInt(position.z / 0.5f); return ((long)num << 32) | (uint)num2; } private static void EnsureMapMask() { if (_mapLayerMask == -1) { _mapLayerMask = LayerMask.GetMask(new string[1] { "Map" }); if (_mapLayerMask == 0) { _mapLayerMask = -5; } } } private static void EnsureWaterMask() { if (_waterLayerMask == -1) { _waterLayerMask = LayerMask.GetMask(new string[1] { "Water" }); } } private static Vector3 ToRayOrigin(float3 position) { //IL_0000: 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_0012: 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) return new Vector3(position.x, position.y + 1f, position.z); } } internal static class FleePathClearanceContext { internal static bool IsActive { get; set; } } internal static class FleePathSearchBudget { private static int _frame = -1; private static int _used; private static int _newSessions; internal static bool TryConsume() { BeginFrameIfNeeded(); int num = 4; if (num <= 0) { return true; } if (_used >= num) { return false; } _used++; return true; } internal static bool TryBeginNewSession() { BeginFrameIfNeeded(); int num = 2; if (num <= 0) { return true; } if (_newSessions >= num) { return false; } _newSessions++; return true; } private static void BeginFrameIfNeeded() { int frameCount = Time.frameCount; if (_frame != frameCount) { _frame = frameCount; _used = 0; _newSessions = 0; } } } internal static class FleePathSimplify { internal const float MinTurnAngleDegrees = 12f; internal const int DensePathThreshold = 6; internal static List PrepareForStorage(List vectorPath, bool seekerAppliedModifiers, int graphMask) { if (vectorPath == null || vectorPath.Count < 2) { return vectorPath; } if (seekerAppliedModifiers && vectorPath.Count <= 6) { return vectorPath; } List list = new List(vectorPath); if (!seekerAppliedModifiers || list.Count > 6) { list = FilterCollinearCorners(list); if (!seekerAppliedModifiers || list.Count > 6) { list = GreedyNavmeshShortcut(list, graphMask); } } if (list.Count < 2) { return vectorPath; } return list; } private static List FilterCollinearCorners(List points) { //IL_001e: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0062: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (points.Count <= 2) { return points; } float num = Mathf.Cos((float)Math.PI / 15f); List list = new List { points[0] }; for (int i = 1; i < points.Count - 1; i++) { Vector3 val = Flat(points[i] - points[i - 1]); Vector3 val2 = Flat(points[i + 1] - points[i]); if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f) && !(((Vector3)(ref val2)).sqrMagnitude < 0.0001f)) { ((Vector3)(ref val)).Normalize(); ((Vector3)(ref val2)).Normalize(); if (Vector3.Dot(val, val2) < num) { list.Add(points[i]); } } } list.Add(points[points.Count - 1]); if (list.Count < 2) { return points; } return list; } private static List GreedyNavmeshShortcut(List points, int graphMask) { //IL_0013: 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_0058: Unknown result type (might be due to invalid IL or missing references) if (points.Count <= 2) { return points; } List list = new List { points[0] }; int num = 0; while (num < points.Count - 1) { int num2 = num + 1; for (int num3 = points.Count - 1; num3 > num + 1; num3--) { if (IsNavmeshSegmentClear(points[num], points[num3], graphMask)) { num2 = num3; break; } } list.Add(points[num2]); num = num2; } if (list.Count < 2) { return points; } return list; } private static bool IsNavmeshSegmentClear(Vector3 from, Vector3 to, int graphMask) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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_0033: 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_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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_007e: 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_0080: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)AstarPath.active == (Object)null) { return false; } NNConstraint none = NNConstraint.None; none.graphMask = GraphMask.op_Implicit(graphMask); NNInfo nearest = AstarPath.active.GetNearest(from, none); NNInfo nearest2 = AstarPath.active.GetNearest(to, none); if (nearest.node == null || nearest2.node == null) { return false; } if (nearest.node.Graph != nearest2.node.Graph) { return false; } NavGraph graph = nearest.node.Graph; IRaycastableGraph val = (IRaycastableGraph)(object)((graph is IRaycastableGraph) ? graph : null); if (val == null) { return false; } GraphHitInfo val2 = default(GraphHitInfo); return !val.Linecast(from, to, nearest.node, ref val2); } private static Vector3 Flat(Vector3 vector) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) vector.y = 0f; return vector; } } internal static class FleePostFleeAttackCooldown { private static readonly Dictionary ResumeAttackTime = new Dictionary(); private static readonly List PruneScratch = new List(); internal static void RecordExit(Entity entity) { //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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!(entity == Entity.Null)) { float num = 1f; if (num <= 0f) { ResumeAttackTime.Remove(entity); } else { ResumeAttackTime[entity] = Time.time + num; } } } internal static bool IsAttackBlocked(Entity entity) { //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_0012: 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) if (entity == Entity.Null || !ResumeAttackTime.TryGetValue(entity, out var value)) { return false; } if (Time.time >= value) { ResumeAttackTime.Remove(entity); return false; } return true; } internal static bool ShouldBlockAttacks(EntityManager entityManager, Entity entity) { //IL_0000: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (IsAttackBlocked(entity)) { return true; } if (!entityManager.IsCreated || !entityManager.Exists(entity)) { return false; } if (!entityManager.HasComponent(entity)) { return false; } return FleeShouldFleeCache.ShouldFlee(entityManager, entity); } internal static void Prune(EntityManager entityManager) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated) { return; } float time = Time.time; PruneScratch.Clear(); foreach (KeyValuePair item in ResumeAttackTime) { if (!entityManager.Exists(item.Key) || time >= item.Value) { PruneScratch.Add(item.Key); } } for (int i = 0; i < PruneScratch.Count; i++) { ResumeAttackTime.Remove(PruneScratch[i]); } } } internal static class FleeShouldFleeCache { private static int _frame = -1; private static readonly Dictionary FrameCache = new Dictionary(); private static readonly Dictionary StickyResult = new Dictionary(); private static readonly List PruneScratch = new List(); internal static void BeginFrame() { if (_frame != Time.frameCount) { _frame = Time.frameCount; FrameCache.Clear(); } } internal static bool ShouldFlee(EntityManager entityManager, Entity entity) { //IL_000a: 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_0023: 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) BeginFrame(); if (FrameCache.TryGetValue(entity, out var value)) { return value; } bool flag = Evaluate(entityManager, entity); FrameCache[entity] = flag; StickyResult[entity] = flag; return flag; } internal static void RefreshStickyFromSnapshot(EntityManager entityManager, IReadOnlyList fleeEntries) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_002f: 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_0045: 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_0048: 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_0075: 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) if (!entityManager.IsCreated || fleeEntries == null) { return; } for (int i = 0; i < fleeEntries.Count; i++) { Entity entity = fleeEntries[i].Entity; if (!FleeDistanceAiState.IsFleeManaged(entity) && !HasLiveTarget(entityManager, entity) && FleeThreatResolver.TryGetGroundPosition(entityManager, entity, out var ground)) { Team team = fleeEntries[i].Team; float value = entityManager.GetComponentData(entity).Value; if (!FleeTeamSnapshot.TryGetClosestEnemy(entityManager, team, ground, out var distance, out var _)) { StickyResult[entity] = false; } else { StickyResult[entity] = distance <= value; } } } } internal static void Prune(EntityManager entityManager) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated) { return; } PruneScratch.Clear(); foreach (KeyValuePair item in StickyResult) { if (!entityManager.Exists(item.Key)) { PruneScratch.Add(item.Key); } } for (int i = 0; i < PruneScratch.Count; i++) { StickyResult.Remove(PruneScratch[i]); } } private static bool Evaluate(EntityManager entityManager, Entity entity) { //IL_0009: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) if (!entityManager.IsCreated || !entityManager.Exists(entity) || !entityManager.HasComponent(entity)) { return false; } float num = entityManager.GetComponentData(entity).Value; bool flag = FleeDistanceAiState.IsFleeManaged(entity); if (flag) { num += 0.5f; } if (HasLiveTarget(entityManager, entity, out var distanceToTarget)) { return distanceToTarget <= num; } if (flag || ShouldRefreshIdle(entity)) { return EvaluateThreatDistance(entityManager, entity, num); } if (StickyResult.TryGetValue(entity, out var value)) { return value; } return EvaluateThreatDistance(entityManager, entity, num); } private static bool HasLiveTarget(EntityManager entityManager, Entity entity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) float distanceToTarget; return HasLiveTarget(entityManager, entity, out distanceToTarget); } private static bool HasLiveTarget(EntityManager entityManager, Entity entity, out float distanceToTarget) { //IL_0008: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0047: 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) distanceToTarget = float.MaxValue; if (!entityManager.HasComponent(entity) || !entityManager.HasComponent(entity)) { return false; } HasTargetTag componentData = entityManager.GetComponentData(entity); if (componentData.Target == Entity.Null || !entityManager.Exists(componentData.Target)) { return false; } distanceToTarget = entityManager.GetComponentData(entity).DistanceToTarget; return true; } private static bool ShouldRefreshIdle(Entity entity) { //IL_0008: 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) int num = 6; if (num <= 1) { return true; } int num2 = entity.Index ^ (entity.Version << 16); return (Time.frameCount + num2) % num == 0; } private static bool EvaluateThreatDistance(EntityManager entityManager, Entity entity, float threshold) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (!FleeThreatResolver.TryGetClosestLivingEnemyDistance(entityManager, entity, out var distance, out var _)) { return false; } return distance <= threshold; } } internal struct FleeEnemySnapshot { internal Entity Entity; internal float3 Position; } internal static class FleeTeamSnapshot { private static readonly List[] TeamEnemies = new List[2] { new List(128), new List(128) }; private static float _lastRefreshTime = float.MinValue; private static int _lastRefreshFrame = -1; internal static bool RefreshIfNeeded(EntityManager entityManager, TeamSystem teamSystem) { if (!entityManager.IsCreated || teamSystem == null) { return false; } int frameCount = Time.frameCount; if (_lastRefreshFrame == frameCount) { return false; } _lastRefreshFrame = frameCount; float time = Time.time; if (time - _lastRefreshTime < 0.25f) { return false; } _lastRefreshTime = time; Rebuild(entityManager, teamSystem); return true; } internal static bool TryGetClosestEnemy(EntityManager entityManager, Team selfTeam, float3 selfGround, out float distance, out Entity enemyEntity) { //IL_0009: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected I4, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) distance = float.MaxValue; enemyEntity = Entity.Null; int num = (int)TeamUtlity.GetOtherTeam(selfTeam); if (num < 0 || num >= TeamEnemies.Length) { return false; } List list = TeamEnemies[num]; bool result = false; for (int i = 0; i < list.Count; i++) { FleeEnemySnapshot fleeEnemySnapshot = list[i]; if (entityManager.Exists(fleeEnemySnapshot.Entity)) { float3 val = fleeEnemySnapshot.Position - selfGround; val.y = 0f; float num2 = math.length(val); if (!(num2 >= distance)) { distance = num2; enemyEntity = fleeEnemySnapshot.Entity; result = true; } } } return result; } internal static int TryCollectNearbyEnemies(EntityManager entityManager, Team selfTeam, float3 selfGround, float maxDistance, List results) { //IL_0015: 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_001c: Expected I4, but got Unknown //IL_004c: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) results?.Clear(); if (maxDistance <= 0f) { return 0; } int num = (int)TeamUtlity.GetOtherTeam(selfTeam); if (num < 0 || num >= TeamEnemies.Length) { return 0; } float num2 = maxDistance * maxDistance; List list = TeamEnemies[num]; int num3 = 0; for (int i = 0; i < list.Count; i++) { FleeEnemySnapshot fleeEnemySnapshot = list[i]; if (entityManager.Exists(fleeEnemySnapshot.Entity)) { float3 val = fleeEnemySnapshot.Position - selfGround; val.y = 0f; float num4 = math.lengthsq(val); if (!(num4 > num2)) { num3++; results?.Add(new FleeNearbyThreat { Position = fleeEnemySnapshot.Position, Distance = math.sqrt(num4) }); } } } return num3; } private static void Rebuild(EntityManager entityManager, TeamSystem teamSystem) { TeamEnemies[0].Clear(); TeamEnemies[1].Clear(); BuildTeamSnapshot(entityManager, teamSystem, (Team)0, TeamEnemies[0]); BuildTeamSnapshot(entityManager, teamSystem, (Team)1, TeamEnemies[1]); } private static void BuildTeamSnapshot(EntityManager entityManager, TeamSystem teamSystem, Team team, List results) { //IL_0001: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_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_005b: 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_0069: Unknown result type (might be due to invalid IL or missing references) List teamUnits = teamSystem.GetTeamUnits(team); if (teamUnits == null) { return; } for (int i = 0; i < teamUnits.Count; i++) { Unit val = teamUnits[i]; if (!((Object)(object)val == (Object)null) && !val.dead && EcsComponentHelper.TryGetEntityManager((Component)(object)val, out var entity, out var _) && entityManager.Exists(entity)) { if (!FleeThreatResolver.TryGetGroundPosition(entityManager, entity, out var ground)) { Vector3 position = ((Component)val).transform.position; ((float3)(ref ground))..ctor(position.x, position.y, position.z); } results.Add(new FleeEnemySnapshot { Entity = entity, Position = ground }); } } } } internal struct FleeNearbyThreat { internal float3 Position; internal float Distance; } internal static class FleeThreatResolver { private struct ClosestThreatCacheEntry { internal bool Found; internal float3 ThreatGround; internal float3 AwayDirection; } private struct PrimaryThreatCacheEntry { internal bool Found; internal FleeNearbyThreat Threat; } private static int _threatCacheFrame = -1; private static readonly Dictionary ClosestThreatCache = new Dictionary(); private static readonly Dictionary PrimaryThreatCache = new Dictionary(); private static void BeginThreatCacheFrame() { int frameCount = Time.frameCount; if (_threatCacheFrame != frameCount) { _threatCacheFrame = frameCount; ClosestThreatCache.Clear(); PrimaryThreatCache.Clear(); } } internal static bool TryGetClosestLivingEnemyDistance(EntityManager entityManager, Entity self, out float distance, out Entity enemyEntity) { //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_001b: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00fd: 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_0103: 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_00ca: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) distance = float.MaxValue; enemyEntity = Entity.Null; if (!entityManager.IsCreated || !entityManager.Exists(self) || !EcsComponentHelper.IsAvailable || !TryGetGroundPosition(entityManager, self, out var ground) || !TryGetSelfTeam(entityManager, self, out var team)) { return false; } if (FleeTeamSnapshot.TryGetClosestEnemy(entityManager, team, ground, out distance, out enemyEntity)) { return true; } TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return false; } List teamUnits = existingManager.GetTeamUnits(TeamUtlity.GetOtherTeam(team)); if (teamUnits == null) { return false; } bool result = false; for (int i = 0; i < teamUnits.Count; i++) { Unit val = teamUnits[i]; if (!((Object)(object)val == (Object)null) && !val.dead && EcsComponentHelper.TryGetEntityManager((Component)(object)val, out var entity, out var _) && entityManager.Exists(entity)) { if (!TryGetGroundPosition(entityManager, entity, out var ground2)) { ((float3)(ref ground2))..ctor(((Component)val).transform.position.x, ((Component)val).transform.position.y, ((Component)val).transform.position.z); } float3 val2 = ground2 - ground; val2.y = 0f; float num = math.length(val2); if (!(num >= distance)) { distance = num; enemyEntity = entity; result = true; } } } return result; } internal static bool TryGetClosestEnemyThreat(EntityManager entityManager, Entity self, out float3 threatGround, out float3 awayDirection) { //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_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_002e: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //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_00a2: 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_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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) threatGround = float3.zero; awayDirection = new float3(0f, 0f, 1f); if (!entityManager.IsCreated || !entityManager.Exists(self) || !EcsComponentHelper.IsAvailable) { return false; } BeginThreatCacheFrame(); if (ClosestThreatCache.TryGetValue(self, out var value)) { threatGround = value.ThreatGround; awayDirection = value.AwayDirection; return value.Found; } bool flag = TryResolveClosestEnemyThreat(entityManager, self, out threatGround, out awayDirection); ClosestThreatCache[self] = new ClosestThreatCacheEntry { Found = flag, ThreatGround = threatGround, AwayDirection = awayDirection }; return flag; } private static bool TryResolveClosestEnemyThreat(EntityManager entityManager, Entity self, out float3 threatGround, out float3 awayDirection) { //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_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_0026: 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_0066: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0073: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) threatGround = float3.zero; awayDirection = new float3(0f, 0f, 1f); if (!TryGetGroundPosition(entityManager, self, out var ground)) { return false; } if (TryGetLivingTargetThreat(entityManager, self, out var _, out threatGround, out var distance)) { awayDirection = GetAwayDirection(ground, threatGround); return math.lengthsq(awayDirection) > 0.0001f; } if (!TryGetClosestLivingEnemyDistance(entityManager, self, out distance, out var enemyEntity) || !TryGetGroundPosition(entityManager, enemyEntity, out threatGround)) { return false; } awayDirection = GetAwayDirection(ground, threatGround); return math.lengthsq(awayDirection) > 0.0001f; } internal static bool HasThreatWithinDistance(EntityManager entityManager, Entity self, float maxDistance) { //IL_000b: 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 (maxDistance <= 0f) { return false; } if (TryGetLivingTargetThreat(entityManager, self, out var _, out var _, out var distance)) { return distance <= maxDistance; } return TryCollectNearbyThreats(entityManager, self, maxDistance, null) > 0; } internal static int TryCollectNearbyThreats(EntityManager entityManager, Entity self, float maxDistance, List results) { //IL_0012: 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_0037: 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_0070: 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) results?.Clear(); if (!entityManager.IsCreated || !entityManager.Exists(self) || maxDistance <= 0f || !EcsComponentHelper.IsAvailable || !TryGetGroundPosition(entityManager, self, out var ground)) { return 0; } if (TryGetLivingTargetThreat(entityManager, self, out var _, out var targetGround, out var distance) && distance <= maxDistance) { results?.Add(new FleeNearbyThreat { Position = targetGround, Distance = distance }); return 1; } return TryCollectNearbyEnemyThreats(entityManager, self, ground, maxDistance, results); } private static int TryCollectNearbyEnemyThreats(EntityManager entityManager, Entity self, float3 selfGround, float maxDistance, List results) { //IL_0001: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_003a: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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_00be: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) if (!TryGetSelfTeam(entityManager, self, out var team)) { return 0; } if (FleeTeamSnapshot.TryCollectNearbyEnemies(entityManager, team, selfGround, maxDistance, results) > 0) { return results?.Count ?? 0; } TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return 0; } Team otherTeam = TeamUtlity.GetOtherTeam(team); List teamUnits = existingManager.GetTeamUnits(otherTeam); if (teamUnits == null) { return 0; } float num = maxDistance * maxDistance; int num2 = 0; for (int i = 0; i < teamUnits.Count; i++) { Unit val = teamUnits[i]; if (!((Object)(object)val == (Object)null) && !val.dead && EcsComponentHelper.TryGetEntityManager((Component)(object)val, out var entity, out var _) && entityManager.Exists(entity)) { if (!TryGetGroundPosition(entityManager, entity, out var ground)) { ((float3)(ref ground))..ctor(((Component)val).transform.position.x, ((Component)val).transform.position.y, ((Component)val).transform.position.z); } float3 val2 = ground - selfGround; val2.y = 0f; float num3 = math.lengthsq(val2); if (!(num3 > num)) { num2++; results?.Add(new FleeNearbyThreat { Position = ground, Distance = math.sqrt(num3) }); } } } return num2; } internal static bool TryGetCompositeAwayDirection(EntityManager entityManager, Entity self, float maxThreatDistance, List scratch, out float3 awayDirection) { //IL_0011: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0034: 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) awayDirection = new float3(0f, 0f, 1f); if (!TryGetGroundPosition(entityManager, self, out var ground)) { return false; } float3 threatGround; if (TryCollectNearbyThreats(entityManager, self, maxThreatDistance, scratch) == 0) { return TryGetClosestEnemyThreat(entityManager, self, out threatGround, out awayDirection); } if (!TryGetCompositeAwayDirection(ground, scratch, out awayDirection)) { return TryGetClosestEnemyThreat(entityManager, self, out threatGround, out awayDirection); } return true; } internal static bool TryGetCompositeAwayDirection(float3 selfGround, IReadOnlyList threats, out float3 awayDirection) { //IL_0010: 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_0027: 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_0039: 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_0045: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_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) awayDirection = new float3(0f, 0f, 1f); if (threats == null || threats.Count == 0) { return false; } float3 val = float3.zero; for (int i = 0; i < threats.Count; i++) { FleeNearbyThreat fleeNearbyThreat = threats[i]; float3 val2 = selfGround - fleeNearbyThreat.Position; val2.y = 0f; if (!(math.length(val2) < 0.0001f)) { float num = 1f / math.max(fleeNearbyThreat.Distance, 0.5f); val += math.normalize(val2) * num; } } if (math.lengthsq(val) < 0.0001f) { return false; } awayDirection = math.normalize(val); return true; } internal static bool DestinationMovesCloserToThreat(float3 selfGround, float3 destination, in FleeNearbyThreat threat) { //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_000c: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) float3 val = threat.Position - selfGround; float3 val2 = threat.Position - destination; val.y = 0f; val2.y = 0f; return math.lengthsq(val2) < math.lengthsq(val) - 0.01f; } internal static bool DestinationMovesCloserToAnyThreat(float3 selfGround, float3 destination, IReadOnlyList threats) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_004f: Unknown result type (might be due to invalid IL or missing references) if (threats == null || threats.Count == 0) { return false; } for (int i = 0; i < threats.Count; i++) { FleeNearbyThreat fleeNearbyThreat = threats[i]; float3 val = fleeNearbyThreat.Position - selfGround; float3 val2 = fleeNearbyThreat.Position - destination; val.y = 0f; val2.y = 0f; if (math.lengthsq(val2) < math.lengthsq(val) - 0.01f) { return true; } } return false; } internal static float ScoreDestinationAgainstThreats(float3 selfGround, float3 destination, IReadOnlyList threats) { //IL_0023: 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_0029: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_003a: 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_005b: Unknown result type (might be due to invalid IL or missing references) if (threats == null || threats.Count == 0) { return 0f; } float num = 0f; for (int i = 0; i < threats.Count; i++) { FleeNearbyThreat fleeNearbyThreat = threats[i]; float3 val = fleeNearbyThreat.Position - selfGround; float3 val2 = fleeNearbyThreat.Position - destination; val.y = 0f; val2.y = 0f; float num2 = math.length(val); float num3 = math.length(val2); float num4 = num3 - num2; num += num4 * 0.35f; if (num3 < num2 - 0.05f) { num -= 3f; } } return num; } internal static float3 GetAwayDirection(float3 selfGround, float3 threatGround) { //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_0014: 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_003a: 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) float3 val = selfGround - threatGround; val.y = 0f; float num = math.length(val); if (!(num > 0.0001f)) { return new float3(0f, 0f, 1f); } return val / num; } internal static bool TryIsLivingTarget(EntityManager entityManager, Entity candidate) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated || !entityManager.Exists(candidate) || !EcsComponentHelper.IsAvailable) { return false; } TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return false; } List allUnits = existingManager.GetAllUnits(); if (allUnits == null) { return false; } for (int i = 0; i < allUnits.Count; i++) { Unit val = allUnits[i]; if (!((Object)(object)val == (Object)null) && !val.dead && EcsComponentHelper.TryGetEntityManager((Component)(object)val, out var entity, out var _) && entity == candidate) { return true; } } return false; } internal static bool TryGetLivingTargetThreat(EntityManager entityManager, Entity self, out Entity targetEntity, out float3 targetGround, out float distance) { //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_000c: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0070: 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_0076: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a7: Unknown result type (might be due to invalid IL or missing references) targetEntity = Entity.Null; targetGround = float3.zero; distance = float.MaxValue; if (!entityManager.IsCreated || !entityManager.Exists(self) || !entityManager.HasComponent(self) || !TryGetGroundPosition(entityManager, self, out var ground)) { return false; } HasTargetTag componentData = entityManager.GetComponentData(self); if (componentData.Target == Entity.Null || !TryIsLivingTarget(entityManager, componentData.Target)) { return false; } targetEntity = componentData.Target; if (!TryGetGroundPosition(entityManager, targetEntity, out targetGround)) { return false; } float3 val = targetGround - ground; val.y = 0f; distance = math.length(val); return true; } internal static bool TryGetPrimaryFleeThreat(EntityManager entityManager, Entity self, out FleeNearbyThreat threat) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) threat = default(FleeNearbyThreat); if (!entityManager.IsCreated || !entityManager.Exists(self)) { return false; } BeginThreatCacheFrame(); if (PrimaryThreatCache.TryGetValue(self, out var value)) { threat = value.Threat; return value.Found; } bool flag = TryResolvePrimaryFleeThreat(entityManager, self, out threat); PrimaryThreatCache[self] = new PrimaryThreatCacheEntry { Found = flag, Threat = threat }; return flag; } private static bool TryResolvePrimaryFleeThreat(EntityManager entityManager, Entity self, out FleeNearbyThreat threat) { //IL_0008: 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_0046: 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_002f: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) threat = default(FleeNearbyThreat); if (!TryGetGroundPosition(entityManager, self, out var _)) { return false; } if (TryGetLivingTargetThreat(entityManager, self, out var _, out var targetGround, out var distance)) { threat = new FleeNearbyThreat { Position = targetGround, Distance = distance }; return true; } if (!TryGetClosestLivingEnemyDistance(entityManager, self, out var distance2, out var enemyEntity) || !TryGetGroundPosition(entityManager, enemyEntity, out var ground2)) { return false; } threat = new FleeNearbyThreat { Position = ground2, Distance = distance2 }; return true; } private static bool TryGetSelfTeam(EntityManager entityManager, Entity self, out Team team) { //IL_0003: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected I4, but got Unknown team = (Team)0; if (FleeUnitRegistry.TryGetTeam(self, out team)) { return true; } TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return false; } List allUnits = existingManager.GetAllUnits(); if (allUnits == null) { return false; } for (int i = 0; i < allUnits.Count; i++) { Unit val = allUnits[i]; if (!((Object)(object)val == (Object)null) && EcsComponentHelper.TryGetEntityManager((Component)(object)val, out var entity, out var _) && !(entity != self)) { team = (Team)(int)val.Team; return true; } } return false; } internal static bool TryGetGroundPosition(EntityManager entityManager, Entity entity, out float3 ground) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_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_003e: Unknown result type (might be due to invalid IL or missing references) ground = float3.zero; if (entityManager.HasComponent(entity)) { ground = entityManager.GetComponentData(entity).Value; return true; } if (entityManager.HasComponent(entity)) { ground = entityManager.GetComponentData(entity).Value; return true; } return false; } } internal struct FleeUnitEntry { internal Unit Unit; internal Entity Entity; internal Team Team; } internal static class FleeUnitRegistry { private static readonly List Entries = new List(); private static readonly Dictionary TeamByEntity = new Dictionary(); private static int _cachedUnitCount = -1; private static int _lastRebuildFrame = -1; private const int RebuildIntervalFrames = 30; internal static void Invalidate() { _cachedUnitCount = -1; Entries.Clear(); TeamByEntity.Clear(); } internal static bool TryGetTeam(Entity entity, out Team team) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return TeamByEntity.TryGetValue(entity, out team); } internal static IReadOnlyList GetEntries(EntityManager entityManager, List allUnits) { int frameCount = Time.frameCount; int num = allUnits?.Count ?? 0; if (_cachedUnitCount == num && Entries.Count > 0 && frameCount - _lastRebuildFrame < 30) { return Entries; } Rebuild(entityManager, allUnits); _cachedUnitCount = num; _lastRebuildFrame = frameCount; return Entries; } private static void Rebuild(EntityManager entityManager, List allUnits) { //IL_0042: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) Entries.Clear(); TeamByEntity.Clear(); if (allUnits == null || !entityManager.IsCreated) { return; } for (int i = 0; i < allUnits.Count; i++) { Unit val = allUnits[i]; if (!((Object)(object)val == (Object)null) && EcsComponentHelper.TryGetEntityManager((Component)(object)val, out var entity, out var _) && entityManager.HasComponent(entity)) { TeamByEntity[entity] = val.Team; Entries.Add(new FleeUnitEntry { Unit = val, Entity = entity, Team = val.Team }); } } } } internal static class GameStatePatches { public static void EnterBattleState_Postfix() { StayFixLogic.InvalidateStayCombatCache(); BarrelRollerDeathLogic.ResetBattleCaches(); WaterPatches.ResetRiverFlowDirections(); BattleStateHelper.InvalidateCache(); FleeUnitRegistry.Invalidate(); } public static void EnterPlacementState_Postfix() { StayFixLogic.InvalidateStayCombatCache(); StayFixLogic.ClearAllTrackedUnits(); BattleStateHelper.InvalidateCache(); FleeUnitRegistry.Invalidate(); } public static void EnterNoneState_Postfix() { BattleStateHelper.InvalidateCache(); FleeUnitRegistry.Invalidate(); } } internal static class GasGrenadePatches { private const float FloorNormalMin = 0.45f; private const float DownwardProbeDistance = 0.75f; private static readonly int MapLayer = LayerMask.NameToLayer("Map"); [ThreadStatic] private static int _floorCatchFrame = -1; [ThreadStatic] private static int _floorCatchProjectileId; public static void ProjectileHit_DisableProjectile_Postfix(ProjectileHit __instance) { //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) if (IsGasGrenade((Component)(object)__instance)) { MoveTransform component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { ((Behaviour)component).enabled = false; component.velocity = Vector3.zero; } } } public static void RaycastTrail_Check_Postfix(RaycastTrail __instance) { //IL_0041: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (!IsGasGrenade((Component)(object)__instance)) { return; } ProjectileHit component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || component.done) { return; } MoveTransform component2 = ((Component)__instance).GetComponent(); if (!((Object)(object)component2 == (Object)null) && ((Behaviour)component2).enabled && TryFindFloorImpact(((Component)__instance).transform.position, component2.velocity, __instance.mask, out var hitInfo)) { int instanceID = ((Object)component).GetInstanceID(); if (_floorCatchFrame != Time.frameCount || _floorCatchProjectileId != instanceID) { _floorCatchFrame = Time.frameCount; _floorCatchProjectileId = instanceID; ((Component)__instance).transform.position = ((RaycastHit)(ref hitInfo)).point; component.Hit(hitInfo, 1f); } } } private static bool IsGasGrenade(Component component) { if ((Object)(object)component != (Object)null) { return ((Object)component.gameObject).name.IndexOf("Grenade_Gas", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static bool TryFindFloorImpact(Vector3 position, Vector3 velocity, LayerMask mask, out RaycastHit hitInfo) { //IL_0001: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_006f: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) hitInfo = default(RaycastHit); if (velocity.y <= 0.25f && TryMapFloorHit(position, Vector3.down, 0.75f, mask, out hitInfo)) { return true; } if (velocity.y > -0.5f || Mathf.Abs(velocity.y) < ((Vector3)(ref velocity)).magnitude * 0.35f) { return false; } Vector3 val = velocity * Time.deltaTime; if (((Vector3)(ref val)).sqrMagnitude <= 1E-06f) { return false; } return TryMapFloorHit(position - val, ((Vector3)(ref val)).normalized, ((Vector3)(ref val)).magnitude + 0.2f, mask, out hitInfo); } private static bool TryMapFloorHit(Vector3 origin, Vector3 direction, float distance, LayerMask mask, out RaycastHit hitInfo) { //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_0005: 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) if (!Physics.Raycast(origin, direction, ref hitInfo, distance, LayerMask.op_Implicit(mask), (QueryTriggerInteraction)1)) { return false; } Collider collider = ((RaycastHit)(ref hitInfo)).collider; if ((Object)(object)collider != (Object)null && ((Component)collider).gameObject.layer == MapLayer) { return ((RaycastHit)(ref hitInfo)).normal.y >= 0.45f; } return false; } } internal static class LayDownAbilityLogic { public const float LookAtEnemyMaxAngleDegrees = 10f; public static bool IsLookingAtEnemy(DataHandler data) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0083: 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_0064: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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) if ((Object)(object)data?.targetMainRig == (Object)null) { return false; } DataHandler componentInParent = ((Component)data.targetMainRig).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && componentInParent.Dead) { return false; } Vector3 val = (((Object)(object)data.torso != (Object)null) ? data.torso.position : (((Object)(object)data.mainRig != (Object)null) ? data.mainRig.position : ((Component)data).transform.position)); Vector3 val2 = data.targetMainRig.position - val; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { return true; } Vector3 lookForward = GetLookForward(data); lookForward.y = 0f; if (((Vector3)(ref lookForward)).sqrMagnitude < 0.0001f) { return false; } return Vector3.Angle(lookForward, val2) <= 10f; } private static Vector3 GetLookForward(DataHandler data) { //IL_006f: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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) if ((Object)(object)data.input != (Object)null && data.input.hasControl) { if ((Object)(object)MainCam.instance != (Object)null) { return ((Component)MainCam.instance).transform.forward; } if ((Object)(object)data.input.Direction != (Object)null) { return data.input.Direction.forward; } } if (((Vector3)(ref data.lookDirectionIntent)).sqrMagnitude > 0.01f) { return data.lookDirectionIntent; } if ((Object)(object)data.characterForwardObject != (Object)null) { return data.characterForwardObject.forward; } if ((Object)(object)data.mainRig != (Object)null) { return ((Component)data.mainRig).transform.forward; } return ((Component)data).transform.forward; } public static bool ShouldAutoTriggerLayDown(DataHandler data) { if ((Object)(object)data == (Object)null || data.Dead || (Object)(object)data.targetMainRig == (Object)null) { return false; } if (!IsLookingAtEnemy(data)) { return false; } return StayFixLogic.IsTargetWithinWeaponFireRange(data); } public static void ConfigureLayDownConditionalEvent(ConditionalEvent conditionalEvent) { if (!LayDownRangeLogic.IsLayDownConditionalEvent(conditionalEvent)) { return; } ConditionalEventInstance[] events = conditionalEvent.events; if (events == null) { return; } for (int i = 0; i < events.Length; i++) { if (events[i] != null) { events[i].checkAutomatically = true; } } } public static void TickLayDownWhilePossessed(ConditionalEvent conditionalEvent) { if (!LayDownRangeLogic.IsLayDownConditionalEvent(conditionalEvent)) { return; } DataHandler data = conditionalEvent.data; if ((Object)(object)data?.input == (Object)null || !data.input.hasControl || conditionalEvent.ignorePossession || !ShouldAutoTriggerLayDown(data)) { return; } ConditionalEventInstance[] events = conditionalEvent.events; if (events == null) { return; } foreach (ConditionalEventInstance val in events) { if (val != null) { val.checkAutomatically = true; conditionalEvent.CheckConditions(val, (ConditionType)8, false, false); } } } } internal static class LayDownAbilityPatches { public static void ConditionalEvent_Start_Postfix(ConditionalEvent __instance) { if (StayFixLogic.IsStayCombatActive()) { DataHandler val = __instance?.data; if ((Object)(object)val != (Object)null && LayDownWeaponExclusions.HasExcludedWeaponEquipped(val)) { LayDownWeaponExclusions.SuppressBundledLayDownForUnit(val); } LayDownAbilityLogic.ConfigureLayDownConditionalEvent(__instance); } } public static void ConditionalEvent_Update_Postfix(ConditionalEvent __instance) { if (StayFixLogic.IsStayCombatActive()) { LayDownAbilityLogic.TickLayDownWhilePossessed(__instance); } } public static bool CheckConditionsUpdate_Prefix(ConditionalEvent __instance, ref bool forceFail) { if (!StayFixLogic.IsStayCombatActive()) { return true; } if (!LayDownRangeLogic.IsLayDownConditionalEvent(__instance)) { return true; } LayDownAbilityLogic.ConfigureLayDownConditionalEvent(__instance); if ((Object)(object)__instance.data == (Object)null || !LayDownAbilityLogic.ShouldAutoTriggerLayDown(__instance.data)) { return false; } if (forceFail) { forceFail = false; } return true; } public static bool CheckConditions_Prefix(ConditionalEvent __instance, ConditionalEventInstance eventToCheck, ref bool __result) { if (!StayFixLogic.IsStayCombatActive()) { return true; } if (eventToCheck == null || (Object)(object)__instance?.data == (Object)null) { return true; } if (!LayDownWeaponExclusions.ShouldBlockLayDownInstance(__instance, eventToCheck, __instance.data)) { return true; } __result = false; return false; } public static void SetEnterUI_Postfix(object __instance, Unit unit) { if (!((Object)(object)unit == (Object)null) && LayDownRangeLogic.IsLayDownConditionalEvent(((Component)unit).GetComponentInChildren())) { CameraAbilityPossessUI value = Traverse.Create(__instance).Field("possessUI").Value; if ((Object)(object)value?.combatM != (Object)null) { value.combatM.SetActive(false); } } } } internal static class LayDownAttackLogic { public static void AfterSetAttackTarget(Rigidbody targetMainRig, DataHandler unitData, TargetData targetData, bool canSeeTarget, bool startAttack) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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) if ((Object)(object)targetMainRig == (Object)null || (Object)(object)unitData == (Object)null || !startAttack || !StayFixLogic.CanLayDownEngageTarget(unitData) || StayFixLogic.IsLayDownPlayerPossessed(unitData)) { return; } unitData.inRange = true; if (!(targetData.TargetInAttackRange == 1 && canSeeTarget) || !((Object)(object)unitData.unit != (Object)null) || !(unitData.unit.InRangeAttackCooldown <= 0f)) { WeaponHandler component = ((Component)unitData).GetComponent(); if (!((Object)(object)component == (Object)null)) { Vector3 position = (((Object)(object)unitData.torso != (Object)null) ? unitData.torso.position : (((Object)(object)unitData.mainRig != (Object)null) ? unitData.mainRig.position : targetMainRig.position)); LayDownWeaponLogic.TryLayDownAttack(component, position, targetMainRig, Vector3.zero, (ForceWeapon)0); } } } } internal static class LayDownAttackPatches { public static void SetAttackTarget_Prefix(DataHandler unitData, ref TargetData targetData) { if (StayFixLogic.ShouldLayDownAutoFire(unitData)) { unitData.inRange = true; targetData.TargetInAttackRange = 1; } } public static void SetAttackTarget_Postfix(Rigidbody mainRig, DataHandler unitData, TargetData targetData, bool canSeeTarget, bool startAttack) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) LayDownAttackLogic.AfterSetAttackTarget(mainRig, unitData, targetData, canSeeTarget, startAttack); } } internal static class LayDownRangeLogic { private static readonly Dictionary LayDownEventCache = new Dictionary(); private static readonly FieldInfo IsStunnedForField = AccessTools.Field(typeof(ConditionalEvent), "isStunnedFor"); private static readonly FieldInfo GameStateManagerField = AccessTools.Field(typeof(ConditionalEvent), "man"); public static void ClearLayDownEventCache() { LayDownEventCache.Clear(); } public static bool IsLayDownConditionalEvent(ConditionalEvent conditionalEvent) { if ((Object)(object)conditionalEvent == (Object)null) { return false; } int instanceID = ((Object)conditionalEvent).GetInstanceID(); if (LayDownEventCache.TryGetValue(instanceID, out var value)) { return value; } value = LayDownWeaponExclusions.ConditionalEventHasLayDown(conditionalEvent) && !LayDownWeaponExclusions.IsOnExcludedWeaponHierarchy(((Component)conditionalEvent).transform, conditionalEvent.data); LayDownEventCache[instanceID] = value; return value; } public static bool EvaluateLayDownDistanceCondition(ConditionalEvent conditionalEvent, EventCondition condition) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) DataHandler val = conditionalEvent?.data; if ((Object)(object)val == (Object)null) { return false; } if ((int)condition.valueType == 1) { if (StayFixLogic.IsTargetWithinWeaponFireRange(val)) { return LayDownAbilityLogic.IsLookingAtEnemy(val); } return false; } if ((int)condition.valueType == 0) { return val.distanceToTarget >= condition.value; } return true; } public static bool PassesConditionalPreamble(ConditionalEvent conditionalEvent, EventCondition condition, ConditionType conditionCall) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Invalid comparison between Unknown and I4 DataHandler data = conditionalEvent.data; if ((Object)(object)data == (Object)null) { return false; } if (data.Dead && !conditionalEvent.ignoreDead) { return false; } if (IsStunnedForField?.GetValue(conditionalEvent) is float num && num > 0f) { return false; } object? obj = GameStateManagerField?.GetValue(conditionalEvent); GameStateManager val = (GameStateManager)((obj is GameStateManager) ? obj : null); if (val != null && (int)val.GameState != 1) { return false; } if (condition.ignoreInPossession && (Object)(object)data.input != (Object)null) { _ = data.input.hasControl; return true; } return true; } public static bool FailsTargetHpFailChance(ConditionalEvent conditionalEvent) { DataHandler data = conditionalEvent.data; if ((Object)(object)data == (Object)null || (Object)(object)data.targetData == (Object)null) { return false; } return data.targetData.maxHealth * conditionalEvent.failChancePer100Hp * Random.value * 0.01f > 1f; } public static void IncrementLayDownCooldownCounters(ConditionalEvent conditionalEvent) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) DataHandler data = conditionalEvent.data; if ((Object)(object)data == (Object)null) { return; } ConditionalEventInstance[] events = conditionalEvent.events; if (events == null) { return; } for (int i = 0; i < events.Length; i++) { EventCondition[] array = events[i]?.conditions; if (array == null) { continue; } foreach (EventCondition val in array) { if ((int)val.conditionType == 0) { if (!val.onlyCountWhenUnitInRange) { val.counter += Time.deltaTime; } else if (StayFixLogic.IsTargetWithinWeaponFireRange(data)) { val.counter += Time.deltaTime; } } } } } } internal static class LayDownRangePatches { public static bool CheckCondition_Prefix(ConditionalEvent __instance, EventCondition condition, ConditionalEventInstance eventToCheck, ConditionType conditionCall, bool justCheck, ref bool __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!StayFixLogic.IsStayCombatActive()) { return true; } if ((int)condition.conditionType != 1) { return true; } if (!LayDownRangeLogic.IsLayDownConditionalEvent(__instance)) { return true; } if (!LayDownRangeLogic.PassesConditionalPreamble(__instance, condition, conditionCall)) { __result = false; return false; } __result = LayDownRangeLogic.EvaluateLayDownDistanceCondition(__instance, condition); if (__result && LayDownRangeLogic.FailsTargetHpFailChance(__instance)) { __result = false; } return false; } public static bool IncrementCounters_Prefix(ConditionalEvent __instance) { if (!StayFixLogic.IsStayCombatActive()) { return true; } if (!LayDownRangeLogic.IsLayDownConditionalEvent(__instance)) { return true; } LayDownRangeLogic.IncrementLayDownCooldownCounters(__instance); return false; } } internal static class LayDownWeaponExclusions { internal const int Mg42EntityId = 1369807881; internal const int M2BrowningEntityId = 1606594406; private static readonly FieldInfo RightObjectField = AccessTools.Field(typeof(HoldingHandler), "rightObject"); private static readonly FieldInfo LeftObjectField = AccessTools.Field(typeof(HoldingHandler), "leftObject"); internal static bool HasExcludedWeaponEquipped(DataHandler data) { if ((Object)(object)data == (Object)null) { return false; } HoldingHandler component = ((Component)data).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (!IsExcludedHoldable(GetHoldable(component, RightObjectField))) { return IsExcludedHoldable(GetHoldable(component, LeftObjectField)); } return true; } internal static bool HasUnitLayDownAbility(DataHandler data) { if ((Object)(object)data == (Object)null) { return false; } ConditionalEvent[] componentsInChildren = ((Component)data).GetComponentsInChildren(); foreach (ConditionalEvent val in componentsInChildren) { if (ConditionalEventHasLayDown(val) && !IsOnExcludedWeaponHierarchy(((Component)val).transform, data)) { return true; } } return false; } internal static bool ShouldBlockLayDownPose(DataHandler data) { if ((Object)(object)data != (Object)null && HasExcludedWeaponEquipped(data)) { return !HasUnitLayDownAbility(data); } return false; } internal static bool ShouldBlockLayDownInstance(ConditionalEvent conditionalEvent, ConditionalEventInstance instance, DataHandler data) { if (instance != null && InstanceHasLayDownMove(instance)) { return IsOnExcludedWeaponHierarchy((conditionalEvent != null) ? ((Component)conditionalEvent).transform : null, data); } return false; } internal static void SuppressBundledLayDownForUnit(DataHandler data) { if ((Object)(object)data == (Object)null) { return; } ConditionalEvent[] componentsInChildren = ((Component)data).GetComponentsInChildren(); foreach (ConditionalEvent val in componentsInChildren) { if (IsOnExcludedWeaponHierarchy(((Component)val).transform, data)) { DisableBuiltInLayDown(val); } } } internal static bool ConditionalEventHasLayDown(ConditionalEvent conditionalEvent) { if ((Object)(object)conditionalEvent == (Object)null) { return false; } if (StayFixLogic.HasLayDownMarkerInHierarchy(((Component)conditionalEvent).transform)) { return true; } ConditionalEventInstance[] events = conditionalEvent.events; if (events == null) { return false; } for (int i = 0; i < events.Length; i++) { if (InstanceHasLayDownMove(events[i])) { return true; } } return false; } internal static bool IsOnExcludedWeaponHierarchy(Transform transform, DataHandler data = null) { if ((Object)(object)transform == (Object)null) { return false; } if (IsExcludedWeaponTransform(transform)) { return true; } if (data == null) { data = ((Component)transform.root).GetComponentInChildren(); } if ((Object)(object)data == (Object)null) { return false; } HoldingHandler component = ((Component)data).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } Holdable holdable = GetHoldable(component, RightObjectField); if (IsExcludedHoldable(holdable) && transform.IsChildOf(((Component)holdable).transform)) { return true; } Holdable holdable2 = GetHoldable(component, LeftObjectField); if (IsExcludedHoldable(holdable2)) { return transform.IsChildOf(((Component)holdable2).transform); } return false; } private static void DisableBuiltInLayDown(ConditionalEvent conditionalEvent) { if (conditionalEvent?.events == null) { return; } for (int i = 0; i < conditionalEvent.events.Length; i++) { ConditionalEventInstance val = conditionalEvent.events[i]; if (val == null || !InstanceHasLayDownMove(val)) { continue; } val.checkAutomatically = false; if (val.isOn) { val.isOn = false; UnityEvent turnOffEvent = val.turnOffEvent; if (turnOffEvent != null) { turnOffEvent.Invoke(); } } } } private static bool InstanceHasLayDownMove(ConditionalEventInstance instance) { Move[] array = instance?.moves; if (array == null) { return false; } for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && StayFixLogic.HasLayDownMarkerInHierarchy(((Component)array[i]).transform)) { return true; } } return false; } private static Holdable GetHoldable(HoldingHandler holding, FieldInfo field) { object? obj = field?.GetValue(holding); return (Holdable)((obj is Holdable) ? obj : null); } private static bool IsExcludedHoldable(Holdable holdable) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)holdable == (Object)null) { return false; } if (IsExcludedWeaponTransform(((Component)holdable).transform)) { return true; } WeaponItem component = ((Component)holdable).GetComponent(); if (((component != null) ? ((CharacterItem)component).Entity : null) != null && IsExcludedEntityId(((CharacterItem)component).Entity.GUID.m_ID)) { return true; } Weapon val = ((Component)holdable).GetComponent() ?? ((Component)holdable).GetComponentInChildren(); if ((Object)(object)val != (Object)null) { return IsExcludedWeaponTransform(((Component)val).transform); } return false; } private static bool IsExcludedWeaponTransform(Transform transform) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)transform == (Object)null) { return false; } if (IsExcludedWeaponName(((Object)transform).name)) { return true; } WeaponItem component = ((Component)transform).GetComponent(); if (((component != null) ? ((CharacterItem)component).Entity : null) != null) { return IsExcludedEntityId(((CharacterItem)component).Entity.GUID.m_ID); } return false; } private static bool IsExcludedEntityId(int entityId) { if (entityId != 1369807881) { return entityId == 1606594406; } return true; } private static bool IsExcludedWeaponName(string name) { string text = NormalizeWeaponName(name); if (!string.IsNullOrEmpty(text)) { if (!text.Contains("mg42")) { return text.Contains("m2browning"); } return true; } return false; } private static string NormalizeWeaponName(string name) { if (string.IsNullOrEmpty(name)) { return string.Empty; } string text = name; if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length); } return text.ToLowerInvariant().Replace(" ", string.Empty).Replace("_", string.Empty) .Replace("-", string.Empty); } } internal static class LayDownWeaponLogic { private static readonly FieldInfo WeaponHandlerDataField = AccessTools.Field(typeof(WeaponHandler), "data"); public static void TickLayDownVisibleCombat(DataHandler handler) { //IL_0040: 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) if (!StayFixLogic.CanLayDownEngageTarget(handler)) { return; } handler.inRange = true; if (StayFixLogic.ShouldLayDownAutoFire(handler)) { WeaponHandler component = ((Component)handler).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)handler.targetMainRig == (Object)null)) { TryLayDownAttack(component, GetAttackPosition(handler, handler.targetMainRig), handler.targetMainRig, Vector3.zero, (ForceWeapon)0); } } } public static bool TryLayDownAttack(WeaponHandler handler, Vector3 position, Rigidbody targetRig, Vector3 forceDirection, ForceWeapon forceWeapon) { //IL_004f: 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_0060: Unknown result type (might be due to invalid IL or missing references) object? obj = WeaponHandlerDataField?.GetValue(handler); DataHandler val = (DataHandler)((obj is DataHandler) ? obj : null); if ((Object)(object)val == (Object)null || (Object)(object)targetRig == (Object)null || !StayFixLogic.ShouldLayDownAutoFire(val)) { return false; } Unit unit = val.unit; if ((Object)(object)unit == (Object)null || !CanUnitAttackNow(unit)) { return false; } if (!TrySelectReadyWeapon(handler, forceWeapon, out var activeWeapon)) { return false; } ExecuteAttack(handler, activeWeapon, position, targetRig, forceDirection); ApplyUnitAttackCooldown(unit, handler); return true; } public static void TickLayDownWeaponCooldown(Weapon weapon, float attackSpeedMultiplier) { if ((Object)(object)weapon == (Object)null) { return; } float num = (weapon.isRange ? attackSpeedMultiplier : Mathf.Clamp((4f + attackSpeedMultiplier) * 0.2f, 1f, 2f)); if (weapon.countSelf) { for (int i = 0; i < weapon.weaponList.Length; i++) { Weapon obj = weapon.weaponList[i]; obj.internalCounter += Time.deltaTime * num; } } } internal static bool CanUnitAttackNow(Unit unit) { if ((Object)(object)unit == (Object)null || !Object.op_Implicit((Object)(object)unit.WeaponHandler)) { return false; } return unit.attackCounter * unit.WeaponHandler.attackSpeedMultiplier >= unit.lowestAttackTimeOfWeapons / 2f; } private static Vector3 GetAttackPosition(DataHandler data, Rigidbody targetRig) { //IL_0014: 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_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)data.torso != (Object)null) { return data.torso.position; } if ((Object)(object)data.mainRig != (Object)null) { return data.mainRig.position; } return targetRig.position; } private static void ApplyUnitAttackCooldown(Unit unit, WeaponHandler handler) { if (!((Object)(object)unit == (Object)null) && !((Object)(object)handler == (Object)null)) { unit.attackCounter = unit.lowestAttackTimeOfWeapons * Random.Range(-0.2f, 0.2f); } } private static bool TrySelectReadyWeapon(WeaponHandler handler, ForceWeapon forceWeapon, out Weapon activeWeapon) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) activeWeapon = null; if ((Object)(object)handler == (Object)null) { return false; } Weapon leftWeapon = handler.leftWeapon; Weapon rightWeapon = handler.rightWeapon; if (!Object.op_Implicit((Object)(object)leftWeapon) && !Object.op_Implicit((Object)(object)rightWeapon)) { return false; } object? obj = WeaponHandlerDataField?.GetValue(handler); DataHandler val = (DataHandler)((obj is DataHandler) ? obj : null); bool flag = (Object)(object)val?.input != (Object)null && val.input.IsRemotelyControlled; activeWeapon = SelectActiveWeapon(handler, leftWeapon, rightWeapon, forceWeapon, flag); if ((Object)(object)activeWeapon == (Object)null) { return false; } return !activeWeapon.IsOnCooldown() || flag; } private static void ExecuteAttack(WeaponHandler handler, Weapon activeWeapon, Vector3 position, Rigidbody targetRig, Vector3 forceDirection) { //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_0090: 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) if (activeWeapon.randomCooldown) { activeWeapon.internalCounter = Mathf.Clamp(Random.Range(activeWeapon.internalCooldown * -0.8f, activeWeapon.internalCooldown * 0.2f), -1f, 1f); } else { activeWeapon.internalCounter = 0f; } activeWeapon.Attack(position, targetRig, forceDirection, false); AttackStartedDelegate value = Traverse.Create((object)handler).Field("AttackStarted").Value; if (value != null) { bool flag = (Object)(object)handler.leftWeapon != (Object)null && (Object)(object)activeWeapon == (Object)(object)handler.leftWeapon; value.Invoke(((Component)handler).GetComponentInParent(), position, targetRig, forceDirection, (ForceWeapon)(flag ? 1 : 2)); } } private static Weapon SelectActiveWeapon(WeaponHandler handler, Weapon leftWeapon, Weapon rightWeapon, ForceWeapon forceWeapon, bool isRemotelyControlled) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Invalid comparison between Unknown and I4 //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Invalid comparison between Unknown and I4 Weapon val = ((!Object.op_Implicit((Object)(object)leftWeapon)) ? rightWeapon : (Object.op_Implicit((Object)(object)rightWeapon) ? ((Object.op_Implicit((Object)(object)leftWeapon) && Random.value > 0.5f) ? leftWeapon : rightWeapon) : leftWeapon)); val = ((val != null) ? val.GetBestWeaponOnWeapon() : null); if (Object.op_Implicit((Object)(object)leftWeapon) && Object.op_Implicit((Object)(object)rightWeapon) && !isRemotelyControlled) { Weapon val2 = (((Object)(object)val == (Object)(object)rightWeapon) ? leftWeapon : rightWeapon); if (val.internalCounter < val.internalCooldown) { if (!Object.op_Implicit((Object)(object)val2) || val2.internalCounter <= val2.internalCooldown) { return val; } val = val2; } if (val2.maxRange > val.maxRange && !val2.IsOnCooldown()) { val = val2; } } if (Object.op_Implicit((Object)(object)leftWeapon) && Object.op_Implicit((Object)(object)rightWeapon)) { if ((int)forceWeapon == 1) { val = leftWeapon; } if ((int)forceWeapon == 2) { val = rightWeapon; } } return val; } } internal static class LayDownWeaponPatches { public static bool WeaponHandler_Attack_Prefix(WeaponHandler __instance, Vector3 position, Rigidbody targetRig, Vector3 forceDirection, ForceWeapon forceWeapon) { //IL_0001: 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) //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (LayDownWeaponLogic.TryLayDownAttack(__instance, position, targetRig, forceDirection, forceWeapon)) { return false; } return true; } public static bool Weapon_UpdateCounters_Prefix(Weapon __instance, float attackSpeedMultiplier) { DataHandler connectedData = __instance.connectedData; if ((Object)(object)connectedData == (Object)null || !StayFixLogic.CanLayDownEngageTarget(connectedData)) { return true; } connectedData.inRange = true; if (!__instance.onlyCountInRange) { return true; } LayDownWeaponLogic.TickLayDownWeaponCooldown(__instance, attackSpeedMultiplier); return false; } } internal static class ModInfo { public const string Author = "Pretz"; public const string PluginGuid = "pretz.staycombatfix"; public const string PluginName = "Stay & Combat Fixes"; public const string Version = "3.0.0"; } public static class ModMain { public static void Register() { } } internal static class MovementStyleConfig { internal static bool FixRangedBackupWithoutSight = true; internal static void Bind(ConfigFile config) { FixRangedBackupWithoutSight = config.Bind("Movement", "FixRangedBackupWithoutSight", true, "Ranged movement style: only back up when the target is in line of sight (CanSeeTarget).").Value; } } internal static class MovementStylePatches { internal static void PreLateUpdateBarrier_OnUpdate_Postfix() { //IL_0084: 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_00b4: 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_00bb: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (!MovementStyleConfig.FixRangedBackupWithoutSight || !EcsComponentHelper.IsAvailable) { return; } TeamSystem existingManager = EcsComponentHelper.GetExistingManager(); if (existingManager == null) { return; } List allUnits = existingManager.GetAllUnits(); if (allUnits == null || allUnits.Count == 0) { return; } EntityManager entityManager = null; Entity entity; for (int i = 0; i < allUnits.Count && !EcsComponentHelper.TryGetEntityManager((Component)(object)allUnits[i], out entity, out entityManager); i++) { } if (!entityManager.IsCreated) { return; } for (int j = 0; j < allUnits.Count; j++) { Unit val = allUnits[j]; if (!((Object)(object)val == (Object)null) && EcsComponentHelper.TryGetEntityManager((Component)(object)val, out var entity2, out var _) && MovementStyleUnitContext.ShouldBlockRangedBackup(entityManager, entity2) && (!FleeConfig.FleeDistanceEnabled || !entityManager.HasComponent(entity2) || (!FleeDistanceAiState.IsFleeManaged(entity2) && !FleeDistanceAiState.ShouldFlee(entityManager, entity2)))) { Velocity componentData = entityManager.GetComponentData(entity2); if (!(componentData.Value.z >= 0f)) { componentData.Value = new float3(0f, 0f, 1f); entityManager.SetComponentData(entity2, componentData); } } } } internal static void UnitApi_SetMovementSpeed_Prefix(object __instance, ref float movementSpeed) { //IL_0022: 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_003b: 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) if (MovementStyleConfig.FixRangedBackupWithoutSight && !(movementSpeed >= 0f) && __instance != null && MovementStyleUnitContext.TryGetEntityFromUnitApi(__instance, out var entity, out var entityManager) && MovementStyleUnitContext.ShouldBlockRangedBackup(entityManager, entity) && (!FleeConfig.FleeDistanceEnabled || !entityManager.HasComponent(entity) || (!FleeDistanceAiState.IsFleeManaged(entity) && !FleeDistanceAiState.ShouldFlee(entityManager, entity)))) { movementSpeed = 1f; } } } internal static class MovementStyleUnitContext { private static readonly FieldInfo UnitApiGoEntityField = AccessTools.Field(AccessTools.TypeByName("Landfall.TABS.AI.UnitAPI, Assembly-CSharp"), "m_goEntity"); private static readonly PropertyInfo GoEntityEntityProperty = AccessTools.Property(EcsComponentHelper.GameObjectEntityType, "Entity"); private static readonly PropertyInfo GoEntityManagerProperty = AccessTools.Property(EcsComponentHelper.GameObjectEntityType, "EntityManager"); internal static bool TryGetEntityFromUnitApi(object unitApi, out Entity entity, out EntityManager entityManager) { //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_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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) entity = Entity.Null; entityManager = null; if (unitApi == null || UnitApiGoEntityField == null) { return false; } object value = UnitApiGoEntityField.GetValue(unitApi); if (value == null || GoEntityEntityProperty == null || GoEntityManagerProperty == null) { return false; } entity = (Entity)GoEntityEntityProperty.GetValue(value, null); entityManager = (EntityManager)GoEntityManagerProperty.GetValue(value, null); if (entityManager.IsCreated) { return entityManager.Exists(entity); } return false; } internal static bool ShouldBlockRangedBackup(EntityManager entityManager, Entity entity) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!entityManager.IsCreated || !entityManager.Exists(entity)) { return false; } if (!entityManager.HasComponent(entity)) { return false; } if (!EcsComponentHelper.TryGetComponentData(entityManager, entity, out TargetData data)) { return false; } if (data.TargetInPreferredRange != 1) { return false; } if (!EcsComponentHelper.TryGetComponentData(entityManager, entity, out CanSeeTarget data2)) { return false; } return data2.CanSee != 1; } } [BepInPlugin("pretz.staycombatfix", "Stay & Combat Fixes", "3.0.0")] public class Plugin : BaseUnityPlugin { internal static Plugin Instance { get; private set; } internal static void LogWarning(string message) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)message); } } internal static void LogInfo(string message) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)message); } } private void Awake() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown Instance = this; ModMain.Register(); BarrelRollerDeathLogic.Initialize((MonoBehaviour)(object)this, ((BaseUnityPlugin)this).Logger); WaterConfig.Cleanup(((BaseUnityPlugin)this).Config); ConfigCleanup.RemoveOrphanedMonolithKeys(((BaseUnityPlugin)this).Config); UnitEditorStatsConfig.Bind(((BaseUnityPlugin)this).Config); UnitMarkerConfig.Bind(((BaseUnityPlugin)this).Config); MovementStyleConfig.Bind(((BaseUnityPlugin)this).Config); FleeConfig.Bind(((BaseUnityPlugin)this).Config); WaterPatches.LogInfo = delegate(string message) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); }; Harmony harmony = new Harmony("pretz.staycombatfix"); int num = 0; num += Patch(harmony, AccessTools.Method(typeof(UnitDontWalkFor), "Go", (Type[])null, (Type[])null), typeof(StayPatches), "UnitDontWalkFor_Go_Prefix", "UnitDontWalkFor_Go_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(PoseHandler), "PlayAnimation", new Type[3] { typeof(StaticAnimation), typeof(Vector3), typeof(Quaternion) }, (Type[])null), typeof(StayPatches), "PoseHandler_PlayAnimation_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(DataHandler), "DontWalkFor", (Type[])null, (Type[])null), typeof(StayPatches), "DataHandler_DontWalkFor_Prefix", "DataHandler_DontWalkFor_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(DataHandler), "BatchedUpdate", (Type[])null, (Type[])null), typeof(StayPatches), "DataHandler_BatchedUpdate_Prefix", "DataHandler_BatchedUpdate_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(DataHandler), "BatchedFixedUpdate", (Type[])null, (Type[])null), typeof(StayPatches), null, "DataHandler_BatchedFixedUpdate_Postfix"); num += Patch(harmony, AccessTools.PropertySetter(typeof(DataHandler), "Dead"), typeof(StayPatches), null, "DataHandler_Dead_Setter_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(Rigidbody), "MovePosition", new Type[1] { typeof(Vector3) }, (Type[])null), typeof(StayPhysicsPatches), "Rigidbody_MovePosition_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(HoldingHandler), "AddForce", (Type[])null, (Type[])null), typeof(WeaponStayPatches), "HoldingHandler_AddForce_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(HoldingHandler), "BatchedFixedUpdate", (Type[])null, (Type[])null), typeof(WeaponStayPatches), null, "HoldingHandler_BatchedFixedUpdate_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(Holdable), "BatchedUpdate", (Type[])null, (Type[])null), typeof(WeaponStayPatches), "Holdable_BatchedUpdate_Prefix", "Holdable_BatchedUpdate_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(Explosion), "Explode", (Type[])null, (Type[])null), typeof(BarrelRollerDeathPatches), "Explosion_Explode_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(KillAfterSeconds), "Spawn", (Type[])null, (Type[])null), typeof(BarrelRollerDeathPatches), null, "KillAfterSeconds_Spawn_Postfix"); Type type = AccessTools.TypeByName("RemoveAfterSeconds"); if (type != null) { num += Patch(harmony, AccessTools.Method(type, "TriggerRemoval", (Type[])null, (Type[])null), typeof(BarrelRollerDeathPatches), null, "RemoveAfterSeconds_TriggerRemoval_Postfix"); } num += Patch(harmony, AccessTools.Method(typeof(DelayEvent), "Go", (Type[])null, (Type[])null), typeof(BarrelRollerDeathPatches), "DelayEvent_Go_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(ConditionalEvent), "OnUnitDead", (Type[])null, (Type[])null), typeof(BarrelRollerDeathPatches), "ConditionalEvent_OnUnitDead_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(GameStateManager), "EnterPlacementState", (Type[])null, (Type[])null), typeof(BarrelRollerDeathPatches), null, "GameStateManager_EnterPlacementState_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(GameStateManager), "EnterPlacementState", (Type[])null, (Type[])null), typeof(GameStatePatches), null, "EnterPlacementState_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(GameStateManager), "EnterBattleState", (Type[])null, (Type[])null), typeof(GameStatePatches), null, "EnterBattleState_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(GameStateManager), "EnterNoneState", (Type[])null, (Type[])null), typeof(GameStatePatches), null, "EnterNoneState_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(Water), "Start", (Type[])null, (Type[])null), typeof(WaterPatches), null, "Water_Start_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(Water), "OnTriggerStay", (Type[])null, (Type[])null), typeof(WaterPatches), "Water_OnTriggerStay_Prefix", "Water_OnTriggerStay_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(ProjectileHit), "DisableProjectile", (Type[])null, (Type[])null), typeof(GasGrenadePatches), null, "ProjectileHit_DisableProjectile_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(RaycastTrail), "Check", (Type[])null, (Type[])null), typeof(GasGrenadePatches), null, "RaycastTrail_Check_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(ConditionalEvent), "CheckCondition", new Type[4] { typeof(EventCondition), typeof(ConditionalEventInstance), typeof(ConditionType), typeof(bool) }, (Type[])null), typeof(LayDownRangePatches), "CheckCondition_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(ConditionalEvent), "IncrementCounters", (Type[])null, (Type[])null), typeof(LayDownRangePatches), "IncrementCounters_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(WeaponHandler), "Attack", new Type[4] { typeof(Vector3), typeof(Rigidbody), typeof(Vector3), typeof(ForceWeapon) }, (Type[])null), typeof(LayDownWeaponPatches), "WeaponHandler_Attack_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(Weapon), "UpdateCounters", new Type[1] { typeof(float) }, (Type[])null), typeof(LayDownWeaponPatches), "Weapon_UpdateCounters_Prefix"); Type type2 = AccessTools.TypeByName("Landfall.TABS.AI.UnitAPI, Assembly-CSharp"); Type type3 = AccessTools.TypeByName("Landfall.TABS.AI.Components.TargetData, Assembly-CSharp"); Type type4 = AccessTools.TypeByName("Unity.Mathematics.float3, Unity.Mathematics"); if (type2 != null && type3 != null && type4 != null) { MethodInfo methodInfo = AccessTools.Method(type2, "SetAttackTarget", new Type[6] { type4, typeof(Rigidbody), typeof(DataHandler), type3, typeof(bool), typeof(bool) }, (Type[])null); if (methodInfo != null) { num += Patch(harmony, methodInfo, typeof(LayDownAttackPatches), "SetAttackTarget_Prefix", "SetAttackTarget_Postfix"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Lay-down attack patch skipped: SetAttackTarget method not found"); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Lay-down attack patch skipped: UnitAPI / TargetData / float3 types not found"); } num += Patch(harmony, AccessTools.Method(typeof(ConditionalEvent), "CheckConditions", new Type[4] { typeof(ConditionalEventInstance), typeof(ConditionType), typeof(bool), typeof(bool) }, (Type[])null), typeof(LayDownAbilityPatches), "CheckConditions_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(ConditionalEvent), "Start", (Type[])null, (Type[])null), typeof(LayDownAbilityPatches), null, "ConditionalEvent_Start_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(ConditionalEvent), "Update", (Type[])null, (Type[])null), typeof(LayDownAbilityPatches), null, "ConditionalEvent_Update_Postfix"); num += Patch(harmony, AccessTools.Method(typeof(ConditionalEvent), "CheckConditionsUpdate", (Type[])null, (Type[])null), typeof(LayDownAbilityPatches), "CheckConditionsUpdate_Prefix"); num += Patch(harmony, AccessTools.Method(typeof(CameraAbilityPossess), "SetEnterUI", new Type[1] { typeof(Unit) }, (Type[])null), typeof(LayDownAbilityPatches), null, "SetEnterUI_Postfix"); MethodInfo methodInfo2 = AccessTools.Method(typeof(FactionCreatorManager), "AddNewUnit", new Type[1] { typeof(UnitBlueprint) }, (Type[])null); if (methodInfo2 != null) { num += Patch(harmony, methodInfo2, typeof(FactionCreatorPatches), null, "AddNewUnit_Postfix"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Faction creator reorder: AddNewUnit patch skipped"); } MethodInfo methodInfo3 = AccessTools.Method(typeof(FactionCreatorManager), "LoadFaction", new Type[1] { typeof(Faction) }, (Type[])null); if (methodInfo3 != null) { num += Patch(harmony, methodInfo3, typeof(FactionCreatorPatches), null, "LoadFaction_Postfix"); } num += Patch(harmony, AccessTools.Method(typeof(ContentDatabase), "AddUserFaction", (Type[])null, (Type[])null), typeof(FactionUnitsLoadFix), "AddUserFaction_Prefix"); MethodInfo methodInfo4 = AccessTools.Method(typeof(FactionCreatorManager), "SaveNewFaction", (Type[])null, (Type[])null); if (methodInfo4 != null) { num += Patch(harmony, methodInfo4, typeof(FactionCreatorPatches), "SaveNewFaction_Prefix"); } MethodInfo methodInfo5 = AccessTools.Method(typeof(FactionCreatorManager), "GetFactionUnits", (Type[])null, (Type[])null); if (methodInfo5 != null) { num += Patch(harmony, methodInfo5, typeof(FactionCreatorPatches), "GetFactionUnits_Prefix"); } MethodInfo methodInfo6 = AccessTools.Method(typeof(UnitButtonFactionCreator), "OnClick", (Type[])null, (Type[])null); if (methodInfo6 != null) { num += Patch(harmony, methodInfo6, typeof(FactionCreatorPatches), "UnitButtonFactionCreator_OnClick_Prefix"); } MethodInfo methodInfo7 = AccessTools.Method(typeof(UnitButtonBase), "OnPointerEnter", (Type[])null, (Type[])null); if (methodInfo7 != null) { num += Patch(harmony, methodInfo7, typeof(FactionCreatorPatches), null, "UnitButtonBase_OnPointerEnter_Postfix"); } MethodInfo methodInfo8 = AccessTools.Method(typeof(UnitButtonBase), "OnPointerExit", (Type[])null, (Type[])null); if (methodInfo8 != null) { num += Patch(harmony, methodInfo8, typeof(FactionCreatorPatches), null, "UnitButtonBase_OnPointerExit_Postfix"); } MethodInfo methodInfo9 = AccessTools.Method(typeof(UnitButtonBase), "OnSelect", (Type[])null, (Type[])null); if (methodInfo9 != null) { num += Patch(harmony, methodInfo9, typeof(FactionCreatorPatches), null, "UnitButtonBase_OnSelect_Postfix"); } MethodInfo methodInfo10 = AccessTools.Method(typeof(UnitButtonBase), "OnDeselect", (Type[])null, (Type[])null); if (methodInfo10 != null) { num += Patch(harmony, methodInfo10, typeof(FactionCreatorPatches), null, "UnitButtonBase_OnDeselect_Postfix"); } Type type5 = AccessTools.TypeByName("BattleCreatorSaveUI"); if (type5 != null) { MethodInfo methodInfo11 = AccessTools.Method(type5, "OnUnitClicked", new Type[1] { typeof(DatabaseID) }, (Type[])null); if (methodInfo11 != null) { num += Patch(harmony, methodInfo11, typeof(BattleCreatorSaveWhitelistPatches), "OnUnitClicked_Prefix"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Save battle whitelist: BattleCreatorSaveUI.OnUnitClicked patch skipped"); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Save battle whitelist: BattleCreatorSaveUI type not found"); } Type type6 = AccessTools.TypeByName("FactionButton"); if (type6 != null) { MethodInfo methodInfo12 = AccessTools.Method(type6, "OnPointerUp", (Type[])null, (Type[])null); if (methodInfo12 != null) { num += Patch(harmony, methodInfo12, typeof(BattleCreatorSaveWhitelistPatches), null, "OnFactionPointerUp_Postfix"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Save battle whitelist: FactionButton.OnPointerUp patch skipped"); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Save battle whitelist: FactionButton type not found"); } num += RegisterUnitEditorStatPatches(harmony); num += RegisterUnitMarkerPatches(harmony); num += RegisterCustomUnitRangedMovementPatches(harmony); num += RegisterFleeDistanceAiPatches(harmony); num += RegisterMovementStylePatches(harmony); _ = FleeConfig.FleeDistanceEnabled; ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Loaded v{0} by {1} — Harmony {2} patches", "3.0.0", "Pretz", num)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Unit editor stats: " + (UnitEditorStatsConfig.Enabled ? "on" : "off"))); ((BaseUnityPlugin)this).Logger.LogInfo((object)($"Custom units: ignoreMissing={UnitMarkerConfig.IgnoreMissingModComponents}, " + $"extendedSave={UnitMarkerConfig.EnableExtendedUnitSave}, " + $"rangedEdgeHold={UnitMarkerConfig.FixRangedEdgeHold}")); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Movement: rangedBackupRequiresSight={MovementStyleConfig.FixRangedBackupWithoutSight}"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Flee distance AI: " + (FleeConfig.FleeDistanceEnabled ? "on" : "off"))); } private int RegisterFleeDistanceAiPatches(Harmony harmony) { int applied = 0; FleeDistanceAiPatches.Register(harmony, ref applied); return applied; } private int RegisterCustomUnitRangedMovementPatches(Harmony harmony) { if (!UnitMarkerConfig.FixRangedEdgeHold) { return 0; } int num = 0; num += Patch(harmony, AccessTools.Method(typeof(UnitBlueprint), "DeserializedUnit", (Type[])null, (Type[])null), typeof(CustomUnitRangedMovementFix), null, "DeserializedUnit_Postfix"); MethodInfo methodInfo = AccessTools.GetDeclaredMethods(typeof(UnitBlueprint)).FirstOrDefault(delegate(MethodInfo method) { if (method.Name != "Spawn") { return false; } ParameterInfo[] parameters = method.GetParameters(); return parameters.Length >= 4 && parameters[3].ParameterType.IsByRef && parameters[3].ParameterType.GetElementType() == typeof(Unit); }); if (methodInfo != null) { num += Patch(harmony, methodInfo, typeof(CustomUnitRangedMovementFix), "Spawn_Prefix"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Custom unit ranged edge hold: UnitBlueprint.Spawn overload not found"); } return num; } private int RegisterUnitMarkerPatches(Harmony harmony) { int num = 0; if (UnitMarkerConfig.EnableExtendedUnitSave) { num += Patch(harmony, AccessTools.Method(typeof(CustomUnitHandler), "SaveUnit", (Type[])null, (Type[])null), typeof(CustomUnitHandlerSaveUnitPatch), "Prefix"); num += Patch(harmony, AccessTools.Method(typeof(CustomContentLoaderModIO), "ReadUnit", (Type[])null, (Type[])null), typeof(CustomContentLoaderReadUnitPatch), "Prefix"); num += Patch(harmony, AccessTools.Method(typeof(UnitBlueprint), "DeserializedUnit", (Type[])null, (Type[])null), typeof(UnitBlueprintDeserializedUnitPatch), "Prefix", "Postfix"); } else if (UnitMarkerConfig.IgnoreMissingModComponents) { num += Patch(harmony, AccessTools.Method(typeof(UnitBlueprint), "DeserializedUnit", (Type[])null, (Type[])null), typeof(UnitBlueprintDeserializedUnitPatch), null, "Postfix"); } return num; } private int RegisterUnitEditorStatPatches(Harmony harmony) { int num = 0; try { Type typeFromHandle = typeof(UnitEditorManager); Type typeFromHandle2 = typeof(UnitEditorUIManager); Type typeFromHandle3 = typeof(UnitEditorStatCell); Type typeFromHandle4 = typeof(UnitEditorStatsPageUI); num += Patch(harmony, AccessTools.Method(typeFromHandle, "Awake", (Type[])null, (Type[])null), typeof(UnitEditorCustomStats), "Awake_Prefix"); if (typeFromHandle2 != null) { num += Patch(harmony, AccessTools.Method(typeFromHandle2, "Start", (Type[])null, (Type[])null), typeof(UnitEditorCustomStats), "UIManager_Start_Prefix"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Unit editor targ stat: UnitEditorUIManager type not found"); } MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "SetStats", new Type[1] { typeof(UnitBlueprint) }, (Type[])null); if (methodInfo != null) { num += Patch(harmony, methodInfo, typeof(UnitEditorCustomStats), null, "SetStats_Postfix"); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Unit editor targ stat: SetStats patch skipped"); } num += Patch(harmony, AccessTools.Method(typeFromHandle, "LoadUnit", new Type[1] { typeof(UnitBlueprint) }, (Type[])null), typeof(UnitEditorCustomStats), "LoadUnit_Prefix", "LoadUnit_Postfix"); num += Patch(harmony, AccessTools.Method(typeFromHandle, "SwitchUnitBase", new Type[1] { typeof(int) }, (Type[])null), typeof(UnitEditorCustomStats), "SwitchUnitBase_Prefix"); if (typeFromHandle3 != null) { Type type = AccessTools.Inner(typeFromHandle, "StatsWrapper"); if (type != null) { num += Patch(harmony, AccessTools.Method(typeFromHandle3, "Init", new Type[1] { type }, (Type[])null), typeof(UnitEditorCustomStats), null, "StatCell_Init_Postfix"); num += Patch(harmony, AccessTools.Method(typeFromHandle3, "Init", new Type[1] { type }, (Type[])null), typeof(UnitEditorWalkSync), null, "StatCell_Init_Postfix"); num += Patch(harmony, AccessTools.Method(typeFromHandle3, "UpdateValue", new Type[1] { typeof(bool) }, (Type[])null), typeof(UnitEditorCustomStats), null, "StatCell_UpdateValue_Postfix"); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Unit editor targ stat: UnitEditorStatCell type not found"); } if (typeFromHandle4 != null) { MethodInfo methodInfo2 = AccessTools.Method(typeFromHandle4, "SpawnStats", (Type[])null, (Type[])null); if (methodInfo2 != null) { num += Patch(harmony, methodInfo2, typeof(UnitEditorStatsScroll), null, "SpawnStats_Postfix"); } MethodInfo methodInfo3 = AccessTools.Method(typeof(UnitEditorSubMenu), "Open", (Type[])null, (Type[])null); if (methodInfo3 != null) { num += Patch(harmony, methodInfo3, typeof(UnitEditorStatsScroll), null, "StatsPage_Open_Postfix"); } MethodInfo methodInfo4 = AccessTools.Method(typeFromHandle4, "Close", (Type[])null, (Type[])null); if (methodInfo4 != null) { num += Patch(harmony, methodInfo4, typeof(UnitEditorStatsScroll), null, "StatsPage_Close_Postfix"); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Unit editor stats scroll: UnitEditorStatsPageUI type not found"); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Unit editor stat patches failed: {arg}"); } return num; } private int RegisterMovementStylePatches(Harmony harmony) { int num = 0; try { Type type = AccessTools.TypeByName("EzECS.Barriers.PreLateUpdateBarrier, Assembly-CSharp"); if (type != null) { if (Patch(harmony, AccessTools.Method(type, "OnUpdate", (Type[])null, (Type[])null), typeof(MovementStylePatches), null, "PreLateUpdateBarrier_OnUpdate_Postfix") > 0) { num++; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Movement style: patched PreLateUpdateBarrier.OnUpdate"); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Movement style: PreLateUpdateBarrier type not found"); } Type type2 = AccessTools.TypeByName("Landfall.TABS.AI.UnitAPI, Assembly-CSharp"); MethodInfo methodInfo = ((type2 != null) ? AccessTools.Method(type2, "SetMovementSpeed", new Type[2] { typeof(float), typeof(bool) }, (Type[])null) : null); if (methodInfo != null) { if (Patch(harmony, methodInfo, typeof(MovementStylePatches), "UnitApi_SetMovementSpeed_Prefix") > 0) { num++; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Movement style: patched UnitAPI.SetMovementSpeed"); } } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Movement style: UnitAPI.SetMovementSpeed(float, bool) not found"); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Movement style patches failed: {arg}"); } return num; } private int Patch(Harmony harmony, MethodBase original, Type patchClass, string prefix = null, string postfix = null, string transpiler = null) { //IL_0047: 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_0067: Unknown result type (might be due to invalid IL or missing references) if (original == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Patch target missing: " + patchClass.Name + "." + (prefix ?? postfix ?? transpiler))); return 0; } try { object obj = harmony; obj = original; obj = (object)((prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(patchClass, prefix, (Type[])null)); obj = (object)((postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(patchClass, postfix, (Type[])null)); obj = (object)((transpiler == null) ? ((HarmonyMethod)null) : new HarmonyMethod(patchClass, transpiler, (Type[])null)); ((Harmony)obj).Patch((MethodBase)obj, (HarmonyMethod)obj, (HarmonyMethod)obj, (HarmonyMethod)obj, (HarmonyMethod)null, (HarmonyMethod)null); return 1; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to patch " + original.DeclaringType?.Name + "." + original.Name + ": " + ex.Message)); return 0; } } } public static class StayFixLogic { private static readonly Dictionary HorizontalAnchorByHandler = new Dictionary(); private static readonly Dictionary StayModeByHandler = new Dictionary(); private static readonly HashSet LayDownEligibleHandlers = new HashSet(); private static readonly Dictionary LayDownActiveUntilTime = new Dictionary(); private static readonly Dictionary LayDownWindUpEndsAt = new Dictionary(); private static readonly HashSet LayDownWasPlayingStaticAnim = new HashSet(); private static readonly HashSet AnchorReleased = new HashSet(); private static int _stayCombatCheckFrame = -1; private static bool _cachedStayCombatActive; private static int _stayWorkTrackingFrame = -1; private static readonly HashSet HandlersWithStayWorkThisFrame = new HashSet(); private static float _stayFixedWorkTime = -1f; private static readonly HashSet HandlersWithStayFixedWorkThisFrame = new HashSet(); private static int _dontMoveCacheFrame = -1; private static readonly Dictionary DontMoveRemainingCache = new Dictionary(); private const float AnchorReleaseSpeed = 2.5f; private const float AnchorReleaseDistance = 0.85f; private const float LayDownWindUpSeconds = 2f; private const float LayDownPulseGraceSeconds = 0.4f; private const float LayDownAnchorReleaseSpeed = 12f; private static readonly FieldInfo DontMoveForField = typeof(DataHandler).GetField("dontMoveFor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo HipField = typeof(DataHandler).GetField("hip", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private const float LayDownWeaponAimPidMultiplier = 2.75f; private const float StayWeaponAimPidMultiplier = 1.85f; internal static bool IsStayCombatActive() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 if (Time.frameCount == _stayCombatCheckFrame) { return _cachedStayCombatActive; } _stayCombatCheckFrame = Time.frameCount; GameStateManager service = ServiceLocator.GetService(); _cachedStayCombatActive = service != null && (int)service.GameState == 1; return _cachedStayCombatActive; } internal static void InvalidateStayCombatCache() { _stayCombatCheckFrame = -1; } internal static bool BeginStayFrameWork(DataHandler handler) { EnsureStayWorkTrackingFrame(); if (HandlersWithStayWorkThisFrame.Contains(handler)) { return true; } if (!NeedsPerFrameStayWork(handler)) { return false; } HandlersWithStayWorkThisFrame.Add(handler); return true; } internal static bool ContinueStayFrameWork(DataHandler handler) { EnsureStayWorkTrackingFrame(); if ((Object)(object)handler != (Object)null) { return HandlersWithStayWorkThisFrame.Contains(handler); } return false; } internal static bool BeginStayFixedWork(DataHandler handler) { if (Time.fixedTime != _stayFixedWorkTime) { _stayFixedWorkTime = Time.fixedTime; HandlersWithStayFixedWorkThisFrame.Clear(); } if (HandlersWithStayFixedWorkThisFrame.Contains(handler)) { return true; } if (!NeedsPerFrameStayWork(handler)) { return false; } HandlersWithStayFixedWorkThisFrame.Add(handler); return true; } private static void EnsureStayWorkTrackingFrame() { if (Time.frameCount != _stayWorkTrackingFrame) { _stayWorkTrackingFrame = Time.frameCount; HandlersWithStayWorkThisFrame.Clear(); } } public static void ClearAllTrackedUnits() { HorizontalAnchorByHandler.Clear(); StayModeByHandler.Clear(); LayDownEligibleHandlers.Clear(); LayDownActiveUntilTime.Clear(); LayDownWindUpEndsAt.Clear(); LayDownWasPlayingStaticAnim.Clear(); AnchorReleased.Clear(); HandlersWithStayWorkThisFrame.Clear(); HandlersWithStayFixedWorkThisFrame.Clear(); _stayWorkTrackingFrame = -1; _stayFixedWorkTime = -1f; DontMoveRemainingCache.Clear(); _dontMoveCacheFrame = -1; InvalidateStayCombatCache(); LayDownRangeLogic.ClearLayDownEventCache(); } public static void OnStayApplied(DataHandler handler, UnitDontWalkFor source) { if (!((Object)(object)handler == (Object)null) && IsStayCombatActive()) { RegisterStayMode(handler, DetectStayModeFromSource(source, handler)); if (IsLayDownStay(handler)) { BeginLayDownStay(handler, ((Object)(object)source != (Object)null) ? source.time : 0f); } else if (ShouldApplyStayFix(handler)) { ForceRefreshHorizontalAnchor(handler); ApplyStayFix(handler); } } } public static void OnStayApplied(DataHandler handler, float staySeconds) { if (!((Object)(object)handler == (Object)null) && IsStayCombatActive()) { RegisterStayMode(handler, ResolveStayMode(handler, null)); if (IsLayDownStay(handler)) { BeginLayDownStay(handler, staySeconds); } else if (ShouldApplyStayFix(handler)) { ForceRefreshHorizontalAnchor(handler); ApplyStayFix(handler); } } } public static void BeginLayDownStay(DataHandler handler, float staySeconds = 0f, float poseDurationSeconds = 0f) { if (!((Object)(object)handler == (Object)null)) { MarkLayDownEligible(handler); RegisterStayMode(handler, StayFixMode.LayDown); BeginLayDownWindUp(handler); RecordLayDownActivity(handler, staySeconds, poseDurationSeconds + 2f); AnchorReleased.Remove(handler); } } internal static void RegisterStayMode(DataHandler handler, StayFixMode mode) { if ((Object)(object)handler != (Object)null) { StayModeByHandler[handler] = mode; } } public static bool IsLayDownStay(DataHandler handler) { if ((Object)(object)handler != (Object)null && StayModeByHandler.TryGetValue(handler, out var value)) { return value == StayFixMode.LayDown; } return false; } internal static bool CanLayDownEngageTarget(DataHandler handler) { if ((Object)(object)handler == (Object)null || !IsLayDownAbilityActive(handler) || !IsLayDownStay(handler)) { return false; } if ((Object)(object)handler.targetMainRig == (Object)null) { return false; } DataHandler componentInParent = ((Component)handler.targetMainRig).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && componentInParent.Dead) { return false; } if (!handler.CanSeeTarget) { return IsTargetWithinWeaponFireRange(handler); } return true; } internal static bool IsLayDownPlayerPossessed(DataHandler handler) { if ((Object)(object)handler?.input != (Object)null) { return handler.input.hasControl; } return false; } internal static bool ShouldLayDownAutoFire(DataHandler handler) { if (CanLayDownEngageTarget(handler)) { return !IsLayDownPlayerPossessed(handler); } return false; } internal static float GetWeaponTrackPidMultiplier(DataHandler handler) { if ((Object)(object)handler == (Object)null) { return 1f; } if (IsLayDownStay(handler) && (CanLayDownEngageTarget(handler) || IsLayDownAbilityActive(handler))) { return 2.75f; } if (IsStayLocked(handler)) { return 1.85f; } return 1f; } public static bool ShouldClampWeaponHoldPosition(DataHandler handler, Holdable holdable) { if (!IsStayLocked(handler) || ShouldSkipStayPhysicsLock(handler)) { return false; } if (!IsLayDownStay(handler)) { return true; } if (!IsHoldableInFireRange(handler, holdable)) { return ShouldTrackTargetWithWeapon(handler, holdable); } return true; } public static bool ShouldApplyStayFix(DataHandler handler) { if (!IsStayCombatActive()) { return false; } if ((Object)(object)handler == (Object)null || handler.Dead || IsRiderRelatedUnit(handler)) { return false; } if (IsLayDownStay(handler) || IsLayDownEligible(handler)) { return ShouldApplyLayDownPhysics(handler); } if (!IsUnderStayEffect(handler)) { return false; } if (IsBearerOrPlayerControlled(handler)) { return false; } return true; } internal static bool MightUseStaySystems(DataHandler handler) { if ((Object)(object)handler == (Object)null || handler.Dead) { return false; } if (LayDownEligibleHandlers.Contains(handler) || IsLayDownStay(handler) || LayDownWasPlayingStaticAnim.Contains(handler) || HorizontalAnchorByHandler.ContainsKey(handler) || StayModeByHandler.ContainsKey(handler) || LayDownActiveUntilTime.ContainsKey(handler) || LayDownWindUpEndsAt.ContainsKey(handler) || AnchorReleased.Contains(handler)) { return true; } return GetCachedDontMoveForRemaining(handler) > 0f; } internal static bool NeedsPerFrameStayWork(DataHandler handler) { if (!IsStayCombatActive() || (Object)(object)handler == (Object)null || handler.Dead || IsRiderRelatedUnit(handler)) { return false; } if (!MightUseStaySystems(handler)) { return false; } if (ShouldApplyStayFix(handler)) { return true; } if (!IsLayDownStay(handler) && !LayDownEligibleHandlers.Contains(handler) && !LayDownWasPlayingStaticAnim.Contains(handler) && !LayDownActiveUntilTime.ContainsKey(handler)) { return LayDownWindUpEndsAt.ContainsKey(handler); } return true; } private static bool ShouldClearStayState(DataHandler handler) { if ((Object)(object)handler == (Object)null || handler.Dead || IsRiderRelatedUnit(handler)) { return true; } if (IsLayDownStay(handler) || IsLayDownEligible(handler)) { return !IsLayDownAbilityActive(handler); } if (IsBearerOrPlayerControlled(handler)) { return true; } return !IsUnderStayEffect(handler); } public static bool IsBearerOrPlayerControlled(DataHandler handler) { if ((Object)(object)handler == (Object)null) { return false; } if ((Object)(object)handler.unitToInheritDirectionFrom != (Object)null) { return true; } if ((Object)(object)handler.input == (Object)null) { return false; } if (handler.input.hasControl) { return true; } if (handler.input.IsRemotelyControlled) { return true; } if ((Object)(object)handler.unit != (Object)null) { return handler.unit.IsRemotelyControlled; } return false; } public static void PrepareStayFrame(DataHandler handler) { //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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_00f9: 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_0106: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)handler == (Object)null) { return; } if (LayDownWeaponExclusions.HasExcludedWeaponEquipped(handler)) { LayDownWeaponExclusions.SuppressBundledLayDownForUnit(handler); } UpdateLayDownAnchorPhase(handler); LayDownWeaponLogic.TickLayDownVisibleCombat(handler); if (ShouldClearStayState(handler)) { ClearStayState(handler); } else if (ShouldTrackLayDownPoseWithoutLock(handler)) { SyncLastPosToBody(handler); } else { if (!ShouldApplyStayFix(handler)) { return; } EnsureHorizontalAnchor(handler); TryReleaseAnchorIfPushed(handler); if ((Object)(object)handler.input != (Object)null) { handler.input.inputDirection = Vector3.zero; } if (!((Object)(object)handler.mainRig == (Object)null)) { Vector3 value; if (IsLayDownStay(handler) && ShouldLayDownHorizontalHold(handler)) { SyncLastPosHorizontalOnly(handler); } else if (!HasHorizontalAnchor(handler)) { handler.lastPos = handler.mainRig.position; } else if (ShouldSkipStayPhysicsLock(handler)) { handler.lastPos = handler.mainRig.position; } else if (HorizontalAnchorByHandler.TryGetValue(handler, out value)) { Vector3 position = handler.mainRig.position; position.x = value.x; position.z = value.z; handler.lastPos = position; } } } } public static void TickStayLight(DataHandler handler) { if ((Object)(object)handler == (Object)null) { return; } if (ShouldClearStayState(handler)) { ClearStayState(handler); } else if (ShouldApplyStayFix(handler)) { EnsureHorizontalAnchor(handler); TryReleaseAnchorIfPushed(handler); PreventStayMovementCreep(handler); if (HasHorizontalAnchor(handler) && !ShouldSkipStayPhysicsLock(handler)) { EnforcePlantPosition(handler); } } } public static void EnforcePlantPosition(DataHandler handler) { if ((Object)(object)handler == (Object)null || !ShouldApplyStayFix(handler)) { return; } EnsureHorizontalAnchor(handler); TryReleaseAnchorIfPushed(handler); PreventStayMovementCreep(handler); if (ShouldSkipStayPhysicsLock(handler)) { return; } if (IsLayDownStay(handler)) { if (ShouldLayDownHorizontalHold(handler)) { ApplyLayDownHorizontalHold(handler, fullStabilize: true); } } else { StabilizeMainBodyHorizontal(handler); ApplyHorizontalLock(handler); } } public static void TickStay(DataHandler handler) { if ((Object)(object)handler == (Object)null) { return; } if (ShouldClearStayState(handler)) { ClearStayState(handler); } else if (ShouldApplyStayFix(handler)) { EnsureHorizontalAnchor(handler); TryReleaseAnchorIfPushed(handler); if (HasHorizontalAnchor(handler) && !ShouldSkipStayPhysicsLock(handler)) { EnforcePlantPosition(handler); } } } public static void OnUnitDied(DataHandler handler) { ClearStayState(handler); } public static bool IsStayLocked(DataHandler handler) { if ((Object)(object)handler == (Object)null || !IsStayCombatActive() || !MightUseStaySystems(handler)) { return false; } return ShouldApplyStayFix(handler); } public static bool IsStayLocked(Component component) { if ((Object)(object)component == (Object)null) { return false; } return IsStayLocked(component.GetComponentInParent()); } public static bool HasHorizontalAnchorForStay(DataHandler handler) { return HasHorizontalAnchor(handler); } public static DataHandler ResolveHandler(UnitDontWalkFor source) { if ((Object)(object)source == (Object)null) { return null; } Unit componentInParent = ((Component)source).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.data != (Object)null) { return componentInParent.data; } return ((Component)source).GetComponentInParent(); } public static bool ShouldSkipStayPhysicsLock(DataHandler handler) { if (!((Object)(object)handler == (Object)null) && !handler.Dead) { return !HasHorizontalAnchor(handler); } return true; } public static bool TryClampBodyMovePosition(Rigidbody rb, ref Vector3 position) { //IL_0057: 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) DataHandler val = ((rb != null) ? ((Component)rb).GetComponentInParent() : null); if ((Object)(object)val == (Object)null || !HasHorizontalAnchor(val) || ShouldSkipStayPhysicsLock(val)) { return false; } if (IsLayDownStay(val) && !ShouldLayDownHorizontalHold(val)) { return false; } if (!IsUnitBodyRigidbody(val, rb)) { return false; } if (!HorizontalAnchorByHandler.TryGetValue(val, out var value)) { return false; } position.x = value.x; position.z = value.z; return true; } public static void ApplyStayFix(DataHandler handler) { EnforcePlantPosition(handler); } public static void StabilizeStayBody(DataHandler handler) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)handler == (Object)null || handler.Dead) { if (handler != null && handler.Dead) { ClearStayState(handler); } } else if (ShouldApplyStayFix(handler) && !ShouldSkipStayPhysicsLock(handler)) { if ((Object)(object)handler.input != (Object)null) { handler.input.inputDirection = Vector3.zero; } PreventStayMovementCreep(handler); StabilizeMainBodyHorizontal(handler); } } public static void StabilizeBodyOnly(DataHandler handler) { EnforcePlantPosition(handler); } private static void StabilizeMainBodyHorizontal(DataHandler handler) { if ((Object)(object)handler == (Object)null) { return; } StabilizeRigidbodyHorizontal(handler.mainRig); if ((Object)(object)handler.torso != (Object)null) { StabilizeRigidbodyHorizontal(((Component)handler.torso).GetComponent()); } if (!handler.isGrounded) { object? obj = HipField?.GetValue(handler); Rigidbody val = (Rigidbody)((obj is Rigidbody) ? obj : null); if (val != null) { StabilizeRigidbodyHorizontal(val); } } } public static void StabilizeWeaponHold(DataHandler handler) { if (!((Object)(object)handler == (Object)null) && ShouldApplyStayFix(handler) && !ShouldSkipStayPhysicsLock(handler)) { HoldingHandler component = ((Component)handler).GetComponent(); if (!((Object)(object)component == (Object)null)) { StabilizeHoldableLinearOnly(handler, GetHoldable(component, "rightObject")); StabilizeHoldableLinearOnly(handler, GetHoldable(component, "leftObject")); } } } internal static bool ShouldDeferToVanillaWeaponAim(DataHandler handler, Holdable holdable) { return ShouldTrackTargetWithWeapon(handler, holdable); } public static void ApplyExtendedLookAtAim(DataHandler handler, Holdable holdable) { //IL_0040: 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_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_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_007e: 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_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)handler?.mainRig == (Object)null) && holdable?.holdableData != null && !((Object)(object)handler.targetMainRig == (Object)null) && !UsesArcingHoldableAim(holdable)) { Vector3 val = handler.targetMainRig.position - ((Component)holdable).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.0001f)) { holdable.holdableData.forwardRotation = ((Component)handler.mainRig).transform.InverseTransformDirection(normalized); } } } internal static bool UsesArcingHoldableAim(Holdable holdable) { if (holdable?.pidData != null) { return holdable.pidData.extraUpPerMeter != 0f; } return false; } public static bool ShouldTrackTargetWithWeapon(DataHandler handler, Holdable holdable = null) { if ((Object)(object)handler == (Object)null || (Object)(object)handler.targetMainRig == (Object)null) { return false; } DataHandler componentInParent = ((Component)handler.targetMainRig).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && componentInParent.Dead) { return false; } if (CanLayDownEngageTarget(handler)) { return true; } if (handler.inRange) { return true; } if ((Object)(object)holdable != (Object)null && IsHoldableInFireRange(handler, holdable)) { return true; } if ((Object)(object)holdable == (Object)null) { HoldingHandler component = ((Component)handler).GetComponent(); if ((Object)(object)component != (Object)null) { if (IsHoldableInFireRange(handler, GetHoldable(component, "rightObject"))) { return true; } if (IsHoldableInFireRange(handler, GetHoldable(component, "leftObject"))) { return true; } } } if (holdable?.holdableData != null && holdable.holdableData.lookAtTargetWhenWithin > 0f && handler.distanceToTarget < holdable.holdableData.lookAtTargetWhenWithin) { return true; } return false; } internal static bool IsHoldableInFireRange(DataHandler handler, Holdable holdable) { if ((Object)(object)holdable == (Object)null) { return false; } float effectiveFireRange = GetEffectiveFireRange(holdable); if (effectiveFireRange <= 0f) { return false; } float num = 0f; if ((Object)(object)handler.targetData?.unit != (Object)null) { num = handler.targetData.unit.thickness; } return handler.distanceToTarget <= effectiveFireRange + num + 1f; } internal static bool IsTargetWithinWeaponFireRange(DataHandler handler) { if ((Object)(object)handler?.targetMainRig == (Object)null) { return false; } DataHandler componentInParent = ((Component)handler.targetMainRig).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && componentInParent.Dead) { return false; } HoldingHandler component = ((Component)handler).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (IsHoldableInFireRange(handler, GetHoldable(component, "rightObject"))) { return true; } return IsHoldableInFireRange(handler, GetHoldable(component, "leftObject")); } public static void StabilizeRigidbodyHorizontal(Rigidbody rb) { //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_0019: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rb == (Object)null) && !rb.isKinematic) { Vector3 velocity = rb.velocity; if (!(Mathf.Abs(velocity.x) < 0.0001f) || !(Mathf.Abs(velocity.z) < 0.0001f)) { velocity.x = 0f; velocity.z = 0f; rb.velocity = velocity; } } } internal static bool IsUnitBodyRigidbody(DataHandler handler, Rigidbody rb) { if ((Object)(object)handler == (Object)null || (Object)(object)rb == (Object)null) { return false; } if ((Object)(object)rb == (Object)(object)handler.mainRig) { return true; } if ((Object)(object)handler.torso != (Object)null && (Object)(object)rb == (Object)(object)((Component)handler.torso).GetComponent()) { return true; } object? obj = HipField?.GetValue(handler); Rigidbody val = (Rigidbody)((obj is Rigidbody) ? obj : null); if (val != null && (Object)(object)rb == (Object)(object)val) { return true; } return false; } public static void ClearStayState(DataHandler handler) { if (!((Object)(object)handler == (Object)null)) { ClearHorizontalAnchor(handler); AnchorReleased.Remove(handler); StayModeByHandler.Remove(handler); LayDownEligibleHandlers.Remove(handler); LayDownActiveUntilTime.Remove(handler); LayDownWindUpEndsAt.Remove(handler); LayDownWasPlayingStaticAnim.Remove(handler); } } public static bool IsLayDownPoseAnimation(StaticAnimation animation) { if (animation == null || string.IsNullOrEmpty(animation.animationName)) { return false; } return HasLayDownMarkerInName(animation.animationName); } internal static StayFixMode DetectStayModeFromSource(UnitDontWalkFor source, DataHandler handler) { if (ShouldUseLayDownStayMode(handler)) { return StayFixMode.LayDown; } if ((Object)(object)source != (Object)null && HasLayDownMarkerInHierarchy(((Component)source).transform) && !LayDownWeaponExclusions.IsOnExcludedWeaponHierarchy(((Component)source).transform, handler)) { MarkLayDownEligible(handler); return StayFixMode.LayDown; } return StayFixMode.BannerAura; } private static bool ShouldUseLayDownStayMode(DataHandler handler) { if ((Object)(object)handler != (Object)null) { if (!IsLayDownEligible(handler)) { return handler.playingStaticAnim; } return true; } return false; } private static StayFixMode ResolveStayMode(DataHandler handler, UnitDontWalkFor source) { if ((Object)(object)source != (Object)null) { return DetectStayModeFromSource(source, handler); } if (ShouldUseLayDownStayMode(handler)) { return StayFixMode.LayDown; } return StayFixMode.BannerAura; } private static void MarkLayDownEligible(DataHandler handler) { if ((Object)(object)handler != (Object)null) { LayDownEligibleHandlers.Add(handler); } } private static bool IsLayDownEligible(DataHandler handler) { if ((Object)(object)handler != (Object)null) { return LayDownEligibleHandlers.Contains(handler); } return false; } private static void ForceRefreshHorizontalAnchor(DataHandler handler) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)handler?.mainRig == (Object)null)) { AnchorReleased.Remove(handler); HorizontalAnchorByHandler[handler] = handler.mainRig.position; } } internal static bool HasLayDownMarkerInHierarchy(Transform transform) { Transform val = transform; while ((Object)(object)val != (Object)null) { if (HasLayDownMarkerInName(((Object)val).name)) { return true; } val = val.parent; } return false; } private static bool HasLayDownMarkerInName(string name) { if (string.IsNullOrEmpty(name)) { return false; } if (name.IndexOf("laydown", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("lay down", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("lay_down", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("prone", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (name.IndexOf("lay", StringComparison.OrdinalIgnoreCase) >= 0) { return name.IndexOf("down", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static void RecordLayDownActivity(DataHandler handler, float staySeconds, float poseDurationSeconds = 0f) { if (!((Object)(object)handler == (Object)null)) { float num = Time.time + 0.4f; if (staySeconds > 0f) { num = Mathf.Max(num, Time.time + staySeconds); } if (poseDurationSeconds > 0f) { num = Mathf.Max(num, Time.time + poseDurationSeconds); } LayDownActiveUntilTime[handler] = num; } } internal static bool IsLayDownAbilityActive(DataHandler handler) { if ((Object)(object)handler == (Object)null || (!IsLayDownStay(handler) && !IsLayDownEligible(handler))) { return false; } if (handler.playingStaticAnim) { return true; } if (LayDownActiveUntilTime.TryGetValue(handler, out var value) && Time.time < value) { return true; } return IsUnderStayEffect(handler); } private static bool IsLayDownWindUpComplete(DataHandler handler) { if ((Object)(object)handler != (Object)null && LayDownWindUpEndsAt.TryGetValue(handler, out var value)) { return Time.time >= value; } return false; } private static bool ShouldTrackLayDownPoseWithoutLock(DataHandler handler) { if (IsLayDownAbilityActive(handler) && (IsLayDownStay(handler) || IsLayDownEligible(handler))) { return !ShouldApplyLayDownPhysics(handler); } return false; } private static void SyncLastPosToBody(DataHandler handler) { //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) if ((Object)(object)handler?.mainRig != (Object)null) { handler.lastPos = handler.mainRig.position; } } internal static bool ShouldApplyLayDownPhysics(DataHandler handler) { if (!IsLayDownAbilityActive(handler)) { return false; } if (!IsLayDownStay(handler) && !IsLayDownEligible(handler)) { return false; } if (!IsLayDownWindUpComplete(handler)) { return false; } if (handler.playingStaticAnim) { return false; } return true; } private static bool ShouldLayDownHorizontalHold(DataHandler handler) { if (ShouldApplyLayDownPhysics(handler)) { return HasHorizontalAnchor(handler); } return false; } private static void BeginLayDownWindUp(DataHandler handler) { if (!((Object)(object)handler == (Object)null) && !LayDownWindUpEndsAt.ContainsKey(handler)) { LayDownWindUpEndsAt[handler] = Time.time + 2f; } } private static void UpdateLayDownAnchorPhase(DataHandler handler) { if ((Object)(object)handler == (Object)null || (!IsLayDownStay(handler) && !IsLayDownEligible(handler))) { return; } bool playingStaticAnim = handler.playingStaticAnim; bool flag = LayDownWasPlayingStaticAnim.Contains(handler); if (playingStaticAnim) { LayDownWasPlayingStaticAnim.Add(handler); } else { LayDownWasPlayingStaticAnim.Remove(handler); } if (!(!IsLayDownAbilityActive(handler) || !IsLayDownWindUpComplete(handler) || playingStaticAnim)) { if (flag && !playingStaticAnim) { FinalizeLayDownPlant(handler); } else if (!HasHorizontalAnchor(handler)) { FinalizeLayDownPlant(handler); } } } private static void FinalizeLayDownPlant(DataHandler handler) { if (!((Object)(object)handler?.mainRig == (Object)null) && ShouldApplyLayDownPhysics(handler)) { RefreshHorizontalAnchorXZ(handler); if (ShouldApplyLayDownPhysics(handler)) { ApplyLayDownHorizontalHold(handler, fullStabilize: true); } } } private static void RefreshHorizontalAnchorXZ(DataHandler handler) { //IL_0027: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) if (!((Object)(object)handler?.mainRig == (Object)null)) { AnchorReleased.Remove(handler); Vector3 position = handler.mainRig.position; if (HorizontalAnchorByHandler.TryGetValue(handler, out var value)) { HorizontalAnchorByHandler[handler] = new Vector3(position.x, value.y, position.z); } else { HorizontalAnchorByHandler[handler] = position; } } } private static bool HasHorizontalAnchor(DataHandler handler) { if ((Object)(object)handler != (Object)null && HorizontalAnchorByHandler.ContainsKey(handler)) { return !AnchorReleased.Contains(handler); } return false; } private static void EnsureHorizontalAnchor(DataHandler handler) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)handler?.mainRig == (Object)null) && !AnchorReleased.Contains(handler) && !HorizontalAnchorByHandler.ContainsKey(handler)) { HorizontalAnchorByHandler[handler] = handler.mainRig.position; } } private static void ClearHorizontalAnchor(DataHandler handler) { if ((Object)(object)handler != (Object)null) { HorizontalAnchorByHandler.Remove(handler); } } private static void ReleaseHorizontalAnchor(DataHandler handler) { if (!((Object)(object)handler == (Object)null)) { AnchorReleased.Add(handler); ClearHorizontalAnchor(handler); } } private static void TryReleaseAnchorIfPushed(DataHandler handler) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)handler == (Object)null || AnchorReleased.Contains(handler) || !HasHorizontalAnchor(handler)) { return; } Rigidbody mainRig = handler.mainRig; if ((Object)(object)mainRig == (Object)null || !HorizontalAnchorByHandler.TryGetValue(handler, out var value)) { return; } if (IsLayDownStay(handler)) { Vector3 velocity = mainRig.velocity; velocity.y = 0f; if (((Vector3)(ref velocity)).sqrMagnitude >= 144f) { ReleaseHorizontalAnchor(handler); } return; } Vector3 val = mainRig.position - value; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude >= 0.7225f) { ReleaseHorizontalAnchor(handler); return; } Vector3 velocity2 = mainRig.velocity; velocity2.y = 0f; if (((Vector3)(ref velocity2)).sqrMagnitude >= 6.25f) { ReleaseHorizontalAnchor(handler); } } private static void ApplyLayDownHorizontalHold(DataHandler handler, bool fullStabilize) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)handler?.mainRig == (Object)null) && HasHorizontalAnchor(handler)) { if ((Object)(object)handler.input != (Object)null) { handler.input.inputDirection = Vector3.zero; } PreventStayMovementCreep(handler); if (fullStabilize) { StabilizeLayDownRigs(handler); } else { StabilizeMainBodyHorizontal(handler); } ApplyHorizontalLock(handler); SyncLastPosHorizontalOnly(handler); } } private static void SyncLastPosHorizontalOnly(DataHandler handler) { //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_0032: 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_004b: 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) if (!((Object)(object)handler?.mainRig == (Object)null) && HorizontalAnchorByHandler.TryGetValue(handler, out var value)) { Vector3 position = handler.mainRig.position; position.x = value.x; position.z = value.z; handler.lastPos = position; } } private static void StabilizeLayDownRigs(DataHandler handler) { StabilizeMainBodyHorizontal(handler); RigidbodyHolder allRigs = handler.allRigs; if (((allRigs != null) ? allRigs.AllRigs : null) == null) { return; } Rigidbody[] allRigs2 = handler.allRigs.AllRigs; foreach (Rigidbody val in allRigs2) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)handler.mainRig)) { StabilizeRigidbodyHorizontal(val); } } } private static void PreventStayMovementCreep(DataHandler handler) { //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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) if ((Object)(object)handler?.input != (Object)null) { handler.input.inputDirection = Vector3.zero; } if (!((Object)(object)handler == (Object)null)) { Vector3 currentVelocity = handler.currentVelocity; currentVelocity.x = 0f; currentVelocity.z = 0f; handler.currentVelocity = currentVelocity; } } private static void ApplyHorizontalLock(DataHandler handler) { //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_0043: 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_005c: 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_0064: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)handler == (Object)null) && !handler.Dead && HasHorizontalAnchor(handler)) { Rigidbody mainRig = handler.mainRig; if (!((Object)(object)mainRig == (Object)null) && HorizontalAnchorByHandler.TryGetValue(handler, out var value)) { Vector3 position = mainRig.position; position.x = value.x; position.z = value.z; mainRig.MovePosition(position); handler.lastPos = position; } } } private static bool IsRiderRelatedUnit(DataHandler handler) { if ((Object)(object)handler == (Object)null) { return false; } Unit unit = handler.unit; if ((Object)(object)unit != (Object)null && (unit.IsRider || unit.IsRiderWithLinkedMount)) { return true; } GameObject val = (((Object)(object)unit != (Object)null) ? ((Component)unit).gameObject : ((Component)handler).gameObject); if ((Object)(object)val == (Object)null) { return false; } RiderHolder[] componentsInParent = ((Component)handler).GetComponentsInParent(true); foreach (RiderHolder val2 in componentsInParent) { if (!HasActiveRiders(val2)) { continue; } for (int j = 0; j < val2.riders.Count; j++) { GameObject val3 = val2.riders[j]; if (!((Object)(object)val3 == (Object)null) && val3.activeInHierarchy && ((Object)(object)val3 == (Object)(object)val || val3.transform.IsChildOf(val.transform) || val.transform.IsChildOf(val3.transform))) { return true; } } } RiderHolder componentInChildren = ((Component)((Component)handler).transform.root).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null && HasActiveRiders(componentInChildren)) { return true; } return false; } private static bool HasActiveRiders(RiderHolder holder) { if (holder?.riders == null) { return false; } for (int i = 0; i < holder.riders.Count; i++) { if ((Object)(object)holder.riders[i] != (Object)null && holder.riders[i].activeInHierarchy) { return true; } } return false; } private static Weapon GetWeaponFromHoldable(Holdable holdable) { if ((Object)(object)holdable == (Object)null) { return null; } return ((Component)holdable).GetComponent() ?? ((Component)holdable).GetComponentInChildren(); } private static float GetEffectiveFireRange(Holdable holdable) { Weapon weaponFromHoldable = GetWeaponFromHoldable(holdable); if ((Object)(object)weaponFromHoldable == (Object)null) { return 0f; } return weaponFromHoldable.maxRange; } private static void StabilizeHoldableLinearOnly(DataHandler handler, Holdable holdable) { if (!((Object)(object)holdable?.rig == (Object)null) && (!IsLayDownStay(handler) || IsHoldableInFireRange(handler, holdable) || ShouldTrackTargetWithWeapon(handler, holdable)) && !ShouldTrackTargetWithWeapon(handler, holdable)) { StabilizeRigidbodyHorizontal(holdable.rig); } } private static Holdable GetHoldable(HoldingHandler holding, string fieldName) { object? obj = typeof(HoldingHandler).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(holding); return (Holdable)((obj is Holdable) ? obj : null); } private static bool IsUnderStayEffect(DataHandler handler) { return GetCachedDontMoveForRemaining(handler) > 0f; } private static float GetCachedDontMoveForRemaining(DataHandler handler) { if ((Object)(object)handler == (Object)null || DontMoveForField == null) { return 0f; } if (Time.frameCount != _dontMoveCacheFrame) { _dontMoveCacheFrame = Time.frameCount; DontMoveRemainingCache.Clear(); } if (DontMoveRemainingCache.TryGetValue(handler, out var value)) { return value; } value = GetDontMoveForRemaining(handler); DontMoveRemainingCache[handler] = value; return value; } private static float GetDontMoveForRemaining(DataHandler handler) { if ((Object)(object)handler == (Object)null || DontMoveForField == null) { return 0f; } object value = DontMoveForField.GetValue(handler); if (value is float) { return (float)value; } return 0f; } } internal enum StayFixMode { BannerAura, LayDown } internal static class StayPatches { public static void PoseHandler_PlayAnimation_Prefix(PoseHandler __instance, StaticAnimation animation, Vector3 pos, Quaternion rot) { if (StayFixLogic.IsLayDownPoseAnimation(animation)) { DataHandler poseHandlerData = GetPoseHandlerData(__instance); if (!((Object)(object)poseHandlerData == (Object)null) && !LayDownWeaponExclusions.ShouldBlockLayDownPose(poseHandlerData)) { float poseDurationSeconds = animation.startDelay + animation.time + 1f; StayFixLogic.BeginLayDownStay(poseHandlerData, 0f, poseDurationSeconds); } } } private static DataHandler GetPoseHandlerData(PoseHandler handler) { if (!((Object)(object)handler != (Object)null)) { return null; } return ((Component)((Component)handler).transform.root).GetComponentInChildren(); } public static void UnitDontWalkFor_Go_Prefix(UnitDontWalkFor __instance) { StayFixLogic.OnStayApplied(StayFixLogic.ResolveHandler(__instance), __instance); } public static void UnitDontWalkFor_Go_Postfix(UnitDontWalkFor __instance) { StayFixLogic.OnStayApplied(StayFixLogic.ResolveHandler(__instance), __instance); } public static void DataHandler_DontWalkFor_Prefix(DataHandler __instance, float time) { StayFixLogic.OnStayApplied(__instance, time); } public static void DataHandler_DontWalkFor_Postfix(DataHandler __instance, float time) { StayFixLogic.OnStayApplied(__instance, time); } public static void DataHandler_BatchedUpdate_Prefix(DataHandler __instance) { if (StayFixLogic.BeginStayFrameWork(__instance)) { StayFixLogic.PrepareStayFrame(__instance); } } public static void DataHandler_BatchedUpdate_Postfix(DataHandler __instance) { if (StayFixLogic.ContinueStayFrameWork(__instance)) { StayFixLogic.TickStayLight(__instance); } } public static void DataHandler_BatchedFixedUpdate_Postfix(DataHandler __instance) { if (StayFixLogic.BeginStayFixedWork(__instance)) { StayFixLogic.TickStay(__instance); } } public static void DataHandler_Dead_Setter_Postfix(DataHandler __instance) { if (__instance.Dead) { StayFixLogic.OnUnitDied(__instance); BarrelRollerDeathLogic.EnsureScheduledFromDead(__instance); } } } internal static class StayPhysicsPatches { public static void Rigidbody_MovePosition_Prefix(Rigidbody __instance, ref Vector3 position) { StayFixLogic.TryClampBodyMovePosition(__instance, ref position); } } internal static class UnitEditorContentScroll { internal enum ScrollMode { InnerContainer, DirectContentY } internal sealed class Config { internal string InnerContainerName; internal string ClipViewportName; internal string NavCoverName; internal Func IsScrollRow; internal Action ConfigureInnerLayout; internal bool PreserveWorldPositionOnReparent; internal ScrollMode Mode; internal float BottomSlack = 85f; } internal sealed class UnitEditorContentScroller : MonoBehaviour { private Config _config; private RectTransform _viewport; private RectTransform _scrollContent; private Transform _pageRoot; private float _scrollOffset; private float _maxScroll; private Vector2 _vanillaAnchoredPosition; private bool _useDirectContentY; internal bool Configure(RectTransform viewport, Transform pageRoot, Config config) { _viewport = viewport; _pageRoot = pageRoot; _config = config; _useDirectContentY = config != null && config.Mode == ScrollMode.DirectContentY; if (_useDirectContentY) { _scrollContent = viewport; ApplyVanillaAnchoredPosition(viewport); } else { _scrollContent = EnsureInnerContainer(viewport, config); } _scrollOffset = 0f; ApplyScrollOffset(); if (ShouldRollback(_scrollContent, config)) { return false; } ForceLayoutChain(_viewport); if (!_useDirectContentY) { ForceLayoutChain(_scrollContent); } RefreshMetrics(); return true; } private void ApplyVanillaAnchoredPosition(RectTransform viewport) { //IL_0027: 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_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)viewport == (Object)null)) { int instanceID = ((Object)viewport).GetInstanceID(); if (!VanillaAnchoredPositions.TryGetValue(instanceID, out _vanillaAnchoredPosition)) { _vanillaAnchoredPosition = viewport.anchoredPosition; VanillaAnchoredPositions[instanceID] = _vanillaAnchoredPosition; } } } internal void HardResetToTop() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) _scrollOffset = 0f; if (_useDirectContentY && (Object)(object)_viewport != (Object)null) { int instanceID = ((Object)_viewport).GetInstanceID(); if (VanillaAnchoredPositions.TryGetValue(instanceID, out _vanillaAnchoredPosition)) { _viewport.anchoredPosition = _vanillaAnchoredPosition; } } ApplyScrollOffset(); RefreshMetrics(); } internal void ResetScrollOffset() { _scrollOffset = 0f; ApplyScrollOffset(); } internal void RefreshScrollMetrics() { RefreshMetrics(); } internal bool IsConfiguredFor(Config config) { if (_config == null || config == null) { return false; } if (_config.Mode == config.Mode && string.Equals(_config.InnerContainerName, config.InnerContainerName, StringComparison.Ordinal)) { return (object)_config.IsScrollRow == config.IsScrollRow; } return false; } private void OnEnable() { if ((Object)(object)_scrollContent != (Object)null) { _scrollOffset = 0f; ApplyScrollOffset(); } } private void Update() { //IL_0016: 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_004d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_scrollContent == (Object)null) && _config != null && Input.mouseScrollDelta.y != 0f && IsPointerOverScrollArea(_viewport, _scrollContent, _config, Vector2.op_Implicit(Input.mousePosition))) { ScrollBy((0f - Input.mouseScrollDelta.y) * 90f); } } private void RefreshMetrics() { if (!((Object)(object)_viewport == (Object)null) && !((Object)(object)_scrollContent == (Object)null) && _config != null) { SyncScrollOffsetFromAppliedPosition(); ForceLayoutChain(_viewport); if (!_useDirectContentY) { ForceLayoutChain(_scrollContent); } if (TryMeasureRowBounds(_scrollContent, _config, out var highestTop, out var lowestBottom)) { float contentExtent = Mathf.Max(0f, highestTop - lowestBottom); float viewportHeight = ResolveScrollViewportHeight(_viewport, _pageRoot); float bottomClearance = ComputeBottomObstructionInset(_viewport, _pageRoot); float bottomSlack = ((_config.BottomSlack > 0f) ? _config.BottomSlack : 85f); _maxScroll = ComputeMaxScroll(viewportHeight, contentExtent, bottomClearance, bottomSlack); _scrollOffset = Mathf.Clamp(_scrollOffset, 0f, _maxScroll); ApplyScrollOffset(); } } } private void SyncScrollOffsetFromAppliedPosition() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (_useDirectContentY && (Object)(object)_viewport != (Object)null) { _scrollOffset = _viewport.anchoredPosition.y - _vanillaAnchoredPosition.y; } else if ((Object)(object)_scrollContent != (Object)null) { _scrollOffset = _scrollContent.anchoredPosition.y; } if (_scrollOffset < 0f) { _scrollOffset = 0f; } } private void ApplyScrollOffset() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_scrollContent == (Object)null)) { _scrollOffset = Mathf.Clamp(_scrollOffset, 0f, Mathf.Max(0f, _maxScroll)); if (_useDirectContentY && (Object)(object)_viewport != (Object)null) { Vector2 vanillaAnchoredPosition = _vanillaAnchoredPosition; vanillaAnchoredPosition.y += _scrollOffset; _viewport.anchoredPosition = vanillaAnchoredPosition; } else { Vector2 anchoredPosition = _scrollContent.anchoredPosition; anchoredPosition.x = 0f; anchoredPosition.y = _scrollOffset; _scrollContent.anchoredPosition = anchoredPosition; } } } private void ScrollBy(float delta) { SyncScrollOffsetFromAppliedPosition(); if (_maxScroll <= 0.5f) { RefreshMetrics(); } if (!(_maxScroll <= 0.5f)) { _scrollOffset = Mathf.Clamp(_scrollOffset + delta, 0f, _maxScroll); ApplyScrollOffset(); } } private static RectTransform EnsureInnerContainer(RectTransform content, Config config) { //IL_0037: 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_006a: 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_008a: 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_00cd: 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) Transform obj = ((Transform)content).Find(config.InnerContainerName); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if ((Object)(object)val == (Object)null) { val = new GameObject(config.InnerContainerName, new Type[1] { typeof(RectTransform) }).GetComponent(); ((Transform)val).SetParent((Transform)(object)content, false); val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(1f, 1f); val.pivot = new Vector2(0f, 1f); val.anchoredPosition = Vector2.zero; val.sizeDelta = Vector2.zero; } AlignInnerContainerTopLeft(val); ReparentScrollChildren(content, val, config); config.ConfigureInnerLayout?.Invoke(content, val); AlignInnerContainerTopLeft(val); val.anchoredPosition = new Vector2(0f, val.anchoredPosition.y); return val; } private static void ReparentScrollChildren(RectTransform from, RectTransform inner, Config config) { ReparentPreservingOrder((Transform)(object)from, (Transform)(object)inner, (Transform child) => (Object)(object)child != (Object)(object)inner && (Object)(object)((Component)child).GetComponent() == (Object)null && ((Object)child).name != config.ClipViewportName && ((Object)child).name != config.NavCoverName && ((Object)child).name != config.InnerContainerName, config.PreserveWorldPositionOnReparent); } private static bool ShouldRollback(RectTransform scrollContent, Config config) { if ((Object)(object)scrollContent == (Object)null || config == null || config.IsScrollRow == null) { return true; } if (((Transform)scrollContent).childCount <= 0) { return true; } return CountRows(scrollContent, config) <= 0; } private static int CountRows(RectTransform scrollContent, Config config) { int num = 0; for (int i = 0; i < ((Transform)scrollContent).childCount; i++) { if (config.IsScrollRow(((Transform)scrollContent).GetChild(i))) { num++; } } return num; } private static bool TryMeasureRowBounds(RectTransform scrollContent, Config config, out float highestTop, out float lowestBottom) { //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_0084: 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) highestTop = float.NegativeInfinity; lowestBottom = float.PositiveInfinity; int num = 0; if ((Object)(object)scrollContent == (Object)null || config == null || config.IsScrollRow == null) { return false; } LayoutRebuilder.ForceRebuildLayoutImmediate(scrollContent); for (int i = 0; i < ((Transform)scrollContent).childCount; i++) { Transform child = ((Transform)scrollContent).GetChild(i); RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null); if (val != null && ((Component)val).gameObject.activeInHierarchy && config.IsScrollRow((Transform)(object)val)) { num++; Vector3[] array = (Vector3[])(object)new Vector3[4]; val.GetWorldCorners(array); float y = ((Transform)scrollContent).InverseTransformPoint(array[1]).y; float y2 = ((Transform)scrollContent).InverseTransformPoint(array[0]).y; if (y > highestTop) { highestTop = y; } if (y2 < lowestBottom) { lowestBottom = y2; } } } return num > 0; } private static bool IsPointerOverScrollArea(RectTransform viewport, RectTransform scrollContent, Config config, Vector2 screenPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (ContainsScreenPoint(viewport, screenPosition)) { return true; } if ((Object)(object)scrollContent == (Object)null || config == null || config.IsScrollRow == null) { return false; } for (int i = 0; i < ((Transform)scrollContent).childCount; i++) { Transform child = ((Transform)scrollContent).GetChild(i); RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null); if (val != null && ((Component)val).gameObject.activeInHierarchy && config.IsScrollRow((Transform)(object)val) && ContainsScreenPoint(val, screenPosition)) { return true; } } return false; } private static bool ContainsScreenPoint(RectTransform rect, Vector2 screenPosition) { //IL_000c: 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) if ((Object)(object)rect == (Object)null) { return false; } if (RectTransformUtility.RectangleContainsScreenPoint(rect, screenPosition, (Camera)null)) { return true; } Canvas componentInParent = ((Component)rect).GetComponentInParent(); Camera val = (((Object)(object)componentInParent != (Object)null) ? componentInParent.worldCamera : null); if ((Object)(object)val != (Object)null && RectTransformUtility.RectangleContainsScreenPoint(rect, screenPosition, val)) { return true; } return false; } private static float GetRectTopY(RectTransform rect) { Vector3[] array = (Vector3[])(object)new Vector3[4]; rect.GetWorldCorners(array); return array[1].y; } private static float GetRectBottomY(RectTransform rect) { Vector3[] array = (Vector3[])(object)new Vector3[4]; rect.GetWorldCorners(array); return array[0].y; } private static float GetWorldRectHeight(RectTransform rect) { if ((Object)(object)rect == (Object)null) { return 0f; } Vector3[] array = (Vector3[])(object)new Vector3[4]; rect.GetWorldCorners(array); return Mathf.Abs(array[1].y - array[0].y); } private static float ResolveRectHeight(RectTransform rect) { //IL_0021: 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) if ((Object)(object)rect == (Object)null) { return 0f; } float worldRectHeight = GetWorldRectHeight(rect); if (worldRectHeight >= 1f) { return worldRectHeight; } Rect rect2 = rect.rect; return ((Rect)(ref rect2)).height; } private static float ResolveScreenVisibleHeight() { return Mathf.Max(100f, (float)Screen.height - 90f - 100f); } private static float ResolveScrollViewportHeight(RectTransform viewport, Transform pageRoot) { if ((Object)(object)viewport == (Object)null) { return ResolveScreenVisibleHeight(); } ForceLayoutChain(viewport); float num = ResolveRectHeight(viewport); if (num >= 100f) { return num; } Transform parent = ((Transform)viewport).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)pageRoot) { num = ResolveRectHeight(val); if (num >= 100f) { return num; } Transform parent2 = ((Transform)val).parent; val = (RectTransform)(object)((parent2 is RectTransform) ? parent2 : null); } return ResolveScreenVisibleHeight(); } private static float ComputeBottomObstructionInset(RectTransform viewport, Transform pageRoot) { RectTransform val = (RectTransform)(object)((pageRoot is RectTransform) ? pageRoot : null); if (val == null) { return 100f; } float rectBottomY = GetRectBottomY(val); float bestClearance = 100f; ConsiderBottomUi(val, viewport, rectBottomY, ref bestClearance); Transform parent = ((Transform)val).parent; RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null); if (val2 != null) { ConsiderBottomUi(val2, viewport, rectBottomY, ref bestClearance); } return bestClearance + 50f; } private static void ConsiderBottomUi(RectTransform root, RectTransform viewport, float pageBottom, ref float bestClearance) { for (int i = 0; i < ((Transform)root).childCount; i++) { Transform child = ((Transform)root).GetChild(i); RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null); if (val == null || !((Component)val).gameObject.activeInHierarchy || ((Object)(object)viewport != (Object)null && ((Object)(object)val == (Object)(object)viewport || ((Transform)val).IsChildOf((Transform)(object)viewport)))) { continue; } float rectBottomY = GetRectBottomY(val); float rectTopY = GetRectTopY(val); if (rectTopY - rectBottomY >= 30f && rectBottomY <= pageBottom + 30f) { float num = rectTopY - pageBottom + 48f; if (num > bestClearance && num < 250f) { bestClearance = num; } } ConsiderBottomUi(val, viewport, pageBottom, ref bestClearance); } } private static float ComputeMaxScroll(float viewportHeight, float contentExtent, float bottomClearance, float bottomSlack) { float num = Mathf.Max(100f, viewportHeight - bottomClearance); return Mathf.Max(0f, contentExtent - num + bottomSlack); } } internal const float DefaultNavTopInset = 90f; internal const float DefaultBottomInset = 100f; internal const float MinScrollViewportHeight = 100f; internal const float ScrollBottomSlack = 85f; internal const float BottomUiMargin = 48f; internal const float ExtraBottomScrollLift = 50f; internal const float WheelScrollPixels = 90f; internal const string BaseScrollInnerName = "BaseScrollInner"; internal const string StatsScrollInnerName = "StatsScrollInner"; internal const string BaseClipViewportName = "BaseClipViewport"; internal const string StatsClipViewportName = "StatsClipViewport"; internal const string BaseNavCoverName = "BaseNavCover"; internal const string StatsNavCoverName = "StatsNavCover"; private static readonly Dictionary VanillaAnchoredPositions = new Dictionary(); internal static void StripInnerLayoutComponents(RectTransform inner) { if (!((Object)(object)inner == (Object)null)) { VerticalLayoutGroup component = ((Component)inner).GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } ContentSizeFitter component2 = ((Component)inner).GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } } internal static void EnsureInnerFillsViewportWidth(RectTransform viewport, RectTransform inner) { //IL_0042: 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) if (!((Object)(object)viewport == (Object)null) && !((Object)(object)inner == (Object)null)) { ForceLayoutChain(viewport); LayoutElement val = ((Component)inner).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)inner).gameObject.AddComponent(); } val.flexibleWidth = 1f; LayoutElement obj = val; Rect rect = viewport.rect; obj.minWidth = Mathf.Max(((Rect)(ref rect)).width, 100f); } } internal static void ForceViewportChildAlignmentUpperLeft(RectTransform viewport) { if (!((Object)(object)viewport == (Object)null)) { VerticalLayoutGroup component = ((Component)viewport).GetComponent(); if ((Object)(object)component != (Object)null) { ForceChildAlignmentUpperLeft((HorizontalOrVerticalLayoutGroup)(object)component); } } } private static void ForceChildAlignmentUpperLeft(HorizontalOrVerticalLayoutGroup layoutGroup) { if (!((Object)(object)layoutGroup == (Object)null)) { PropertyInfo property = typeof(HorizontalOrVerticalLayoutGroup).GetProperty("childAlignment", BindingFlags.Instance | BindingFlags.Public); if (!(property == null)) { object value = Enum.ToObject(property.PropertyType, 0); property.SetValue(layoutGroup, value); } } } internal static void CopyVerticalLayoutGroup(RectTransform source, RectTransform dest) { if ((Object)(object)source == (Object)null || (Object)(object)dest == (Object)null) { return; } VerticalLayoutGroup component = ((Component)source).GetComponent(); if (!((Object)(object)component == (Object)null)) { VerticalLayoutGroup val = ((Component)dest).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)dest).gameObject.AddComponent(); } ((LayoutGroup)val).padding = ((LayoutGroup)component).padding; ((HorizontalOrVerticalLayoutGroup)val).spacing = ((HorizontalOrVerticalLayoutGroup)component).spacing; ((HorizontalOrVerticalLayoutGroup)val).childControlWidth = ((HorizontalOrVerticalLayoutGroup)component).childControlWidth; ((HorizontalOrVerticalLayoutGroup)val).childControlHeight = ((HorizontalOrVerticalLayoutGroup)component).childControlHeight; ((HorizontalOrVerticalLayoutGroup)val).childForceExpandWidth = ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth; ((HorizontalOrVerticalLayoutGroup)val).childForceExpandHeight = ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight; CopyChildAlignment((HorizontalOrVerticalLayoutGroup)(object)component, (HorizontalOrVerticalLayoutGroup)(object)val); if ((Object)(object)((Component)dest).GetComponent() == (Object)null) { ContentSizeFitter obj = ((Component)dest).gameObject.AddComponent(); obj.horizontalFit = (FitMode)0; obj.verticalFit = (FitMode)2; } } } internal static void AlignInnerContainerTopLeft(RectTransform inner) { //IL_0015: 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_003f: 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_0055: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)inner == (Object)null)) { inner.anchorMin = new Vector2(0f, 1f); inner.anchorMax = new Vector2(1f, 1f); inner.pivot = new Vector2(0f, 1f); inner.anchoredPosition = Vector2.zero; inner.sizeDelta = Vector2.zero; inner.offsetMin = new Vector2(0f, inner.offsetMin.y); inner.offsetMax = new Vector2(0f, inner.offsetMax.y); } } private static void CopyChildAlignment(HorizontalOrVerticalLayoutGroup source, HorizontalOrVerticalLayoutGroup dest) { if (!((Object)(object)source == (Object)null) && !((Object)(object)dest == (Object)null)) { PropertyInfo property = typeof(HorizontalOrVerticalLayoutGroup).GetProperty("childAlignment", BindingFlags.Instance | BindingFlags.Public); if (!(property == null)) { property.SetValue(dest, property.GetValue(source)); } } } internal static bool EnsureSetup(RectTransform content, Transform pageRoot, Config config, string logPrefix) { if ((Object)(object)content == (Object)null || config == null || config.IsScrollRow == null) { return false; } if (((Transform)content).childCount <= 0) { return false; } try { CleanupLegacyScrollArtifacts(pageRoot, content, config); UnitEditorContentScroller unitEditorContentScroller = ((Component)content).GetComponent(); if ((Object)(object)unitEditorContentScroller == (Object)null) { unitEditorContentScroller = ((Component)content).gameObject.AddComponent(); } if (!unitEditorContentScroller.Configure(content, pageRoot, config)) { RollbackToVanillaLayout(content, config); return false; } return true; } catch (Exception ex) { Plugin.LogWarning(logPrefix + ": EnsureSetup failed: " + ex.Message); return false; } } internal static void CleanupLegacyScrollArtifacts(Transform pageRoot, RectTransform contentParent, Config config) { if (!((Object)(object)contentParent == (Object)null) && config != null) { RectMask2D component = ((Component)contentParent).GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } DestroyLegacyDirectScrollComponents(contentParent); DestroyNamedChild((Transform)(object)contentParent, config.NavCoverName); if ((Object)(object)pageRoot != (Object)null) { DestroyNamedChild(pageRoot, config.NavCoverName); } UnitEditorUIManager val = ((pageRoot != null) ? ((Component)pageRoot).GetComponentInParent() : null); if ((Object)(object)val != (Object)null) { DestroyNamedChild(((Component)val).transform, config.NavCoverName); } if ((Object)(object)((Transform)contentParent).parent != (Object)null && ((Object)((Transform)contentParent).parent).name == config.ClipViewportName) { UnwrapLegacyContainer(((Transform)contentParent).parent); } Transform val2 = ((Transform)contentParent).Find(config.ClipViewportName); if ((Object)(object)val2 != (Object)null) { UnwrapLegacyContainer(val2); } UnwrapInnerContainer(contentParent, config); } } private static void UnwrapInnerContainer(RectTransform contentParent, Config config) { if ((Object)(object)contentParent == (Object)null || config == null || string.IsNullOrEmpty(config.InnerContainerName)) { return; } Transform val = ((Transform)contentParent).Find(config.InnerContainerName); if (!((Object)(object)val == (Object)null)) { ReparentPreservingOrder(val, (Transform)(object)contentParent, (Transform _) => true); Object.Destroy((Object)(object)((Component)val).gameObject); } } internal static void RollbackToVanillaLayout(RectTransform contentParent, Config config) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)contentParent == (Object)null || config == null) { return; } RectMask2D component = ((Component)contentParent).GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } DestroyLegacyDirectScrollComponents(contentParent); Transform parent = ((Transform)contentParent).parent; if ((Object)(object)parent != (Object)null && ((Object)parent).name == config.ClipViewportName) { UnwrapLegacyContainer(parent); } UnwrapInnerContainer(contentParent, config); if (config.Mode == ScrollMode.DirectContentY) { int instanceID = ((Object)contentParent).GetInstanceID(); if (VanillaAnchoredPositions.TryGetValue(instanceID, out var value)) { contentParent.anchoredPosition = value; } VanillaAnchoredPositions.Remove(instanceID); } else { Transform val = ((Transform)contentParent).Find(config.InnerContainerName); if ((Object)(object)val != (Object)null) { ReparentPreservingOrder(val, (Transform)(object)contentParent, (Transform _) => true); Object.Destroy((Object)(object)((Component)val).gameObject); } } UnitEditorContentScroller component2 = ((Component)contentParent).GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } internal static void ResetScrollState(RectTransform content, Config config) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)content == (Object)null || config == null) { return; } if (config.Mode == ScrollMode.DirectContentY) { int instanceID = ((Object)content).GetInstanceID(); if (VanillaAnchoredPositions.TryGetValue(instanceID, out var value)) { content.anchoredPosition = value; } } ((Component)content).GetComponent()?.HardResetToTop(); } internal static void ClearVanillaAnchoredPosition(RectTransform content) { if (!((Object)(object)content == (Object)null)) { VanillaAnchoredPositions.Remove(((Object)content).GetInstanceID()); } } internal static void SetVanillaAnchoredPosition(RectTransform content, Vector2 position) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)content == (Object)null)) { VanillaAnchoredPositions[((Object)content).GetInstanceID()] = position; } } internal static bool TryFastReopen(RectTransform content, Config config) { if ((Object)(object)content == (Object)null || config == null) { return false; } UnitEditorContentScroller component = ((Component)content).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsConfiguredFor(config)) { return false; } component.HardResetToTop(); return true; } internal static RectTransform ResolveContentRect(Transform contentParent) { if ((Object)(object)contentParent == (Object)null) { return null; } RectTransform val = (RectTransform)(object)((contentParent is RectTransform) ? contentParent : null); if (val != null) { return val; } return ((Component)contentParent).GetComponent(); } internal static void ForceLayoutChain(RectTransform root) { Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate(root); Transform parent = ((Transform)root).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(val); } } internal static void PrepareSharedViewport(RectTransform content) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)content == (Object)null)) { UnitEditorContentScroller component = ((Component)content).GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } RectMask2D component2 = ((Component)content).GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } DestroyLegacyDirectScrollComponents(content); if ((Object)(object)((Transform)content).parent != (Object)null && ((Object)((Transform)content).parent).name == "BaseClipViewport") { UnwrapLegacyContainer(((Transform)content).parent); } if ((Object)(object)((Transform)content).parent != (Object)null && ((Object)((Transform)content).parent).name == "StatsClipViewport") { UnwrapLegacyContainer(((Transform)content).parent); } Transform val = ((Transform)content).Find("BaseClipViewport"); if ((Object)(object)val != (Object)null) { UnwrapLegacyContainer(val); } Transform val2 = ((Transform)content).Find("StatsClipViewport"); if ((Object)(object)val2 != (Object)null) { UnwrapLegacyContainer(val2); } DestroyNamedChild((Transform)(object)content, "BaseNavCover"); DestroyNamedChild((Transform)(object)content, "StatsNavCover"); UnwrapNamedInner(content, "BaseScrollInner"); UnwrapNamedInner(content, "StatsScrollInner"); int instanceID = ((Object)content).GetInstanceID(); if (VanillaAnchoredPositions.TryGetValue(instanceID, out var value)) { content.anchoredPosition = value; } ForceLayoutChain(content); } } private static void UnwrapNamedInner(RectTransform contentParent, string innerName) { if ((Object)(object)contentParent == (Object)null || string.IsNullOrEmpty(innerName)) { return; } Transform val = ((Transform)contentParent).Find(innerName); if (!((Object)(object)val == (Object)null)) { ReparentPreservingOrder(val, (Transform)(object)contentParent, (Transform _) => true); Object.Destroy((Object)(object)((Component)val).gameObject); } } private static void DestroyLegacyDirectScrollComponents(RectTransform contentParent) { if ((Object)(object)contentParent == (Object)null) { return; } MonoBehaviour[] components = ((Component)contentParent).GetComponents(); foreach (MonoBehaviour val in components) { if (!((Object)(object)val == (Object)null) && ((object)val).GetType().Name == "UnitEditorBaseContentScroller") { Object.Destroy((Object)(object)val); } } } private static void DestroyNamedChild(Transform parent, string name) { if (!((Object)(object)parent == (Object)null) && !string.IsNullOrEmpty(name)) { Transform val = parent.Find(name); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } private static void ReparentPreservingOrder(Transform from, Transform to, Func shouldMove, bool preserveWorldPosition = false) { List list = new List(); for (int i = 0; i < from.childCount; i++) { Transform child = from.GetChild(i); if (shouldMove == null || shouldMove(child)) { list.Add(child); } } for (int j = 0; j < list.Count; j++) { list[j].SetParent(to, preserveWorldPosition); list[j].SetSiblingIndex(j); } } private static void UnwrapLegacyContainer(Transform clip) { if (!((Object)(object)((clip != null) ? clip.parent : null) == (Object)null)) { ReparentPreservingOrder(clip, clip.parent, (Transform _) => true); Object.Destroy((Object)(object)((Component)clip).gameObject); } } } internal static class UnitEditorCustomStats { private sealed class CustomStatDef { internal readonly UnitStat UnitStat; internal readonly string Name; internal readonly string Description; internal readonly float MinValue; private readonly Func _readUiFromBlueprint; private readonly Action _writeBlueprintFromUi; internal CustomStatDef(UnitStat unitStat, string name, string description, Func readUiFromBlueprint, Action writeBlueprintFromUi, float minValue = 0f) { //IL_0007: 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) UnitStat = unitStat; Name = name; Description = description; MinValue = minValue; _readUiFromBlueprint = readUiFromBlueprint; _writeBlueprintFromUi = writeBlueprintFromUi; } internal float ReadUiFromBlueprint(UnitBlueprint blueprint) { return _readUiFromBlueprint(blueprint); } internal void WriteBlueprintFromUi(UnitBlueprint blueprint, float uiValue) { _writeBlueprintFromUi(blueprint, uiValue); } } internal static readonly UnitStat TargetPriorityMultiplier = (UnitStat)6; internal static readonly UnitStat AnimationMultiplier = (UnitStat)7; internal static readonly UnitStat StepMultiplier = (UnitStat)8; internal static readonly UnitStat TurnSpeedMultiplier = (UnitStat)9; private const float CustomTurnSpeedBaseline = 100f; private static readonly FieldInfo LoadedUnitField = AccessTools.Field(typeof(UnitEditorManager), "loadedUnit"); private static readonly FieldInfo StatCellStatField = AccessTools.Field(typeof(UnitEditorStatCell), "stat"); private static readonly FieldInfo StatCellValueField = AccessTools.Field(typeof(UnitEditorStatCell), "value"); private static readonly FieldInfo StatCellInputField = AccessTools.Field(typeof(UnitEditorStatCell), "m_InputField"); private static readonly PropertyInfo TmpInputTextProperty = AccessTools.Property(AccessTools.TypeByName("TMPro.TMP_InputField"), "text"); private static readonly CustomStatDef[] Definitions = new CustomStatDef[4] { new CustomStatDef(TargetPriorityMultiplier, "Target Priority", "HOW MUCH ENEMIES WILL TARGET THIS UNIT OVER OTHER UNITS.", (UnitBlueprint bp) => BlueprintToUi(bp.targetingPriorityMultiplier), delegate(UnitBlueprint bp, float ui) { bp.targetingPriorityMultiplier = UiToBlueprint(ui); }), new CustomStatDef(AnimationMultiplier, "Animation Speed", "HOW FAST THE UNIT'S MOVEMENT ANIMATIONS PLAY.", (UnitBlueprint bp) => bp.animationMultiplier, delegate(UnitBlueprint bp, float ui) { bp.animationMultiplier = ui; }), new CustomStatDef(StepMultiplier, "Step Frequency", "HOW OFTEN THE UNIT TAKES STEPS WHILE WALKING.", (UnitBlueprint bp) => bp.stepMultiplier, delegate(UnitBlueprint bp, float ui) { bp.stepMultiplier = ui; }), new CustomStatDef(TurnSpeedMultiplier, "Turn Speed", "HOW FAST THE UNIT TURNS TO FACE TARGETS AND MOVEMENT.", ReadTurnSpeedUi, WriteTurnSpeedUi, 0.1f) }; private static bool _isLoadingUnit; internal static float BlueprintToUi(float stored) { if (float.IsNaN(stored)) { return 0f; } if (stored == 0f) { return 1f; } return stored; } internal static float UiToBlueprint(float ui) { if (Mathf.Approximately(ui, 0f)) { return float.NaN; } if (Mathf.Approximately(ui, 1f)) { return 0f; } return ui; } internal static string FormatUiMultiplier(float ui) { return ui.ToString("F2") + "x"; } private static float GetEffectiveTurnSpeed(UnitBlueprint blueprint) { if ((Object)(object)blueprint == (Object)null) { return 100f; } if ((Object)(object)blueprint.turningData != (Object)null) { return blueprint.turningData.TurnSpeed; } if (!(blueprint.turnSpeed > 0f)) { return 100f; } return blueprint.turnSpeed; } private static float ReadTurnSpeedUi(UnitBlueprint blueprint) { return GetEffectiveTurnSpeed(blueprint) / 100f; } private static void WriteTurnSpeedUi(UnitBlueprint blueprint, float ui) { if (!((Object)(object)blueprint == (Object)null)) { blueprint.turningData = null; blueprint.turnSpeed = ui * 100f; } } internal static void EnsureStatsInjected(UnitEditorManager manager) { //IL_0029: 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_003d: 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_0055: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown if (!UnitEditorStatsConfig.Enabled || manager?.Stats == null) { return; } CustomStatDef[] definitions = Definitions; foreach (CustomStatDef customStatDef in definitions) { if (!HasStat(manager, customStatDef.UnitStat)) { StatsWrapper val = new StatsWrapper { name = customStatDef.Name, description = customStatDef.Description, unitStat = customStatDef.UnitStat, defaultValue = 1f, minValue = customStatDef.MinValue, maxValue = 100f, statsMode = (StatMode)1 }; StatsWrapper[] stats = manager.Stats; StatsWrapper[] array = (StatsWrapper[])(object)new StatsWrapper[stats.Length + 1]; for (int j = 0; j < stats.Length; j++) { array[j] = stats[j]; } array[stats.Length] = val; manager.Stats = array; } } } private static bool HasStat(UnitEditorManager manager, UnitStat unitStat) { //IL_000c: 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) for (int i = 0; i < manager.Stats.Length; i++) { if (manager.Stats[i].unitStat == unitStat) { return true; } } return false; } private static CustomStatDef FindDefinition(UnitStat unitStat) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < Definitions.Length; i++) { if (Definitions[i].UnitStat == unitStat) { return Definitions[i]; } } return null; } private static UnitBlueprint GetLoadedUnit(UnitEditorManager manager) { object? obj = LoadedUnitField?.GetValue(manager); return (UnitBlueprint)((obj is UnitBlueprint) ? obj : null); } private static void SyncStatsFromBlueprint(UnitEditorManager manager, UnitBlueprint blueprint) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)manager == (Object)null) && !((Object)(object)blueprint == (Object)null)) { for (int i = 0; i < Definitions.Length; i++) { CustomStatDef customStatDef = Definitions[i]; manager.SetStatValue(customStatDef.UnitStat, customStatDef.ReadUiFromBlueprint(blueprint)); } } } private static void SetInputFieldText(UnitEditorStatCell cell, string text) { object obj = StatCellInputField?.GetValue(cell); if (obj != null && !(TmpInputTextProperty == null)) { TmpInputTextProperty.SetValue(obj, text, null); } } public static void Awake_Prefix(UnitEditorManager __instance) { if (UnitEditorStatsConfig.Enabled) { EnsureStatsInjected(__instance); } } public static void UIManager_Start_Prefix(UnitEditorUIManager __instance) { if (UnitEditorStatsConfig.Enabled) { UnitEditorManager val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { EnsureStatsInjected(val); } } } public static void SetStats_Postfix(UnitEditorManager __instance, UnitBlueprint blueprint) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (UnitEditorStatsConfig.Enabled && !((Object)(object)blueprint == (Object)null) && !((Object)(object)__instance == (Object)null)) { for (int i = 0; i < Definitions.Length; i++) { CustomStatDef customStatDef = Definitions[i]; customStatDef.WriteBlueprintFromUi(blueprint, __instance.GetStatValue(customStatDef.UnitStat)); } } } public static void LoadUnit_Prefix(UnitEditorManager __instance) { if (UnitEditorStatsConfig.Enabled) { _isLoadingUnit = true; EnsureStatsInjected(__instance); } } public static void LoadUnit_Postfix(UnitEditorManager __instance, UnitBlueprint blueprint) { if (!UnitEditorStatsConfig.Enabled) { _isLoadingUnit = false; return; } if ((Object)(object)__instance != (Object)null && (Object)(object)blueprint != (Object)null) { SyncStatsFromBlueprint(__instance, blueprint); UnitEditorUIManager uIManager = __instance.UIManager; if (uIManager != null) { uIManager.UpdateStatUI(); } } _isLoadingUnit = false; } public static void SwitchUnitBase_Prefix(UnitEditorManager __instance) { if (UnitEditorStatsConfig.Enabled && _isLoadingUnit) { UnitBlueprint loadedUnit = GetLoadedUnit(__instance); if (!((Object)(object)loadedUnit == (Object)null)) { SyncStatsFromBlueprint(__instance, loadedUnit); } } } public static void StatCell_Init_Postfix(UnitEditorStatCell __instance, StatsWrapper stat) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!UnitEditorStatsConfig.Enabled) { return; } CustomStatDef customStatDef = FindDefinition((UnitStat)((stat != null) ? ((int)stat.unitStat) : 0)); if (customStatDef != null) { stat.minValue = customStatDef.MinValue; if ((Object)(object)__instance.m_NameText != (Object)null) { __instance.m_NameText.Localized = false; __instance.m_NameText.LocaleID = customStatDef.Name; } if ((Object)(object)__instance.m_DescriptionText != (Object)null) { __instance.m_DescriptionText.Localized = false; __instance.m_DescriptionText.LocaleID = customStatDef.Description; } } } public static void StatCell_UpdateValue_Postfix(UnitEditorStatCell __instance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!UnitEditorStatsConfig.Enabled) { return; } object? obj = StatCellStatField?.GetValue(__instance); StatsWrapper val = (StatsWrapper)((obj is StatsWrapper) ? obj : null); if (val != null && val.unitStat == TargetPriorityMultiplier && StatCellInputField?.GetValue(__instance) != null) { float num = ((StatCellValueField != null) ? ((float)StatCellValueField.GetValue(__instance)) : val.CurrentValue); if (float.IsNaN(num)) { num = 0f; } SetInputFieldText(__instance, FormatUiMultiplier(num)); } } } internal static class UnitEditorStatsConfig { internal static bool Enabled = true; internal static void Bind(ConfigFile config) { Enabled = config.Bind("UnitEditor", "CustomStatsAndScroll", true, "Enable unit editor custom stats (Target Priority, Animation Speed, Step Frequency) and STATS tab scroll. Set false for vanilla unit editor stats behavior.").Value; } } internal static class UnitEditorStatsScroll { [CompilerGenerated] private sealed class d__7 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public UnitEditorStatsPageUI statsPage; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown RectTransform val; switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)statsPage?.contentParent == (Object)null) { _setupCoroutine = null; return false; } val = UnitEditorContentScroll.ResolveContentRect(statsPage.contentParent); if ((Object)(object)val == (Object)null) { Plugin.LogWarning("StatsScroll: contentParent has no RectTransform; skipping scroll wrapper"); _setupCoroutine = null; return false; } if (UnitEditorContentScroll.TryFastReopen(val, ScrollConfig)) { _setupCoroutine = null; return false; } 5__2 = 0; break; case 2: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 3; return true; case 3: <>1__state = -1; 5__2++; break; } if (5__2 < 12) { if ((Object)(object)statsPage == (Object)null || (Object)(object)statsPage.contentParent == (Object)null) { _setupCoroutine = null; return false; } val = UnitEditorContentScroll.ResolveContentRect(statsPage.contentParent); if (!((Object)(object)val != (Object)null) || CountStatsRows(val) <= 0) { <>2__current = null; <>1__state = 2; return true; } } val = UnitEditorContentScroll.ResolveContentRect(statsPage.contentParent); if ((Object)(object)val == (Object)null) { _setupCoroutine = null; return false; } Transform transform = ((Component)statsPage).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val2 != null) { UnitEditorContentScroll.ForceLayoutChain(val2); } UnitEditorContentScroll.PrepareSharedViewport(val); UnitEditorContentScroll.ForceLayoutChain(val); if (EnsureSetup(statsPage, val)) { _setupCoroutine = null; return false; } Plugin.LogWarning("StatsScroll: scroll setup failed; stat rows may not be ready yet"); _setupCoroutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const int MaxSetupAttempts = 12; private static Coroutine _setupCoroutine; private static readonly UnitEditorContentScroll.Config ScrollConfig = new UnitEditorContentScroll.Config { InnerContainerName = "StatsScrollInner", ClipViewportName = "StatsClipViewport", NavCoverName = "StatsNavCover", IsScrollRow = IsStatsScrollRow, ConfigureInnerLayout = ConfigureStatsInnerLayout, PreserveWorldPositionOnReparent = true, Mode = UnitEditorContentScroll.ScrollMode.InnerContainer, BottomSlack = 8f }; public static void StatsPage_Open_Postfix(UnitEditorSubMenu __instance) { if (UnitEditorStatsConfig.Enabled) { UnitEditorStatsPageUI val = (UnitEditorStatsPageUI)(object)((__instance is UnitEditorStatsPageUI) ? __instance : null); if (val != null) { ScheduleSetup(val); } } } public static void StatsPage_Close_Postfix(UnitEditorStatsPageUI __instance) { if (!((Object)(object)__instance?.contentParent == (Object)null)) { RectTransform val = UnitEditorContentScroll.ResolveContentRect(__instance.contentParent); if (!((Object)(object)val == (Object)null)) { UnitEditorContentScroll.ResetScrollState(val, ScrollConfig); } } } public static void SpawnStats_Postfix(UnitEditorStatsPageUI __instance) { if (UnitEditorStatsConfig.Enabled && !((Object)(object)__instance == (Object)null)) { ScheduleSetup(__instance); } } private static void ScheduleSetup(UnitEditorStatsPageUI statsPage) { if (!((Object)(object)Plugin.Instance == (Object)null) && !((Object)(object)statsPage == (Object)null)) { if (_setupCoroutine != null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_setupCoroutine); _setupCoroutine = null; } _setupCoroutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(SetupScrollAfterOpen(statsPage)); } } [IteratorStateMachine(typeof(d__7))] private static IEnumerator SetupScrollAfterOpen(UnitEditorStatsPageUI statsPage) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { statsPage = statsPage }; } private static bool EnsureSetup(UnitEditorStatsPageUI statsPage, RectTransform content) { if (!UnitEditorStatsConfig.Enabled) { return false; } if ((Object)(object)content == (Object)null || ((Transform)content).childCount <= 0 || CountStatsRows(content) <= 0) { return false; } return UnitEditorContentScroll.EnsureSetup(content, ((Component)statsPage).transform, ScrollConfig, "StatsScroll"); } private static void ConfigureStatsInnerLayout(RectTransform content, RectTransform inner) { if (!((Object)(object)content == (Object)null) && !((Object)(object)inner == (Object)null)) { UnitEditorContentScroll.CopyVerticalLayoutGroup(content, inner); UnitEditorContentScroll.AlignInnerContainerTopLeft(inner); } } private static int CountStatsRows(RectTransform content) { if ((Object)(object)content == (Object)null) { return 0; } int num = 0; for (int i = 0; i < ((Transform)content).childCount; i++) { if (IsStatsScrollRow(((Transform)content).GetChild(i))) { num++; } } return num; } private static bool IsStatsScrollRow(Transform child) { if ((Object)(object)child == (Object)null) { return false; } return (Object)(object)((Component)child).GetComponent() != (Object)null; } } internal static class UnitEditorWalkSync { private sealed class WalkSyncButtonMarker : MonoBehaviour { } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__12_0; internal void b__12_0() { ApplySync(Object.FindObjectOfType()); } } private const string SyncButtonName = "StayCombatFix_WalkSync"; private const string SyncButtonLabel = "Sync Walk Animation"; private const float SyncButtonWidth = 148f; private const float SyncButtonMinHeight = 52f; private const float SyncButtonGap = 8f; private const float SyncButtonFontSize = 11f; private static readonly FieldInfo StatCellInputField = AccessTools.Field(typeof(UnitEditorStatCell), "m_InputField"); private static readonly MethodInfo RespawnUnitMethod = AccessTools.Method(typeof(UnitEditorManager), "RespawnUnit", (Type[])null, (Type[])null); internal static void ComputeVanillaWalkCycle(float moveSpeed, out float animation, out float step) { float num = Mathf.Lerp(moveSpeed, 1f, 0.8f); if (Mathf.Approximately(num, 0f)) { num = 0.01f; } animation = num; step = 1f / num; } internal static void ApplySync(UnitEditorManager manager) { //IL_0022: 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 (UnitEditorStatsConfig.Enabled && !((Object)(object)manager == (Object)null)) { ComputeVanillaWalkCycle(manager.GetStatValue((UnitStat)3), out var animation, out var step); manager.SetStatValue(UnitEditorCustomStats.AnimationMultiplier, animation); manager.SetStatValue(UnitEditorCustomStats.StepMultiplier, step); UnitEditorUIManager uIManager = manager.UIManager; if (uIManager != null) { uIManager.UpdateStatUI(); } if (RespawnUnitMethod != null) { RespawnUnitMethod.Invoke(manager, null); } } } public static void StatCell_Init_Postfix(UnitEditorStatCell __instance, StatsWrapper stat) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if (UnitEditorStatsConfig.Enabled && stat != null && (int)stat.unitStat == 3) { EnsureSyncButton(__instance); } } private static void EnsureSyncButton(UnitEditorStatCell cell) { if ((Object)(object)((cell != null) ? ((Component)cell).transform : null) == (Object)null) { return; } RectTransform inputRect = GetInputRect(cell); if (!((Object)(object)inputRect == (Object)null)) { Transform val = ((Component)cell).transform.Find("StayCombatFix_WalkSync"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } GameObject val2 = CreateSyncButtonObject(); if (!((Object)(object)val2 == (Object)null)) { ((Object)val2).name = "StayCombatFix_WalkSync"; val2.transform.SetParent(((Component)cell).transform, false); ConfigureSyncButton(val2, inputRect, cell); } } } private static void ConfigureSyncButton(GameObject buttonObject, RectTransform inputRect, UnitEditorStatCell cell) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0056: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown RectTransform component = buttonObject.GetComponent(); if ((Object)(object)component == (Object)null) { return; } float num = Mathf.Max(ResolveButtonHeight(inputRect), 52f); component.anchorMin = inputRect.anchorMin; component.anchorMax = inputRect.anchorMax; component.pivot = new Vector2(1f, 0.5f); component.sizeDelta = new Vector2(148f, num); component.anchoredPosition = inputRect.anchoredPosition + new Vector2(0f - inputRect.sizeDelta.x - 8f, 0f); Button component2 = buttonObject.GetComponent