Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AH64 v1.3.3
plugins/AH64.dll
Decompiled a week 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using AH64.Modules; using AH64.Modules.Achievements; using AH64.Modules.Characters; using AH64.Survivors; using AH64.Survivors.Components; using AH64.Survivors.SkillStates; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.AI.Walker; using EntityStates.Commando; using EntityStates.Engi.EngiMissilePainter; using EntityStates.Headstompers; using HG; using HG.BlendableTypes; using HG.Reflection; using KinematicCharacterController; using On.EntityStates.Headstompers; using On.RoR2; using On.RoR2.Projectile; using On.RoR2.UI; using R2API; using R2API.Utils; using Rewired; using RoR2; using RoR2.Achievements; using RoR2.Audio; using RoR2.CharacterAI; using RoR2.ConVar; using RoR2.ContentManagement; using RoR2.Networking; using RoR2.Projectile; using RoR2.Skills; using RoR2.SurvivorMannequins; using RoR2.UI; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("AH64")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c8488c53bca37208cfa1827eaa36caf89baedc29")] [assembly: AssemblyProduct("AH64")] [assembly: AssemblyTitle("AH64")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace AH64 { [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.JohnstonStu.AH64", "AH64", "1.3.3")] public class AH64Plugin : BaseUnityPlugin { public const string MODUID = "com.JohnstonStu.AH64"; public const string MODNAME = "AH64"; public const string MODVERSION = "1.3.3"; public static AH64Plugin instance; private void Awake() { instance = this; Log.Init(((BaseUnityPlugin)this).Logger); AH64HellfireNetwork.Init(); AH64BombingRunNetwork.Init(); AH64PlaytestConfig.Init(((BaseUnityPlugin)this).Config); Language.Init(); new AH64Survivor().Initialize(); new ContentPacks().Initialize(); DevAutopilot.TryStart(); } private void OnDestroy() { AH64BombingRunNetwork.Shutdown(); AH64HellfireNetwork.Shutdown(); } } [DefaultExecutionOrder(10000)] internal sealed class DevAutopilot : MonoBehaviour { [Serializable] private sealed class BalanceResult { public int schema = 1; public int expectedChecks = 9; public string sourceSha; public string runId; public string dllSha256; public string status; public bool complete; public Check[] checks; public string limitation = "SOLO native request/stock/state/reload pipeline with isolated M230 override, no inventory grants. Cadence is fixed-tick scheduled. Physical controls, real target damage, alternate-primary gameplay and item scaling remain unverified by this delta test."; } [Serializable] private sealed class BombingResult { public int schema = 1; public int expectedChecks; public string runId; public string sourceSha; public string dllSha256; public string suite; public string status; public string limitation; public bool complete; public bool hooksReleased; public string[] expectedIds; public Check[] checks; } [Serializable] private sealed class BombingObservation : Record { public ulong castId; public uint ownerId; public uint targetId; public int dropIndex; public int projectileId; public int acceptedHits; public int icbmCount; public string kind; public string reason; public string bodyState; public string weapon2State; public float scheduledTime; public float actualTime; public float time; public float damage; public float procCoefficient; public float remainingBaseCoefficient; public float airtime; public float targetHeight; public Vector3 position; public Vector3 velocity; public Vector3 nativeCore; public Vector3 nativeVelocity; public bool crit; public bool jumpHeld; public bool ascending; } [Serializable] private sealed class BombingDamage : Record { public ulong castId; public uint ownerId; public uint targetId; public int projectileId; public int dropIndex; public float time; public float damageDealt; public float rawDamage; public float procCoefficient; public bool bomb; public bool crit; public bool rejected; public string dot; } [Serializable] private sealed class BombingFixture : Record { public uint targetId; public uint masterId; public float health; public float fullHealth; public float armor; public float pilotBleedChance; public Vector3 position; public bool godMode; public bool invulnerable; public string fixture; } [Serializable] private sealed class BombingCleanup : Record { public ulong castId; public float time; public int bombs; public int bleedBefore; public int bleedAfter; public int icbmBefore; public int icbmAfter; public int stockBefore; public int stockBeforeRestore; public bool targetAlive; public bool targetMasterAlive; public bool obstructionAlive; public bool noRefund; public bool originValid; public bool overrideReferencesReleased; public string weapon2State; } [Serializable] private sealed class BombingPayload { public ulong castId; public uint ownerId; public uint targetId; public string kind; public string reason; public int dropIndex; public int acceptedHits; public float scheduledTime; public float actualTime; public float remainingBaseCoefficient; public float damage; public float procCoefficient; public Vector3 position; public Vector3 velocity; public bool crit; } [Serializable] private sealed class BrakingResult { public int schema = 1; public int expectedChecks; public int renderSamples; public int renderViolations; public string runId; public string sourceSha; public string dllSha256; public string suite; public string status; public string limitation; public string utilityInterruptPriority; public bool complete; public string[] expectedIds; public Check[] checks; } [Serializable] private sealed class BrakingSample : Record { public int tick; public int appliedSteps; public float simulationTime; public float progress; public float appliedAge; public float targetHeight; public float airtime; public float groundDistance; public string capture; public string phase; public string yieldReason; public Vector3 commandedHeading; public Vector3 position; public Vector3 velocity; public Vector3 nativeAim; public Vector3 nativeVelocity; public Vector3 appliedVelocity; public Quaternion displayedBaseWorld; public bool ascending; public bool lease; public bool visualOwner; public bool visualRecovery; } [Serializable] private sealed class BrakingRender : Record { public int poseEpoch; public float renderedTime; public float renderDeltaTime; public float observedDelta; public float alarmBound; public Quaternion worldAttitude; public string bodyState; public bool visualActive; } [Serializable] private sealed class WindowCaptureStage { public string sourceSha; public string gameDirectory; public string owner; public string reservation; public string runtimeLockPath; } [Serializable] private sealed class WindowPhaseEvidence { public string runId; public string token; public string confirmedUtc; public string limitation; public bool phaseValid; public int phaseChecks; public int confirmedFrame; public float confirmedFixedTime; } [Serializable] private class StageIdentity { public string status = ""; public string sourceSha = ""; public string profile = ""; public string dirtyWorkspaceFingerprint = ""; } [Serializable] private class Record { public int schemaVersion = 1; public string recordType; public string runId; public string scenario; } [Serializable] private class Header : Record { public string sourceSha; public string dirtyWorkspaceFingerprint; public string pluginVersion; public string dllSha256; public string bundleSha256; public string bankSha256; public string configSha256; public string gameBuild; public string profile; public string role; public string identityFile; public int requestedAssertionCount; public int seed; } [Serializable] private class Sample : Record { public int tick; public int entityId; public int ownerId; public int poseEpoch; public float simulationTime; public Vector3 position; public Vector3 velocity; public Vector3 facing; public Vector3 nativeAim; public Quaternion modelAttitude; public bool authority; public string role; public string maneuverCapture; public string guidanceToken; public string attitudeSamplePhase; } [Serializable] private class ProjectileSample : Record { public int tick; public int projectileId; public int combo; public uint token; public Vector3 position; public Vector3 heading; public float lastTurnDegrees; public float remainingTurnDegrees; } [Serializable] private class EventRecord : Record { public int tick; public int entityId; public int ownerId; public float simulationTime; public string role; public string eventName; public string reason; } [Serializable] private class AssertionRecord : Record { public string assertionId; public string expected; public string actual; public float tolerance; public bool passed; } [Serializable] private class Check { public string id; public string expected; public string actual; public string scenario; public float tolerance; public bool passed; } [Serializable] private class Summary : Record { public int schema = 1; public int expectedAssertions; public int assertions; public int failedAssertions; public int executed; public int passed; public int failed; public int skipped; public int captures; public int samples; public int errors; public int warnings; public int visualFlags; public string suite; public string status; public string reason; public string warningClassification; public string errorClassification; public string limitation; public Check[] checks; public string[] artifactPaths; } [Serializable] private sealed class PrototypeResult { public int schema = 1; public int expectedChecks; public string runId; public string sourceSha; public string dllSha256; public string status; public string limitation; public bool complete; public Check[] checks; } private readonly List<Check> balanceChecks = new List<Check>(); private bool balanceStarted; private bool balanceComplete; private const string BombingSuite = "bombing-solo-v1"; private static readonly string[] BombingNames = new string[5] { "stationary", "bleed", "curve", "interrupt", "invalid" }; private static readonly string[] BombingChecks = new string[5] { "activation", "opportunities", "motion", "payload", "cleanup" }; private readonly List<Check> bombingChecks = new List<Check>(); private readonly List<BombingObservation> bombingObservations = new List<BombingObservation>(); private readonly HashSet<int> bombingProjectileIds = new HashSet<int>(); private readonly Dictionary<int, int> bombingDropByProjectile = new Dictionary<int, int>(); private readonly Dictionary<int, ulong> bombingCastByProjectile = new Dictionary<int, ulong>(); private readonly List<BombingDamage> bombingReports = new List<BombingDamage>(); private readonly HashSet<DamageInfo> bombingAcceptedNativeInfo = new HashSet<DamageInfo>(); private bool bombingStarted; private bool bombingComplete; private bool bombingHooks; private bool bombingCaseActive; private bool bombingAddedBleed; private bool bombingAddedIcbm; private int bombingOnEnemy; private int bombingOnAll; private ulong bombingCastId; private CharacterMaster bombingTargetMaster; private CharacterBody bombingTarget; private uint bombingTargetId; private uint bombingTargetMasterId; private GameObject bombingObstruction; private SkillDef bombingSpecialOverride; private SkillDef bombingUtilityOverride; private NetworkUser startedNetworkUser; private BodyIndex expectedBody = (BodyIndex)(-1); private readonly List<Check> brakingChecks = new List<Check>(); private bool brakingStarted; private bool brakingComplete; private bool brakingCollective; private bool brakingHasRender; private bool brakingPreviousVisualActive; private Quaternion brakingPreviousRender; private int brakingRenderEpoch; private int brakingRenderViolations; private int brakingRenderSamples; private static readonly string[] BrakingCaseNames = new string[6] { "stationary", "small", "fast", "spare", "collective", "interrupt" }; private static readonly string[] BrakingCaseChecks = new string[5] { "activation-capture", "midflight", "motion", "exit", "cleanup" }; private WindowCaptureRequest pendingCapture; private bool capturePhaseInvalid; private int capturePhaseChecks; internal const string Suite = "baseline-v1"; internal const int ExpectedAssertions = 12; private string output; private string segment = "startup"; private CharacterBody pilot; private Vector3 mark; private Vector3 facing = Vector3.forward; private Vector3 move; private float started; private float quitAt; private bool gameLoaded; private bool scripting; private bool finished; private int tick; private int samples; private int errors; private int warnings; private int visualFlags; private int launches; private int captures; private readonly List<Check> checks = new List<Check>(); private bool prototypeHeld; private Vector3 prototypeAim; private StreamWriter jsonl; private StreamWriter csv; private StreamWriter trace; private StreamWriter runtimeLog; private static readonly CultureInfo Invariant = CultureInfo.InvariantCulture; private readonly Dictionary<string, EntityState> previousStates = new Dictionary<string, EntityState>(); private readonly HashSet<int> observedProjectiles = new HashSet<int>(); private readonly HashSet<int> liveProjectiles = new HashSet<int>(); private Quaternion previousAttitude; private bool hasAttitude; private int poseEpoch; private int terminalExit; private readonly List<Check> prototypeChecks = new List<Check>(); private bool prototypeStarted; private bool prototypeComplete; private void BalanceCheck(string id, bool passed, string actual) { balanceChecks.Add(new Check { id = id, passed = passed, actual = actual, scenario = segment }); Event("balance-check", id + " " + (passed ? "PASS" : "FAIL") + " " + actual); } private IEnumerator M230BalanceCase() { balanceStarted = true; yield return ResetCase("m230-balance"); Event("balance-scope", "SOLO native GenericSkill.ExecuteIfReady requests at fixed cadence with explicit M230 override; no physical hold, target-hit/damage or item-scaling acceptance"); GenericSkill slot = pilot.skillLocator.primary; SkillDef original = slot.skillDef; SkillDef skill = Variant(slot, typeof(FireChaingun)); slot.SetSkillOverride((object)this, skill, (SkillOverridePriority)4); try { yield return Until(() => slot.stock == slot.maxStock && slot.CanExecute(), 10f, "M230 full native drum"); float attackSpeed = pilot.attackSpeed; BalanceCheck("m230.defaults", FireChaingun.baseDuration == 0.11f && Mathf.Abs(attackSpeed - 1f) < 0.001f, "nominal interval=" + FireChaingun.baseDuration + " attackSpeed=" + attackSpeed + " damage=" + AH64PlaytestConfig.ChaingunDamage + " HE=" + AH64PlaytestConfig.ChaingunSplashDamage + " proc=" + 0.5f); BalanceCheck("m230.native-magazine", skill.baseMaxStock == 20 && slot.maxStock == 20 && slot.stock == 20, "SkillDef=" + skill.baseMaxStock + " native max=" + slot.maxStock + " stock=" + slot.stock); List<float> nativeEntries = new List<float>(); EntityState last = null; Action observe = delegate { EntityState state = Machine("Weapon").state; if (last != state) { last = state; if (state is FireChaingun) { nativeEntries.Add(Time.fixedTime); Event("m230-native-fire-entry", "entry=" + nativeEntries.Count + " stock=" + slot.stock + " fixedTime=" + Time.fixedTime.ToString("R", Invariant)); } } }; int accepted = 0; bool singleStock = true; float lastRequest = 0f; float deadline = Time.realtimeSinceStartup + 15f; while (slot.stock > 0 && Time.realtimeSinceStartup < deadline) { observe(); int stock = slot.stock; if (slot.ExecuteIfReady()) { accepted++; lastRequest = Time.fixedTime; singleStock &= slot.stock == stock - 1; Event("m230-accepted-request", "request=" + accepted + " stock=" + stock + "->" + slot.stock + " fixedTime=" + lastRequest.ToString("R", Invariant)); } yield return (object)new WaitForFixedUpdate(); } yield return (object)new WaitForFixedUpdate(); observe(); yield return (object)new WaitForFixedUpdate(); observe(); BalanceCheck("m230.stock-cost", accepted == 20 && singleStock && slot.stock == 0, "accepted=" + accepted + " one-stock-each=" + singleStock + " stock=" + slot.stock); BalanceCheck("m230.native-fire-entries", nativeEntries.Count == 20, "actual FireChaingun state entries=" + nativeEntries.Count); float[] array = nativeEntries.Skip(1).Select((float time, int index) => time - nativeEntries[index]).ToArray(); float nominal = FireChaingun.baseDuration / attackSpeed; bool passed = array.Length == 19 && array.All((float dt) => dt >= nominal - 0.001f && dt <= nominal + Time.fixedDeltaTime * 3f + 0.001f); BalanceCheck("m230.native-cadence", passed, "nominal=" + nominal + " observed min=" + ((array.Length != 0) ? array.Min().ToString("R", Invariant) : "none") + " max=" + ((array.Length != 0) ? array.Max().ToString("R", Invariant) : "none") + " intervals=" + array.Length + "; fixed-tick request/state scheduling, not nominal RPM measurement"); bool flag = slot.ExecuteIfReady(); BalanceCheck("m230.empty-blocked", !flag && slot.stock == 0, "empty ExecuteIfReady=" + flag + " stock=" + slot.stock); float reload = skill.GetRechargeInterval(slot); yield return Until(() => slot.stock > 0, 10f, "M230 native full reload"); float num = Time.fixedTime - lastRequest; BalanceCheck("m230.whole-reload", slot.stock == 20 && slot.maxStock == 20, "native stock=" + slot.stock + " max=" + slot.maxStock); BalanceCheck("m230.reload-timing", Mathf.Abs(num - reload) <= Time.fixedDeltaTime * 3f + 0.001f, "native elapsed from last request=" + num.ToString("R", Invariant) + " expected=" + reload.ToString("R", Invariant)); yield return Until(() => !(Machine("Weapon").state is FireChaingun), 5f, "M230 firing state exit"); } finally { slot.UnsetSkillOverride((object)this, skill, (SkillOverridePriority)4); } BalanceCheck("m230.override-cleanup", (Object)(object)slot.skillDef == (Object)(object)original && !(Machine("Weapon").state is FireChaingun), "original primary restored; no live FireChaingun state"); balanceComplete = true; } private bool FinishBalanceEvidence() { if (Environment.GetEnvironmentVariable("AH64_AUTOPILOT_BALANCE_CHECKS") != "m230-v1") { return true; } bool flag = balanceStarted && balanceComplete && balanceChecks.Count == 9 && balanceChecks.All((Check c) => c.passed); File.WriteAllText(Path.Combine(output, "balance-result.json"), JsonUtility.ToJson((object)new BalanceResult { sourceSha = JsonUtility.FromJson<StageIdentity>(File.ReadAllText(Path.Combine(output, "identity.json"))).sourceSha, runId = Path.GetFileName(output), dllSha256 = Hash(typeof(AH64Plugin).Assembly.Location), status = (flag ? "passed" : "failed"), complete = balanceComplete, checks = balanceChecks.ToArray() }, true)); return flag; } private void InstallBombingProbeHooks() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown if (!(Environment.GetEnvironmentVariable("AH64_AUTOPILOT_BOMBING_CHECKS") != "bombing-solo-v1") && !bombingHooks) { bombingHooks = true; AH64BombingRunTrace.Emitted += ObserveBombingTrace; GlobalEventManager.onServerDamageDealt += ObserveBombingDamage; GlobalEventManager.OnHitEnemy += new hook_OnHitEnemy(ObserveBombingOnHitEnemy); GlobalEventManager.OnHitAll += new hook_OnHitAll(ObserveBombingOnHitAll); } } private void CleanupBombingProbe() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown if (bombingHooks) { AH64BombingRunTrace.Emitted -= ObserveBombingTrace; GlobalEventManager.onServerDamageDealt -= ObserveBombingDamage; GlobalEventManager.OnHitEnemy -= new hook_OnHitEnemy(ObserveBombingOnHitEnemy); GlobalEventManager.OnHitAll -= new hook_OnHitAll(ObserveBombingOnHitAll); bombingHooks = false; } CleanupBombingFixture(); } private void CleanupBombingFixture() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) bombingCaseActive = false; brakingCollective = false; prototypeHeld = false; prototypeAim = Vector3.zero; move = Vector3.zero; if (Object.op_Implicit((Object)(object)pilot)) { pilot.inputBank.jump.down = (pilot.inputBank.skill4.down = false); if (Object.op_Implicit((Object)(object)bombingSpecialOverride)) { pilot.skillLocator.special.UnsetSkillOverride((object)this, bombingSpecialOverride, (SkillOverridePriority)4); } if (Object.op_Implicit((Object)(object)bombingUtilityOverride)) { pilot.skillLocator.utility.UnsetSkillOverride((object)this, bombingUtilityOverride, (SkillOverridePriority)4); } if (Object.op_Implicit((Object)(object)pilot.inventory)) { if (bombingAddedBleed) { pilot.inventory.RemoveItem(Items.BleedOnHit.itemIndex, 20); } if (bombingAddedIcbm) { pilot.inventory.RemoveItem(Items.MoreMissile.itemIndex, 1); } } } bombingSpecialOverride = (bombingUtilityOverride = null); bombingAddedBleed = (bombingAddedIcbm = false); if (Object.op_Implicit((Object)(object)bombingObstruction)) { bombingObstruction.SetActive(false); Object.Destroy((Object)(object)bombingObstruction); } bombingObstruction = null; if (NetworkServer.active) { if (Object.op_Implicit((Object)(object)bombingTarget)) { NetworkServer.Destroy(((Component)bombingTarget).gameObject); } if (Object.op_Implicit((Object)(object)bombingTargetMaster)) { NetworkServer.Destroy(((Component)bombingTargetMaster).gameObject); } } bombingTarget = null; bombingTargetMaster = null; } private void BombingCheck(string id, bool passed, string actual) { bombingChecks.Add(new Check { id = id, passed = passed, actual = actual, scenario = segment }); Event("bombing-check", id + " " + (passed ? "PASS" : "FAIL") + " " + actual); } private IEnumerator BombingCases() { bombingStarted = true; Event("bombing-scope", "SOLO actual GenericSkill, native World/HealthComponent/DamageReport and downstream Bleed; scripted inputs and owned disposable fixtures. No physical feel, media, peer or complete terrain matrix acceptance."); GenericSkill special = pilot.skillLocator.special; Variant[] variants = special.skillFamily.variants; SkillDef val = Variant(special, typeof(BombingRun)); BombingCheck("catalog.order", variants.Length == 3 && ((SerializableEntityStateType)(ref variants[0].skillDef.activationState)).stateType == typeof(PaintLongbow) && ((SerializableEntityStateType)(ref variants[1].skillDef.activationState)).stateType == typeof(FireHellfire) && (Object)(object)variants[2].skillDef == (Object)(object)val, string.Join(",", variants.Select((Variant v) => ((SerializableEntityStateType)(ref v.skillDef.activationState)).stateType.Name))); BombingCheck("catalog.definition", val.activationStateMachineName == "Weapon2" && val.baseMaxStock == 1 && val.stockToConsume == 1 && val.baseRechargeInterval == 10f && val.mustKeyPress && (int)val.interruptPriority == 1, "machine=" + val.activationStateMachineName + " priority=" + ((object)Unsafe.As<InterruptPriority, InterruptPriority>(ref val.interruptPriority)/*cast due to .constrained prefix*/).ToString() + " stock=" + val.baseMaxStock); try { string[] bombingNames = BombingNames; foreach (string name in bombingNames) { yield return BombingCase(name); } bombingComplete = true; } finally { CleanupBombingProbe(); } } private IEnumerator SpawnBombingTarget() { RaycastHit val = default(RaycastHit); if (!Physics.Raycast(mark + facing * 3f + Vector3.up * 6f, Vector3.down, ref val, 20f, LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.world)).mask), (QueryTriggerInteraction)1)) { throw new InvalidOperationException("Bombing target fixture lacks native terrain."); } GameObject val2 = MasterCatalog.FindMasterPrefab("GolemMaster"); if (!Object.op_Implicit((Object)(object)val2)) { throw new InvalidOperationException("Native GolemMaster unavailable."); } bombingTargetMaster = new MasterSummon { masterPrefab = val2, position = ((RaycastHit)(ref val)).point + Vector3.up, rotation = Quaternion.LookRotation(-facing), summonerBodyObject = null, teamIndexOverride = (TeamIndex)2, ignoreTeamMemberLimit = true, preSpawnSetupCallback = delegate(CharacterMaster master) { BaseAI[] components2 = ((Component)master).GetComponents<BaseAI>(); for (int i = 0; i < components2.Length; i++) { ((Behaviour)components2[i]).enabled = false; } } }.Perform(); if (!Object.op_Implicit((Object)(object)bombingTargetMaster)) { throw new InvalidOperationException("Native target summon failed."); } BaseAI[] components = ((Component)bombingTargetMaster).GetComponents<BaseAI>(); for (int num = 0; num < components.Length; num++) { ((Behaviour)components[num]).enabled = false; } yield return Until(() => Object.op_Implicit((Object)(object)bombingTargetMaster) && Object.op_Implicit((Object)(object)bombingTargetMaster.GetBody()), 5f, "damageable native Golem body"); bombingTarget = bombingTargetMaster.GetBody(); DevAutopilot devAutopilot = this; NetworkInstanceId netId = ((NetworkBehaviour)bombingTarget.healthComponent).netId; devAutopilot.bombingTargetId = ((NetworkInstanceId)(ref netId)).Value; DevAutopilot devAutopilot2 = this; netId = ((NetworkBehaviour)bombingTargetMaster).netId; devAutopilot2.bombingTargetMasterId = ((NetworkInstanceId)(ref netId)).Value; yield return FixedSeconds(0.5f); if (bombingTarget.healthComponent.godMode || !bombingTarget.healthComponent.alive || bombingTarget.HasBuff(Buffs.HiddenInvincibility)) { throw new InvalidOperationException("Positive damage fixture is protected or dead."); } DevAutopilot devAutopilot3 = this; BombingFixture obj = new BombingFixture { recordType = "bombing-fixture", runId = Path.GetFileName(output), scenario = segment, targetId = bombingTargetId }; netId = ((NetworkBehaviour)bombingTargetMaster).netId; obj.masterId = ((NetworkInstanceId)(ref netId)).Value; obj.health = bombingTarget.healthComponent.health; obj.fullHealth = bombingTarget.healthComponent.fullHealth; obj.armor = bombingTarget.armor; obj.position = bombingTarget.corePosition; obj.godMode = bombingTarget.healthComponent.godMode; obj.invulnerable = bombingTarget.HasBuff(Buffs.HiddenInvincibility); obj.pilotBleedChance = pilot.bleedChance; obj.fixture = "native GolemMaster; AI disabled; no health/stat writes, healing or pinning"; devAutopilot3.Write(obj); } private AH64BombingRunProjectile[] NativeBombs() { return (from p in Object.FindObjectsOfType<AH64BombingRunProjectile>() where Object.op_Implicit((Object)(object)p) && Object.op_Implicit((Object)(object)((Component)p).GetComponent<ProjectileController>()) && (Object)(object)((Component)p).GetComponent<ProjectileController>().owner == (Object)(object)((Component)pilot).gameObject select p).ToArray(); } private IEnumerator BombingCase(string name) { CleanupBombingFixture(); ((Component)pilot).GetComponent<AH64HoverController>().ResetAfterTeleport(); yield return ResetCase("bombing-" + name); yield return Until(() => NativeBombs().Length == 0, 8f, "preceding native bombs drain"); bombingObservations.Clear(); bombingReports.Clear(); bombingAcceptedNativeInfo.Clear(); bombingProjectileIds.Clear(); bombingDropByProjectile.Clear(); bombingCastByProjectile.Clear(); bombingCastId = 0uL; DevAutopilot devAutopilot = this; DevAutopilot devAutopilot2 = this; uint num = 0u; devAutopilot2.bombingTargetMasterId = 0u; devAutopilot.bombingTargetId = num; DevAutopilot devAutopilot3 = this; DevAutopilot devAutopilot4 = this; int num2 = 0; devAutopilot4.bombingOnAll = 0; devAutopilot3.bombingOnEnemy = num2; bool targetCase = name == "stationary" || name == "bleed"; bool curve = name == "curve"; bool invalid = name == "invalid"; GenericSkill slot = pilot.skillLocator.special; SkillDef originalSpecial = slot.skillDef; SkillDef originalUtility = pilot.skillLocator.utility.skillDef; bombingSpecialOverride = Variant(slot, typeof(BombingRun)); slot.SetSkillOverride((object)this, bombingSpecialOverride, (SkillOverridePriority)4); int bleedBefore = pilot.inventory.GetItemCount(Items.BleedOnHit); int icbmBefore = pilot.inventory.GetItemCount(Items.MoreMissile); float healthBefore = 0f; int stockBefore = 0; int stockBeforeRestore = -1; bool interrupted = false; bool primary = false; bool hydra = false; bool brake = false; bool nativeOverlap = false; bool noRefund = false; try { if (name == "bleed") { pilot.inventory.GiveItem(Items.BleedOnHit, 20); bombingAddedBleed = true; yield return Until(() => pilot.bleedChance >= 200f, 5f, "actual native bleedChance >=200 at proc0.5"); } if (curve) { if (icbmBefore != 0) { throw new InvalidOperationException("Curve fixture requires exactly one isolated ICBM."); } pilot.inventory.GiveItem(Items.MoreMissile, 1); bombingAddedIcbm = true; bombingUtilityOverride = Variant(pilot.skillLocator.utility, typeof(BrakingTurn)); pilot.skillLocator.utility.SetSkillOverride((object)this, bombingUtilityOverride, (SkillOverridePriority)4); yield return Until(() => pilot.skillLocator.utility.CanExecute(), 12f, "curve braking readiness"); } if (targetCase) { yield return SpawnBombingTarget(); healthBefore = bombingTarget.healthComponent.health; } yield return Until(() => slot.CanExecute() && (!curve || (pilot.skillLocator.primary.CanExecute() && pilot.skillLocator.secondary.CanExecute())), 15f, "native bombing readiness"); if (!AH64BombingRunCast.SafeOrigin(pilot.corePosition, pilot.corePosition + Vector3.down * 0.5f)) { throw new InvalidOperationException("Native origin invalid before owned fixture."); } if (invalid) { bombingObstruction = new GameObject("AH64OwnedBombingInvalidOriginFixture"); bombingObstruction.layer = LayerIndex.world.intVal; bombingObstruction.transform.SetParent(((Component)pilot).gameObject.transform, true); bombingObstruction.transform.position = pilot.corePosition + Vector3.down * 0.25f; bombingObstruction.AddComponent<BoxCollider>().size = Vector3.one; Physics.SyncTransforms(); if (AH64BombingRunCast.SafeOrigin(pilot.corePosition, pilot.corePosition + Vector3.down * 0.5f)) { throw new InvalidOperationException("Actual native World obstruction did not reject origin."); } } if (curve) { move = facing; prototypeAim = facing; brakingCollective = true; pilot.inputBank.jump.down = true; } bombingCaseActive = true; stockBefore = slot.stock; bool accepted = slot.ExecuteIfReady(); yield return Until(() => Machine("Weapon2").state is BombingRun, 2f, "native bombing Weapon2 entry"); EntityState state = Machine("Weapon2").state; BombingCheck(name + ".activation", accepted && stockBefore > 0 && slot.stock == stockBefore - 1 && bombingCastId != 0, "accepted=" + accepted + " stock=" + stockBefore + "->" + slot.stock + " nativeCast=" + bombingCastId); if (curve) { yield return FixedSeconds(0.4f); move = Quaternion.AngleAxis(70f, Vector3.up) * facing; prototypeAim = move; pilot.inputBank.moveVector = move; pilot.inputBank.aimDirection = move; brake = pilot.skillLocator.utility.ExecuteIfReady(); primary = pilot.skillLocator.primary.ExecuteIfReady(); hydra = pilot.skillLocator.secondary.ExecuteIfReady(); yield return (object)new WaitForFixedUpdate(); nativeOverlap = Machine("Weapon2").state == state && Machine("Body").state is BrakingTurn && Machine("Weapon").state is FireChaingun && Machine("Weapon3").state is FireRocketPods; Event("bombing-native-overlap", "primary=" + primary + " hydra=" + hydra + " brake=" + brake + " actual=" + ((object)Machine("Body").state).GetType().Name + "/" + ((object)Machine("Weapon").state).GetType().Name + "/" + ((object)Machine("Weapon3").state).GetType().Name); } if (name == "interrupt") { yield return FixedSeconds(0.45f); interrupted = Machine("Weapon2").SetInterruptState((EntityState)new Idle(), (InterruptPriority)5); } yield return Until(() => Machine("Weapon2").state != state, 3f, "finite native bombing exit"); int consumedAtExit = Opportunities().Length; brakingCollective = false; pilot.inputBank.jump.down = false; move = Vector3.zero; prototypeAim = Vector3.zero; yield return Until(() => NativeBombs().Length == 0, 8f, "native bombing lifetime drain"); if (name == "bleed") { yield return FixedSeconds(1f); } BombingObservation[] array = Opportunities(); BombingObservation[] releases = bombingObservations.Where((BombingObservation o) => o.kind == "release").ToArray(); BombingObservation[] array2 = bombingObservations.Where((BombingObservation o) => o.kind == "impact" || o.kind == "despawn").ToArray(); BombingObservation[] array3 = bombingObservations.Where((BombingObservation o) => o.kind == "hit" && o.targetId == bombingTargetId).ToArray(); BombingDamage[] direct = bombingReports.Where((BombingDamage r) => r.bomb && r.targetId == bombingTargetId && r.damageDealt > 0f && !r.rejected).ToArray(); BombingObservation[] array4 = bombingObservations.Where((BombingObservation o) => o.kind == "end").ToArray(); int num3 = ((name == "interrupt") ? consumedAtExit : 6); bool flag = array.Length == num3 && array.Select((BombingObservation o) => o.dropIndex).Distinct().Count() == num3 && (from o in array select o.dropIndex into i orderby i select i).SequenceEqual(Enumerable.Range(0, num3)) && array.All((BombingObservation o) => Mathf.Abs(o.scheduledTime - (float)o.dropIndex * 0.3f) < 0.001f && o.actualTime >= o.scheduledTime - 0.001f && o.actualTime - o.scheduledTime < 0.2f) && bombingProjectileIds.Count == releases.Length && releases.All((BombingObservation o) => o.projectileId != 0) && array2.Length == releases.Length && array2.Select((BombingObservation o) => o.dropIndex).Distinct().Count() == releases.Length && array2.All((BombingObservation t) => releases.Any((BombingObservation r) => r.dropIndex == t.dropIndex && t.time >= r.time && t.time - r.time <= 6.2f)) && array4.Length == 1 && array4[0].reason == ((name == "interrupt") ? "interrupted" : "complete"); if (name == "interrupt") { flag &= interrupted && num3 > 0 && num3 < 6 && array.Length == consumedAtExit; } BombingCheck(passed: (!invalid) ? (flag & (releases.Length == num3)) : (flag & (releases.Length == 0 && array.All((BombingObservation o) => o.kind == "suppressed" && o.reason == "invalid-or-obstructed-origin"))), id: name + ".opportunities", actual: "due=" + array.Length + " releases=" + releases.Length + " actualProjectileIds=" + bombingProjectileIds.Count + " end=" + string.Join(",", array4.Select((BombingObservation o) => o.reason)) + " interrupted=" + interrupted); bool flag2 = releases.All(delegate(BombingObservation o) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (Finite(o.position) && Finite(o.velocity)) { Vector3 val3 = o.position - (o.nativeCore + Vector3.down * 0.5f); if (((Vector3)(ref val3)).magnitude < 0.001f) { val3 = o.velocity - (Vector3.ClampMagnitude(new Vector3(o.nativeVelocity.x, 0f, o.nativeVelocity.z), 25f) + Vector3.down * 4f); return ((Vector3)(ref val3)).magnitude < 0.001f; } } return false; }); float num4 = 0f; if (curve && releases.Length >= 4) { Vector3 val = releases[2].position - releases[0].position; Vector3 val2 = releases[releases.Length - 1].position - releases[2].position; val.y = (val2.y = 0f); num4 = ((((Vector3)(ref val)).magnitude > 0.1f && ((Vector3)(ref val2)).magnitude > 0.1f) ? Vector3.Angle(val, val2) : 0f); flag2 &= num4 > 5f && primary && hydra && brake && nativeOverlap && releases.All((BombingObservation o) => AH64BombingRunCast.Finite(o.airtime) && AH64BombingRunCast.Finite(o.targetHeight) && o.airtime >= 0f && o.icbmCount == 1 && o.jumpHeld) && releases.Any((BombingObservation o) => o.ascending); } BombingCheck(name + ".motion", flag2 && (!curve || releases.Length == 6), "same-time native release origin/velocity agreement; path bend=" + num4 + "; simultaneous native states=" + nativeOverlap); bool flag3 = (targetCase ? (array3.Length == 3 && direct.Length == 3 && array3.All((BombingObservation h) => h.damage > 0f && Mathf.Abs(h.procCoefficient - 0.5f) < 0.001f) && direct.All((BombingDamage d) => Mathf.Abs(d.procCoefficient - 0.5f) < 0.001f && d.castId == bombingCastId) && direct.Select((BombingDamage d) => d.dropIndex).Distinct().Count() == 3 && array3.Select((BombingObservation h) => h.dropIndex).Distinct().Count() == 3 && (from d in direct select d.dropIndex into i orderby i select i).SequenceEqual(from h in array3 select h.dropIndex into i orderby i select i) && bombingOnEnemy == 3 && bombingOnAll == 3 && bombingObservations.Any((BombingObservation o) => o.kind == "hit-suppressed" && o.targetId == bombingTargetId && o.reason == "overlap-budget")) : (!invalid || bombingReports.Count == 0)); int num5 = bombingReports.Count((BombingDamage r) => r.dot == ((object)(DotIndex)0/*cast due to .constrained prefix*/).ToString() && r.targetId == bombingTargetId && r.damageDealt > 0f && !r.rejected); if (name == "bleed") { flag3 &= pilot.bleedChance >= 200f && num5 > 0 && direct.Any() && bombingReports.Any((BombingDamage r) => r.dot == ((object)(DotIndex)0/*cast due to .constrained prefix*/).ToString() && r.time >= direct[0].time && r.targetId == bombingTargetId && r.damageDealt > 0f); } flag3 &= bombingReports.All((BombingDamage r) => AH64BombingRunCast.Finite(r.damageDealt) && AH64BombingRunCast.Finite(r.rawDamage) && AH64BombingRunCast.Finite(r.procCoefficient)); BombingCheck(name + ".payload", flag3, "native direct=" + direct.Length + " trace accepted=" + array3.Length + " native Bleed=" + num5 + " separate OnHitEnemy/All=" + bombingOnEnemy + "/" + bombingOnAll + " bleedChance=" + pilot.bleedChance + " HP=" + healthBefore + "->" + (Object.op_Implicit((Object)(object)bombingTarget) ? bombingTarget.healthComponent.health : (-1f)) + "; HP delta includes regeneration and is not raw coefficient proof"); stockBeforeRestore = slot.stock; noRefund = stockBeforeRestore == stockBefore - 1; } finally { CleanupBombingFixture(); } Physics.SyncTransforms(); yield return (object)new WaitForFixedUpdate(); bool flag4 = bombingTargetId != 0 && Object.FindObjectsOfType<CharacterBody>().Any(delegate(CharacterBody b) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)b) && Object.op_Implicit((Object)(object)b.healthComponent)) { NetworkInstanceId netId = ((NetworkBehaviour)b.healthComponent).netId; return ((NetworkInstanceId)(ref netId)).Value == bombingTargetId; } return false; }); bool flag5 = bombingTargetMasterId != 0 && Object.FindObjectsOfType<CharacterMaster>().Any(delegate(CharacterMaster m) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)m)) { NetworkInstanceId netId = ((NetworkBehaviour)m).netId; return ((NetworkInstanceId)(ref netId)).Value == bombingTargetMasterId; } return false; }); bool flag6 = !Object.op_Implicit((Object)(object)bombingSpecialOverride) && !Object.op_Implicit((Object)(object)bombingUtilityOverride) && (Object)(object)slot.skillDef == (Object)(object)originalSpecial && (Object)(object)pilot.skillLocator.utility.skillDef == (Object)(object)originalUtility; Write(new BombingCleanup { recordType = "bombing-cleanup", runId = Path.GetFileName(output), scenario = segment, time = Time.fixedTime, castId = bombingCastId, bombs = NativeBombs().Length, targetAlive = flag4, targetMasterAlive = flag5, obstructionAlive = ((Object)(object)bombingObstruction != (Object)null), stockBefore = stockBefore, stockBeforeRestore = stockBeforeRestore, bleedBefore = bleedBefore, bleedAfter = pilot.inventory.GetItemCount(Items.BleedOnHit), icbmBefore = icbmBefore, icbmAfter = pilot.inventory.GetItemCount(Items.MoreMissile), noRefund = noRefund, originValid = AH64BombingRunCast.SafeOrigin(pilot.corePosition, pilot.corePosition + Vector3.down * 0.5f), weapon2State = ((object)Machine("Weapon2").state).GetType().Name, overrideReferencesReleased = flag6 }); BombingCheck(name + ".cleanup", !Object.op_Implicit((Object)(object)bombingObstruction) && !flag4 && !flag5 && flag6 && !bombingAddedBleed && !bombingAddedIcbm && pilot.inventory.GetItemCount(Items.BleedOnHit) == bleedBefore && pilot.inventory.GetItemCount(Items.MoreMissile) == icbmBefore && NativeBombs().Length == 0 && !(Machine("Weapon2").state is BombingRun) && noRefund && AH64BombingRunCast.SafeOrigin(pilot.corePosition, pilot.corePosition + Vector3.down * 0.5f), "owned target/world fixture/overrides/items removed; native payloads drained; no refund; origin valid"); } private BombingObservation[] Opportunities() { return bombingObservations.Where((BombingObservation o) => o.kind == "release" || (o.kind == "suppressed" && o.reason == "invalid-or-obstructed-origin")).ToArray(); } private void ObserveBombingTrace(AH64BombingRunTrace.Record value) { //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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) if (!bombingCaseActive || finished || !Object.op_Implicit((Object)(object)pilot) || value == null) { return; } uint ownerId = value.ownerId; NetworkInstanceId netId = ((NetworkBehaviour)pilot).netId; if (ownerId != ((NetworkInstanceId)(ref netId)).Value) { return; } if (value.kind == "begin") { if (bombingCastId != 0L) { throw new InvalidOperationException("Multiple native casts in one fixture."); } bombingCastId = value.castId; } if (value.castId != bombingCastId) { return; } int num = 0; if (value.kind == "release") { AH64BombingRunProjectile[] array = (from p in NativeBombs() where !bombingProjectileIds.Contains(((Object)((Component)p).gameObject).GetInstanceID()) select p).ToArray(); if (array.Length == 1) { num = ((Object)((Component)array[0]).gameObject).GetInstanceID(); bombingProjectileIds.Add(num); bombingDropByProjectile[num] = value.dropIndex; bombingCastByProjectile[num] = value.castId; } } AH64HoverController component = ((Component)pilot).GetComponent<AH64HoverController>(); BombingObservation bombingObservation = new BombingObservation { recordType = "bombing-observation", runId = Path.GetFileName(output), scenario = segment, castId = value.castId, ownerId = value.ownerId, targetId = value.targetId, kind = value.kind, reason = value.reason, dropIndex = value.dropIndex, scheduledTime = value.scheduledTime, actualTime = value.actualTime, time = Time.fixedTime, position = value.position, velocity = value.velocity, nativeCore = pilot.corePosition, nativeVelocity = pilot.characterMotor.velocity, projectileId = num, damage = value.damage, procCoefficient = value.procCoefficient, acceptedHits = value.acceptedHits, remainingBaseCoefficient = value.remainingBaseCoefficient, crit = value.crit, airtime = component.Airtime, targetHeight = component.TargetHeight, icbmCount = pilot.inventory.GetItemCountEffective(Items.MoreMissile), jumpHeld = pilot.inputBank.jump.down, ascending = component.IsAscending, bodyState = ((object)Machine("Body").state).GetType().Name, weapon2State = ((object)Machine("Weapon2").state).GetType().Name }; bombingObservations.Add(bombingObservation); Write(bombingObservation); } private bool OwnedBomb(DamageInfo info) { if (info != null && Object.op_Implicit((Object)(object)pilot) && (Object)(object)info.attacker == (Object)(object)((Component)pilot).gameObject && Object.op_Implicit((Object)(object)info.inflictor)) { return Object.op_Implicit((Object)(object)info.inflictor.GetComponent<AH64BombingRunDamage>()); } return false; } private void ObserveBombingDamage(DamageReport report) { //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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (!bombingCaseActive || finished || report == null || !Object.op_Implicit((Object)(object)pilot) || (Object)(object)report.attacker != (Object)(object)((Component)pilot).gameObject) { return; } DamageInfo damageInfo = report.damageInfo; int num = (Object.op_Implicit((Object)(object)damageInfo.inflictor) ? ((Object)damageInfo.inflictor).GetInstanceID() : 0); bool flag = OwnedBomb(damageInfo); NetworkInstanceId netId; if (flag && Object.op_Implicit((Object)(object)report.victim)) { netId = ((NetworkBehaviour)report.victim).netId; if (((NetworkInstanceId)(ref netId)).Value == bombingTargetId && report.damageDealt > 0f && AH64BombingRunCast.Finite(report.damageDealt) && !damageInfo.rejected) { bombingAcceptedNativeInfo.Add(damageInfo); } } ulong value; int value2; BombingDamage obj = new BombingDamage { recordType = "bombing-damage", runId = Path.GetFileName(output), scenario = segment, castId = (bombingCastByProjectile.TryGetValue(num, out value) ? value : 0), dropIndex = (bombingDropByProjectile.TryGetValue(num, out value2) ? value2 : (-1)) }; netId = ((NetworkBehaviour)pilot).netId; obj.ownerId = ((NetworkInstanceId)(ref netId)).Value; int targetId; if (!Object.op_Implicit((Object)(object)report.victim)) { targetId = 0; } else { netId = ((NetworkBehaviour)report.victim).netId; targetId = (int)((NetworkInstanceId)(ref netId)).Value; } obj.targetId = (uint)targetId; obj.projectileId = num; obj.time = Time.fixedTime; obj.bomb = flag; obj.dot = ((object)Unsafe.As<DotIndex, DotIndex>(ref report.dotType)/*cast due to .constrained prefix*/).ToString(); obj.damageDealt = report.damageDealt; obj.rawDamage = damageInfo.damage; obj.procCoefficient = damageInfo.procCoefficient; obj.crit = damageInfo.crit; obj.rejected = damageInfo.rejected; BombingDamage bombingDamage = obj; bombingReports.Add(bombingDamage); Write(bombingDamage); } private void ObserveBombingOnHitEnemy(orig_OnHitEnemy orig, GlobalEventManager self, DamageInfo info, GameObject victim) { if (bombingCaseActive && !finished && OwnedBomb(info) && bombingAcceptedNativeInfo.Contains(info) && Object.op_Implicit((Object)(object)bombingTarget) && (Object)(object)victim == (Object)(object)((Component)bombingTarget).gameObject) { bombingOnEnemy++; Event("bombing-native-OnHitEnemy", "projectile=" + ((Object)info.inflictor).GetInstanceID() + " victim=" + ((Object)victim).GetInstanceID()); } orig.Invoke(self, info, victim); } private void ObserveBombingOnHitAll(orig_OnHitAll orig, GlobalEventManager self, DamageInfo info, GameObject victim) { if (bombingCaseActive && !finished && OwnedBomb(info) && bombingAcceptedNativeInfo.Contains(info) && Object.op_Implicit((Object)(object)bombingTarget) && (Object)(object)victim == (Object)(object)((Component)bombingTarget).gameObject) { bombingOnAll++; Event("bombing-native-OnHitAll", "projectile=" + ((Object)info.inflictor).GetInstanceID() + " victim=" + (Object.op_Implicit((Object)(object)victim) ? ((Object)victim).GetInstanceID() : 0)); } orig.Invoke(self, info, victim); } private bool FinishBombingEvidence() { if (Environment.GetEnvironmentVariable("AH64_AUTOPILOT_BOMBING_CHECKS") != "bombing-solo-v1") { return true; } string[] array = new string[2] { "catalog.order", "catalog.definition" }.Concat(BombingNames.SelectMany((string n) => BombingChecks.Select((string c) => n + "." + c))).ToArray(); bool flag = bombingStarted && bombingComplete && !bombingHooks && !bombingCaseActive && bombingChecks.Count == array.Length && bombingChecks.All((Check c) => c.passed) && bombingChecks.Select((Check c) => c.id).Distinct().Count() == array.Length && !array.Except(bombingChecks.Select((Check c) => c.id)).Any(); File.WriteAllText(Path.Combine(output, "bombing-result.json"), JsonUtility.ToJson((object)new BombingResult { runId = Path.GetFileName(output), sourceSha = JsonUtility.FromJson<StageIdentity>(File.ReadAllText(Path.Combine(output, "identity.json"))).sourceSha, dllSha256 = Hash(typeof(AH64Plugin).Assembly.Location), suite = "bombing-solo-v1", status = (flag ? "passed" : "failed"), complete = bombingComplete, expectedChecks = array.Length, expectedIds = array, checks = bombingChecks.ToArray(), hooksReleased = !bombingHooks, limitation = "Bounded scripted SOLO native smoke. Raw reports, cast/owner/target/drop/time retained; OnHit callbacks are distinct from actual downstream Bleed. No physical bindings/feel, peer, long-session, full natural terrain, audio or authentic media acceptance. Raw strict runtime outcomes remain independently blocking/classifiable." }, true)); return flag; } private void OnBombingTrace(AH64BombingRunTrace.Record value) { //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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if (scripting && !finished && Object.op_Implicit((Object)(object)pilot) && value != null) { uint ownerId = value.ownerId; NetworkInstanceId netId = ((NetworkBehaviour)pilot).netId; if (ownerId == ((NetworkInstanceId)(ref netId)).Value) { Event("bombing-" + value.kind, JsonUtility.ToJson((object)new BombingPayload { castId = value.castId, ownerId = value.ownerId, kind = value.kind, reason = value.reason, dropIndex = value.dropIndex, scheduledTime = value.scheduledTime, actualTime = value.actualTime, position = value.position, velocity = value.velocity, targetId = value.targetId, acceptedHits = value.acceptedHits, remainingBaseCoefficient = value.remainingBaseCoefficient, damage = value.damage, procCoefficient = value.procCoefficient, crit = value.crit })); } } } private static void DisableCombatDirectors() { CombatDirector[] array = CombatDirector.instancesList.ToArray(); foreach (CombatDirector val in array) { if (Object.op_Implicit((Object)(object)val)) { ((Behaviour)val).enabled = false; } } } private void OnNetworkStarted(NetworkUser networkUser) { if (((NetworkBehaviour)networkUser).isLocalPlayer) { startedNetworkUser = networkUser; Event("bootstrap-network-started", "completed NetworkUser.Start; preference=" + ((object)Unsafe.As<BodyIndex, BodyIndex>(ref networkUser.bodyIndexPreference)/*cast due to .constrained prefix*/).ToString()); } } private IEnumerator Bootstrap() { yield return BootstrapWait(delegate { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene2 = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene2)).name; if (gameLoaded && name != "title" && name != "splash") { IntroCutsceneController.shouldSkip = true; } return gameLoaded && name == "title" && LocalUserManager.GetFirstLocalUser() != null; }, 90f, "title/local-user", null); LocalUser user = LocalUserManager.GetFirstLocalUser(); if (LocalUserManager.readOnlyLocalUsersList.Count != 1 || Object.op_Implicit((Object)(object)user.currentNetworkUser) || NetworkServer.active || NetworkClient.active) { throw new InvalidOperationException("Bootstrap requires one offline local user before hosting: " + BootstrapSnapshot(user)); } UserProfile profile = user.userProfile; if (profile == null) { throw new InvalidOperationException("No player profile for save protection."); } profile.canSave = false; profile.saveRequestPending = false; Event("save-protection", "loaded player profile canSave=false for this diagnostic process; no disk save changes"); SurvivorDef survivor = null; yield return BootstrapWait(delegate { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_0068: 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) expectedBody = BodyCatalog.FindBodyIndex("AH64Body"); survivor = SurvivorCatalog.GetSurvivorDef(SurvivorCatalog.GetSurvivorIndexFromBodyIndex(expectedBody)); return (int)expectedBody != -1 && Object.op_Implicit((Object)(object)survivor) && Object.op_Implicit((Object)(object)survivor.bodyPrefab) && BodyCatalog.FindBodyIndex(survivor.bodyPrefab) == expectedBody; }, 15f, "AH64-catalog", user); SurvivorDef survivorPreference = profile.GetSurvivorPreference(); Event("bootstrap-profile", "prior=" + (Object.op_Implicit((Object)(object)survivorPreference) ? survivorPreference.cachedName : "null") + "; selecting=" + survivor.cachedName + "; body=" + ((object)Unsafe.As<BodyIndex, BodyIndex>(ref expectedBody)/*cast due to .constrained prefix*/).ToString()); profile.SetSurvivorPreference(survivor); if (profile.canSave || (Object)(object)profile.GetSurvivorPreference() != (Object)(object)survivor) { throw new InvalidOperationException("Protected in-memory AH64 selection was not retained."); } Console.instance.SubmitCmd((NetworkUser)null, "transition_command \"gamemode ClassicRun; host 0;\"", false); yield return BootstrapWait(() => Object.op_Implicit((Object)(object)PreGameController.instance) && Object.op_Implicit((Object)(object)user.currentNetworkUser) && (Object)(object)startedNetworkUser == (Object)(object)user.currentNetworkUser && NetworkServer.active && NetworkClient.active && NetworkUser.readOnlyInstancesList.Count == 1 && ((NetworkBehaviour)user.currentNetworkUser).isLocalPlayer && ((NetworkBehaviour)user.currentNetworkUser).hasAuthority, 45f, "solo-lobby/NetworkUser.Start", user); user.currentNetworkUser.SetSurvivorPreferenceClient(survivor); yield return BootstrapWait(() => user.currentNetworkUser.bodyIndexPreference == expectedBody, 10f, "AH64-selection-acknowledged", user); if (!Object.op_Implicit((Object)(object)PreGameController.instance)) { throw new InvalidOperationException("Lobby launched before explicit launch."); } PreGameController.instance.runSeed = 1301uL; Random.InitState(1301); Event("bootstrap-launch", BootstrapSnapshot(user)); PreGameController.instance.StartLaunch(); yield return BootstrapWait(() => Object.op_Implicit((Object)(object)Run.instance) && Object.op_Implicit((Object)(object)user.cachedBody) && BodyProblem(user).Length == 0, 60f, "first-body/AH64-prerequisites", user); RequireBody(user); SceneDef val = SceneCatalog.FindSceneDef("golemplains"); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Fixed arena missing."); } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "golemplains") { CharacterBody previousBody = user.cachedBody; Run.instance.AdvanceStage(val); yield return BootstrapWait(delegate { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene2 = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene2)).name == "golemplains" && Object.op_Implicit((Object)(object)user.cachedBody) && user.cachedBody != previousBody && BodyProblem(user).Length == 0; }, 60f, "fixed-arena/new-body", user); } yield return (object)new WaitForSecondsRealtime(2f); RequireBody(user); pilot = user.cachedBody; Event("bootstrap-ready", BootstrapSnapshot(user)); } private void RequireBody(LocalUser user) { string text = BodyProblem(user); if (text.Length != 0) { throw new InvalidOperationException("AH64 prerequisite: " + text + "; " + BootstrapSnapshot(user)); } } private string BodyProblem(LocalUser user) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) CharacterBody cachedBody = user.cachedBody; if (!Object.op_Implicit((Object)(object)cachedBody)) { return "missing body"; } if (cachedBody.bodyIndex != expectedBody) { return "wrong body index"; } if (!((NetworkBehaviour)cachedBody).hasAuthority) { return "body lacks authority"; } if (!Object.op_Implicit((Object)(object)cachedBody.characterMotor)) { return "missing CharacterMotor"; } if (!Object.op_Implicit((Object)(object)cachedBody.inputBank)) { return "missing InputBankTest"; } if (!Object.op_Implicit((Object)(object)cachedBody.characterDirection)) { return "missing CharacterDirection"; } if (!Object.op_Implicit((Object)(object)cachedBody.modelLocator)) { return "missing ModelLocator"; } if (!Object.op_Implicit((Object)(object)cachedBody.modelLocator.modelTransform)) { return "missing model transform"; } if (!Object.op_Implicit((Object)(object)user.cachedMaster) || !Object.op_Implicit((Object)(object)user.cachedMasterController) || (Object)(object)user.cachedMasterController.master != (Object)(object)user.cachedMaster || (Object)(object)user.cachedMaster.GetBody() != (Object)(object)cachedBody) { return "local master/controller/body control-chain mismatch"; } string[] array = new string[2] { "Body", "Weapon2" }; foreach (string name in array) { EntityStateMachine[] array2 = (from m in ((Component)cachedBody).GetComponents<EntityStateMachine>() where m.customName == name select m).ToArray(); if (array2.Length != 1 || array2[0].state == null) { return "missing/ambiguous/uninitialized state machine " + name; } } return ""; } private IEnumerator BootstrapWait(Func<bool> predicate, float timeout, string phase, LocalUser user) { segment = "bootstrap:" + phase; float end = Time.realtimeSinceStartup + timeout; string previous = null; string text; while (true) { bool num = predicate(); text = BootstrapSnapshot(user); if (text != previous) { Event("bootstrap-wait", phase + "; " + text); previous = text; } if (num) { Event("bootstrap-phase-ready", phase + "; " + text); yield break; } if (Time.realtimeSinceStartup > end) { break; } yield return null; } throw new TimeoutException("bootstrap " + phase + "; " + text); } private string BootstrapSnapshot(LocalUser user) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) NetworkUser val = ((user == null) ? null : user.currentNetworkUser); CharacterBody val2 = ((user == null) ? null : user.cachedBody); string[] array = new string[22]; array[0] = "scene="; Scene activeScene = SceneManager.GetActiveScene(); array[1] = ((Scene)(ref activeScene)).name; array[2] = "; expectedBody="; array[3] = ((object)Unsafe.As<BodyIndex, BodyIndex>(ref expectedBody)/*cast due to .constrained prefix*/).ToString(); array[4] = "; localUsers="; array[5] = LocalUserManager.readOnlyLocalUsersList.Count.ToString(); array[6] = "; networkUsers="; array[7] = NetworkUser.readOnlyInstancesList.Count.ToString(); array[8] = "; server="; array[9] = NetworkServer.active.ToString(); array[10] = "; client="; array[11] = NetworkClient.active.ToString(); array[12] = "; networkStarted="; array[13] = (Object.op_Implicit((Object)(object)val) && (Object)(object)startedNetworkUser == (Object)(object)val).ToString(); array[14] = "; preference="; array[15] = (Object.op_Implicit((Object)(object)val) ? ((object)Unsafe.As<BodyIndex, BodyIndex>(ref val.bodyIndexPreference)/*cast due to .constrained prefix*/).ToString() : "none"); array[16] = "; body="; array[17] = (Object.op_Implicit((Object)(object)val2) ? (((Object)((Component)val2).gameObject).name + "/" + ((object)Unsafe.As<BodyIndex, BodyIndex>(ref val2.bodyIndex)/*cast due to .constrained prefix*/).ToString()) : "none"); array[18] = "; authority="; array[19] = (Object.op_Implicit((Object)(object)val2) && ((NetworkBehaviour)val2).hasAuthority).ToString(); array[20] = "; prerequisite="; array[21] = ((user == null) ? "no local user" : BodyProblem(user)); return string.Concat(array); } private void BrakingCheck(string id, bool passed, string actual) { brakingChecks.Add(new Check { id = id, passed = passed, actual = actual, scenario = segment }); Event("braking-check", id + " " + (passed ? "PASS" : "FAIL") + " " + actual); } private IEnumerator BrakingCases() { if (Environment.GetEnvironmentVariable("AH64_AUTOPILOT_BRAKING_CHECKS") == "braking-solo-v1") { throw new InvalidOperationException("braking-solo-v1 is retired for Banked Break. Use the four pilot-visible cases in tools/braking-turn/BANKED-BREAK-HANDOFF.md."); } brakingStarted = true; Event("braking-scope", "braking-solo-v1: actual SOLO skill/stock and native PreMove; scripted aim, held collective, initial momentum, inventory and overrides. No physical input, peer, collision/item, target-hit or audio acceptance."); GenericSkill utility = pilot.skillLocator.utility; Variant[] variants = utility.skillFamily.variants; SkillDef val = Variant(utility, typeof(BrakingTurn)); BrakingCheck("catalog.order", variants.Length == 3 && ((SerializableEntityStateType)(ref variants[0].skillDef.activationState)).stateType == typeof(ServoDash) && ((SerializableEntityStateType)(ref variants[1].skillDef.activationState)).stateType == typeof(SmokeBackflip) && (Object)(object)variants[2].skillDef == (Object)(object)val, string.Join(",", variants.Select((Variant v) => ((SerializableEntityStateType)(ref v.skillDef.activationState)).stateType.Name)) + "; current default=" + utility.skillDef.skillName); BrakingCheck("catalog.definition", val.activationStateMachineName == "Body" && val.baseMaxStock == 1 && val.baseRechargeInterval == 4f && val.stockToConsume == 1 && AH64BrakingTurnAcceptance.Priority(val.interruptPriority) && val.mustKeyPress && Object.op_Implicit((Object)(object)val.icon), "machine=" + val.activationStateMachineName + " stock=" + val.baseMaxStock + " recharge=" + val.baseRechargeInterval + " priority=" + ((object)Unsafe.As<InterruptPriority, InterruptPriority>(ref val.interruptPriority)/*cast due to .constrained prefix*/).ToString() + "; placeholder icon=" + (Object.op_Implicit((Object)(object)val.icon) ? ((Object)val.icon).name : "missing")); string[] brakingCaseNames = BrakingCaseNames; foreach (string name in brakingCaseNames) { yield return BrakingMotionCase(name); } yield return BrakingGuidanceCase(); brakingComplete = true; } private IEnumerator ResetBrakingCase(string name) { brakingCollective = false; prototypeAim = Vector3.zero; move = Vector3.zero; ((Component)pilot).GetComponent<AH64HoverController>().ResetAfterTeleport(); yield return ResetCase(name); Event("braking-fixture", "teleport plus body-owned hover reset; no private stat writes or airtime restoration"); } private unsafe IEnumerator BrakingMotionCase(string name) { yield return ResetBrakingCase("braking-" + name); GenericSkill slot = pilot.skillLocator.utility; SkillDef skill = Variant(slot, typeof(BrakingTurn)); AH64HoverController hover = ((Component)pilot).GetComponent<AH64HoverController>(); AH64FlightVisuals visuals = ((Component)pilot).GetComponent<AH64FlightVisuals>(); CameraTargetParams camera = ((Component)pilot).GetComponent<CameraTargetParams>(); bool spare = name == "spare"; bool collective = name == "collective"; bool interruption = name == "interrupt"; bool removedSafety = false; if (spare) { pilot.inventory.GiveItem(Items.UtilitySkillMagazine, 1); } slot.SetSkillOverride((object)this, skill, (SkillOverridePriority)4); try { yield return Until(() => slot.CanExecute() && (!spare || slot.maxStock >= 2), 12f, "braking readiness"); if (spare && slot.stock < 2) { slot.RestockSteplike(); } yield return Until(() => !spare || slot.stock >= 2, 12f, "braking spare stock"); if (hover.GroundDistance < 0f || hover.GroundDistance > 8f) { throw new InvalidOperationException("Braking fixture lacks safe low terrain: " + hover.GroundDistance); } if (collective) { brakingCollective = true; pilot.inputBank.jump.down = true; yield return FixedSeconds(0.12f); } float entryFov = camera.fovOverride; float entryAirControl = pilot.characterMotor.airControl; int beforeStock = slot.stock; int renderBefore = brakingRenderViolations; float targetBefore = hover.TargetHeight; float airtimeBefore = hover.Airtime; Vector3 requested = (prototypeAim = ((name == "small") ? (Quaternion.AngleAxis(30f, Vector3.up) * facing) : ((name == "stationary") ? (Quaternion.AngleAxis(90f, Vector3.up) * facing) : (-facing)))); move = Vector3.zero; pilot.inputBank.moveVector = move; pilot.inputBank.aimDirection = requested; Vector3 val = ((name == "stationary" || collective) ? Vector3.zero : (facing * pilot.moveSpeed * ((name == "fast") ? 2f : 1f))); pilot.characterMotor.velocity = val + Vector3.up * pilot.characterMotor.velocity.y; if (spare) { pilot.RemoveBuff(Buffs.HiddenInvincibility); removedSafety = true; } bool accepted = slot.ExecuteIfReady(); yield return Until(() => Machine("Body").state is BrakingTurn, 2f, "native braking entry"); BrakingTurn state = (BrakingTurn)(object)Machine("Body").state; AH64BrakingTurnCapture capture = state.EntrySnapshot; AH64BrakingTurnMotor motor = ((Component)pilot).GetComponent<AH64BrakingTurnMotor>(); AH64BrakingTurnPresentation presentation = ((Component)pilot).GetComponent<AH64BrakingTurnPresentation>(); Vector3 val2 = AH64BrakingTurnMath.Horizontal(capture.EntryVelocity); float capturedSpeed = ((Vector3)(ref val2)).magnitude; BrakingCheck(name + ".activation-capture", accepted && slot.stock == beforeStock - 1 && capturedSpeed >= 0f && Vector3.Angle(capture.RequestedHeading, requested) < 0.1f && capture.Duration == 1f && (name != "stationary" || capturedSpeed < 0.2f) && (name != "small" || Mathf.Abs(capture.SignedCorrection - 30f) < 5f) && (name != "fast" || capturedSpeed > capture.MoveSpeed), "accepted=" + accepted + " stock=" + beforeStock + "->" + slot.stock + " captured=" + JsonUtility.ToJson((object)capture)); int spareStock = slot.stock; bool early = spare && slot.ExecuteIfReady(); prototypeAim = facing; yield return FixedSeconds(0.36f); AH64BrakingTurnFrame frame; bool flag = (object)Machine("Body").state == state && presentation.TryGetFrame(state, out frame); bool flag2 = spare && slot.ExecuteIfReady(); bool flag3 = flag && !state.MotionYielded && motor.HasActiveLease && Vector3.Angle(state.EntrySnapshot.RequestedHeading, requested) < 0.1f; bool checkTurn = name == "small" || name == "fast"; if (checkTurn) { flag3 &= AH64BrakingTurnAcceptance.Turned(capture, motor.LastAppliedVelocity, completed: false); } if (spare) { flag3 &= spareStock >= 1 && !early && !flag2 && slot.stock == spareStock && !pilot.HasBuff(Buffs.HiddenInvincibility) && !pilot.HasBuff(Buffs.Cloak); } if (collective) { flag3 &= hover.TargetHeight >= targetBefore && hover.IsAscending && hover.Airtime > 0f && hover.Airtime <= airtimeBefore + Time.fixedDeltaTime * 2f; } BrakingCheck(name + ".midflight", flag3, "active=" + flag + " yielded=" + state.MotionYielded + " age=" + motor.AppliedAge + " reentry=" + early + "," + flag2 + " target=" + targetBefore + "->" + hover.TargetHeight + " airtime=" + airtimeBefore + "->" + hover.Airtime + " actual directed turn=" + AH64BrakingTurnAcceptance.SignedProgress(capture, motor.LastAppliedVelocity)); bool interruptAccepted = true; if (interruption) { interruptAccepted = Machine("Body").SetInterruptState((EntityState)(object)new AH64Main(), (InterruptPriority)5); } yield return Until(() => (object)Machine("Body").state != state, 3f, "braking exit"); val2 = AH64BrakingTurnMath.Horizontal(motor.LastAppliedVelocity); float magnitude = ((Vector3)(ref val2)).magnitude; bool flag4 = motor.AppliedSteps > 0 && Finite(motor.LastAppliedVelocity) && motor.LastAppliedVelocity.y == motor.LastNativeVelocity.y && magnitude <= Mathf.Max(capturedSpeed, capture.ExitSpeed) + 0.1f; if (name == "stationary") { flag4 = flag4 && magnitude < 0.2f; } if (name == "fast") { flag4 &= motor.AppliedAge >= 0.95f && magnitude <= capture.MoveSpeed + 0.1f && magnitude > 0.1f; } if (checkTurn) { flag4 &= AH64BrakingTurnAcceptance.Turned(capture, motor.LastAppliedVelocity, completed: true); } DevAutopilot devAutopilot = this; string id = name + ".motion"; bool passed = flag4; string[] obj = new string[17] { "steps=", motor.AppliedSteps.ToString(), " last age=", motor.AppliedAge.ToString(), " native=", null, null, null, null, null, null, null, null, null, null, null, null }; val2 = motor.LastNativeVelocity; obj[5] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[6] = " applied="; val2 = motor.LastAppliedVelocity; obj[7] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[8] = " final active speed="; obj[9] = magnitude.ToString(); obj[10] = " exit ceiling="; obj[11] = capture.ExitSpeed.ToString(); obj[12] = " actual directed turn="; obj[13] = AH64BrakingTurnAcceptance.SignedProgress(capture, motor.LastAppliedVelocity).ToString(); obj[14] = " final alignment="; obj[15] = AH64BrakingTurnAcceptance.Alignment(capture, motor.LastAppliedVelocity).ToString(); obj[16] = "; post-Main velocity is not used as exit carry"; devAutopilot.BrakingCheck(id, passed, string.Concat(obj)); BrakingCheck(name + ".exit", interruptAccepted && Machine("Body").state is AH64Main && !(Machine("Body").state is BrakingTurn) && !motor.HasActiveLease && !presentation.HasActiveOwner && (interruption || motor.AppliedAge >= 0.95f), "actual=" + ((object)Machine("Body").state).GetType().Name + " native stronger interruption=" + interruptAccepted + " age=" + motor.AppliedAge); brakingCollective = false; pilot.inputBank.jump.down = false; prototypeAim = Vector3.zero; yield return FixedSeconds(1.4f); BrakingCheck(name + ".cleanup", MovementResourcesReleased(entryFov, entryAirControl) && !motor.HasActiveLease && !presentation.HasActiveOwner && !visuals.HasBrakingOwner && !visuals.IsBrakingRecovering && brakingRenderViolations == renderBefore, "motor=" + motor.HasActiveLease + " presentation=" + presentation.HasActiveOwner + " visual=" + visuals.HasBrakingOwner + " recovery=" + visuals.IsBrakingRecovering + " render violations=" + (brakingRenderViolations - renderBefore)); } finally { DevAutopilot devAutopilot2 = this; devAutopilot2.brakingCollective = false; devAutopilot2.prototypeAim = Vector3.zero; devAutopilot2.move = Vector3.zero; slot.UnsetSkillOverride((object)devAutopilot2, skill, (SkillOverridePriority)4); if (spare) { devAutopilot2.pilot.inventory.RemoveItem(Items.UtilitySkillMagazine.itemIndex, 1); } if (removedSafety && Object.op_Implicit((Object)(object)devAutopilot2.pilot) && devAutopilot2.pilot.healthComponent.alive) { devAutopilot2.pilot.AddBuff(Buffs.HiddenInvincibility); } } } private IEnumerator BrakingGuidanceCase() { yield return ResetBrakingCase("braking-guidance"); GenericSkill utility = pilot.skillLocator.utility; GenericSkill special = pilot.skillLocator.special; SkillDef brake = Variant(utility, typeof(BrakingTurn)); SkillDef hellfire = Variant(special, typeof(FireHellfire)); utility.SetSkillOverride((object)this, brake, (SkillOverridePriority)4); special.SetSkillOverride((object)this, hellfire, (SkillOverridePriority)4); try { yield return Until(() => utility.CanExecute() && special.CanExecute(), 15f, "concurrent guidance readiness"); prototypeHeld = true; DevAutopilot devAutopilot = this; Vector3 val = facing + Vector3.up * 1.5f; devAutopilot.prototypeAim = ((Vector3)(ref val)).normalized; pilot.inputBank.skill4.down = true; pilot.inputBank.aimDirection = prototypeAim; bool launch = special.ExecuteIfReady(); yield return FixedSeconds(0.12f); ProjectileController lead = ((IEnumerable<ProjectileController>)NativeHellfires()).SingleOrDefault((Func<ProjectileController, bool>)((ProjectileController p) => p.combo == 0)); if (!Object.op_Implicit((Object)(object)lead)) { throw new InvalidOperationException("Braking guidance has no unique native lead."); } AH64HellfireGuidance guidance = ((Component)lead).GetComponent<AH64HellfireGuidance>(); AH64HellfireOwner owner = ((Component)pilot).GetComponent<AH64HellfireOwner>(); uint token = guidance.Token; Vector3 heading = ((Component)lead).transform.forward; bool activate = utility.ExecuteIfReady(); yield return FixedSeconds(0.08f); BrakingCheck("guidance.entry", launch && activate && Machine("Body").state is BrakingTurn && token != 0 && owner.Policy.CanGuide(token, Time.fixedTime), "braking=" + ((object)Machine("Body").state).GetType().Name + " token=" + token); prototypeAim = Quaternion.AngleAxis(30f, Vector3.up) * prototypeAim; pilot.inputBank.aimDirection = prototypeAim; bool primary = pilot.skillLocator.primary.ExecuteIfReady(); bool hydra = pilot.skillLocator.secondary.ExecuteIfReady(); yield return FixedSeconds(0.3f); BrakingCheck("guidance.turn-weapons", Object.op_Implicit((Object)(object)lead) && Machine("Body").state is BrakingTurn && primary && hydra && owner.Policy.CanGuide(token, Time.fixedTime) && guidance.LastTurnDegrees > 0f && Vector3.Angle(heading, ((Component)lead).transform.forward) > 0.1f, "primary=" + primary + " hydra=" + hydra + " active=" + owner.Policy.ActiveToken + " turn=" + (Object.op_Implicit((Object)(object)lead) ? Vector3.Angle(heading, ((Component)lead).transform.forward) : (-1f))); prototypeHeld = false; pilot.inputBank.skill4.down = false; yield return FixedSeconds(0.12f); Vector3 coast = (Object.op_Implicit((Object)(object)lead) ? ((Component)lead).transform.forward : Vector3.zero); prototypeAim = Quaternion.AngleAxis(-90f, Vector3.up) * prototypeAim; yield return FixedSeconds(0.2f); BrakingCheck("guidance.release", Object.op_Implicit((Object)(object)lead) && owner.Policy.ActiveToken == 0 && Vector3.Angle(coast, ((Component)lead).transform.forward) < 0.01f, "active=" + owner.Policy.ActiveToken + "; native release coasts"); yield return Until(() => NativeHellfires().Length == 0, 12f, "braking Hellfire drain"); BrakingCheck("guidance.drain", NativeHellfires().Length == 0 && !(Machine("Body").state is BrakingTurn) && !((Component)pilot).GetComponent<AH64BrakingTurnMotor>().HasActiveLease, "all native guided missiles drained; no damage/hit claim"); } finally { DevAutopilot devAutopilot2 = this; devAutopilot2.prototypeHeld = false; devAutopilot2.prototypeAim = Vector3.zero; utility.UnsetSkillOverride((object)devAutopilot2, brake, (SkillOverridePriority)4); special.UnsetSkillOverride((object)devAutopilot2, hellfire, (SkillOverridePriority)4); } } private void ObserveBrakingPhysics() { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) if (brakingStarted) { AH64BrakingTurnMotor component = ((Component)pilot).GetComponent<AH64BrakingTurnMotor>(); AH64HoverController component2 = ((Component)pilot).GetComponent<AH64HoverController>(); AH64FlightVisuals component3 = ((Component)pilot).GetComponent<AH64FlightVisuals>(); BrakingTurn brakingTurn = Machine("Body").state as BrakingTurn; AH64BrakingTurnPresentation component4 = ((Component)pilot).GetComponent<AH64BrakingTurnPresentation>(); AH64BrakingTurnFrame frame = default(AH64BrakingTurnFrame); bool flag = brakingTurn != null && Object.op_Implicit((Object)(object)component4) && component4.TryGetFrame(brakingTurn, out frame); Write(new BrakingSample { recordType = "braking-sample", runId = Path.GetFileName(output), scenario = segment, tick = tick, simulationTime = Time.fixedTime, capture = ((brakingTurn != null) ? JsonUtility.ToJson((object)brakingTurn.EntrySnapshot) : "none"), phase = (flag ? frame.Phase.ToString() : "inactive"), progress = (brakingTurn?.ManeuverProgress ?? 0f), commandedHeading = frame.CommandedHeading, position = ((Component)pilot).gameObject.transform.position, velocity = pilot.characterMotor.velocity, nativeAim = pilot.inputBank.aimDirection, targetHeight = component2.TargetHeight, airtime = component2.Airtime, groundDistance = component2.GroundDistance, ascending = component2.IsAscending, appliedAge = (Object.op_Implicit((Object)(object)component) ? component.AppliedAge : 0f), appliedSteps = (Object.op_Implicit((Object)(object)component) ? component.AppliedSteps : 0), nativeVelocity = (Object.op_Implicit((Object)(object)component) ? component.LastNativeVelocity : Vector3.zero), appliedVelocity = (Object.op_Implicit((Object)(object)component) ? component.LastAppliedVelocity : Vector3.zero), lease = (Object.op_Implicit((Object)(object)component) && component.HasActiveLease), yieldReason = (Object.op_Implicit((Object)(object)component) ? component.YieldReason : "none"), visualOwner = (Object.op_Implicit((Object)(object)component3) && component3.HasBrakingOwner), visualRecovery = (Object.op_Implicit((Object)(object)component3) && component3.IsBrakingRecovering), displayedBaseWorld = (Object.op_Implicit((Object)(object)component3) ? component3.RenderedBaseWorld : Quaternion.identity) }); } } private void LateUpdate() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) if (brakingStarted && scripting && !finished && Object.op_Implicit((Object)(object)pilot)) { Quaternion rotation = pilot.modelLocator.modelTransform.rotation; AH64FlightVisuals component = ((Component)pilot).GetComponent<AH64FlightVisuals>(); bool flag = Object.op_Implicit((Object)(object)component) && (component.HasBrakingOwner || component.IsBrakingRecovering); float num = ((brakingHasRender && brakingRenderEpoch == poseEpoch) ? Quaternion.Angle(brakingPreviousRender, rotation) : 0f); float num2 = 5f + 360f * Time.deltaTime; if (brakingHasRender && brakingRenderEpoch == poseEpoch && (flag || brakingPreviousVisualActive) && num > num2) { brakingRenderViolations++; } Write(new BrakingRender { recordType = "braking-render", runId = Path.GetFileName(output), scenario = segment, renderedTime = Time.time, renderDeltaTime = Time.deltaTime, poseEpoch = poseEpoch, worldAttitude = rotation, observedDelta = num, alarmBound = num2, visualActive = flag, bodyState = ((object)Machine("Body").state).GetType().Name }); brakingPreviousRender = rotation; brakingHasRender = true; brakingRenderEpoch = poseEpoch; brakingRenderSamples++; brakingPreviousVisualActive = flag; } } private bool FinishBrakingEvidence() { if (Environment.GetEnvironmentVariable("AH64_AUTOPILOT_BRAKING_CHECKS") != "braking-solo-v1") { return true; } string[] array = new string[2] { "catalog.order", "catalog.definition" }.Concat(BrakingCaseNames.SelectMany((string n) => BrakingCaseChecks.Select((string c) => n + "." + c))).Concat(new string[4] { "guidance.entry", "guidance.turn-weapons", "guidance.release", "guidance.drain" }).ToArray(); bool flag = brakingStarted && brakingComplete && brakingChecks.Count == array.Length && brakingChecks.All((Check c) => c.passed) && brakingChecks.Select((Check c) => c.id).Distinct().Count() == array.Length && !array.Except(brakingChecks.Select((Check c) => c.id)).Any() && brakingRenderSamples > 0 && brakingRenderViolations == 0; File.WriteAllText(Path.Combine(output, "braking-result.json"), JsonUtility.ToJson((object)new BrakingResult { runId = Path.GetFileName(output), sourceSha = JsonUtility.FromJson<StageIdentity>(File.ReadAllText(Path.Combine(output, "identity.json"))).sourceSha, dllSha256 = Hash(typeof(AH64Plugin).Assembly.Location), suite = "braking-solo-v1", status = (flag ? "passed" : "failed"), complete = brakingComplete, expectedChecks = array.Length, expectedIds = array, checks = brakingChecks.ToArray(), renderSamples = brakingRenderSamples, renderViolations = brakingRenderViolations, utilityInterruptPriority = ((object)Unsafe.As<InterruptPriority, InterruptPriority>(ref Variant(pilot.skillLocator.utility, typeof(BrakingTurn)).interruptPriority)/*cast due to .constrained prefix*/).ToString(), limitation = "SOLO scripted input, initial velocity and isolated inventory/overrides. No new braking screenshots. The five baseline images do not show braking. Physical modern descend, native geometry/force/item edge fixtures, targeted hits/audio, controller feel, peers and long sessions remain unverified. Render bound is a coarse alarm. Raw strict runtime failures retain independent blocking/classification." }, true)); return flag; } private void CheckWindowCapturePhase() { if (pendingCapture != null) { capturePhaseChecks++; if (!Object.op_Implicit((Object)(object)pilot) || ((Object)((Component)pilot).gameObject).GetInstanceID() != pendingCapture.bodyId || segment != pendingCapture.phase || ((object)Machine("Body").state).GetType().FullName != pendingCapture.bodyState || ((object)Machine("Weapon2").state).GetType().FullName != pendingCapture.weaponState || (pendingCapture.requiresProjectile && OwnedProjectiles() == 0)) { capturePhaseInvalid = true; } } } private IEnumerator Capture(string name) { if (Environment.GetEnvironmentVariable("AH64_AUTOPILOT_WINDOW_CAPTURE") != "1") { throw new InvalidOperationException("Baseline requires its explicitly configured owned-window helper."); } yield return (object)new WaitForEndOfFrame(); WindowCaptureStage windowCaptureStage = JsonUtility.FromJson<WindowCaptureStage>(File.ReadAllText(Path.Combine(output, "identity.json"))); string directory = Path.Combine(output, "window-captures"); Directory.CreateDirectory(directory); WindowCaptureRequest request = (pendingCapture = new WindowCaptureRequest { runId = Path.GetFileName(output), token = Guid.NewGuid().ToString("N"), name = name, phase = segment, bodyId = ((Object)((Component)pilot).gameObject).GetInstanceID(), bodyName = ((Object)((Component)pilot).gameObject).name, bodyState = ((object)Machine("Body").state).GetType().FullName, weaponState = ((object)Machine("Weapon2").state).GetType().FullName, requiresProjectile = (name == "hellfire-launched"), pid = Process.GetCurrentProcess().Id, executable = Path.Combine(windowCaptureStage.gameDirectory, "Risk of Rain 2.exe"), sourceSha = windowCaptureStage.sourceSha, owner = windowCaptureStage.owner, reservation = windowCaptureStage.reservation, lockPath = windowCaptureStage.runtimeLockPath, requestFrame = Time.frameCount, requestFixedTime = Time.fixedTime, requestRealtime = Time.realtimeSinceStartup, requestedUtc = DateTime.UtcNow.ToString("o") }); capturePhaseInvalid = false; capturePhaseChecks = 0; string text = Path.Combine(directory, request.token + ".request.json"); string ackPath = Path.Combine(directory, request.token + ".ack.json"); try { CheckWindowCapturePhase(); File.WriteAllText(text + ".tmp", JsonUtility.ToJson((object)request, true)); File.Move(text + ".tmp", text); Event("capture-request", name + "; token=" + request.token + "; frame=" + request.requestFrame + "; utc=" + request.requestedUtc); float deadline = Time.realtimeSinceStartup + 10f; while (!File.Exists(ackPath)) { CheckWindowCapturePhase(); if (capturePhaseInvalid) { throw new InvalidOperationException("Requested capture phase expired: " + name); } if (Time.realtimeSinceStartup > deadline) { throw new TimeoutException("Owned-window acknowledgement: " + name); } yield return null; } CheckWindowCapturePhase(); WindowCaptureAck windowCaptureAck = JsonUtility.FromJson<WindowCaptureAck>(File.ReadAllText(ackPath)); string path = Path.Combine(output, name + ".png"); WindowCaptureContract.Validate(request, windowCaptureAck, capturePhaseInvalid, Hash(path), File.ReadAllBytes(path), DateTime.UtcNow); File.WriteAllText(Path.Combine(directory, request.token + ".phase.json"), JsonUtility.ToJson((object)new WindowPhaseEvidence { runId = request.runId, token = request.token, phaseValid = true, phaseChecks = capturePhaseChecks, confirmedFrame = Time.frameCount, confirmedFixedTime = Time.fixedTime, confirmedUtc = DateTime.UtcNow.ToString("o"), limitation = "State/body/phase observed at frame and physics cadence through acknowledgement; request frame is not the captured rendered frame; simulation never paused" }, true)); captures++; Event("capture", name + ".png; token=" + request.token + "; source=owned-game-window; interval=" + windowCaptureAck.startedUtc + ".." + windowCaptureAck.finishedUtc + "; state/phase retained; no exact rendered-frame claim; controller/audio unverified"); } finally { pendingCapture = null; } } internal static void TryStart() { //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_0084: Expected O, but got Unknown string environmentVariable = Environment.GetEnvironmentVariable("AH64_AUTOPILOT_DIR"); if (!(Environment.GetEnvironmentVariable("AH64_AUTOPILOT_MODE") != "solo-baseline-v1") && !string.IsNullOrEmpty(environmentVariable)) { if (!Path.IsPathRooted(environmentVariable) || !Directory.Exists(environmentVariable) || !File.Exists(Path.Combine(environmentVariable, "identity.json"))) { throw new InvalidOperationException("AH64 autopilot requires an existing absolute run directory and staged identity."); } if (File.Exists(Path.Combine(environmentVariable, "telemetry.jsonl"))) { throw new InvalidOperationException("AH64 autopilot refuses reused output."); } GameObject val = new GameObject("AH64DevAutopilot"); Object.DontDestroyOnLoad((Object)val); DevAutopilot devAutopilot = val.AddComponent<DevAutopilot>(); devAutopilot.output = environmentVariable; devAutopilot.started = Time.realtimeSinceStartup; devAutopilot.OpenEvidence(); devAutopilot.InstallHooks(); devAutopilot.InstallBombingProbeHooks(); ((MonoBehaviour)devAutopilot).StartCoroutine(devAutopilot.Guarded(devAutopilot.Script())); } } private void InstallHooks() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnLoaded)); NetworkUser.onPostNetworkUserStart += new NetworkUserGenericDelegate(OnNetworkStarted); Application.logMessageReceived += new LogCallback(OnLog); PlayerCharacterMasterController.FixedUpdate += new hook_FixedUpdate(AfterInput); PlayerCharacterMasterController.Update += new hook_Update(AfterAim); ProjectileManager.FireProjectile_FireProjectileInfo += new hook_FireProjectile_FireProjectileInfo(OnProjectile); AH64BombingRunTrace.Emitted += OnBombingTrace; } private void OnDestroy() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(OnLoaded)); NetworkUser.onPostNetworkUserStart -= new NetworkUserGenericDelegate(OnNetworkStarted); Application.logMessageReceived -= new LogCallback(OnLog); PlayerCharacterMasterController.FixedUpdate -= new hook_FixedUpdate(AfterInput); PlayerCharacterMasterController.Update -= new hook_Update(AfterAim); ProjectileManager.FireProjectile_FireProjectileInfo -= new hook_FireProjectile_FireProjectileInfo(OnProjectile); AH64BombingRunTrace.Emitted -= OnBombingTrace; CleanupBombingProbe(); if (output != null && !finished) { Finish("incomplete", "runner destroyed"); } } private void OnLoaded() { gameLoaded = true; } private void Update() { CheckWindowCapturePhase(); if (finished) { if (Time.realtimeSinceStartup >= quitAt) { Application.Quit(terminalExit); } return; } if (Time.realtimeSinceStartup - started > 240f) { Finish("incomplete", "runtime deadline"); } if (NetworkUser.readOnlyInstancesList.Count > 1 || LocalUserManager.readOnlyLocalUsersList.Count > 1) { Finish("failed", "solo guard: multiple users"); } } private IEnumerator Guarded(IEnumerator root) { Stack<IEnumerator> stack = new Stack<IEnumerator>(); stack.Push(root); while (stack.Count > 0 && !finished) { object obj = null; bool flag = false; try { flag = stack.Peek().MoveNext(); if (flag) { obj = stack.Peek().Current; } } catch (Exception ex) { Finish("failed", "script exception: " + ex); } if (finished) { yield break; } if (!flag) { stack.Pop(); } else if (obj is IEnumerator item) { stack.Push(item); } else { yield return obj; } } if (!finished) { Finish("completed", "script ended"); } } private IEnumerator Until(Func<bool> predicate, float timeout, string reason) { float end = Time.realtimeSinceStartup + timeout; while (!predicate()) { if (Time.realtimeSinceStartup > end) { throw new TimeoutException(reason); } yield return null; } } private unsafe IEnumerator Script() { yield return Bootstrap(); DisableCombatDirectors(); pilot.AddBuff(Buffs.HiddenInvincibility); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(new Vector3(-112.88f, -