Decompiled source of AH64Crew v0.3.1

BepInEx/plugins/AH64Crew/AH64Crew.dll

Decompiled 21 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.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;
		}
	}
}