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 AH64Crew v0.3.1
BepInEx/plugins/AH64Crew/AH64Crew.dll
Decompiled a day agousing 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.Versioning; using AH64; using AH64.Modules.Characters; using AH64.Survivors; using AH64.Survivors.Components; using AH64.Survivors.SkillStates; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Railgunner.Scope; using EntityStates.TitanMonster; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using R2API; using R2API.Utils; using RoR2; using RoR2.ContentManagement; using RoR2.Skills; using RoR2.UI; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AH64Crew { internal static class AbilityContent { [CompilerGenerated] private static class <>O { public static StatHookEventHandler <0>__Stats; } internal static SkillDef Minigun; internal static SkillDef Scope; internal static SkillDef Laser; internal static SkillDef Overdrive; internal static BuffDef Boost; internal static BuffDef Defense; internal static BuffDef OverdriveDamage; internal static SkillDef[] OnFootSkills; internal static void Build(ContentPack pack, GameObject pilot, GameObject gunner) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) Boost = Buff("AH64CrewBoost", new Color(0.2f, 0.8f, 1f)); Defense = Buff("AH64CrewDefense", new Color(0.3f, 1f, 0.4f)); OverdriveDamage = Buff("AH64CrewOverdriveDamage", new Color(1f, 0.75f, 0.2f)); pack.buffDefs.Add((BuffDef[])(object)new BuffDef[3] { Boost, Defense, OverdriveDamage }); object obj = <>O.<0>__Stats; if (obj == null) { StatHookEventHandler val = Stats; <>O.<0>__Stats = val; obj = (object)val; } RecalculateStatsAPI.GetStatCoefficients += (StatHookEventHandler)obj; AddMachine(pilot, "CrewSupport"); AddMachine(gunner, "CrewScope"); AddMachine(gunner, "CrewSupport"); SkillLocator component = pilot.GetComponent<SkillLocator>(); SkillLocator component2 = gunner.GetComponent<SkillLocator>(); OnFootSkills = ((IEnumerable<GenericSkill>)(object)new GenericSkill[4] { component2.primary, component2.secondary, component2.utility, component2.special }).Select((GenericSkill slot) => slot.skillFamily.variants[0].skillDef).ToArray(); SkillDef val2 = Object.Instantiate<SkillDef>(component.secondary.skillFamily.variants[0].skillDef); Name(val2, "CrewRocketPods", "Rocket Pods", "Hold <style=cIsUtility>Primary</style> to fire explosive, unguided rockets from the wing pods. <style=cIsUtility>24 rocket charges.</style> Reload speed increases with <style=cIsDamage>attack speed</style>. Aim ahead of moving enemies and use the explosions to hit clustered targets."); val2.activationState = new SerializableEntityStateType(typeof(PilotRockets)); val2.baseMaxStock = 24; val2.attackSpeedBuffsRestockSpeed = true; val2.attackSpeedBuffsRestockSpeed_Multiplier = 1f; SkillDef val3 = Object.Instantiate<SkillDef>(component.special.skillFamily.variants.First((Variant v) => ((SerializableEntityStateType)(ref v.skillDef.activationState)).stateType == typeof(PaintLongbow)).skillDef); Name(val3, "CrewMissileBarrage", "Lock-On Barrage", "Hold <style=cIsUtility>Secondary</style> and aim at enemies to acquire locks. Release to launch <style=cIsDamage>homing missiles</style> at the marked targets. Stack multiple locks on one enemy for focused damage."); val3.activationState = new SerializableEntityStateType(typeof(PilotBarrage)); SkillDef val4 = Object.Instantiate<SkillDef>(component.utility.skillFamily.variants.First((Variant v) => ((SerializableEntityStateType)(ref v.skillDef.activationState)).stateType == typeof(ServoDash)).skillDef); Name(val4, "CrewFlightBoost", "Boosted Evasive Roll", "Perform the AH-64's evasive barrel roll with its flares and brief protection. Gain <style=cIsUtility>+100% movement speed</style> and faster climbing and descent for <style=cIsUtility>3 seconds</style>. <style=cSub>Base cooldown: 8 seconds.</style>"); val4.activationState = new SerializableEntityStateType(typeof(PilotBoost)); val4.baseRechargeInterval = 8f; SkillDef val5 = Skill<SkillDef, PilotDefense>("CrewCountermeasures", "Defensive Countermeasures", "Immediately gain <style=cIsHealing>barrier equal to 30% of maximum health and shields</style>. Gain <style=cIsHealing>100 armor</style> for <style=cIsUtility>5 seconds</style>. Barrier decays normally. <style=cSub>Base cooldown: 18 seconds.</style>", "CrewSupport", 18f, component.special.skillFamily.variants[0].skillDef.icon); SetFamily(pack, component.primary, val2); SetFamily(pack, component.secondary, val3); SetFamily(pack, component.utility, val4); SetFamily(pack, component.special, val5); Minigun = (SkillDef)(object)Skill<MagazineSkillDef, GunnerShot>("CrewMinigun", "Minigun", string.Format(CultureInfo.InvariantCulture, "Hold to fire the mounted minigun at <style=cIsDamage>{0:0.#} rounds per second</style> for <style=cIsDamage>{1:0.#}% damage per round</style>. Attack speed increases fire rate. <style=cIsUtility>100-round magazine</style>; reloads automatically when empty in <style=cIsUtility>2.5 seconds</style>. Scoped weak-point hits critically strike.", Plugin.FireRate.Value, Plugin.Damage.Value * 100f), "Weapon", 2.5f, AbilityIcons.Load("minigun")); Minigun.baseMaxStock = 100; Minigun.stockToConsume = 0; Minigun.mustKeyPress = false; Minigun.resetCooldownTimerOnUse = true; Minigun.autoHandleLuminousShot = false; Scope = Skill<SkillDef, GunnerScope>("CrewScope", "Weak-Point Scope", "Hold to zoom into a <style=cIsUtility>precision targeting scope</style> and reveal enemy weak points. Minigun hits on highlighted weak points <style=cIsDamage>critically strike</style>. Release to return to third-person aim. <style=cSub>No cooldown.</style>", "CrewScope", 0f, AbilityIcons.Load("scope")); Scope.stockToConsume = 0; Scope.mustKeyPress = false; Laser = Skill<SkillDef, GunnerLaser>("CrewTitanLaser", "Titan Laser", "Charge for <style=cIsUtility>2 seconds</style>, then aim a continuous Stone Titan beam for <style=cIsUtility>6 seconds</style>, dealing <style=cIsDamage>1800% damage per second</style>. Minigun fire pauses during the attack. <style=cSub>Base cooldown: 12 seconds.</style>", "Weapon", 12f, AbilityIcons.Load("laser")); Laser.interruptPriority = (InterruptPriority)2; Overdrive = Skill<SkillDef, GunnerOverdrive>("CrewAmmoOverdrive", "Ammo Overdrive", "Instantly <style=cIsUtility>refill the minigun magazine</style>. For <style=cIsUtility>6 seconds</style>, gain <style=cIsDamage>+10% damage</style> in addition to <style=cIsDamage>50% faster minigun fire</style>, and consume <style=cIsUtility>no ammunition</style>. Can refill during reload. <style=cSub>Base cooldown: 18 seconds.</style>", "CrewSupport", 18f, AbilityIcons.Load("overdrive")); SetFamily(pack, component2.primary, Minigun); SetFamily(pack, component2.secondary, Scope); SetFamily(pack, component2.utility, Laser); SetFamily(pack, component2.special, Overdrive); AbilityValidation.CheckMenu(gunner); pack.skillDefs.Add((SkillDef[])(object)new SkillDef[8] { val2, val3, val4, val5, Minigun, Scope, Laser, Overdrive }); pack.entityStateTypes.Add(new Type[8] { typeof(PilotRockets), typeof(PilotBarrage), typeof(PilotBoost), typeof(PilotDefense), typeof(GunnerShot), typeof(GunnerScope), typeof(GunnerLaser), typeof(GunnerOverdrive) }); } private static BuffDef Buff(string name, Color color) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) BuffDef obj = ScriptableObject.CreateInstance<BuffDef>(); ((Object)obj).name = name; obj.buffColor = color; obj.canStack = false; return obj; } private static void Stats(CharacterBody body, StatHookEventArgs args) { if (Object.op_Implicit((Object)(object)Boost) && body.HasBuff(Boost)) { args.moveSpeedMultAdd += 1f; } if (Object.op_Implicit((Object)(object)Defense) && body.HasBuff(Defense)) { args.armorAdd += 100f; } if (Object.op_Implicit((Object)(object)OverdriveDamage) && body.HasBuff(OverdriveDamage)) { args.damageMultAdd += 0.1f; } } internal static void Dispose() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown object obj = <>O.<0>__Stats; if (obj == null) { StatHookEventHandler val = Stats; <>O.<0>__Stats = val; obj = (object)val; } RecalculateStatsAPI.GetStatCoefficients -= (StatHookEventHandler)obj; } private static T Skill<T, S>(string name, string title, string description, string machine, float cooldown, Sprite icon) where T : SkillDef where S : EntityState { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) T val = ScriptableObject.CreateInstance<T>(); Name((SkillDef)(object)val, name, title, description); ((SkillDef)val).activationState = new SerializableEntityStateType(typeof(S)); ((SkillDef)val).activationStateMachineName = machine; ((SkillDef)val).baseMaxStock = (((SkillDef)val).rechargeStock = (((SkillDef)val).requiredStock = (((SkillDef)val).stockToConsume = 1))); ((SkillDef)val).baseRechargeInterval = cooldown; ((SkillDef)val).fullRestockOnAssign = true; ((SkillDef)val).mustKeyPress = true; ((SkillDef)val).cancelSprintingOnActivation = false; ((SkillDef)val).canceledFromSprinting = false; ((SkillDef)val).interruptPriority = (InterruptPriority)1; ((SkillDef)val).icon = icon; return val; } private static void Name(SkillDef s, string name, string title, string description) { ((Object)s).name = name; s.skillName = name; s.skillNameToken = name + "_NAME"; s.skillDescriptionToken = name + "_DESCRIPTION"; LanguageAPI.Add(s.skillNameToken, title); LanguageAPI.Add(s.skillDescriptionToken, description); } internal static void SetFamily(ContentPack pack, GenericSkill slot, SkillDef skill) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) SkillFamily val = ScriptableObject.CreateInstance<SkillFamily>(); ((Object)val).name = skill.skillName + "Family"; Variant[] array = new Variant[1]; Variant val2 = new Variant { skillDef = skill }; ((Variant)(ref val2)).viewableNode = new Node(skill.skillNameToken, false, (Node)null); array[0] = val2; val.variants = (Variant[])(object)array; typeof(GenericSkill).GetField("_skillFamily", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(slot, val); pack.skillFamilies.Add((SkillFamily[])(object)new SkillFamily[1] { val }); } private static void AddMachine(GameObject prefab, string name) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) EntityStateMachine val = prefab.AddComponent<EntityStateMachine>(); val.customName = name; val.initialStateType = (val.mainStateType = new SerializableEntityStateType(typeof(Idle))); NetworkStateMachine component = prefab.GetComponent<NetworkStateMachine>(); FieldInfo? field = typeof(NetworkStateMachine).GetField("stateMachines", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); EntityStateMachine[] first = (EntityStateMachine[])field.GetValue(component); field.SetValue(component, first.Concat((IEnumerable<EntityStateMachine>)(object)new EntityStateMachine[1] { val }).ToArray()); CharacterDeathBehavior component2 = prefab.GetComponent<CharacterDeathBehavior>(); if (Object.op_Implicit((Object)(object)component2)) { component2.idleStateMachine = component2.idleStateMachine.Concat((IEnumerable<EntityStateMachine>)(object)new EntityStateMachine[1] { val }).ToArray(); } SetStateOnHurt component3 = prefab.GetComponent<SetStateOnHurt>(); if (Object.op_Implicit((Object)(object)component3)) { component3.idleStateMachine = component3.idleStateMachine.Concat((IEnumerable<EntityStateMachine>)(object)new EntityStateMachine[1] { val }).ToArray(); } CharacterBody component4 = prefab.GetComponent<CharacterBody>(); component4.vehicleIdleStateMachine = component4.vehicleIdleStateMachine.Concat((IEnumerable<EntityStateMachine>)(object)new EntityStateMachine[1] { val }).ToArray(); } } internal static class AbilityIcons { internal static Sprite Load(string name) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AH64Crew.Icons." + name + ".png"); if (stream == null) { throw new InvalidOperationException("Missing ability icon: " + name); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ((Object)val).name = "CrewIcon_" + name; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), true)) { throw new InvalidOperationException("Invalid ability icon: " + name); } Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)obj).name = ((Object)val).name; return obj; } } internal static class AbilityValidation { internal static void CheckMenu(GameObject gunner) { SkillDef skillDef = ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab.GetComponent<SkillLocator>().primary.skillFamily.variants[0].skillDef; Require(skillDef.baseMaxStock == 24 && skillDef.attackSpeedBuffsRestockSpeed && skillDef.attackSpeedBuffsRestockSpeed_Multiplier == 1f, "24 rockets with attack-speed reload scaling"); SkillDef skillDef2 = ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab.GetComponent<SkillLocator>().utility.skillFamily.variants[0].skillDef; Require(((SerializableEntityStateType)(ref skillDef2.activationState)).stateType == typeof(PilotBoost) && skillDef2.activationStateMachineName == "Body" && typeof(ServoDash).IsAssignableFrom(typeof(PilotBoost)), "Native roll on Body state machine"); Require(Object.op_Implicit((Object)(object)AbilityContent.OverdriveDamage), "Overdrive damage buff"); SkillLocator component = gunner.GetComponent<SkillLocator>(); GenericSkill[] array = (GenericSkill[])(object)new GenericSkill[4] { component.primary, component.secondary, component.utility, component.special }; SkillDef[] array2 = (SkillDef[])(object)new SkillDef[4] { AbilityContent.Minigun, AbilityContent.Scope, AbilityContent.Laser, AbilityContent.Overdrive }; Require(AbilityContent.Minigun.baseMaxStock == 100, "100-round gunner magazine"); Require(AbilityContent.OnFootSkills.Length == 4, "Four preserved on-foot skills"); for (int i = 0; i < array.Length; i++) { Require((Object)(object)array[i].skillFamily.variants[0].skillDef == (Object)(object)array2[i], "Mounted menu skill " + i); Require(Object.op_Implicit((Object)(object)array2[i].icon) && ((Texture)array2[i].icon.texture).width > 1, "Generated icon " + i); Require(Object.op_Implicit((Object)(object)AbilityContent.OnFootSkills[i]) && (Object)(object)AbilityContent.OnFootSkills[i] != (Object)(object)array2[i], "Separate on-foot skill " + i); } Require(value: true, "Seat loadout priority"); Plugin.Log.LogInfo((object)"MENU CHECK PASS: 100-round gunner magazine; native boosted roll and Overdrive buff; 24 rockets with attack-speed reload; four mounted skill families, four generated icons, separate on-foot skills and seat priority."); } internal static void Run() { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Invalid comparison between Unknown and I4 //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Invalid comparison between Unknown and I4 //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Expected O, but got Unknown //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Expected O, but got Unknown if (!Plugin.CrewEnabled.Value) { return; } try { GameObject val = BodyCatalog.FindBodyPrefab("AH64CrewEjectedPilotBody"); Require(Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)val.GetComponent<CrewGunner>()), "Separate ejected pilot body"); SkillLocator component = val.GetComponent<SkillLocator>(); Require((Object)(object)component.primary.skillFamily.variants[0].skillDef == (Object)(object)AbilityContent.OnFootSkills[0] && (Object)(object)component.secondary.skillFamily.variants[0].skillDef == (Object)(object)AbilityContent.OnFootSkills[1] && (Object)(object)component.utility.skillFamily.variants[0].skillDef == (Object)(object)AbilityContent.OnFootSkills[2], "Commando first three skills"); Require((Object)(object)component.special.skillFamily.variants[0].skillDef == (Object)(object)PilotRecoveryContent.Rebuild && !((SkillDef)PilotRecoveryContent.Rebuild).fullRestockOnAssign && ((SkillDef)PilotRecoveryContent.Rebuild).baseRechargeInterval == 180f, "Rebuild starts on 180-second cooldown"); Require((int)PilotRecoveryContent.Countdown.buffIndex != -1 && (int)PilotRecoveryContent.Ready.buffIndex != -1, "Replicated rebuild timer buffs"); Require(EntityStateCatalog.InstantiateState(typeof(RebuildHelicopter)) is RebuildHelicopter, "Network rebuild state registration"); Plugin.Log.LogInfo((object)"RECOVERY CHECK PASS: Commando body, three basic skills, gated rebuild skill, timer buffs and network state registered. Gameplay not yet verified."); GameObject bodyPrefab = ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab; GameObject val2 = BodyCatalog.FindBodyPrefab("AH64CrewGunnerBody"); Require(Object.op_Implicit((Object)(object)val2), "Gunner body catalog entry"); SkillLocator component2 = bodyPrefab.GetComponent<SkillLocator>(); Require(((SerializableEntityStateType)(ref component2.primary.skillFamily.variants[0].skillDef.activationState)).stateType == typeof(PilotRockets), "Pilot rockets family"); Require(((SerializableEntityStateType)(ref component2.secondary.skillFamily.variants[0].skillDef.activationState)).stateType == typeof(PilotBarrage), "Pilot barrage family"); Require(((SerializableEntityStateType)(ref component2.utility.skillFamily.variants[0].skillDef.activationState)).stateType == typeof(PilotBoost), "Pilot boost family"); Require(((SerializableEntityStateType)(ref component2.special.skillFamily.variants[0].skillDef.activationState)).stateType == typeof(PilotDefense), "Pilot defense family"); EntityStateMachine[] source = (EntityStateMachine[])typeof(NetworkStateMachine).GetField("stateMachines", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(val2.GetComponent<NetworkStateMachine>()); Require(source.Any((EntityStateMachine m) => m.customName == "CrewScope") && source.Any((EntityStateMachine m) => m.customName == "CrewSupport"), "Networked gunner machines"); ActiveScopeHeavy val3 = new ActiveScopeHeavy(); FireMegaLaser val4 = new FireMegaLaser(); ChargeMegaLaser val5 = new ChargeMegaLaser(); Require(Object.op_Implicit((Object)(object)((BaseScopeState)val3).scopeOverlayPrefab) && Object.op_Implicit((Object)(object)((BaseScopeState)val3).cameraParams) && Object.op_Implicit((Object)(object)((BaseScopeState)val3).crosshairOverridePrefab), "Native Railgunner scope assets"); Require(Object.op_Implicit((Object)(object)val4.laserPrefab) && Object.op_Implicit((Object)(object)val4.hitEffectPrefab) && Object.op_Implicit((Object)(object)val5.effectPrefab), "Native Titan beam assets"); Require((Object)(object)bodyPrefab.GetComponent<VehicleSeat>().targetParams == (Object)null, "Independent passenger camera"); Plugin.Log.LogInfo((object)"ABILITY CHECK PASS: pilot loadout, gunner catalog/network machines, Railgunner scope and Titan beam assets. Gameplay not yet verified."); } catch (Exception ex) { Plugin.Log.LogError((object)("ABILITY CHECK FAILED: " + ex)); } } private static void Require(bool value, string name) { if (!value) { throw new InvalidOperationException(name); } } } internal sealed class CrewContent : IContentPackProvider { private readonly ContentPack pack = new ContentPack(); internal static GameObject Tracer; internal static GameObject HitEffect; internal static SeatBlockedSkill BlockedSkill; public string identifier => "local.ah64crew"; public void Initialize() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_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) ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)delegate(AddContentPackProviderDelegate add) { add.Invoke((IContentPackProvider)(object)this); }; GameObject bodyPrefab = ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab; Transform transform = new GameObject("CrewSeatAnchor").transform; transform.SetParent(bodyPrefab.transform, false); transform.localPosition = new Vector3(0f, 1f, 3f); Transform transform2 = new GameObject("CrewExit").transform; transform2.SetParent(bodyPrefab.transform, false); transform2.localPosition = new Vector3(4f, 0f, 0f); VehicleSeat obj = bodyPrefab.AddComponent<VehicleSeat>(); obj.seatPosition = transform; obj.exitPosition = transform2; obj.passengerState = new SerializableEntityStateType(typeof(GunnerSeated)); obj.hidePassenger = true; obj.disablePassengerMotor = true; obj.disableAllCollidersAndHurtboxes = true; obj.disableCharacterNetworkTransform = false; obj.smoothPassengerPosition = true; obj.inheritRotation = false; obj.shouldSetIdle = true; obj.ejectOnCollision = false; obj.enterVehicleContextString = "AH64CREW_BOARD"; obj.exitVehicleContextString = "AH64CREW_EXIT"; bodyPrefab.AddComponent<CrewSeat>(); LanguageAPI.Add("AH64CREW_BOARD", "Board gunner seat"); LanguageAPI.Add("AH64CREW_EXIT", "Leave gunner seat"); LanguageAPI.Add("AH64CREW_NAME", "Crew Gunner"); LanguageAPI.Add("AH64CREW_DESCRIPTION", "The <style=cIsUtility>Crew Gunner</style> turns an allied AH-64 into a flying weapons platform. Let your pilot handle the flight while you track targets, exploit weak points, and unleash sustained fire.\n\n<style=cIsDamage>Minigun</style> supplies steady fire. <style=cIsUtility>Weak-Point Scope</style> rewards precise aim. <style=cIsDamage>Titan Laser</style> burns down tough targets, while <style=cIsUtility>Ammo Overdrive</style> keeps the gun firing.\n\n<style=cSub>The abilities shown here are the mounted loadout. Requires another player to choose AH-64. Automatically boards at each stage start. Interact exits; on foot, uses Commando's basic kit.</style>"); LanguageAPI.Add("AH64CREW_OUTRO", "...and so they left, watching each other's backs."); } public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) { typeof(ContentPack).GetProperty("identifier").GetSetMethod(nonPublic: true).Invoke(pack, new object[1] { identifier }); Tracer = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Commando/TracerCommandoDefault.prefab").WaitForCompletion(); HitEffect = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Commando/HitsparkCommando.prefab").WaitForCompletion(); BlockedSkill = ScriptableObject.CreateInstance<SeatBlockedSkill>(); ((SkillDef)BlockedSkill).skillName = "AH64CrewSeated"; ((Object)BlockedSkill).name = "AH64CrewSeated"; ((SkillDef)BlockedSkill).skillNameToken = "AH64CREW_BOARD"; pack.skillDefs.Add((SkillDef[])(object)new SkillDef[1] { BlockedSkill }); SurvivorDef val = Addressables.LoadAssetAsync<SurvivorDef>((object)"RoR2/Base/Commando/Commando.asset").WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Could not load Commando survivor for the gunner."); } GameObject val2 = PrefabAPI.InstantiateClone(val.bodyPrefab, "AH64CrewGunnerBody", true); val2.GetComponent<CharacterBody>().baseNameToken = "AH64CREW_NAME"; val2.AddComponent<CrewGunner>(); AbilityContent.Build(pack, ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab, val2); PilotRecoveryContent.Build(pack, val.bodyPrefab); SurvivorDef val3 = ScriptableObject.CreateInstance<SurvivorDef>(); val3.cachedName = "AH64CrewGunner"; val3.bodyPrefab = val2; val3.displayPrefab = val.displayPrefab; val3.primaryColor = new Color(0.25f, 0.5f, 0.35f); val3.displayNameToken = "AH64CREW_NAME"; val3.descriptionToken = "AH64CREW_DESCRIPTION"; val3.outroFlavorToken = "AH64CREW_OUTRO"; val3.mainEndingEscapeFailureFlavorToken = "AH64CREW_OUTRO"; val3.desiredSortPosition = 101f; pack.bodyPrefabs.Add((GameObject[])(object)new GameObject[1] { val2 }); pack.survivorDefs.Add((SurvivorDef[])(object)new SurvivorDef[1] { val3 }); pack.entityStateTypes.Add(new Type[1] { typeof(GunnerSeated) }); Plugin.Log.LogInfo((object)"Crew Gunner body, survivor, seat state and effects registered."); args.ReportProgress(1f); yield break; } public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) { ContentPack.Copy(pack, args.output); args.ReportProgress(1f); yield break; } public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) { args.ReportProgress(1f); yield break; } } public sealed class CrewGunner : MonoBehaviour { private CharacterBody body; private float nextBoard; private Stage boardingStage; private bool initialBoardPending = true; internal bool Scoped; internal float OverdriveUntil; private int[] savedStock; private float[] savedRecharge; internal bool OverdriveActive => Time.time < OverdriveUntil; internal void SaveAmmo() { SkillLocator skillLocator = body.skillLocator; GenericSkill[] array = (GenericSkill[])(object)new GenericSkill[4] { skillLocator.primary, skillLocator.secondary, skillLocator.utility, skillLocator.special }; savedStock = new int[4]; savedRecharge = new float[4]; for (int i = 0; i < 4; i++) { savedStock[i] = array[i].stock; savedRecharge[i] = array[i].rechargeStopwatch; } Scoped = false; OverdriveUntil = 0f; if (NetworkServer.active && Object.op_Implicit((Object)(object)AbilityContent.OverdriveDamage)) { body.ClearTimedBuffs(AbilityContent.OverdriveDamage); } } internal void RestoreAmmo() { if (savedStock != null) { SkillLocator skillLocator = body.skillLocator; GenericSkill[] array = (GenericSkill[])(object)new GenericSkill[4] { skillLocator.primary, skillLocator.secondary, skillLocator.utility, skillLocator.special }; for (int i = 0; i < 4; i++) { array[i].stock = Mathf.Min(savedStock[i], array[i].maxStock); array[i].rechargeStopwatch = savedRecharge[i]; } } } private void Awake() { body = ((Component)this).GetComponent<CharacterBody>(); } private void Start() { SkillLocator skillLocator = body.skillLocator; GenericSkill[] array = (GenericSkill[])(object)new GenericSkill[4] { skillLocator.primary, skillLocator.secondary, skillLocator.utility, skillLocator.special }; for (int i = 0; i < array.Length; i++) { array[i].SetSkillOverride((object)this, AbilityContent.OnFootSkills[i], (SkillOverridePriority)3); } } public void PauseBoarding() { initialBoardPending = false; nextBoard = Time.time + 10f; } private void FixedUpdate() { //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !Object.op_Implicit((Object)(object)Stage.instance)) { return; } if (boardingStage != Stage.instance) { boardingStage = Stage.instance; initialBoardPending = true; nextBoard = 0f; } if (!Object.op_Implicit((Object)(object)body) || !body.isPlayerControlled || !Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive) { return; } if (Object.op_Implicit((Object)(object)body.currentVehicle)) { initialBoardPending = false; } else { if ((!initialBoardPending && !Plugin.AutoBoard.Value) || Time.time < nextBoard) { return; } nextBoard = Time.time + (initialBoardPending ? 0.1f : 1f); CrewSeat crewSeat = null; float num = (initialBoardPending ? float.PositiveInfinity : 625f); foreach (CrewSeat item in CrewSeat.Active) { if (Object.op_Implicit((Object)(object)item) && item.CanBoard(body)) { Vector3 val = ((Component)item).transform.position - ((Component)this).transform.position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { crewSeat = item; num = sqrMagnitude; } } } if (Object.op_Implicit((Object)(object)crewSeat)) { crewSeat.Seat.AssignPassenger(((Component)this).gameObject); if ((Object)(object)body.currentVehicle == (Object)(object)crewSeat.Seat) { initialBoardPending = false; } } } } } public sealed class CrewSeat : MonoBehaviour { internal static readonly HashSet<CrewSeat> Active = new HashSet<CrewSeat>(); private CharacterBody pilot; private AH64ChinTurret turret; private static readonly FieldInfo TurretInput = typeof(AH64ChinTurret).GetField("inputBank", BindingFlags.Instance | BindingFlags.NonPublic); public VehicleSeat Seat { get; private set; } private void Awake() { Seat = ((Component)this).GetComponent<VehicleSeat>(); pilot = ((Component)this).GetComponent<CharacterBody>(); Seat.targetParams = null; turret = ((Component)this).GetComponent<AH64ChinTurret>(); Seat.onPassengerExit += OnExit; Seat.onPassengerEnter += OnEnter; Seat.enterVehicleAllowedCheck.AddCallback((CallbackDelegate<Interactability, CharacterBody>)CheckBoard); Seat.handleVehicleEnterRequestServer.AddCallback((CallbackDelegate<bool, GameObject>)CheckRequest); Active.Add(this); } internal bool CanBoard(CharacterBody passenger) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)pilot) && pilot.isPlayerControlled && Object.op_Implicit((Object)(object)pilot.healthComponent) && pilot.healthComponent.alive && Object.op_Implicit((Object)(object)passenger) && Object.op_Implicit((Object)(object)((Component)passenger).GetComponent<CrewGunner>()) && passenger.healthComponent.alive && !Object.op_Implicit((Object)(object)passenger.currentVehicle) && (Object)(object)passenger != (Object)(object)pilot && passenger.teamComponent.teamIndex == pilot.teamComponent.teamIndex) { return !Seat.hasPassenger; } return false; } private void CheckBoard(CharacterBody passenger, ref Interactability? result) { if (!CanBoard(passenger)) { result = (Interactability)1; } } private void CheckRequest(GameObject passenger, ref bool? result) { if (!Object.op_Implicit((Object)(object)passenger) || !CanBoard(passenger.GetComponent<CharacterBody>())) { result = false; } } private void OnEnter(GameObject passenger) { if (Object.op_Implicit((Object)(object)passenger)) { ApplyLoadout(passenger, seated: true); passenger.GetComponent<CrewGunner>()?.RestoreAmmo(); } } private void ApplyLoadout(GameObject passenger, bool seated) { SkillLocator component = passenger.GetComponent<SkillLocator>(); Apply(component.primary, AbilityContent.Minigun, seated); Apply(component.secondary, AbilityContent.Scope, seated); Apply(component.utility, AbilityContent.Laser, seated); Apply(component.special, AbilityContent.Overdrive, seated); } private void Apply(GenericSkill slot, SkillDef skill, bool seated) { if (seated) { slot.SetSkillOverride((object)this, skill, (SkillOverridePriority)4); } else { slot.UnsetSkillOverride((object)this, skill, (SkillOverridePriority)4); } } private void Update() { if (Object.op_Implicit((Object)(object)turret) && Object.op_Implicit((Object)(object)pilot)) { TurretInput.SetValue(turret, Seat.hasPassenger ? Seat.currentPassengerInputBank : pilot.inputBank); } if (NetworkServer.active && Seat.hasPassenger && (!pilot.healthComponent.alive || !Object.op_Implicit((Object)(object)Seat.currentPassengerBody) || !Seat.currentPassengerBody.healthComponent.alive)) { Seat.EjectPassenger(); } } private void OnExit(GameObject passenger) { if (!Object.op_Implicit((Object)(object)passenger)) { return; } CrewGunner component = passenger.GetComponent<CrewGunner>(); component?.SaveAmmo(); EntityStateMachine[] components = passenger.GetComponents<EntityStateMachine>(); foreach (EntityStateMachine val in components) { if (val.state is GunnerScope || val.state is GunnerLaser || val.state is GunnerShot || val.state is GunnerOverdrive) { val.SetNextStateToMain(); } } ApplyLoadout(passenger, seated: false); component?.PauseBoarding(); } private void OnDestroy() { Active.Remove(this); if (Object.op_Implicit((Object)(object)Seat) && NetworkServer.active && Seat.hasPassenger) { Seat.EjectPassenger(); } if (Object.op_Implicit((Object)(object)Seat)) { Seat.onPassengerExit -= OnExit; Seat.onPassengerEnter -= OnEnter; Seat.enterVehicleAllowedCheck.RemoveCallback((CallbackDelegate<Interactability, CharacterBody>)CheckBoard); Seat.handleVehicleEnterRequestServer.RemoveCallback((CallbackDelegate<bool, GameObject>)CheckRequest); } } } public sealed class CrewGroundReference : MonoBehaviour { internal bool HasGround; internal float GroundY; internal float NextRecoveryLog; } internal sealed class FlightHooks : IDisposable { private delegate bool UpdateLaunch(Component self, float dt); private delegate bool GetBool(); private delegate void GaugeUpdate(Component self); private delegate float GetFloat(Component self); private delegate void UpdateAir(Component self, bool jump, float dt); private delegate void ApplyHover(Component self, bool jump, bool descend, float dt); private readonly List<Hook> hooks = new List<Hook>(); private readonly Type hover = typeof(AH64Plugin).Assembly.GetType("AH64.Survivors.Components.AH64HoverController", throwOnError: true); private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private readonly FieldInfo locked; private readonly FieldInfo holding; private readonly FieldInfo externalActive; private readonly FieldInfo externalAge; private readonly FieldInfo lastAirControl; private readonly FieldInfo altitude; private readonly FieldInfo altitudeValid; private readonly MethodInfo feetY; private readonly MethodInfo setAirtime; private readonly MethodInfo getBudget; public FlightHooks() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Expected O, but got Unknown //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Expected O, but got Unknown //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Expected O, but got Unknown //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Expected O, but got Unknown //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Expected O, but got Unknown Type type = typeof(AH64Plugin).Assembly.GetType("AH64.Survivors.Components.AH64AirtimeGauge", throwOnError: true); FieldInfo gaugeGroup = type.GetField("group", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); hooks.Add(new Hook((MethodBase)type.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)(Action<GaugeUpdate, Component>)delegate(GaugeUpdate orig, Component self) { object? value = gaugeGroup.GetValue(self); CanvasGroup val = (CanvasGroup)((value is CanvasGroup) ? value : null); if (Object.op_Implicit((Object)(object)val)) { val.alpha = 0f; } })); locked = hover.GetField("climbLocked", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); holding = hover.GetField("holdingAltitude", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); externalActive = hover.GetField("externalLaunchActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); externalAge = hover.GetField("externalLaunchAge", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); lastAirControl = hover.GetField("lastDisableAirControl", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); altitude = hover.GetField("pilotAltitude", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); altitudeValid = hover.GetField("pilotAltitudeValid", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); feetY = hover.GetMethod("FeetY", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); hooks.Add(new Hook((MethodBase)hover.GetMethod("UpdateExternalLaunch", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Func<UpdateLaunch, Component, float, bool>(ExternalLaunch))); MethodInfo getMethod = typeof(AH64Plugin).Assembly.GetType("AH64.Survivors.AH64PlaytestConfig", throwOnError: true).GetProperty("ClassicAltitude", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetGetMethod(nonPublic: true); hooks.Add(new Hook((MethodBase)getMethod, (Delegate)(Func<GetBool, bool>)((GetBool orig) => !Plugin.Unlimited.Value && orig()))); setAirtime = hover.GetProperty("Airtime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetSetMethod(nonPublic: true); getBudget = hover.GetMethod("GetAirtimeBudget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); hooks.Add(new Hook((MethodBase)hover.GetMethod("GetMaxRise", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Func<GetFloat, Component, float>(Rise))); hooks.Add(new Hook((MethodBase)hover.GetMethod("UpdateAirtime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<UpdateAir, Component, bool, float>(Airtime))); hooks.Add(new Hook((MethodBase)hover.GetMethod("ProbeGround", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Func<GetFloat, Component, float>(Ground))); hooks.Add(new Hook((MethodBase)hover.GetMethod("ApplyHover", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic), (Delegate)new Action<ApplyHover, Component, bool, bool, float>(BoostHover))); } private void BoostHover(ApplyHover orig, Component self, bool jump, bool descend, float dt) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (Plugin.Unlimited.Value) { holding.SetValue(self, true); locked.SetValue(self, false); setAirtime.Invoke(self, new object[1] { getBudget.Invoke(self, null) }); } CharacterBody component = self.GetComponent<CharacterBody>(); bool flag = Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)AbilityContent.Boost) && component.HasBuff(AbilityContent.Boost) && (jump || descend); orig(self, jump, descend, flag ? (dt * 2f) : dt); if (flag) { CharacterMotor component2 = self.GetComponent<CharacterMotor>(); if (Object.op_Implicit((Object)(object)component2)) { Vector3 moveDirection = component2.moveDirection; moveDirection.y *= 2f; component2.moveDirection = moveDirection; } } } private bool ExternalLaunch(UpdateLaunch orig, Component self, float dt) { if (!Plugin.Unlimited.Value) { return orig(self, dt); } CharacterMotor component = self.GetComponent<CharacterMotor>(); CharacterBody component2 = self.GetComponent<CharacterBody>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || !Object.op_Implicit((Object)(object)component2.healthComponent) || !component2.healthComponent.alive) { return orig(self, dt); } if (component.useCustomGravity && component.CustomGravity > 0f) { return orig(self, dt); } bool flag = (bool)externalActive.GetValue(self); bool flag2 = Object.op_Implicit((Object)(object)AbilityContent.Boost) && component2.HasBuff(AbilityContent.Boost); bool flag3 = (flag || component.disableAirControlUntilCollision) && component.velocity.y <= 0f; bool flag4 = flag2 && !component.disableAirControlUntilCollision; if (!flag3 && !flag4) { return orig(self, dt); } externalActive.SetValue(self, false); externalAge.SetValue(self, 0f); lastAirControl.SetValue(self, false); component.disableAirControlUntilCollision = false; if (flag3 || (flag4 && flag)) { altitude.SetValue(self, (float)feetY.Invoke(self, null)); altitudeValid.SetValue(self, true); holding.SetValue(self, true); CrewGroundReference component3 = self.GetComponent<CrewGroundReference>(); if (Object.op_Implicit((Object)(object)component3) && Time.time >= component3.NextRecoveryLog) { component3.NextRecoveryLog = Time.time + 5f; Plugin.Log.LogInfo((object)("FLIGHT RECOVERY: resumed altitude hold after external impulse/boost. Airtime=" + hover.GetProperty("Airtime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(self))); } } return false; } private float Rise(GetFloat orig, Component self) { return Mathf.Max(0f, orig(self) - 12f) + Plugin.MaxRise.Value; } private void Airtime(UpdateAir orig, Component self, bool jump, float dt) { if (!Plugin.Unlimited.Value) { orig(self, jump, dt); return; } locked.SetValue(self, false); setAirtime.Invoke(self, new object[1] { getBudget.Invoke(self, null) }); } private float Ground(GetFloat orig, Component self) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) CharacterMotor component = self.GetComponent<CharacterMotor>(); if (!Object.op_Implicit((Object)(object)component)) { return orig(self); } Vector3 position = self.transform.position; position.y += component.capsuleYOffset - component.capsuleHeight * 0.5f + 2f; CrewGroundReference crewGroundReference = self.GetComponent<CrewGroundReference>(); if (!Object.op_Implicit((Object)(object)crewGroundReference)) { crewGroundReference = self.gameObject.AddComponent<CrewGroundReference>(); } Vector3 val = position; Vector3 down = Vector3.down; LayerIndex world = LayerIndex.world; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, down, ref val2, 4096f, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1)) { crewGroundReference.GroundY = ((RaycastHit)(ref val2)).point.y; crewGroundReference.HasGround = true; return Mathf.Max(((RaycastHit)(ref val2)).distance - 2f, 0f); } if (Plugin.Unlimited.Value) { float num = position.y - 2f; if (!crewGroundReference.HasGround) { crewGroundReference.GroundY = num - 20f; crewGroundReference.HasGround = true; altitude.SetValue(self, num); altitudeValid.SetValue(self, true); holding.SetValue(self, true); hover.GetField("anchorGroundY", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(self, crewGroundReference.GroundY); hover.GetField("hasAnchor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(self, true); } crewGroundReference.GroundY = Mathf.Min(crewGroundReference.GroundY, num - 20f); return num - crewGroundReference.GroundY; } return -1f; } public void Dispose() { foreach (Hook hook in hooks) { hook.Dispose(); } } } internal static class GunnerAim { internal static bool Seated(CharacterBody body) { if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.currentVehicle)) { return Object.op_Implicit((Object)(object)((Component)body.currentVehicle).GetComponent<CrewSeat>()); } return false; } internal static Ray Ray(CharacterBody body) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) Ray aimRay = body.inputBank.GetAimRay(); VehicleSeat currentVehicle = body.currentVehicle; Vector3 val = (Object.op_Implicit((Object)(object)currentVehicle) ? currentVehicle.seatPosition.position : ((Ray)(ref aimRay)).origin); if (Object.op_Implicit((Object)(object)currentVehicle)) { CharacterBody component = ((Component)currentVehicle).GetComponent<CharacterBody>(); ChildLocator val2 = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.modelLocator) && Object.op_Implicit((Object)(object)component.modelLocator.modelTransform)) ? ((Component)component.modelLocator.modelTransform).GetComponent<ChildLocator>() : null); Transform val3 = (Object.op_Implicit((Object)(object)val2) ? val2.FindChild("Muzzle") : null); if (Object.op_Implicit((Object)(object)val3)) { val = val3.position; } } Vector3 point = ((Ray)(ref aimRay)).GetPoint(500f); Ray val4 = aimRay; LayerIndex world = LayerIndex.world; RaycastHit val5 = default(RaycastHit); if (Physics.Raycast(val4, ref val5, 500f, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1)) { point = ((RaycastHit)(ref val5)).point; } Vector3 val6 = val; Vector3 val7 = point - val; return new Ray(val6, ((Vector3)(ref val7)).normalized); } } public sealed class GunnerShot : BaseSkillState { private float duration; public override void OnEnter() { //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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0143: 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_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) ((BaseState)this).OnEnter(); CrewGunner component = ((EntityState)this).GetComponent<CrewGunner>(); bool flag = Object.op_Implicit((Object)(object)component) && component.Scoped; duration = 1f / Mathf.Clamp(Plugin.FireRate.Value * ((BaseState)this).attackSpeedStat * ((Object.op_Implicit((Object)(object)component) && component.OverdriveActive) ? 1.5f : 1f), 1f, 50f); if (GunnerAim.Seated(((EntityState)this).characterBody)) { Ray val = GunnerAim.Ray(((EntityState)this).characterBody); if (((EntityState)this).isAuthority) { new BulletAttack { owner = ((EntityState)this).gameObject, weapon = ((Component)((EntityState)this).characterBody.currentVehicle).gameObject, origin = ((Ray)(ref val)).origin, aimVector = ((Ray)(ref val)).direction, damage = ((BaseState)this).damageStat * Plugin.Damage.Value, force = 4f, bulletCount = 1u, maxDistance = 500f, radius = (flag ? 0f : 0.15f), maxSpread = (flag ? 0f : 0.5f), procCoefficient = 0.5f, isCrit = ((BaseState)this).RollCrit(), sniper = flag, falloffModel = (FalloffModel)0, hitMask = CommonMasks.bullet, stopperMask = CommonMasks.bullet, tracerEffectPrefab = CrewContent.Tracer, hitEffectPrefab = CrewContent.HitEffect }.Fire(); } Util.PlaySound("Play_commando_M1", ((EntityState)this).gameObject); } } public override void FixedUpdate() { ((EntityState)this).FixedUpdate(); if (((EntityState)this).isAuthority && ((EntityState)this).fixedAge >= duration) { ((EntityState)this).outer.SetNextStateToMain(); } } public override InterruptPriority GetMinimumInterruptPriority() { return (InterruptPriority)2; } } public sealed class GunnerScope : BaseScopeState { public override void OnEnter() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ActiveScopeHeavy val = new ActiveScopeHeavy(); base.scopeOverlayPrefab = ((BaseScopeState)val).scopeOverlayPrefab; base.crosshairOverridePrefab = ((BaseScopeState)val).crosshairOverridePrefab; base.cameraParams = ((BaseScopeState)val).cameraParams; base.cameraOverridePriority = 100f; ((BaseScopeState)this).OnEnter(); CrewGunner component = ((EntityState)this).GetComponent<CrewGunner>(); if (Object.op_Implicit((Object)(object)component)) { component.Scoped = true; } ((BaseScopeState)this).SetScopeAlpha(1f); if (Object.op_Implicit((Object)(object)base.cameraParams)) { ((BaseScopeState)this).StartScopeParamsOverride(0.1f); } } public override void FixedUpdate() { ((EntityState)this).FixedUpdate(); if (((EntityState)this).isAuthority && (!((EntityState)this).inputBank.skill2.down || !GunnerAim.Seated(((EntityState)this).characterBody))) { ((EntityState)this).outer.SetNextStateToMain(); } } public override void OnExit() { CrewGunner component = ((EntityState)this).GetComponent<CrewGunner>(); if (Object.op_Implicit((Object)(object)component)) { component.Scoped = false; } ((BaseScopeState)this).EndScopeParamsOverride(0.1f); ((BaseScopeState)this).OnExit(); } } public sealed class GunnerOverdrive : BaseSkillState { public override void OnEnter() { ((BaseState)this).OnEnter(); CrewGunner component = ((EntityState)this).GetComponent<CrewGunner>(); if (Object.op_Implicit((Object)(object)component)) { component.OverdriveUntil = Time.time + 6f; } if (NetworkServer.active) { ((EntityState)this).characterBody.AddTimedBuff(AbilityContent.OverdriveDamage, 6f); } ((EntityState)this).skillLocator.primary.stock = ((EntityState)this).skillLocator.primary.maxStock; ((EntityState)this).skillLocator.primary.rechargeStopwatch = 0f; } public override void FixedUpdate() { ((EntityState)this).FixedUpdate(); if (((EntityState)this).isAuthority) { ((EntityState)this).outer.SetNextStateToMain(); } } } public sealed class GunnerLaser : BaseSkillState { private const float ChargeTime = 2f; private const float BeamTime = 6f; private const float Tick = 0.1f; private GameObject visual; private Transform end; private bool firing; private float nextTick; private FireMegaLaser native; public override void OnEnter() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown ((BaseState)this).OnEnter(); native = new FireMegaLaser(); ChargeMegaLaser val = new ChargeMegaLaser(); if (Object.op_Implicit((Object)(object)val.effectPrefab)) { visual = Object.Instantiate<GameObject>(val.effectPrefab); } Util.PlaySound(ChargeMegaLaser.chargeAttackSoundString, ((EntityState)this).gameObject); } public override void FixedUpdate() { //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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0261: 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) ((EntityState)this).FixedUpdate(); if (!GunnerAim.Seated(((EntityState)this).characterBody)) { if (((EntityState)this).isAuthority) { ((EntityState)this).outer.SetNextStateToMain(); } return; } Ray val = GunnerAim.Ray(((EntityState)this).characterBody); if (!firing && ((EntityState)this).fixedAge >= 2f) { firing = true; nextTick = ((EntityState)this).fixedAge; if (Object.op_Implicit((Object)(object)visual)) { Object.Destroy((Object)(object)visual); } if (Object.op_Implicit((Object)(object)native.laserPrefab)) { visual = Object.Instantiate<GameObject>(native.laserPrefab); ChildLocator component = visual.GetComponent<ChildLocator>(); end = (Object.op_Implicit((Object)(object)component) ? component.FindChild("LaserEnd") : null); } Util.PlaySound(FireMegaLaser.playAttackSoundString, ((EntityState)this).gameObject); Util.PlaySound(FireMegaLaser.playLoopSoundString, ((EntityState)this).gameObject); } if (Object.op_Implicit((Object)(object)visual)) { visual.transform.SetPositionAndRotation(((Ray)(ref val)).origin, Util.QuaternionSafeLookRotation(((Ray)(ref val)).direction)); if (Object.op_Implicit((Object)(object)end)) { RaycastHit val2 = default(RaycastHit); end.position = (Physics.Raycast(val, ref val2, 500f, LayerMask.op_Implicit(CommonMasks.bullet), (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point : ((Ray)(ref val)).GetPoint(500f)); } } if (((EntityState)this).isAuthority && firing && ((EntityState)this).fixedAge >= nextTick && ((EntityState)this).fixedAge < 8f) { nextTick += 0.1f; new BulletAttack { owner = ((EntityState)this).gameObject, weapon = ((Component)((EntityState)this).characterBody.currentVehicle).gameObject, origin = ((Ray)(ref val)).origin, aimVector = ((Ray)(ref val)).direction, damage = ((BaseState)this).damageStat * 1.8f, force = 10f, bulletCount = 1u, maxDistance = 500f, radius = 0f, procCoefficient = 0.1f, isCrit = ((BaseState)this).RollCrit(), falloffModel = (FalloffModel)0, hitEffectPrefab = native.hitEffectPrefab, hitMask = CommonMasks.bullet, stopperMask = CommonMasks.bullet }.Fire(); } if (((EntityState)this).isAuthority && ((EntityState)this).fixedAge >= 8f) { ((EntityState)this).outer.SetNextStateToMain(); } } public override void OnExit() { if (Object.op_Implicit((Object)(object)visual)) { Object.Destroy((Object)(object)visual); } Util.PlaySound(FireMegaLaser.stopLoopSoundString, ((EntityState)this).gameObject); ((EntityState)this).OnExit(); } public override InterruptPriority GetMinimumInterruptPriority() { return (InterruptPriority)7; } } internal sealed class GunnerScopeVisibility : IDisposable { private readonly Dictionary<SceneCamera, List<KeyValuePair<Renderer, bool>>> hidden = new Dictionary<SceneCamera, List<KeyValuePair<Renderer, bool>>>(); public GunnerScopeVisibility() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown SceneCamera.onSceneCameraPreCull += new SceneCameraDelegate(BeforeCamera); SceneCamera.onSceneCameraPostRender += new SceneCameraDelegate(AfterCamera); } private void BeforeCamera(SceneCamera camera) { AfterCamera(camera); CameraRigController cameraRigController = camera.cameraRigController; CharacterBody val = ((Object.op_Implicit((Object)(object)cameraRigController) && Object.op_Implicit((Object)(object)cameraRigController.target)) ? cameraRigController.target.GetComponent<CharacterBody>() : null); CrewGunner crewGunner = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<CrewGunner>() : null); if (!Object.op_Implicit((Object)(object)crewGunner) || !crewGunner.Scoped || !GunnerAim.Seated(val)) { return; } CharacterBody component = ((Component)val.currentVehicle).GetComponent<CharacterBody>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.modelLocator) || !Object.op_Implicit((Object)(object)component.modelLocator.modelTransform)) { return; } List<KeyValuePair<Renderer, bool>> list = new List<KeyValuePair<Renderer, bool>>(); Renderer[] componentsInChildren = ((Component)component.modelLocator.modelTransform).GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val2)) { list.Add(new KeyValuePair<Renderer, bool>(val2, val2.forceRenderingOff)); val2.forceRenderingOff = true; } } hidden[camera] = list; } private void AfterCamera(SceneCamera camera) { if (!hidden.TryGetValue(camera, out var value)) { return; } foreach (KeyValuePair<Renderer, bool> item in value) { if (Object.op_Implicit((Object)(object)item.Key)) { item.Key.forceRenderingOff = item.Value; } } hidden.Remove(camera); } public void Dispose() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown SceneCamera.onSceneCameraPreCull -= new SceneCameraDelegate(BeforeCamera); SceneCamera.onSceneCameraPostRender -= new SceneCameraDelegate(AfterCamera); foreach (List<KeyValuePair<Renderer, bool>> value in hidden.Values) { foreach (KeyValuePair<Renderer, bool> item in value) { if (Object.op_Implicit((Object)(object)item.Key)) { item.Key.forceRenderingOff = item.Value; } } } hidden.Clear(); } } public sealed class GunnerSeated : GenericCharacterVehicleSeated { private CameraParamsOverrideHandle viewHandle; private Transform previousPivot; private Transform seatPivot; private bool previousDontRaycastToPivot; public override void OnEnter() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) ((GenericCharacterVehicleSeated)this).OnEnter(); if (Object.op_Implicit((Object)(object)((EntityState)this).cameraTargetParams)) { previousPivot = ((EntityState)this).cameraTargetParams.cameraPivotTransform; VehicleSeat currentVehicle = ((EntityState)this).characterBody.currentVehicle; CameraTargetParams val = (Object.op_Implicit((Object)(object)currentVehicle) ? ((Component)currentVehicle).GetComponent<CameraTargetParams>() : null); seatPivot = ((!Object.op_Implicit((Object)(object)val)) ? null : (Object.op_Implicit((Object)(object)val.cameraPivotTransform) ? val.cameraPivotTransform : ((Component)val).transform)); if (Object.op_Implicit((Object)(object)seatPivot)) { ((EntityState)this).cameraTargetParams.cameraPivotTransform = seatPivot; } previousDontRaycastToPivot = ((EntityState)this).cameraTargetParams.dontRaycastToPivot; ((EntityState)this).cameraTargetParams.dontRaycastToPivot = true; CharacterCameraParamsData cameraParamsData = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.cameraParams)) ? val.cameraParams.data : CharacterCameraParamsData.basic); viewHandle = ((EntityState)this).cameraTargetParams.AddParamsOverride(new CameraParamsOverrideRequest { cameraParamsData = cameraParamsData, priority = 10f }, 0f); } } public override void OnExit() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)((EntityState)this).cameraTargetParams) && (Object)(object)((EntityState)this).cameraTargetParams.cameraPivotTransform == (Object)(object)seatPivot) { ((EntityState)this).cameraTargetParams.cameraPivotTransform = previousPivot; } if (Object.op_Implicit((Object)(object)((EntityState)this).cameraTargetParams)) { ((EntityState)this).cameraTargetParams.dontRaycastToPivot = previousDontRaycastToPivot; if (((CameraParamsOverrideHandle)(ref viewHandle)).isValid) { ((EntityState)this).cameraTargetParams.RemoveParamsOverride(viewHandle, 0f); } } ((EntityState)this).OnExit(); } public override void FixedUpdate() { ((EntityState)this).FixedUpdate(); if (!((EntityState)this).isAuthority) { return; } if (!Object.op_Implicit((Object)(object)((EntityState)this).characterBody.currentVehicle) || !Object.op_Implicit((Object)(object)((Component)((EntityState)this).characterBody.currentVehicle).GetComponent<CrewSeat>())) { ((EntityState)this).outer.SetNextStateToMain(); return; } if (((ButtonState)(ref ((EntityState)this).inputBank.skill4)).justPressed) { ((EntityState)this).skillLocator.special.ExecuteIfReady(); } if (((ButtonState)(ref ((EntityState)this).inputBank.skill3)).justPressed) { ((EntityState)this).skillLocator.utility.ExecuteIfReady(); } if (((EntityState)this).inputBank.skill2.down) { ((EntityState)this).skillLocator.secondary.ExecuteIfReady(); } if (((EntityState)this).inputBank.skill1.down) { ((EntityState)this).skillLocator.primary.ExecuteIfReady(); } } } internal sealed class GunnerViewHooks : IDisposable { private delegate void Enable(CrosshairManager self); [CompilerGenerated] private static class <>O { public static ShouldShowCrosshairDelegate <0>__Show; public static PickCrosshairDelegate <1>__Pick; } private readonly Hook hook; private readonly GunnerScopeVisibility scopeVisibility = new GunnerScopeVisibility(); private readonly HashSet<CrosshairManager> managers = new HashSet<CrosshairManager>(); public GunnerViewHooks() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown hook = new Hook((MethodBase)typeof(CrosshairManager).GetMethod("OnEnable", BindingFlags.Instance | BindingFlags.NonPublic), (Delegate)new Action<Enable, CrosshairManager>(OnEnable)); } private void OnEnable(Enable orig, CrosshairManager self) { //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_0032: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown orig(self); if (managers.Add(self)) { object obj = <>O.<0>__Show; if (obj == null) { ShouldShowCrosshairDelegate val = Show; <>O.<0>__Show = val; obj = (object)val; } self.shouldShowCrosshairGlobal += (ShouldShowCrosshairDelegate)obj; object obj2 = <>O.<1>__Pick; if (obj2 == null) { PickCrosshairDelegate val2 = Pick; <>O.<1>__Pick = val2; obj2 = (object)val2; } self.pickCrosshairGlobal += (PickCrosshairDelegate)obj2; } } private static CharacterBody Body(CrosshairManager manager) { if (!Object.op_Implicit((Object)(object)manager.cameraRigController) || !Object.op_Implicit((Object)(object)manager.cameraRigController.target)) { return null; } return manager.cameraRigController.target.GetComponent<CharacterBody>(); } private static void Show(CrosshairManager manager, ref bool show) { CharacterBody val = Body(manager); if (GunnerAim.Seated(val) && Object.op_Implicit((Object)(object)((Component)val).GetComponent<CrewGunner>())) { show = Object.op_Implicit((Object)(object)val.healthComponent) && val.healthComponent.alive && !val.hideCrosshair; } } private static void Pick(CrosshairManager manager, ref GameObject prefab) { CharacterBody val = Body(manager); CrewGunner crewGunner = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<CrewGunner>() : null); if (Object.op_Implicit((Object)(object)crewGunner) && GunnerAim.Seated(val) && !crewGunner.Scoped) { prefab = val.defaultCrosshairPrefab; } } public void Dispose() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown hook.Dispose(); scopeVisibility.Dispose(); foreach (CrosshairManager manager in managers) { if (Object.op_Implicit((Object)(object)manager)) { object obj = <>O.<0>__Show; if (obj == null) { ShouldShowCrosshairDelegate val = Show; <>O.<0>__Show = val; obj = (object)val; } manager.shouldShowCrosshairGlobal -= (ShouldShowCrosshairDelegate)obj; object obj2 = <>O.<1>__Pick; if (obj2 == null) { PickCrosshairDelegate val2 = Pick; <>O.<1>__Pick = val2; obj2 = (object)val2; } manager.pickCrosshairGlobal -= (PickCrosshairDelegate)obj2; } } managers.Clear(); } } public sealed class MagazineSkillDef : SkillDef { public override void OnExecute(GenericSkill slot) { ((SkillDef)this).OnExecute(slot); CrewGunner component = ((Component)slot).GetComponent<CrewGunner>(); if (!Object.op_Implicit((Object)(object)component) || !component.OverdriveActive) { slot.stock = Math.Max(0, slot.stock - 1); } } public override void OnFixedUpdate(GenericSkill slot, float dt) { if (slot.stock <= 0) { ((SkillDef)this).OnFixedUpdate(slot, dt); if (slot.stock > 0) { slot.stock = slot.maxStock; } } } } public sealed class PilotRockets : FireRocketPods { public override void OnEnter() { SkillLocator component = ((EntityState)this).GetComponent<SkillLocator>(); GenericSkill secondary = component.secondary; try { component.secondary = component.primary; ((FireRocketPods)this).OnEnter(); } finally { component.secondary = secondary; } } } public sealed class PilotBarrage : PaintLongbow { public override void FixedUpdate() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) ButtonState skill = ((EntityState)this).inputBank.skill4; try { ((EntityState)this).inputBank.skill4 = ((EntityState)this).inputBank.skill2; ((PaintLongbow)this).FixedUpdate(); } finally { ((EntityState)this).inputBank.skill4 = skill; } } } public sealed class PilotBoost : ServoDash { public override void OnEnter() { ((ServoDash)this).OnEnter(); if (NetworkServer.active) { ((EntityState)this).characterBody.AddTimedBuff(AbilityContent.Boost, 3f); } } } public sealed class PilotDefense : BaseSkillState { public override void OnEnter() { ((BaseState)this).OnEnter(); if (NetworkServer.active) { ((EntityState)this).healthComponent.AddBarrier(((EntityState)this).healthComponent.fullCombinedHealth * 0.3f); ((EntityState)this).characterBody.AddTimedBuff(AbilityContent.Defense, 5f); } } public override void FixedUpdate() { ((EntityState)this).FixedUpdate(); if (((EntityState)this).isAuthority) { ((EntityState)this).outer.SetNextStateToMain(); } } } internal static class PilotRecoveryContent { internal const float RebuildSeconds = 180f; internal static GameObject EjectedPrefab; internal static BuffDef Countdown; internal static BuffDef Ready; internal static RebuildSkillDef Rebuild; internal static void Build(ContentPack pack, GameObject commando) { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) EjectedPrefab = PrefabAPI.InstantiateClone(commando, "AH64CrewEjectedPilotBody", true); EjectedPrefab.GetComponent<CharacterBody>().baseNameToken = "AH64CREW_EJECTED_NAME"; LanguageAPI.Add("AH64CREW_EJECTED_NAME", "Ejected Pilot"); Countdown = ScriptableObject.CreateInstance<BuffDef>(); ((Object)Countdown).name = "AH64CrewRebuildCountdown"; Countdown.canStack = true; Countdown.isHidden = true; Ready = ScriptableObject.CreateInstance<BuffDef>(); ((Object)Ready).name = "AH64CrewRebuildReady"; Ready.isHidden = true; pack.buffDefs.Add((BuffDef[])(object)new BuffDef[2] { Countdown, Ready }); Rebuild = ScriptableObject.CreateInstance<RebuildSkillDef>(); ((Object)Rebuild).name = (((SkillDef)Rebuild).skillName = "AH64CrewRebuild"); ((SkillDef)Rebuild).skillNameToken = "AH64CREW_REBUILD_NAME"; ((SkillDef)Rebuild).skillDescriptionToken = "AH64CREW_REBUILD_DESCRIPTION"; LanguageAPI.Add(((SkillDef)Rebuild).skillNameToken, "Rebuild AH-64"); LanguageAPI.Add(((SkillDef)Rebuild).skillDescriptionToken, "Return to your <style=cIsUtility>AH-64</style> at full health. Starts unavailable after ejection: survive <style=cIsUtility>180 seconds</style> on foot to rebuild. This timer persists between stages and cannot be shortened by cooldown items."); ((SkillDef)Rebuild).icon = AbilityIcons.Load("overdrive"); ((SkillDef)Rebuild).activationState = new SerializableEntityStateType(typeof(RebuildHelicopter)); ((SkillDef)Rebuild).activationStateMachineName = "Weapon"; ((SkillDef)Rebuild).baseRechargeInterval = 180f; ((SkillDef)Rebuild).fullRestockOnAssign = false; ((SkillDef)Rebuild).mustKeyPress = true; ((SkillDef)Rebuild).cancelSprintingOnActivation = false; SkillLocator component = EjectedPrefab.GetComponent<SkillLocator>(); AbilityContent.SetFamily(pack, component.primary, AbilityContent.OnFootSkills[0]); AbilityContent.SetFamily(pack, component.secondary, AbilityContent.OnFootSkills[1]); AbilityContent.SetFamily(pack, component.utility, AbilityContent.OnFootSkills[2]); AbilityContent.SetFamily(pack, component.special, (SkillDef)(object)Rebuild); pack.bodyPrefabs.Add((GameObject[])(object)new GameObject[1] { EjectedPrefab }); pack.skillDefs.Add((SkillDef[])(object)new SkillDef[1] { Rebuild }); pack.entityStateTypes.Add(new Type[1] { typeof(RebuildHelicopter) }); Plugin.Log.LogInfo((object)"Commando ejected pilot and 180-second rebuild registered."); } internal static bool IsEjected(CharacterBody body) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)EjectedPrefab)) { return body.bodyIndex == EjectedPrefab.GetComponent<CharacterBody>().bodyIndex; } return false; } } public sealed class RebuildSkillDef : SkillDef { public override bool IsReady(GenericSkill slot) { if (PilotRecoveryContent.IsEjected(slot.characterBody) && slot.characterBody.HasBuff(PilotRecoveryContent.Ready)) { return ((SkillDef)this).IsReady(slot); } return false; } public override void OnFixedUpdate(GenericSkill slot, float dt) { CharacterBody characterBody = slot.characterBody; bool flag = Object.op_Implicit((Object)(object)characterBody) && characterBody.HasBuff(PilotRecoveryContent.Ready); slot.stock = (flag ? 1 : 0); int num = (Object.op_Implicit((Object)(object)characterBody) ? characterBody.GetBuffCount(PilotRecoveryContent.Countdown) : 0); slot.rechargeStopwatch = (flag ? 0f : (slot.GetFinalRechargeInterval() - ((num > 0) ? ((float)num) : 180f))); } } public sealed class RebuildHelicopter : BaseSkillState { public override void OnEnter() { ((BaseState)this).OnEnter(); if (NetworkServer.active && Object.op_Implicit((Object)(object)((EntityState)this).characterBody) && Object.op_Implicit((Object)(object)((EntityState)this).characterBody.master)) { ((Component)((EntityState)this).characterBody.master).GetComponent<PilotRecovery>()?.RequestRebuild(((EntityState)this).characterBody); } } public override void FixedUpdate() { ((EntityState)this).FixedUpdate(); if (((EntityState)this).isAuthority) { ((EntityState)this).outer.SetNextStateToMain(); } } } public sealed class PilotRecovery : MonoBehaviour { private CharacterMaster master; private CharacterBody crashBody; private bool onFoot; private bool crashPending; private bool rebuildPending; private float remaining; private void Awake() { master = ((Component)this).GetComponent<CharacterMaster>(); } internal bool QueueCrash(HealthComponent health) { if (crashPending) { return true; } if (onFoot || !Object.op_Implicit((Object)(object)master) || (Object)(object)master.GetBody() != (Object)(object)health.body) { return false; } crashBody = health.body; crashPending = true; health.Networkhealth = 1f; health.godMode = true; return true; } internal void RequestRebuild(CharacterBody requester) { if (NetworkServer.active && onFoot && !crashPending && remaining <= 0f && (Object)(object)requester == (Object)(object)master.GetBody() && PilotRecoveryContent.IsEjected(requester) && requester.healthComponent.alive) { rebuildPending = true; } } private void FixedUpdate() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !Object.op_Implicit((Object)(object)master)) { return; } if (crashPending) { Eject(); return; } CharacterBody body = master.GetBody(); if (!onFoot || !PilotRecoveryContent.IsEjected(body) || !body.healthComponent.alive) { return; } if (rebuildPending) { rebuildPending = false; if (!(remaining > 0f)) { GameObject bodyPrefab = ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab; master.TransformBody(((Object)bodyPrefab).name); CharacterBody body2 = master.GetBody(); if (Object.op_Implicit((Object)(object)body2) && body2.bodyIndex == bodyPrefab.GetComponent<CharacterBody>().bodyIndex) { onFoot = false; FullHealth(body2); Plugin.Log.LogInfo((object)"Pilot rebuilt AH-64."); } } } else { if (Object.op_Implicit((Object)(object)Stage.instance)) { remaining = Mathf.Max(0f, remaining - Time.fixedDeltaTime); } SyncTimer(body); } } private void SyncTimer(CharacterBody body) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.CeilToInt(remaining); if (body.GetBuffCount(PilotRecoveryContent.Countdown) != num) { body.SetBuffCount(PilotRecoveryContent.Countdown.buffIndex, num); } int num2 = ((remaining <= 0f) ? 1 : 0); if (body.GetBuffCount(PilotRecoveryContent.Ready) != num2) { body.SetBuffCount(PilotRecoveryContent.Ready.buffIndex, num2); } } private void Eject() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) crashPending = false; if (!Object.op_Implicit((Object)(object)crashBody) || (Object)(object)master.GetBody() != (Object)(object)crashBody) { return; } try { Vector3? val = TeleportHelper.FindSafeTeleportDestination(crashBody.footPosition, PilotRecoveryContent.EjectedPrefab.GetComponent<CharacterBody>(), RoR2Application.rng); VehicleSeat component = ((Component)crashBody).GetComponent<VehicleSeat>(); CharacterBody val2 = (Object.op_Implicit((Object)(object)component) ? component.currentPassengerBody : null); if (Object.op_Implicit((Object)(object)component) && component.hasPassenger) { component.EjectPassenger(); } if (val.HasValue && Object.op_Implicit((Object)(object)val2) && val2.healthComponent.alive) { TeleportHelper.TeleportBody(val2, val.Value, true); } remaining = 180f; master.TransformBody(((Object)PilotRecoveryContent.EjectedPrefab).name); CharacterBody body = master.GetBody(); if (!PilotRecoveryContent.IsEjected(body)) { throw new InvalidOperationException("Ejected body was not spawned."); } onFoot = true; if (val.HasValue) { TeleportHelper.TeleportBody(body, val.Value, true); } FullHealth(body); SyncTimer(body); Plugin.Log.LogInfo((object)"Pilot ejected as Commando; rebuild available after 180 seconds alive on foot."); } catch (Exception ex) { Plugin.Log.LogError((object)("Pilot ejection failed: " + ex)); if (Object.op_Implicit((Object)(object)crashBody)) { crashBody.healthComponent.godMode = false; crashBody.healthComponent.Suicide((GameObject)null, (GameObject)null, default(DamageTypeCombo)); } } finally { crashBody = null; } } private static void FullHealth(CharacterBody body) { body.healthComponent.Networkhealth = body.healthComponent.fullHealth; body.healthComponent.Networkshield = body.healthComponent.fullShield; } } internal sealed class PilotRecoveryHooks : IDisposable { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<Instruction, bool> <>9__1_1; public static Manipulator <>9__1_0; internal void <.ctor>b__1_0(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall<GlobalEventManager>(i, "ServerDamageDealt") })) { throw new InvalidOperationException("AH64 ejection: lethal damage hook location not found."); } val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Action<HealthComponent>>((Action<HealthComponent>)InterceptLethalDamage); } internal bool <.ctor>b__1_1(Instruction i) { return ILPatternMatchingExt.MatchCall<GlobalEventManager>(i, "ServerDamageDealt"); } } private readonly ILHook damageHook; internal PilotRecoveryHooks() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown MethodInfo? method = typeof(HealthComponent).GetMethod("TakeDamageProcess", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); object obj = <>c.<>9__1_0; if (obj == null) { Manipulator val = delegate(ILContext il) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) ILCursor val2 = new ILCursor(il); if (!val2.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchCall<GlobalEventManager>(i, "ServerDamageDealt") })) { throw new InvalidOperationException("AH64 ejection: lethal damage hook location not found."); } val2.Emit(OpCodes.Ldarg_0); val2.EmitDelegate<Action<HealthComponent>>((Action<HealthComponent>)InterceptLethalDamage); }; <>c.<>9__1_0 = val; obj = (object)val; } damageHook = new ILHook((MethodBase)method, (Manipulator)obj); Plugin.Log.LogInfo((object)"Pilot lethal-damage ejection hook installed."); } private static void InterceptLethalDamage(HealthComponent health) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active && !health.alive && Object.op_Implicit((Object)(object)PilotRecoveryContent.EjectedPrefab)) { CharacterBody body = health.body; CharacterBody component = ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab.GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)body) && body.bodyIndex == component.bodyIndex && body.isPlayerControlled && Object.op_Implicit((Object)(object)body.master) && Object.op_Implicit((Object)(object)body.master.playerCharacterMasterController)) { (((Component)body.master).GetComponent<PilotRecovery>() ?? ((Component)body.master).gameObject.AddComponent<PilotRecovery>()).QueueCrash(health); } } } public void Dispose() { ILHook obj = damageHook; if (obj != null) { obj.Dispose(); } } } [BepInPlugin("local.ah64crew", "AH64 Crew Prototype", "0.3.1")] [BepInDependency("com.JohnstonStu.AH64", "1.3.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "local.ah64crew"; public const string Version = "0.3.1"; internal static ConfigEntry<bool> Unlimited; internal static ConfigEntry<bool> CrewEnabled; internal static ConfigEntry<bool> AutoBoard; internal static ConfigEntry<float> MaxRise; internal static ConfigEntry<float> FireRate; internal static ConfigEntry<float> Damage; internal static ManualLogSource Log; private FlightHooks hooks; private GunnerViewHooks viewHooks; private PilotRecoveryHooks recoveryHooks; private void Awake() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Unlimited = ((BaseUnityPlugin)this).Config.Bind<bool>("Flight", "Unlimited airtime", true, "Keep altitude hold without draining airtime."); MaxRise = ((BaseUnityPlugin)this).Config.Bind<float>("Flight", "Maximum climb above hover", 100f, new ConfigDescription("Base climb allowance above resting hover, in world units. Extra jumps still add their normal bonus. Stage boundaries still apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(12f, 300f), Array.Empty<object>())); CrewEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Crew", "Enable prototype gunner", true, "Adds the selectable Crew Gunner and a passenger seat. Requires restart."); AutoBoard = ((BaseUnityPlugin)this).Config.Bind<bool>("Crew", "Automatically board nearby pilot", true, "After exiting, automatically reboard a free allied helicopter within 25 units, with a 10-second grace period. Initial boarding on each stage/spawn always occurs regardless of distance once a pilot is available."); FireRate = ((BaseUnityPlugin)this).Config.Bind<float>("Crew", "Gunner rounds per second", 12f, new ConfigDescription("Base fire rate, scaled by the gunner's attack speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>())); Damage = ((BaseUnityPlugin)this).Config.Bind<float>("Crew", "Gunner damage coefficient", 0.4f, new ConfigDescription("Damage per round, using the gunner's damage and items.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>())); CharacterBody component = ((CharacterBase<AH64Survivor>)(object)CharacterBase<AH64Survivor>.instance).bodyPrefab.GetComponent<CharacterBody>(); component.baseMoveSpeed *= 1.1f; component.baseMaxHealth *= 1.1f; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Pilot base stats: speed=" + component.baseMoveSpeed + ", health=" + component.baseMaxHealth)); hooks = new FlightHooks(); viewHooks = new GunnerViewHooks(); if (CrewEnabled.Value) { new CrewContent().Initialize(); recoveryHooks = new PilotRecoveryHooks(); } ((ResourceAvailability)(ref EntityStateCatalog.availability)).CallWhenAvailable((Action)delegate { ((ResourceAvailability)(ref BodyCatalog.availability)).CallWhenAvailable((Action)AbilityValidation.Run); }); ((BaseUnityPlugin)this).Logger.LogInfo((object)"AH64 Crew 0.3.1 loaded. Prototype: multiplayer playtesting required."); } private void OnDestroy() { recoveryHooks?.Dispose(); hooks?.Dispose(); viewHooks?.Dispose(); AbilityContent.Dispose(); } } public sealed class SeatBlockedSkill : SkillDef { public override bool IsReady(GenericSkill skillSlot) { return false; } public override bool CanExecute(GenericSkill skillSlot) { return false; } } }