Decompiled source of StayCombatFix v1.1.0
StayCombatFix.dll
Decompiled 7 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Landfall.TABS; using Landfall.TABS.AI.Components; using Landfall.TABS.GameState; using Microsoft.CodeAnalysis; using TFBGames; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; 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("1.1.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.1.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 <ProcessDeathQueue>d__46 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ProcessDeathQueue>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<int, float> RecentBarrelExplosionTimeByRoot = new Dictionary<int, float>(); private static readonly Dictionary<int, float> AllowedBarrelExplosionTimeByRoot = new Dictionary<int, float>(); private static readonly Dictionary<int, Transform> ActiveBarrelRollerRoots = new Dictionary<int, Transform>(); private static readonly HashSet<int> KnownBarrelRollerRootIds = new HashSet<int>(); private static readonly HashSet<int> NotBarrelRollerRootIds = new HashSet<int>(); private static readonly List<PendingBarrelDeath> PendingDeaths = new List<PendingBarrelDeath>(32); private static readonly HashSet<int> PendingDeathRootIds = new HashSet<int>(); 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<TeamHolder>() ?? ((Component)explosionTransform).GetComponentInParent<TeamHolder>(); 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<Unit>(true) != (Object)null) { return false; } return ContainsBarrelExplosionName(((Object)root).name); } private static Transform FindBarrelRollerRootNear(Vector3 position) { //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_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) Transform result = null; float num = 400f; foreach (KeyValuePair<int, Transform> activeBarrelRollerRoot in ActiveBarrelRollerRoots) { 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; } if (objectName.IndexOf("Barrel", StringComparison.OrdinalIgnoreCase) >= 0) { return objectName.IndexOf("Explosion", StringComparison.OrdinalIgnoreCase) >= 0; } 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<Unit>(); 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(<ProcessDeathQueue>d__46))] private static IEnumerator ProcessDeathQueue() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ProcessDeathQueue>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<ConditionalEvent>(true)); Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren<Holdable>(true); CollectBarrelHoldableData(root, componentsInChildren, out var barrelRigidbodies, out var barrelAnchors, out var barrelVisuals); PickExplosionAssets(((Component)root).GetComponentsInChildren<Explosion>(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<Unit>() }; 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<Rigidbody> list = new List<Rigidbody>(); List<Transform> list2 = new List<Transform>(); List<GameObject> list3 = new List<GameObject>(); HashSet<int> hashSet = new HashSet<int>(); HashSet<int> hashSet2 = new HashSet<int>(); HashSet<int> hashSet3 = new HashSet<int>(); if (holdables != null) { foreach (Holdable holdable in holdables) { if (IsBarrelHoldable(holdable)) { AddBarrelHoldable(holdable, list, list2, list3, hashSet, hashSet2, hashSet3); } } } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(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<Rigidbody>(); 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<Rigidbody> rigidbodies, List<Transform> anchors, List<GameObject> visuals, HashSet<int> seenBodies, HashSet<int> seenAnchors, HashSet<int> 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<Rigidbody>(); 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<RemoveAfterSeconds>(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<KillAfterSeconds>(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<SpawnObject>(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<CollisionEvent>(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<ConditionalEvent>(); 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<RemoveAfterSeconds>(); 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) { if (MatchesBarrelRollerBlueprint(unit)) { return true; } return HasBarrelAbilityGear(root); } private static bool HasBarrelAbilityGear(Transform root) { if ((Object)(object)root == (Object)null) { return false; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (IsBarrelAbilityMountTransform(componentsInChildren[i])) { return true; } } Holdable[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<Holdable>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { if (IsBarrelHoldable(componentsInChildren2[i])) { return true; } } Explosion[] componentsInChildren3 = ((Component)root).GetComponentsInChildren<Explosion>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { if (IsBarrelDeathExplosionSource(((Component)componentsInChildren3[i]).transform, root)) { return true; } } DelayEvent[] componentsInChildren4 = ((Component)root).GetComponentsInChildren<DelayEvent>(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; } if (name.IndexOf("Barrel", StringComparison.OrdinalIgnoreCase) >= 0) { return name.IndexOf("Roller", StringComparison.OrdinalIgnoreCase) >= 0; } 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<DataHandler>(); 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<Holdable>(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<Transform>(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<DataHandler>(); 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<Holdable>(true); foreach (Holdable val2 in componentsInChildren) { if (!IsBarrelHoldable(val2)) { continue; } Rigidbody val3 = val2.rig ?? ((Component)val2).GetComponentInChildren<Rigidbody>(); 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<Rigidbody>(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<Renderer>(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<Rigidbody>(); 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<Unit>(); 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<GameObject>(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<GameObject>(_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<GameObject>(((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<Explosion>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].addEffectFromParent = false; } ExplosionEffect[] componentsInChildren2 = instance.GetComponentsInChildren<ExplosionEffect>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.Destroy((Object)(object)componentsInChildren2[i]); } AddTargetableEffect[] componentsInChildren3 = instance.GetComponentsInChildren<AddTargetableEffect>(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<Level>() ?? instance.AddComponent<Level>(); obj.levelMultiplier = val.levelMultiplier; obj.level = val.level; obj.ignoreTeam = val.ignoreTeam; TargetableEffect[] componentsInChildren = instance.GetComponentsInChildren<TargetableEffect>(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<Level>(); if ((Object)(object)component != (Object)null) { return component; } return ((Component)ownerUnit).GetComponentInChildren<Level>(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<Holdable>(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<Transform>(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<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)null) { val.enabled = false; } } Collider[] componentsInChildren2 = target.GetComponentsInChildren<Collider>(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<Explosion>(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<Explosion>(); 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<Explosion>(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<GameObject>("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<DataHandler>(); if ((Object)(object)componentInChildren == (Object)null || !componentInChildren.Dead) { return true; } return false; } public static void GameStateManager_EnterPlacementState_Postfix() { BarrelRollerDeathLogic.ResetBattleCaches(); } } 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<FactionCreatorCostHoverState>() ?? ((Component)button).gameObject.AddComponent<FactionCreatorCostHoverState>(); } } 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<RectTransform>(); ((Transform)component).SetParent((Transform)(object)listParent, false); ((Transform)component).localScale = Vector3.one; LayoutElement obj = val.AddComponent<LayoutElement>(); 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<UnitButtonBase>(); Image val = component?.NameSelect; float num = Mathf.Min(width, height); GameObject val2 = new GameObject("Highlight", new Type[1] { typeof(RectTransform) }); RectTransform component2 = val2.GetComponent<RectTransform>(); ((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<Image>(); ((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<UnitButtonBase>(), __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<FactionCreatorUnitDragReorder>(); 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<FactionCreatorUnitDragReorder>() != (Object)null)) { ((Component)button).gameObject.AddComponent<FactionCreatorUnitDragReorder>().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<UnitButtonBase>(); 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<UnitButtonBase, object> dictionary = new Dictionary<UnitButtonBase, object>(); 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<object> list = new List<object>(); for (int j = 0; j < val.childCount; j++) { UnitButtonBase component = ((Component)val.GetChild(j)).GetComponent<UnitButtonBase>(); 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<ScrollRect>(); } 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<FactionCreatorManager>() != (Object)null)) { return (Object)(object)((Component)button).GetComponentInParent<FactionCreatorUnitBrowser>() != (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<FactionCreatorCostHoverState>()?.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<Canvas>(); _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<CanvasGroup>(); if ((Object)(object)_canvasGroup == (Object)null) { _canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>(); } _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<FactionCreatorDragScrollSession>(); _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 GameStatePatches { public static void EnterBattleState_Postfix() { BarrelRollerDeathLogic.ResetBattleCaches(); WaterPatches.ResetRiverFlowDirections(); MirrorShieldLogic.ResetBattleState(); } } 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<MoveTransform>(); 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<ProjectileHit>(); if ((Object)(object)component == (Object)null || component.done) { return; } MoveTransform component2 = ((Component)__instance).GetComponent<MoveTransform>(); 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: