Decompiled source of CloseAirSupport v1.15.0

CloseAirSupport.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using HG;
using Microsoft.CodeAnalysis;
using On.RoR2;
using R2API;
using R2API.Utils;
using RiskOfOptions;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Projectile;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CloseAirSupport")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1a3f752dbf2b8aeb408a97e9c168d317a502eceb")]
[assembly: AssemblyProduct("CloseAirSupport")]
[assembly: AssemblyTitle("CloseAirSupport")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ExamplePlugin
{
	internal static class Log
	{
		private static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void Debug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void Error(object data)
		{
			_logSource.LogError(data);
		}

		internal static void Fatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
}
namespace CloseAirSupport
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.MyName.CloseAirSupport", "Close Air Support", "1.15.0")]
	public class CloseAirSupport : BaseUnityPlugin
	{
		public static class MyEntityStates
		{
			public class Engi_DroneATGMSalvo : BaseSkillState
			{
				public static int missilesPerDrone = 10;

				public static float missileDamageCoef = 3f;

				private bool fired;

				public override void OnEnter()
				{
					((BaseState)this).OnEnter();
					CharacterBody characterBody = ((EntityState)this).characterBody;
					if (characterBody != null)
					{
						characterBody.SetAimTimer(2f);
					}
					((EntityState)this).PlayCrossfade("Gesture, Additive", "FireGrenade", "FireGrenade.playbackRate", 0.25f, 0.05f);
				}

				public override void FixedUpdate()
				{
					//IL_0104: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
					//IL_0109: Unknown result type (might be due to invalid IL or missing references)
					//IL_010b: Unknown result type (might be due to invalid IL or missing references)
					//IL_010d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0124: Unknown result type (might be due to invalid IL or missing references)
					//IL_0129: Unknown result type (might be due to invalid IL or missing references)
					//IL_0153: 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_013b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0145: Unknown result type (might be due to invalid IL or missing references)
					//IL_014a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0158: Unknown result type (might be due to invalid IL or missing references)
					//IL_015a: 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_0161: Unknown result type (might be due to invalid IL or missing references)
					//IL_017d: Unknown result type (might be due to invalid IL or missing references)
					//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
					//IL_01c6: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
					//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
					//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
					//IL_0206: Unknown result type (might be due to invalid IL or missing references)
					//IL_0208: Unknown result type (might be due to invalid IL or missing references)
					//IL_020a: Unknown result type (might be due to invalid IL or missing references)
					//IL_020c: Unknown result type (might be due to invalid IL or missing references)
					//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
					//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
					//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
					((EntityState)this).FixedUpdate();
					if (!fired)
					{
						fired = true;
						if (NetworkServer.active)
						{
							EnsurePrefabs();
							if (Object.op_Implicit((Object)(object)MissileProjectilePrefab))
							{
								CharacterBody characterBody = ((EntityState)this).characterBody;
								if (Object.op_Implicit((Object)(object)((characterBody != null) ? characterBody.master : null)))
								{
									List<CharacterMaster> ownedMasters = OwnerUtils.GetOwnedMasters(((EntityState)this).characterBody.master);
									foreach (CharacterMaster item in ownedMasters)
									{
										if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)((Component)item).GetComponent<PermDroneMarkerHeli>()))
										{
											continue;
										}
										CharacterBody body = item.GetBody();
										if (!Object.op_Implicit((Object)(object)body))
										{
											continue;
										}
										TryGetMuzzle(body, out var muzzle);
										Vector3 val = (Object.op_Implicit((Object)(object)body.inputBank) ? body.inputBank.aimDirection : body.transform.forward);
										if (val == Vector3.zero)
										{
											val = body.transform.forward;
										}
										Vector3 val2 = (Object.op_Implicit((Object)(object)muzzle) ? muzzle.position : (body.corePosition + Vector3.up * 0.5f));
										Quaternion val3 = Util.QuaternionSafeLookRotation(val);
										Xoroshiro128Plus val4 = (Xoroshiro128Plus)(Object.op_Implicit((Object)(object)Run.instance) ? ((object)Run.instance.runRNG) : ((object)new Xoroshiro128Plus((ulong)DateTime.Now.Ticks)));
										for (int i = 0; i < missilesPerDrone; i++)
										{
											float num = val4.RangeFloat(-2f, 2f);
											float num2 = val4.RangeFloat(-1.5f, 1.5f);
											Quaternion val5 = Quaternion.AngleAxis(num, Vector3.up) * Quaternion.AngleAxis(num2, Vector3.right);
											if (Object.op_Implicit((Object)(object)muzzle))
											{
												SpawnMuzzleFlash(muzzle, val3 * val5);
											}
											ProjectileManager.instance.FireProjectile(MissileProjectilePrefab, val2, val3 * val5, ((Component)body).gameObject, body.damage * missileDamageCoef, 0f, body.RollCrit(), (DamageColorIndex)0, (GameObject)null, -1f, (DamageTypeCombo?)null);
										}
									}
									GenericSkill val6 = ((EntityState)this).skillLocator?.secondary;
									if (Object.op_Implicit((Object)(object)val6))
									{
										val6.rechargeStopwatch = 0f;
									}
								}
							}
						}
					}
					if (((EntityState)this).fixedAge >= 0.3f)
					{
						((EntityState)this).outer.SetNextStateToMain();
					}
				}

				public override InterruptPriority GetMinimumInterruptPriority()
				{
					return (InterruptPriority)1;
				}
			}

			public class Engi_CallEmergencyDrones : BaseSkillState
			{
				public static float lifeSeconds = 45f;

				public static float healFractionPerSecond = 0.1f;

				public static float spawnUp = 2f;

				public static float spawnRadius = 3.5f;

				private bool spawned;

				public override void OnEnter()
				{
					((BaseState)this).OnEnter();
					CharacterBody characterBody = ((EntityState)this).characterBody;
					if (characterBody != null)
					{
						characterBody.SetAimTimer(2f);
					}
					((EntityState)this).PlayCrossfade("Gesture, Additive", "FireGrenade", "FireGrenade.playbackRate", 0.25f, 0.05f);
				}

				public override void FixedUpdate()
				{
					//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_00c1: Unknown result type (might be due to invalid IL or missing references)
					//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
					//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
					//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
					//IL_0104: Unknown result type (might be due to invalid IL or missing references)
					//IL_0109: Unknown result type (might be due to invalid IL or missing references)
					//IL_010b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0110: 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_0118: Unknown result type (might be due to invalid IL or missing references)
					//IL_011a: Unknown result type (might be due to invalid IL or missing references)
					//IL_011f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0120: Unknown result type (might be due to invalid IL or missing references)
					//IL_0122: Unknown result type (might be due to invalid IL or missing references)
					//IL_0127: Unknown result type (might be due to invalid IL or missing references)
					//IL_0134: Unknown result type (might be due to invalid IL or missing references)
					//IL_0140: 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_0155: Expected O, but got Unknown
					//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
					//IL_019f: Unknown result type (might be due to invalid IL or missing references)
					//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
					//IL_01db: Unknown result type (might be due to invalid IL or missing references)
					//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
					((EntityState)this).FixedUpdate();
					if (!spawned)
					{
						spawned = true;
						if (NetworkServer.active)
						{
							EnsurePrefabs();
							GameObject droneEmergencyMasterPrefab = DroneEmergencyMasterPrefab;
							if (Object.op_Implicit((Object)(object)droneEmergencyMasterPrefab))
							{
								foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
								{
									if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.master))
									{
										continue;
									}
									CharacterMaster master = instance.master;
									CharacterBody body = master.GetBody();
									if (!Object.op_Implicit((Object)(object)body))
									{
										continue;
									}
									Vector3 val = body.corePosition + Vector3.up * spawnUp;
									float num = Random.Range(0f, 360f);
									Quaternion val2 = Quaternion.AngleAxis(num, Vector3.up);
									Vector3 val3 = val + val2 * (Vector3.forward * spawnRadius);
									MasterSummon val4 = new MasterSummon
									{
										masterPrefab = droneEmergencyMasterPrefab,
										position = val3,
										rotation = val2,
										summonerBodyObject = ((Component)body).gameObject,
										useAmbientLevel = true,
										teamIndexOverride = (TeamIndex)1,
										ignoreTeamMemberLimit = true
									};
									CharacterMaster val5 = val4.Perform();
									if (Object.op_Implicit((Object)(object)val5))
									{
										CharacterBody body2 = val5.GetBody();
										if (Object.op_Implicit((Object)(object)((body2 != null) ? body2.healthComponent : null)))
										{
											body2.healthComponent.HealFraction(1f, default(ProcChainMask));
										}
										EnsureNetworkSfx();
										PlaySfxAll(sfxDroneRepair, val3);
										GameObject val6 = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/DroneRepairEffect");
										if (Object.op_Implicit((Object)(object)val6))
										{
											EffectManager.SimpleEffect(val6, val3, Quaternion.identity, true);
										}
										TimedKill timedKill = ((Component)val5).gameObject.AddComponent<TimedKill>();
										timedKill.life = lifeSeconds;
										HealOwnerOverTime healOwnerOverTime = ((Component)val5).gameObject.AddComponent<HealOwnerOverTime>();
										healOwnerOverTime.owner = body;
										healOwnerOverTime.fractionPerSecond = healFractionPerSecond;
									}
								}
								GenericSkill val7 = ((EntityState)this).skillLocator?.utility;
								if (Object.op_Implicit((Object)(object)val7))
								{
									val7.rechargeStopwatch = 0f;
								}
							}
						}
					}
					if (((EntityState)this).fixedAge >= 0.35f)
					{
						((EntityState)this).outer.SetNextStateToMain();
					}
				}

				public override InterruptPriority GetMinimumInterruptPriority()
				{
					return (InterruptPriority)1;
				}
			}

			public class Engi_SummonPermanentDrone : BaseSkillState
			{
				public static int maxOwned = 1;

				public static float spawnUp = 3f;

				public static float spawnForward = 3f;

				private bool spawned;

				public override void OnEnter()
				{
					((BaseState)this).OnEnter();
					CharacterBody characterBody = ((EntityState)this).characterBody;
					if (characterBody != null)
					{
						characterBody.SetAimTimer(2f);
					}
					((EntityState)this).PlayCrossfade("Gesture, Additive", "FireGrenade", "FireGrenade.playbackRate", 0.25f, 0.05f);
				}

				public override void FixedUpdate()
				{
					//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
					//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
					//IL_00de: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
					//IL_0101: Unknown result type (might be due to invalid IL or missing references)
					//IL_0106: Unknown result type (might be due to invalid IL or missing references)
					//IL_010b: Unknown result type (might be due to invalid IL or missing references)
					//IL_010d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0112: Unknown result type (might be due to invalid IL or missing references)
					//IL_0119: Unknown result type (might be due to invalid IL or missing references)
					//IL_011a: Unknown result type (might be due to invalid IL or missing references)
					//IL_011c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0121: Unknown result type (might be due to invalid IL or missing references)
					//IL_0122: Unknown result type (might be due to invalid IL or missing references)
					//IL_0124: Unknown result type (might be due to invalid IL or missing references)
					//IL_0129: Unknown result type (might be due to invalid IL or missing references)
					//IL_0135: Unknown result type (might be due to invalid IL or missing references)
					//IL_014b: 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_0163: Unknown result type (might be due to invalid IL or missing references)
					//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
					//IL_0206: Unknown result type (might be due to invalid IL or missing references)
					//IL_0208: Unknown result type (might be due to invalid IL or missing references)
					((EntityState)this).FixedUpdate();
					if (!spawned)
					{
						spawned = true;
						if (NetworkServer.active)
						{
							GameObject strikeDroneMasterPrefab = StrikeDroneMasterPrefab;
							if (Object.op_Implicit((Object)(object)strikeDroneMasterPrefab))
							{
								CharacterBody characterBody = ((EntityState)this).characterBody;
								if (Object.op_Implicit((Object)(object)((characterBody != null) ? characterBody.master : null)))
								{
									int num = PermDroneManager.CountOwnedHeliDrones(((EntityState)this).characterBody.master);
									if (num >= maxOwned)
									{
										PermDroneManager.KillOldestHeliDrone(((EntityState)this).characterBody.master);
									}
									num = PermDroneManager.CountOwnedHeliDrones(((EntityState)this).characterBody.master);
									if (num < maxOwned)
									{
										Vector3 val = ((EntityState)this).characterBody.corePosition + Vector3.up * spawnUp;
										Ray aimRay = ((BaseState)this).GetAimRay();
										Quaternion val2 = Util.QuaternionSafeLookRotation(((Ray)(ref aimRay)).direction);
										Vector3 val3 = val + val2 * Vector3.forward * spawnForward;
										CharacterMaster val4 = new MasterSummon
										{
											masterPrefab = strikeDroneMasterPrefab,
											position = val3,
											rotation = val2,
											summonerBodyObject = ((EntityState)this).gameObject,
											inventoryToCopy = ((EntityState)this).characterBody.master.inventory,
											useAmbientLevel = true,
											teamIndexOverride = (TeamIndex)1,
											ignoreTeamMemberLimit = true
										}.Perform();
										if (Object.op_Implicit((Object)(object)val4))
										{
											PermDroneMarkerHeli permDroneMarkerHeli = ((Component)val4).gameObject.AddComponent<PermDroneMarkerHeli>();
											permDroneMarkerHeli.spawnedAt = (Object.op_Implicit((Object)(object)Run.instance) ? ((double)Run.instance.fixedTime) : Time.fixedTimeAsDouble);
											CharacterBody body = val4.GetBody();
											if (Object.op_Implicit((Object)(object)body))
											{
												body.baseNameToken = "CYA_MK1_NAME";
												EnsureNetworkSfx();
												PlaySfxAll(sfxDroneRepair, val3);
												GameObject val5 = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/DroneRepairEffect");
												if (Object.op_Implicit((Object)(object)val5))
												{
													EffectManager.SimpleEffect(val5, val3, Quaternion.identity, true);
												}
											}
											DroneSyncWithOwner droneSyncWithOwner = ((Component)val4).gameObject.AddComponent<DroneSyncWithOwner>();
											droneSyncWithOwner.owner = ((EntityState)this).characterBody;
											droneSyncWithOwner.drone = val4.GetBody();
											droneSyncWithOwner.scale = Mathf.Max(0f, cfgDroneDamageScale.Value);
											droneSyncWithOwner.updateRate = 1f;
										}
										GenericSkill val6 = ((EntityState)this).skillLocator?.special;
										if (Object.op_Implicit((Object)(object)val6))
										{
											val6.rechargeStopwatch = 0f;
										}
									}
								}
							}
						}
					}
					if (((EntityState)this).fixedAge >= 0.3f)
					{
						((EntityState)this).outer.SetNextStateToMain();
					}
				}

				public override InterruptPriority GetMinimumInterruptPriority()
				{
					return (InterruptPriority)1;
				}
			}
		}

		internal static class OwnerUtils
		{
			public static List<CharacterMaster> GetOwnedMasters(CharacterMaster owner)
			{
				List<CharacterMaster> list = new List<CharacterMaster>();
				if (!Object.op_Implicit((Object)(object)owner))
				{
					return list;
				}
				foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
				{
					if (Object.op_Implicit((Object)(object)readOnlyInstances))
					{
						MinionOwnership component = ((Component)readOnlyInstances).GetComponent<MinionOwnership>();
						if (Object.op_Implicit((Object)(object)component) && (Object)(object)component.ownerMaster == (Object)(object)owner)
						{
							list.Add(readOnlyInstances);
						}
					}
				}
				return list;
			}

			public static int CountOwnedDrones(CharacterMaster owner)
			{
				if (!Object.op_Implicit((Object)(object)owner))
				{
					return 0;
				}
				int num = 0;
				foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
				{
					if (!Object.op_Implicit((Object)(object)readOnlyInstances))
					{
						continue;
					}
					MinionOwnership component = ((Component)readOnlyInstances).GetComponent<MinionOwnership>();
					if (!Object.op_Implicit((Object)(object)component) || (Object)(object)component.ownerMaster != (Object)(object)owner)
					{
						continue;
					}
					if ((Object)(object)((Component)readOnlyInstances).GetComponent<PermDroneMarkerHeli>() != (Object)null)
					{
						num++;
						continue;
					}
					CharacterBody body = readOnlyInstances.GetBody();
					string text = ((Object)readOnlyInstances).name ?? string.Empty;
					string text2 = (Object.op_Implicit((Object)(object)body) ? (body.baseNameToken ?? string.Empty) : string.Empty);
					if (text.IndexOf("Drone", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("DRONE", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						num++;
					}
				}
				return num;
			}
		}

		public class PermDroneMarkerHeli : MonoBehaviour
		{
			public double spawnedAt;
		}

		public class PlayerDroneBarrierPassive : MonoBehaviour
		{
			public CharacterBody body;

			private CharacterMaster master;

			private float timer;

			private void Awake()
			{
				body = body ?? ((Component)this).GetComponent<CharacterBody>();
				master = (Object.op_Implicit((Object)(object)body) ? body.master : null);
			}

			private void FixedUpdate()
			{
				if (!NetworkServer.active)
				{
					return;
				}
				if (!cfgPassive_Enable.Value || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.healthComponent))
				{
					Object.Destroy((Object)(object)this);
					return;
				}
				timer += Time.fixedDeltaTime;
				if (timer < 0.2f)
				{
					return;
				}
				timer = 0f;
				if (!Object.op_Implicit((Object)(object)master))
				{
					master = body.master;
				}
				if (Object.op_Implicit((Object)(object)master))
				{
					int num = OwnerUtils.CountOwnedDrones(master);
					float num2 = body.maxHealth * Mathf.Max(0f, cfgPassive_BarrierPerDroneFraction.Value) * (float)num;
					float barrier = body.healthComponent.barrier;
					if (barrier + 1f < num2)
					{
						body.healthComponent.AddBarrier(num2 - barrier);
					}
				}
			}
		}

		public class PlayerAerialOverwatchPassive : MonoBehaviour
		{
			public CharacterBody body;

			private CharacterMaster master;

			private float tick;

			private float cooldown;

			private EquipmentDef scannerDef;

			private MethodInfo miFireScanner;

			private MethodInfo miPerformAction;

			private void Awake()
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				body = body ?? ((Component)this).GetComponent<CharacterBody>();
				master = (Object.op_Implicit((Object)(object)body) ? body.master : null);
				try
				{
					scannerDef = Addressables.LoadAssetAsync<EquipmentDef>((object)"RoR2/Base/Scanner/Scanner.asset").WaitForCompletion() ?? Equipment.Scanner;
				}
				catch
				{
					scannerDef = Equipment.Scanner;
				}
				try
				{
					miFireScanner = typeof(EquipmentSlot).GetMethod("FireScanner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
				}
				try
				{
					miPerformAction = typeof(EquipmentSlot).GetMethod("PerformEquipmentAction", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(EquipmentDef) }, null);
				}
				catch
				{
				}
			}

			private void FixedUpdate()
			{
				if (!NetworkServer.active)
				{
					return;
				}
				if (!cfgPassive_Enable.Value || !Object.op_Implicit((Object)(object)body))
				{
					Object.Destroy((Object)(object)this);
					return;
				}
				tick += Time.fixedDeltaTime;
				cooldown -= Time.fixedDeltaTime;
				if (!(tick < 0.2f))
				{
					tick = 0f;
					if (!Object.op_Implicit((Object)(object)master))
					{
						master = body.master;
					}
					if (Object.op_Implicit((Object)(object)master) && OwnerUtils.CountOwnedDrones(master) >= 1 && !(cooldown > 0f) && TryFireScanner(body))
					{
						cooldown = Mathf.Max(5f, cfgPassive_AerialOverwatchPeriod.Value);
					}
				}
			}

			private bool TryFireScanner(CharacterBody cb)
			{
				try
				{
					EquipmentSlot val = (Object.op_Implicit((Object)(object)cb) ? ((Component)cb).GetComponent<EquipmentSlot>() : null);
					if (!Object.op_Implicit((Object)(object)val) || (Object)(object)scannerDef == (Object)null)
					{
						return false;
					}
					if (miFireScanner != null)
					{
						miFireScanner.Invoke(val, null);
						return true;
					}
					if (miPerformAction != null && (bool)miPerformAction.Invoke(val, new object[1] { scannerDef }))
					{
						return true;
					}
					return false;
				}
				catch (Exception ex)
				{
					Debug.LogWarning((object)("[CAS] Aerial Overwatch scanner trigger failed: " + ex.Message));
					return false;
				}
			}
		}

		public class HealOwnerOverTime : MonoBehaviour
		{
			public CharacterBody owner;

			public float fractionPerSecond = 0.1f;

			private void FixedUpdate()
			{
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				if (NetworkServer.active)
				{
					if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)owner.healthComponent))
					{
						Object.Destroy((Object)(object)this);
						return;
					}
					float num = owner.maxHealth * Mathf.Max(0f, fractionPerSecond) * Time.fixedDeltaTime;
					owner.healthComponent.Heal(num, default(ProcChainMask), true);
				}
			}
		}

		public class DroneSyncWithOwner : MonoBehaviour
		{
			public CharacterBody owner;

			public CharacterBody drone;

			public float scale = 2.5f;

			public float updateRate = 1f;

			private float timer;

			private void FixedUpdate()
			{
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_013e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0145: Invalid comparison between Unknown and I4
				//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
				//IL_0138: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: 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)
				//IL_0116: 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)
				if (!NetworkServer.active)
				{
					return;
				}
				timer += Time.fixedDeltaTime;
				if (timer < updateRate)
				{
					return;
				}
				timer = 0f;
				if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)drone))
				{
					Object.Destroy((Object)(object)this);
					return;
				}
				drone.baseDamage = owner.damage * Mathf.Max(0f, cfgDroneDamageScale.Value);
				drone.RecalculateStats();
				Inventory inventory = owner.inventory;
				Inventory inventory2 = drone.inventory;
				if (!((Object)(object)inventory != (Object)null) || !((Object)(object)inventory2 != (Object)null))
				{
					return;
				}
				for (ItemIndex val = (ItemIndex)0; (int)val < ItemCatalog.itemCount; val = (ItemIndex)(val + 1))
				{
					int itemCount = inventory.GetItemCount(val);
					int itemCount2 = inventory2.GetItemCount(val);
					if (itemCount != itemCount2)
					{
						if (itemCount2 > 0)
						{
							inventory2.RemoveItem(val, itemCount2);
						}
						if (itemCount > 0)
						{
							inventory2.GiveItem(val, itemCount);
						}
					}
				}
			}
		}

		public class TimedKill : MonoBehaviour
		{
			public float life = 45f;

			private float t;

			private CharacterMaster cm;

			private void Awake()
			{
				cm = ((Component)this).GetComponent<CharacterMaster>();
			}

			private void FixedUpdate()
			{
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				if (!NetworkServer.active)
				{
					return;
				}
				t += Time.fixedDeltaTime;
				if (t < life)
				{
					return;
				}
				Vector3 pos = ((Component)this).transform.position;
				CharacterBody val = (Object.op_Implicit((Object)(object)cm) ? cm.GetBody() : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					pos = val.corePosition;
				}
				EnsureNetworkSfx();
				PlaySfxAll(sfxDroneDeath, pos);
				if (Object.op_Implicit((Object)(object)cm))
				{
					CharacterBody body = cm.GetBody();
					if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)((Component)body).gameObject))
					{
						((Behaviour)body).enabled = false;
						Object.Destroy((Object)(object)((Component)body).gameObject);
					}
					cm.TrueKill();
					if (Object.op_Implicit((Object)(object)((Component)cm).gameObject))
					{
						NetworkServer.Destroy(((Component)cm).gameObject);
					}
				}
				Object.Destroy((Object)(object)this);
			}
		}

		internal static class PermDroneManager
		{
			public static int CountOwnedHeliDrones(CharacterMaster owner)
			{
				int num = 0;
				foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
				{
					if (Object.op_Implicit((Object)(object)readOnlyInstances))
					{
						MinionOwnership component = ((Component)readOnlyInstances).GetComponent<MinionOwnership>();
						if (Object.op_Implicit((Object)(object)component) && !((Object)(object)component.ownerMaster != (Object)(object)owner) && Object.op_Implicit((Object)(object)((Component)readOnlyInstances).GetComponent<PermDroneMarkerHeli>()))
						{
							num++;
						}
					}
				}
				return num;
			}

			public static bool KillOldestHeliDrone(CharacterMaster owner)
			{
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0113: Unknown result type (might be due to invalid IL or missing references)
				if (!NetworkServer.active || !Object.op_Implicit((Object)(object)owner))
				{
					return false;
				}
				CharacterMaster val = null;
				double num = double.MaxValue;
				foreach (CharacterMaster readOnlyInstances in CharacterMaster.readOnlyInstancesList)
				{
					if (!Object.op_Implicit((Object)(object)readOnlyInstances))
					{
						continue;
					}
					MinionOwnership component = ((Component)readOnlyInstances).GetComponent<MinionOwnership>();
					if (Object.op_Implicit((Object)(object)component) && !((Object)(object)component.ownerMaster != (Object)(object)owner))
					{
						PermDroneMarkerHeli component2 = ((Component)readOnlyInstances).GetComponent<PermDroneMarkerHeli>();
						if (Object.op_Implicit((Object)(object)component2) && component2.spawnedAt < num)
						{
							num = component2.spawnedAt;
							val = readOnlyInstances;
						}
					}
				}
				if (!Object.op_Implicit((Object)(object)val))
				{
					return false;
				}
				Vector3 pos = ((Component)val).transform.position;
				CharacterBody body = val.GetBody();
				if (Object.op_Implicit((Object)(object)body))
				{
					pos = body.corePosition;
				}
				EnsureNetworkSfx();
				PlaySfxAll(sfxDroneDeath, pos);
				CharacterBody body2 = val.GetBody();
				if (Object.op_Implicit((Object)(object)body2) && Object.op_Implicit((Object)(object)((Component)body2).gameObject))
				{
					((Behaviour)body2).enabled = false;
					Object.Destroy((Object)(object)((Component)body2).gameObject);
				}
				val.TrueKill();
				if (Object.op_Implicit((Object)(object)((Component)val).gameObject))
				{
					NetworkServer.Destroy(((Component)val).gameObject);
				}
				return true;
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static hook_Start <>9__25_0;

			public static Func<GenericSkill, bool> <>9__26_0;

			public static Func<GenericSkill, bool> <>9__27_0;

			public static EventHandler <>9__28_0;

			public static EventHandler <>9__28_1;

			public static EventHandler <>9__28_2;

			public static EventHandler <>9__28_3;

			public static EventHandler <>9__28_4;

			public static EventHandler <>9__28_5;

			public static EventHandler <>9__28_6;

			public static EventHandler <>9__28_7;

			public static EventHandler <>9__28_8;

			public static EventHandler <>9__28_9;

			internal void <Awake>b__25_0(orig_Start orig, CharacterBody self)
			{
				orig.Invoke(self);
				if (!Object.op_Implicit((Object)(object)self))
				{
					return;
				}
				if (NetworkServer.active && cfgMicrobots_Enable.Value && self.baseNameToken == "ENGI_BODY_NAME" && Object.op_Implicit((Object)(object)self.skillLocator) && Object.op_Implicit((Object)(object)self.skillLocator.special) && (Object)(object)self.skillLocator.special.skillDef == (Object)(object)Special_Perm_Def)
				{
					Inventory inventory = self.inventory;
					if ((Object)(object)inventory != (Object)null && inventory.GetItemCount(Items.CaptainDefenseMatrix) < 1)
					{
						inventory.GiveItem(Items.CaptainDefenseMatrix, 1);
						self.RecalculateStats();
					}
				}
				if (!NetworkServer.active || !self.isPlayerControlled)
				{
					return;
				}
				SkillDef selectedPassiveDef = GetSelectedPassiveDef(self);
				bool flag = cfgPassive_Enable.Value && (Object)(object)selectedPassiveDef == (Object)(object)Passive_DroneTinkering_Def;
				bool flag2 = cfgPassive_Enable.Value && (Object)(object)selectedPassiveDef == (Object)(object)Passive_AerialOverwatch_Def;
				PlayerDroneBarrierPassive component = ((Component)self).GetComponent<PlayerDroneBarrierPassive>();
				if (flag)
				{
					if (!Object.op_Implicit((Object)(object)component))
					{
						component = ((Component)self).gameObject.AddComponent<PlayerDroneBarrierPassive>();
						component.body = self;
					}
				}
				else if (Object.op_Implicit((Object)(object)component))
				{
					Object.Destroy((Object)(object)component);
				}
				PlayerAerialOverwatchPassive component2 = ((Component)self).GetComponent<PlayerAerialOverwatchPassive>();
				if (flag2)
				{
					if (!Object.op_Implicit((Object)(object)component2))
					{
						component2 = ((Component)self).gameObject.AddComponent<PlayerAerialOverwatchPassive>();
						component2.body = self;
					}
				}
				else if (Object.op_Implicit((Object)(object)component2))
				{
					Object.Destroy((Object)(object)component2);
				}
			}

			internal bool <EnsureCustomPassiveSlotOnEngi>b__26_0(GenericSkill s)
			{
				return Object.op_Implicit((Object)(object)s) && (Object)(object)s.skillFamily == (Object)(object)PassiveSkillFamily;
			}

			internal bool <GetSelectedPassiveDef>b__27_0(GenericSkill s)
			{
				return Object.op_Implicit((Object)(object)s) && (Object)(object)s.skillFamily == (Object)(object)PassiveSkillFamily;
			}

			internal void <BindConfig>b__28_0(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_1(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_2(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_3(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_4(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_5(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_6(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_7(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_8(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}

			internal void <BindConfig>b__28_9(object _, EventArgs __)
			{
				ApplyConfigToRuntime();
			}
		}

		internal static GameObject MissileProjectilePrefab;

		internal static GameObject DroneEmergencyMasterPrefab;

		internal static GameObject StrikeDroneMasterPrefab;

		private string _pluginDir;

		private static bool _initialized;

		internal static SkillDef Secondary_ATGM_Def;

		internal static SkillDef Utility_Call_Def;

		internal static SkillDef Special_Perm_Def;

		internal static SkillDef Passive_DroneTinkering_Def;

		internal static SkillDef Passive_AerialOverwatch_Def;

		private static SkillFamily PassiveSkillFamily;

		private const string PassiveSlotComponentName = "CAS_PassiveSlot";

		private static ConfigEntry<float> cfgSecondaryCooldown;

		private static ConfigEntry<float> cfgUtilityCooldown;

		private static ConfigEntry<int> cfgATGMCount;

		internal static ConfigEntry<float> cfgDroneDamageScale;

		private static ConfigEntry<int> cfgMaxDrones;

		internal static ConfigEntry<float> cfgUtilityHealFractionPerSecond;

		private static ConfigEntry<bool> cfgPassive_Enable;

		private static ConfigEntry<float> cfgPassive_BarrierPerDroneFraction;

		private static ConfigEntry<float> cfgPassive_AerialOverwatchPeriod;

		private static ConfigEntry<bool> cfgMicrobots_Enable;

		public static NetworkSoundEventDef sfxDroneRepair;

		public static NetworkSoundEventDef sfxDroneDeath;

		private static GameObject s_muzzleVfx;

		public void Awake()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_0552: Unknown result type (might be due to invalid IL or missing references)
			//IL_0557: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Expected O, but got Unknown
			if (_initialized)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"[CAS] Awake already ran.");
				return;
			}
			_initialized = true;
			_pluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			BindConfig();
			bool flag = default(bool);
			ContentAddition.AddEntityState<MyEntityStates.Engi_DroneATGMSalvo>(ref flag);
			ContentAddition.AddEntityState<MyEntityStates.Engi_CallEmergencyDrones>(ref flag);
			ContentAddition.AddEntityState<MyEntityStates.Engi_SummonPermanentDrone>(ref flag);
			EnsurePrefabs();
			EnsureNetworkSfx();
			GameObject val = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Engi/EngiBody.prefab").WaitForCompletion();
			if (!Object.op_Implicit((Object)(object)val))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[CAS] Failed to load EngiBody.");
				return;
			}
			LanguageAPI.Add("ENGI_SECONDARY_ATGM_NAME", "Portable Missile Silos");
			LanguageAPI.Add("ENGI_SECONDARY_ATGM_DESCRIPTION", $"Order your <style=cIsUtility>permanent drones</style> to fire <style=cIsDamage>{cfgATGMCount.Value}</style> ATGM missiles each. <style=cIsUtility>Cooldown: {cfgSecondaryCooldown.Value:0}s</style>.");
			LanguageAPI.Add("ENGI_UTILITY_CALL_NAME", "Call Reinforcements");
			LanguageAPI.Add("ENGI_UTILITY_CALL_DESCRIPTION", $"Call an <style=cIsUtility>Emergency Drone</style> for <style=cIsUtility>each player</style> for <style=cIsUtility>45s</style>. Heals owner for <style=cIsHealing>{(int)(cfgUtilityHealFractionPerSecond.Value * 100f)}% max health/s</style>. <style=cIsUtility>Cooldown: {cfgUtilityCooldown.Value:0}s</style>.");
			LanguageAPI.Add("ENGI_SPECIAL_PERMDRONE_NAME", "Close Air Support");
			LanguageAPI.Add("ENGI_SPECIAL_PERMDRONE_DESCRIPTION", $"Deploy a <style=cIsUtility>permanent C.Y.A. Mk 1 Drone</style> (max <style=cIsUtility>{cfgMaxDrones.Value}</style>). Drones inherit your items and deal <style=cIsDamage>{(int)(cfgDroneDamageScale.Value * 100f)}% base damage</style>.");
			LanguageAPI.Add("CYA_MK1_NAME", "(C.Y.A. Mk 1)");
			LanguageAPI.Add("CAS_PASSIVE_DRONETINKER_NAME", "Drone Tinkering");
			LanguageAPI.Add("CAS_PASSIVE_DRONETINKER_DESC", "Gain barrier equal to <style=cIsHealing>5% of your max health</style> per drone you control.");
			LanguageAPI.Add("CAS_PASSIVE_AERIALWATCH_NAME", "Aerial Overwatch");
			LanguageAPI.Add("CAS_PASSIVE_AERIALWATCH_DESC", "While you control at least one drone, automatically trigger <style=cIsUtility>Radar Scanner</style> every 90s.");
			Secondary_ATGM_Def = ScriptableObject.CreateInstance<SkillDef>();
			Secondary_ATGM_Def.skillNameToken = "ENGI_SECONDARY_ATGM_NAME";
			Secondary_ATGM_Def.skillDescriptionToken = "ENGI_SECONDARY_ATGM_DESCRIPTION";
			Secondary_ATGM_Def.icon = LoadSprite("icon_secondary.png");
			Secondary_ATGM_Def.activationState = new SerializableEntityStateType(typeof(MyEntityStates.Engi_DroneATGMSalvo));
			Secondary_ATGM_Def.activationStateMachineName = "Weapon";
			Secondary_ATGM_Def.baseMaxStock = 1;
			Secondary_ATGM_Def.baseRechargeInterval = Mathf.Max(0.1f, cfgSecondaryCooldown.Value);
			Secondary_ATGM_Def.beginSkillCooldownOnSkillEnd = true;
			Secondary_ATGM_Def.isCombatSkill = true;
			Secondary_ATGM_Def.mustKeyPress = true;
			Secondary_ATGM_Def.interruptPriority = (InterruptPriority)1;
			ContentAddition.AddSkillDef(Secondary_ATGM_Def);
			Utility_Call_Def = ScriptableObject.CreateInstance<SkillDef>();
			Utility_Call_Def.skillNameToken = "ENGI_UTILITY_CALL_NAME";
			Utility_Call_Def.skillDescriptionToken = "ENGI_UTILITY_CALL_DESCRIPTION";
			Utility_Call_Def.icon = LoadSprite("icon_utility.png");
			Utility_Call_Def.activationState = new SerializableEntityStateType(typeof(MyEntityStates.Engi_CallEmergencyDrones));
			Utility_Call_Def.activationStateMachineName = "Weapon";
			Utility_Call_Def.baseMaxStock = 1;
			Utility_Call_Def.baseRechargeInterval = Mathf.Max(0.1f, cfgUtilityCooldown.Value);
			Utility_Call_Def.beginSkillCooldownOnSkillEnd = true;
			Utility_Call_Def.isCombatSkill = true;
			Utility_Call_Def.mustKeyPress = true;
			Utility_Call_Def.interruptPriority = (InterruptPriority)1;
			ContentAddition.AddSkillDef(Utility_Call_Def);
			Special_Perm_Def = ScriptableObject.CreateInstance<SkillDef>();
			Special_Perm_Def.skillNameToken = "ENGI_SPECIAL_PERMDRONE_NAME";
			Special_Perm_Def.skillDescriptionToken = "ENGI_SPECIAL_PERMDRONE_DESCRIPTION";
			Special_Perm_Def.icon = LoadSprite("icon_special.png");
			Special_Perm_Def.activationState = new SerializableEntityStateType(typeof(MyEntityStates.Engi_SummonPermanentDrone));
			Special_Perm_Def.activationStateMachineName = "Weapon";
			Special_Perm_Def.baseMaxStock = Mathf.Max(1, cfgMaxDrones.Value);
			Special_Perm_Def.baseRechargeInterval = 30f;
			Special_Perm_Def.beginSkillCooldownOnSkillEnd = true;
			Special_Perm_Def.isCombatSkill = true;
			Special_Perm_Def.mustKeyPress = true;
			Special_Perm_Def.interruptPriority = (InterruptPriority)1;
			ContentAddition.AddSkillDef(Special_Perm_Def);
			SkillLocator component = val.GetComponent<SkillLocator>();
			AppendVariantUnique(component.secondary.skillFamily, Secondary_ATGM_Def);
			AppendVariantUnique(component.utility.skillFamily, Utility_Call_Def);
			AppendVariantUnique(component.special.skillFamily, Special_Perm_Def);
			if (!Object.op_Implicit((Object)(object)Passive_DroneTinkering_Def))
			{
				Passive_DroneTinkering_Def = ScriptableObject.CreateInstance<SkillDef>();
				Passive_DroneTinkering_Def.skillNameToken = "CAS_PASSIVE_DRONETINKER_NAME";
				Passive_DroneTinkering_Def.skillDescriptionToken = "CAS_PASSIVE_DRONETINKER_DESC";
				Passive_DroneTinkering_Def.icon = LoadSprite("icon_passive_dronetinker.png");
				Passive_DroneTinkering_Def.isCombatSkill = false;
				ContentAddition.AddSkillDef(Passive_DroneTinkering_Def);
			}
			if (!Object.op_Implicit((Object)(object)Passive_AerialOverwatch_Def))
			{
				Passive_AerialOverwatch_Def = ScriptableObject.CreateInstance<SkillDef>();
				Passive_AerialOverwatch_Def.skillNameToken = "CAS_PASSIVE_AERIALWATCH_NAME";
				Passive_AerialOverwatch_Def.skillDescriptionToken = "CAS_PASSIVE_AERIALWATCH_DESC";
				Passive_AerialOverwatch_Def.icon = LoadSprite("icon_passive_aerialoverwatch.png");
				Passive_AerialOverwatch_Def.isCombatSkill = false;
				ContentAddition.AddSkillDef(Passive_AerialOverwatch_Def);
			}
			EnsureCustomPassiveSlotOnEngi(val);
			ApplyConfigToRuntime();
			object obj = <>c.<>9__25_0;
			if (obj == null)
			{
				hook_Start val2 = delegate(orig_Start orig, CharacterBody self)
				{
					orig.Invoke(self);
					if (Object.op_Implicit((Object)(object)self))
					{
						if (NetworkServer.active && cfgMicrobots_Enable.Value && self.baseNameToken == "ENGI_BODY_NAME" && Object.op_Implicit((Object)(object)self.skillLocator) && Object.op_Implicit((Object)(object)self.skillLocator.special) && (Object)(object)self.skillLocator.special.skillDef == (Object)(object)Special_Perm_Def)
						{
							Inventory inventory = self.inventory;
							if ((Object)(object)inventory != (Object)null && inventory.GetItemCount(Items.CaptainDefenseMatrix) < 1)
							{
								inventory.GiveItem(Items.CaptainDefenseMatrix, 1);
								self.RecalculateStats();
							}
						}
						if (NetworkServer.active && self.isPlayerControlled)
						{
							SkillDef selectedPassiveDef = GetSelectedPassiveDef(self);
							bool flag2 = cfgPassive_Enable.Value && (Object)(object)selectedPassiveDef == (Object)(object)Passive_DroneTinkering_Def;
							bool flag3 = cfgPassive_Enable.Value && (Object)(object)selectedPassiveDef == (Object)(object)Passive_AerialOverwatch_Def;
							PlayerDroneBarrierPassive component2 = ((Component)self).GetComponent<PlayerDroneBarrierPassive>();
							if (flag2)
							{
								if (!Object.op_Implicit((Object)(object)component2))
								{
									component2 = ((Component)self).gameObject.AddComponent<PlayerDroneBarrierPassive>();
									component2.body = self;
								}
							}
							else if (Object.op_Implicit((Object)(object)component2))
							{
								Object.Destroy((Object)(object)component2);
							}
							PlayerAerialOverwatchPassive component3 = ((Component)self).GetComponent<PlayerAerialOverwatchPassive>();
							if (flag3)
							{
								if (!Object.op_Implicit((Object)(object)component3))
								{
									component3 = ((Component)self).gameObject.AddComponent<PlayerAerialOverwatchPassive>();
									component3.body = self;
								}
							}
							else if (Object.op_Implicit((Object)(object)component3))
							{
								Object.Destroy((Object)(object)component3);
							}
						}
					}
				};
				<>c.<>9__25_0 = val2;
				obj = (object)val2;
			}
			CharacterBody.Start += (hook_Start)obj;
			TryRegisterRiskOfOptions();
		}

		private static void EnsureCustomPassiveSlotOnEngi(GameObject engiBodyPrefab)
		{
			//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_008a: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)engiBodyPrefab))
			{
				if (!Object.op_Implicit((Object)(object)PassiveSkillFamily))
				{
					PassiveSkillFamily = ScriptableObject.CreateInstance<SkillFamily>();
					PassiveSkillFamily.variants = Array.Empty<Variant>();
					ContentAddition.AddSkillFamily(PassiveSkillFamily);
					ref Variant[] variants = ref PassiveSkillFamily.variants;
					Variant val = new Variant
					{
						skillDef = Passive_DroneTinkering_Def,
						unlockableDef = null
					};
					((Variant)(ref val)).viewableNode = new Node(Passive_DroneTinkering_Def.skillNameToken, false, (Node)null);
					ArrayUtils.ArrayAppend<Variant>(ref variants, ref val);
					ref Variant[] variants2 = ref PassiveSkillFamily.variants;
					val = new Variant
					{
						skillDef = Passive_AerialOverwatch_Def,
						unlockableDef = null
					};
					((Variant)(ref val)).viewableNode = new Node(Passive_AerialOverwatch_Def.skillNameToken, false, (Node)null);
					ArrayUtils.ArrayAppend<Variant>(ref variants2, ref val);
				}
				GenericSkill[] components = engiBodyPrefab.GetComponents<GenericSkill>();
				if (!components.Any((GenericSkill s) => Object.op_Implicit((Object)(object)s) && (Object)(object)s.skillFamily == (Object)(object)PassiveSkillFamily))
				{
					GenericSkill val2 = engiBodyPrefab.AddComponent<GenericSkill>();
					val2._skillFamily = PassiveSkillFamily;
					val2.skillName = "CAS_PassiveSlot";
				}
			}
		}

		private static SkillDef GetSelectedPassiveDef(CharacterBody body)
		{
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)PassiveSkillFamily))
			{
				return null;
			}
			GenericSkill val = ((Component)body).GetComponents<GenericSkill>()?.FirstOrDefault((Func<GenericSkill, bool>)((GenericSkill s) => Object.op_Implicit((Object)(object)s) && (Object)(object)s.skillFamily == (Object)(object)PassiveSkillFamily));
			return Object.op_Implicit((Object)(object)val) ? val.skillDef : null;
		}

		private void BindConfig()
		{
			cfgSecondaryCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Skills", "SecondaryCooldownSeconds", 10f, "Cooldown (s) for Portable Missile Silos.");
			cfgUtilityCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Skills", "UtilityCooldownSeconds", 60f, "Cooldown (s) for Call Reinforcements.");
			cfgATGMCount = ((BaseUnityPlugin)this).Config.Bind<int>("Secondary", "MissilesPerDrone", 20, "ATGMs each permanent drone fires.");
			cfgDroneDamageScale = ((BaseUnityPlugin)this).Config.Bind<float>("PermanentDrones", "DroneDamagePlayerScaling", 2.5f, "Drone base damage as fraction of owner’s.");
			cfgMaxDrones = ((BaseUnityPlugin)this).Config.Bind<int>("PermanentDrones", "MaxPermanentDrones", 3, "Max permanent drones.");
			cfgUtilityHealFractionPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Utility", "HealFractionPerSecond", 0.1f, "Emergency Drone healing per second (fraction of max HP).");
			cfgPassive_Enable = ((BaseUnityPlugin)this).Config.Bind<bool>("Passive", "Enable", true, "Enable selectable passives for Engineer (CAS passive row).");
			cfgPassive_BarrierPerDroneFraction = ((BaseUnityPlugin)this).Config.Bind<float>("Passive", "BarrierPerDroneFraction", 0.05f, "Barrier = fraction * max HP per owned drone.");
			cfgPassive_AerialOverwatchPeriod = ((BaseUnityPlugin)this).Config.Bind<float>("Passive", "AerialOverwatchPeriodSeconds", 90f, "Seconds between auto Radar Scanner activations (needs ≥1 owned drone).");
			cfgMicrobots_Enable = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "EnableDefensiveMicrobots", true, "If true, Engineer gains one stack of Defensive Microbots while Close Air Support special is equipped.");
			cfgSecondaryCooldown.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgUtilityCooldown.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgATGMCount.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgDroneDamageScale.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgMaxDrones.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgUtilityHealFractionPerSecond.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgPassive_Enable.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgPassive_BarrierPerDroneFraction.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgPassive_AerialOverwatchPeriod.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			cfgMicrobots_Enable.SettingChanged += delegate
			{
				ApplyConfigToRuntime();
			};
			ApplyConfigToRuntime();
		}

		private static void ApplyConfigToRuntime()
		{
			MyEntityStates.Engi_DroneATGMSalvo.missilesPerDrone = Mathf.Max(0, cfgATGMCount.Value);
			MyEntityStates.Engi_SummonPermanentDrone.maxOwned = Mathf.Max(1, cfgMaxDrones.Value);
			MyEntityStates.Engi_CallEmergencyDrones.healFractionPerSecond = Mathf.Max(0f, cfgUtilityHealFractionPerSecond.Value);
			if (Object.op_Implicit((Object)(object)Secondary_ATGM_Def))
			{
				Secondary_ATGM_Def.baseRechargeInterval = Mathf.Max(0.1f, cfgSecondaryCooldown.Value);
			}
			if (Object.op_Implicit((Object)(object)Utility_Call_Def))
			{
				Utility_Call_Def.baseRechargeInterval = Mathf.Max(0.1f, cfgUtilityCooldown.Value);
			}
			if (Object.op_Implicit((Object)(object)Special_Perm_Def))
			{
				Special_Perm_Def.baseMaxStock = Mathf.Max(1, cfgMaxDrones.Value);
			}
		}

		private void TryRegisterRiskOfOptions()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			try
			{
				ModSettingsManager.SetModDescription("Close Air Support — drone skills only (no cosmetics).");
				Sprite val = LoadSprite("icon_special.png");
				if (Object.op_Implicit((Object)(object)val))
				{
					ModSettingsManager.SetModIcon(val);
				}
				ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(cfgSecondaryCooldown));
				ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(cfgUtilityCooldown));
				ModSettingsManager.AddOption((BaseOption)new IntFieldOption(cfgATGMCount));
				ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(cfgDroneDamageScale));
				ModSettingsManager.AddOption((BaseOption)new IntFieldOption(cfgMaxDrones));
				ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(cfgUtilityHealFractionPerSecond));
				ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(cfgPassive_Enable));
				ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(cfgPassive_BarrierPerDroneFraction));
				ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(cfgPassive_AerialOverwatchPeriod));
				ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(cfgMicrobots_Enable));
				((BaseUnityPlugin)this).Logger.LogMessage((object)"[CAS] Risk of Options (gameplay options) registered.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[CAS] Risk of Options not available or failed to register: " + ex.Message));
			}
		}

		internal static void EnsureMuzzleVfx()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)s_muzzleVfx))
			{
				s_muzzleVfx = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Common/VFX/Muzzleflash1.prefab").WaitForCompletion() ?? Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Common/VFX/MuzzleflashSMG.prefab").WaitForCompletion() ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/Muzzleflash1") ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/MuzzleflashSMG");
			}
		}

		internal static void SpawnMuzzleFlash(Transform muzzle, Quaternion dir)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)muzzle))
			{
				EnsureMuzzleVfx();
				if (Object.op_Implicit((Object)(object)s_muzzleVfx))
				{
					EffectManager.SpawnEffect(s_muzzleVfx, new EffectData
					{
						origin = muzzle.position,
						rotation = dir
					}, true);
				}
			}
		}

		public static void EnsureNetworkSfx()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)sfxDroneRepair))
			{
				sfxDroneRepair = Addressables.LoadAssetAsync<NetworkSoundEventDef>((object)"RoR2/Base/Common/NetworkSoundEventDefs/Play_item_proc_drone_repair.asset").WaitForCompletion() ?? LegacyResourcesAPI.Load<NetworkSoundEventDef>("NetworkSoundEventDefs/Play_item_proc_drone_repair");
			}
			if (!Object.op_Implicit((Object)(object)sfxDroneDeath))
			{
				sfxDroneDeath = Addressables.LoadAssetAsync<NetworkSoundEventDef>((object)"RoR2/Base/Drone/NetworkSoundEventDefs/Play_drone_deathpt1.asset").WaitForCompletion() ?? LegacyResourcesAPI.Load<NetworkSoundEventDef>("NetworkSoundEventDefs/Play_drone_deathpt1");
			}
		}

		public static void PlaySfxAll(NetworkSoundEventDef def, Vector3 pos)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)def != (Object)null)
			{
				EffectManager.SimpleSoundEffect(def.index, pos, true);
			}
		}

		private static void AppendVariantUnique(SkillFamily fam, SkillDef def)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			Variant[] variants = fam.variants;
			foreach (Variant val in variants)
			{
				if ((Object)(object)val.skillDef == (Object)(object)def)
				{
					return;
				}
			}
			Array.Resize(ref fam.variants, fam.variants.Length + 1);
			Variant[] variants2 = fam.variants;
			int num = variants2.Length - 1;
			Variant val2 = new Variant
			{
				skillDef = def,
				unlockableDef = null
			};
			((Variant)(ref val2)).viewableNode = new Node(def.skillNameToken, false, (Node)null);
			variants2[num] = val2;
		}

		internal static void EnsurePrefabs()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)MissileProjectilePrefab))
			{
				MissileProjectilePrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Missile/MissileProjectile.prefab").WaitForCompletion() ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/Projectiles/MissileProjectile");
			}
			if (!Object.op_Implicit((Object)(object)DroneEmergencyMasterPrefab))
			{
				DroneEmergencyMasterPrefab = MasterCatalog.FindMasterPrefab("EmergencyDroneMaster") ?? MasterCatalog.FindMasterPrefab("DroneEmergencyMaster") ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/EmergencyDroneMaster") ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/DroneEmergencyMaster") ?? MasterCatalog.FindMasterPrefab("Drone2Master") ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/Drone2Master");
			}
			if (!Object.op_Implicit((Object)(object)StrikeDroneMasterPrefab))
			{
				StrikeDroneMasterPrefab = MasterCatalog.FindMasterPrefab("DroneStrikeMaster") ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/DroneStrikeMaster") ?? MasterCatalog.FindMasterPrefab("DroneBackupMaster") ?? LegacyResourcesAPI.Load<GameObject>("Prefabs/CharacterMasters/DroneBackupMaster");
			}
		}

		private Sprite LoadSprite(string fileName)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			string path = Path.Combine(_pluginDir, fileName);
			if (!File.Exists(path))
			{
				return null;
			}
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, array);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}

		internal static bool TryGetMuzzle(CharacterBody body, out Transform muzzle)
		{
			muzzle = null;
			if (!Object.op_Implicit((Object)(object)body))
			{
				return false;
			}
			Transform val = (Object.op_Implicit((Object)(object)body.modelLocator) ? body.modelLocator.modelTransform : null);
			ChildLocator val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ChildLocator>() : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				muzzle = val2.FindChild("Muzzle") ?? val2.FindChild("GunMuzzle") ?? val2.FindChild("MuzzleLeft") ?? val2.FindChild("MuzzleRight");
			}
			return Object.op_Implicit((Object)(object)muzzle);
		}
	}
}