Decompiled source of AlliedDefenses v0.18.0

AlliedDefenses.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using AlliedDefenses.Beacon;
using AlliedDefenses.Config;
using AlliedDefenses.Core;
using AlliedDefenses.Defenses;
using AlliedDefenses.NetcodePatcher;
using AlliedDefenses.Networking;
using AlliedDefenses.Patches;
using AlliedDefenses.UI;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AlliedDefenses")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.7.0.0")]
[assembly: AssemblyInformationalVersion("0.7.0+a4593bf9e22da4f04eef194295e741d43d2c4dfa")]
[assembly: AssemblyProduct("AlliedDefenses")]
[assembly: AssemblyTitle("AlliedDefenses")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.7.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 AlliedDefenses
{
	[BepInPlugin("Remilulz_91.AlliedDefenses", "AlliedDefenses", "0.18.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Author = "Remilulz_91";

		public const string Guid = "Remilulz_91.AlliedDefenses";

		public const string Name = "AlliedDefenses";

		public const string Version = "0.18.0";

		private readonly Harmony _harmony = new Harmony("Remilulz_91.AlliedDefenses");

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			UpgradeManager.Init(((BaseUnityPlugin)this).Config);
			try
			{
				_harmony.PatchAll();
				DefenseRegistry.RegisterDefaults();
				try
				{
					MethodInfo methodInfo = AccessTools.Method(typeof(GameNetworkManager), "ResetSavedGameValues", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(UpgradeGameOverPatch), "AfterReset", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					else
					{
						Log.LogWarning((object)"ResetSavedGameValues not found; PerSave upgrades will rely on the save-slot lifecycle only.");
					}
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Could not hook the game-over reset: " + ex.Message));
				}
				try
				{
					MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerControllerB), "GameNetcodeStuff.IVisibleThreat.GetVisibility", (Type[])null, (Type[])null);
					if (methodInfo2 != null)
					{
						_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(CloakPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					else
					{
						Log.LogWarning((object)"IVisibleThreat.GetVisibility not found; the 'cloak' upgrade won't apply.");
					}
				}
				catch (Exception ex2)
				{
					Log.LogWarning((object)("Could not hook GetVisibility for the cloak: " + ex2.Message));
				}
				HijackTicker.EnsureExists();
				Log.LogInfo((object)string.Format("{0} v{1} by {2} loaded. {3} defense module(s) active.", "AlliedDefenses", "0.18.0", "Remilulz_91", DefenseRegistry.Count));
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to apply Harmony patches: {arg}");
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "AlliedDefenses";

		public const string PLUGIN_NAME = "AlliedDefenses";

		public const string PLUGIN_VERSION = "0.7.0";
	}
}
namespace AlliedDefenses.UI
{
	public static class CommandText
	{
		private static string Keyword => ModConfig.HijackCommand.Value.Trim();

		private static bool Fr => ModConfig.TerminalLanguage.Value == Language.Francais;

		public static string Usage()
		{
			if (!Fr)
			{
				return UsageEn();
			}
			return UsageFr();
		}

		public static string HowItWorks()
		{
			if (!Fr)
			{
				return HowItWorksEn();
			}
			return HowItWorksFr();
		}

		public static string CurrentConfig()
		{
			if (!Fr)
			{
				return CurrentConfigEn();
			}
			return CurrentConfigFr();
		}

		private static string UsageEn()
		{
			string keyword = Keyword;
			return "ALLIED DEFENSES\n-------------------------\n" + keyword + " <id>     : hijack one defense by its id (turret, mine or spike, e.g. " + keyword + " U9)\n" + keyword + " turrets  : list all turrets and their ids\n" + keyword + " mines    : list all mines and their ids\n" + keyword + " spikes   : list all spike traps and their ids\n" + keyword + " upgrades : buy upgrades with ship credits\n" + keyword + " beacon   : buy the deployable Defense Beacon\n" + keyword + " hack     : buy the Hack Tool (aim at a door/turret + key)\n" + keyword + " help     : how the mod works\n" + keyword + " config   : show the current settings\n";
		}

		private static string HowItWorksEn()
		{
			string keyword = Keyword;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("ALLIED DEFENSES - HOW IT WORKS");
			stringBuilder.AppendLine("------------------------------------");
			stringBuilder.AppendLine("Normally the facility defenses target YOU (the employees) and");
			stringBuilder.AppendLine("ignore the monsters. This mod lets you flip that.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("TURRETS / MINES / SPIKE TRAPS:");
			stringBuilder.AppendLine("  " + keyword + " turrets | mines | spikes   list them and their ids.");
			stringBuilder.AppendLine("  " + keyword + " <id>   hijack one (same id you'd use to disable it).");
			stringBuilder.AppendLine("  Allied, they hurt ENEMIES instead of players: turrets shoot the");
			stringBuilder.AppendLine("  nearest enemy, mines/spikes only trigger on enemies.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("UPGRADES:");
			stringBuilder.AppendLine("  " + keyword + " upgrades       see upgrades, levels and costs.");
			stringBuilder.AppendLine("  " + keyword + " upgrade <id>   buy the next level with ship credits.");
			stringBuilder.AppendLine("  " + keyword + " upgrade reset  reset all upgrades to level 0.");
			stringBuilder.AppendLine("  Upgrades are TEAM-WIDE: bought once from shared credits, every");
			stringBuilder.AppendLine("  player in the lobby benefits (levels are synced to everyone).");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("DEFENSE BEACON (deploy protection anywhere):");
			stringBuilder.AppendLine("  " + keyword + " beacon  buy it once. Then press the deploy key ([" + ModConfig.BeaconDeployKey.Value + "] by");
			stringBuilder.AppendLine("  default) to drop it at your position - out in the field where there");
			stringBuilder.AppendLine("  are no turrets or mines. Press again to move it. It anchors the");
			stringBuilder.AppendLine("  counter-play auras below.");
			stringBuilder.AppendLine("  Recall it with [" + ModConfig.BeaconRecallKey.Value + "] or '" + keyword + " beacon recall'.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("HACK TOOL (control the facility from inside):");
			stringBuilder.AppendLine("  " + keyword + " hack  buy it. Then AIM at a locked big door, turret, mine or");
			stringBuilder.AppendLine("  spike trap and press the hack key ([" + ModConfig.HackKey.Value + "]) to trigger it -");
			stringBuilder.AppendLine("  like typing its code at the terminal, but from inside the facility.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("UNKILLABLE ENEMIES (counter-play auras, near a defense OR beacon):");
			stringBuilder.AppendLine("  sanity     : calms your mind, so the Ghost Girl escalates less.");
			stringBuilder.AppendLine("  neutralize : an allied turret freezes a Coil-Head it watches.");
			stringBuilder.AppendLine("  seismic    : the sand worm can't target you in the radius.");
			stringBuilder.AppendLine("  muffle     : Eyeless Dogs (blind) can't hear noise in the radius.");
			stringBuilder.AppendLine("  barber     : the Barber can't target you in the radius.");
			stringBuilder.AppendLine("  slime      : the Hygrodere can't target you (it wanders off).");
			stringBuilder.AppendLine("  bees       : Circuit Bees drop their chase in the radius.");
			stringBuilder.AppendLine("  cloak      : big DETECTION enemies can't see you in the radius -");
			stringBuilder.AppendLine("               the Old Bird (unkillable), Forest Giant, Baboon Hawk,");
			stringBuilder.AppendLine("               Kidnapper Fox, Giant Kiwi.");
			stringBuilder.AppendLine("  Each is a separate upgrade (level 0 = off).");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("All hijacks last a set time, then turn hostile again. Everyone in");
			stringBuilder.AppendLine("the lobby must have the mod; effects are synced.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("Type  " + keyword + " config  to see the exact current settings.");
			return stringBuilder.ToString();
		}

		private static string CurrentConfigEn()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("ALLIED DEFENSES - CURRENT CONFIG");
			stringBuilder.AppendLine("------------------------------------");
			stringBuilder.AppendLine("Command keyword       : " + Keyword);
			stringBuilder.AppendLine("Allied duration       : " + DurationText(fr: false));
			stringBuilder.AppendLine($"Turret detect range   : {UpgradeManager.EffectiveDetectionRange():0} meters");
			stringBuilder.AppendLine($"Mine trigger radius   : {UpgradeManager.EffectiveMineRadius():0} meters");
			stringBuilder.AppendLine("Players can be hit    : " + (ModConfig.IgnorePlayersWhenAllied.Value ? "NO - allied defenses never hurt players" : "yes - friendly fire is ON"));
			stringBuilder.AppendLine("Hijack cost           : " + ((ModConfig.HijackCreditCost.Value > 0) ? $"{ModConfig.HijackCreditCost.Value} credits per hijack" : "free"));
			stringBuilder.AppendLine("Allied colour cue     : " + (ModConfig.ColorAlliedDefenses.Value ? "ON (green in dungeon, blue code on radar)" : "off"));
			stringBuilder.AppendLine("Defense Beacon        : " + BeaconText(fr: false));
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine($"Defense types supported : {DefenseRegistry.Count}");
			stringBuilder.AppendLine($"Currently hijacked      : {HijackManager.ActiveCount}");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("(Settings live in BepInEx/config/Remilulz_91.AlliedDefenses.cfg)");
			return stringBuilder.ToString();
		}

		private static string UsageFr()
		{
			string keyword = Keyword;
			return "DEFENSES ALLIEES\n-------------------------\n" + keyword + " <id>     : pirater une defense par son id (tourelle, mine ou pique, ex. " + keyword + " U9)\n" + keyword + " turrets  : lister toutes les tourelles et leurs ids\n" + keyword + " mines    : lister toutes les mines et leurs ids\n" + keyword + " spikes   : lister tous les pieges a pointes et leurs ids\n" + keyword + " upgrades : acheter des ameliorations avec les credits du vaisseau\n" + keyword + " beacon   : acheter la balise de defense deployable\n" + keyword + " hack     : acheter l'outil de piratage (viser + touche)\n" + keyword + " help     : comment fonctionne le mod\n" + keyword + " config   : afficher les reglages actuels\n";
		}

		private static string HowItWorksFr()
		{
			string keyword = Keyword;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("DEFENSES ALLIEES - FONCTIONNEMENT");
			stringBuilder.AppendLine("------------------------------------");
			stringBuilder.AppendLine("Normalement les defenses du complexe VOUS visent (les employes)");
			stringBuilder.AppendLine("et ignorent les monstres. Ce mod inverse la situation.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("TOURELLES / MINES / PIEGES A POINTES :");
			stringBuilder.AppendLine("  " + keyword + " turrets | mines | spikes   les lister avec leurs ids.");
			stringBuilder.AppendLine("  " + keyword + " <id>   en pirater une (le meme id que pour la desactiver).");
			stringBuilder.AppendLine("  Alliees, elles frappent les ENNEMIS au lieu des joueurs : la");
			stringBuilder.AppendLine("  tourelle vise l'ennemi le plus proche, mines/pieges ne se");
			stringBuilder.AppendLine("  declenchent que sur les ennemis.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("AMELIORATIONS :");
			stringBuilder.AppendLine("  " + keyword + " upgrades       voir les ameliorations, niveaux et couts.");
			stringBuilder.AppendLine("  " + keyword + " upgrade <id>   acheter le niveau suivant avec les credits.");
			stringBuilder.AppendLine("  " + keyword + " upgrade reset  remettre toutes les ameliorations a 0.");
			stringBuilder.AppendLine("  Les ameliorations sont D'EQUIPE : achetees une fois avec les");
			stringBuilder.AppendLine("  credits partages, tout le lobby en profite (niveaux synchronises).");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("BALISE DE DEFENSE (protection deployable partout) :");
			stringBuilder.AppendLine("  " + keyword + " beacon  achat unique. Ensuite appuie sur la touche de depot");
			stringBuilder.AppendLine("  ([" + ModConfig.BeaconDeployKey.Value + "] par defaut) pour la poser a ta position, sur le terrain");
			stringBuilder.AppendLine("  la ou il n'y a ni tourelle ni mine. Reappuie pour la deplacer.");
			stringBuilder.AppendLine("  Elle ancre les auras de contre-jeu ci-dessous.");
			stringBuilder.AppendLine("  Range-la avec [" + ModConfig.BeaconRecallKey.Value + "] ou '" + keyword + " beacon recall'.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("OUTIL DE PIRATAGE (piloter le complexe depuis l'interieur) :");
			stringBuilder.AppendLine("  " + keyword + " hack  achete-le. Ensuite VISE une porte verrouillee, une");
			stringBuilder.AppendLine("  tourelle, une mine ou un piege et appuie sur la touche ([" + ModConfig.HackKey.Value + "])");
			stringBuilder.AppendLine("  pour le declencher - comme taper son code, mais depuis l'interieur.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("ENNEMIS INCREVABLES (auras de contre-jeu, pres d'une defense/balise) :");
			stringBuilder.AppendLine("  sanity     : calme ton esprit, la Fille fantome t'escalade moins.");
			stringBuilder.AppendLine("  neutralize : une tourelle alliee fige un Coil-Head qu'elle regarde.");
			stringBuilder.AppendLine("  seismic    : le ver des sables ne peut pas te cibler dans le rayon.");
			stringBuilder.AppendLine("  muffle     : les Chiens (aveugles) n'entendent plus le bruit ici.");
			stringBuilder.AppendLine("  barber     : le Coiffeur ne peut pas te cibler dans le rayon.");
			stringBuilder.AppendLine("  slime      : l'Hygrodere ne peut pas te cibler (il s'en va).");
			stringBuilder.AppendLine("  bees       : les Abeilles abandonnent leur poursuite dans le rayon.");
			stringBuilder.AppendLine("  cloak      : les gros ennemis a DETECTION ne te voient plus dans le");
			stringBuilder.AppendLine("               rayon - Vieil Oiseau (increvable), Gardien de la foret,");
			stringBuilder.AppendLine("               Faucon babouin, Renard, Kiwi geant.");
			stringBuilder.AppendLine("  Chacune est une amelioration separee (niveau 0 = desactive).");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("Chaque piratage dure un temps donne, puis redevient hostile. Tous");
			stringBuilder.AppendLine("les joueurs du lobby doivent avoir le mod ; les effets sont synchro.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("Tape  " + keyword + " config  pour voir les reglages exacts.");
			return stringBuilder.ToString();
		}

		private static string CurrentConfigFr()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("DEFENSES ALLIEES - CONFIG ACTUELLE");
			stringBuilder.AppendLine("------------------------------------");
			stringBuilder.AppendLine("Mot-cle de commande   : " + Keyword);
			stringBuilder.AppendLine("Duree alliee          : " + DurationText(fr: true));
			stringBuilder.AppendLine($"Portee tourelle       : {UpgradeManager.EffectiveDetectionRange():0} metres");
			stringBuilder.AppendLine($"Rayon mine            : {UpgradeManager.EffectiveMineRadius():0} metres");
			stringBuilder.AppendLine("Joueurs touchables    : " + (ModConfig.IgnorePlayersWhenAllied.Value ? "NON - les defenses alliees n'atteignent jamais les joueurs" : "oui - tir ami ACTIF"));
			stringBuilder.AppendLine("Cout de piratage      : " + ((ModConfig.HijackCreditCost.Value > 0) ? $"{ModConfig.HijackCreditCost.Value} credits par piratage" : "gratuit"));
			stringBuilder.AppendLine("Indice couleur allie  : " + (ModConfig.ColorAlliedDefenses.Value ? "OUI (vert dans le donjon, code bleu au radar)" : "non"));
			stringBuilder.AppendLine("Balise de defense     : " + BeaconText(fr: true));
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine($"Types de defense pris en charge : {DefenseRegistry.Count}");
			stringBuilder.AppendLine($"Actuellement piratees           : {HijackManager.ActiveCount}");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("(Reglages dans BepInEx/config/Remilulz_91.AlliedDefenses.cfg)");
			return stringBuilder.ToString();
		}

		private static string DurationText(bool fr)
		{
			float num = UpgradeManager.EffectiveDuration();
			if (num > 0f)
			{
				if (!fr)
				{
					return $"{num:0} seconds, then it turns hostile again";
				}
				return $"{num:0} secondes, puis redevient hostile";
			}
			if (!fr)
			{
				return "unlimited (stays allied until end of round)";
			}
			return "illimitee (alliee jusqu'a la fin de la manche)";
		}

		private static string BeaconText(bool fr)
		{
			if (!ModConfig.EnableBeacon.Value)
			{
				if (!fr)
				{
					return "disabled";
				}
				return "desactivee";
			}
			if (UpgradeManager.BeaconOwned)
			{
				if (!fr)
				{
					return "owned";
				}
				return "possedee";
			}
			if (!fr)
			{
				return $"available for {ModConfig.BeaconPrice.Value} credits";
			}
			return $"disponible pour {ModConfig.BeaconPrice.Value} credits";
		}
	}
}
namespace AlliedDefenses.Patches
{
	internal static class CloakPatch
	{
		public static void Postfix(PlayerControllerB __instance, ref float __result)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (UpgradeManager.CloakEnabled && !((Object)(object)__instance == (Object)null))
			{
				float num = UpgradeManager.CloakRadius();
				if (!(num <= 0f) && HijackManager.AnyAlliedWithin(((Component)__instance).transform.position, num))
				{
					__result = 0f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Landmine))]
	public static class MinePatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnTriggerEnter")]
		public static bool OnTriggerEnterPrefix(Landmine __instance, Collider other)
		{
			if (ShouldProtectPlayers(__instance) && ((Component)other).CompareTag("Player"))
			{
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("OnTriggerExit")]
		public static bool OnTriggerExitPrefix(Landmine __instance, Collider other)
		{
			if (ShouldProtectPlayers(__instance) && ((Component)other).CompareTag("Player"))
			{
				return false;
			}
			return true;
		}

		private static bool ShouldProtectPlayers(Landmine mine)
		{
			if (ModConfig.IgnorePlayersWhenAllied.Value)
			{
				return HijackManager.IsAllied((Component)(object)mine);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(MouthDogAI), "DetectNoise")]
	internal static class MouthDogMufflePatch
	{
		[HarmonyPrefix]
		private static bool MuffleNoiseInQuietZone(Vector3 noisePosition)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!UpgradeManager.MuffleEnabled)
				{
					return true;
				}
				float num = UpgradeManager.MuffleRadius();
				if (num <= 0f)
				{
					return true;
				}
				if (HijackManager.AnyAlliedWithin(noisePosition, num))
				{
					return false;
				}
			}
			catch
			{
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(EnemyAI), "PlayerIsTargetable")]
	internal static class UntargetableAuraPatch
	{
		[HarmonyPrefix]
		private static bool MakeCloakedPlayerUntargetable(EnemyAI __instance, PlayerControllerB playerScript, ref bool __result)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)playerScript == (Object)null)
			{
				return true;
			}
			float num;
			if (__instance is SandWormAI && UpgradeManager.SeismicEnabled)
			{
				num = UpgradeManager.SeismicRadius();
			}
			else if (__instance is ClaySurgeonAI && UpgradeManager.BarberEnabled)
			{
				num = UpgradeManager.BarberRadius();
			}
			else if (__instance is BlobAI && UpgradeManager.SlimeEnabled)
			{
				num = UpgradeManager.SlimeRadius();
			}
			else
			{
				if (!(__instance is RedLocustBees) || !UpgradeManager.BeesEnabled)
				{
					return true;
				}
				num = UpgradeManager.BeesRadius();
			}
			if (num > 0f && HijackManager.AnyAlliedWithin(((Component)playerScript).transform.position, num))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SpikeRoofTrap))]
	public static class SpikePatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnTriggerStay")]
		public static bool OnTriggerStayPrefix(SpikeRoofTrap __instance, Collider other)
		{
			if (ModConfig.IgnorePlayersWhenAllied.Value && HijackManager.IsAllied((Component)(object)__instance) && (Object)(object)other != (Object)null && ((Component)other).CompareTag("Player"))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SpringManAI), "Update")]
	internal static class SpringManFreezePatch
	{
		[HarmonyPostfix]
		private static void ForceFreeze(SpringManAI __instance)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!CoilheadNeutralizer.IsNeutralized(__instance))
			{
				return;
			}
			try
			{
				if ((Object)(object)((EnemyAI)__instance).agent != (Object)null && ((Behaviour)((EnemyAI)__instance).agent).isActiveAndEnabled && ((EnemyAI)__instance).agent.isOnNavMesh)
				{
					((EnemyAI)__instance).agent.speed = 0f;
					((EnemyAI)__instance).agent.velocity = Vector3.zero;
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	public static class TerminalPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("ParsePlayerSentence")]
		public static bool ParsePrefix(Terminal __instance, ref TerminalNode __result)
		{
			string typedText = GetTypedText(__instance);
			if (string.IsNullOrWhiteSpace(typedText))
			{
				return true;
			}
			typedText = typedText.Trim();
			string text = ModConfig.HijackCommand.Value.Trim();
			bool flag = typedText.Equals(text, StringComparison.OrdinalIgnoreCase);
			bool flag2 = typedText.StartsWith(text + " ", StringComparison.OrdinalIgnoreCase);
			if (!flag && !flag2)
			{
				return true;
			}
			string text2 = (flag ? "" : typedText.Substring(text.Length).Trim());
			string typeId;
			string text3 = (string.IsNullOrEmpty(text2) ? CommandText.Usage() : ((!text2.Equals("help", StringComparison.OrdinalIgnoreCase) && !text2.Equals("howitworks", StringComparison.OrdinalIgnoreCase) && !text2.Equals("info", StringComparison.OrdinalIgnoreCase)) ? ((!text2.Equals("config", StringComparison.OrdinalIgnoreCase) && !text2.Equals("settings", StringComparison.OrdinalIgnoreCase)) ? (text2.Equals("upgrades", StringComparison.OrdinalIgnoreCase) ? UpgradeManager.ListText(ShipCredits.Get(__instance)) : (text2.StartsWith("upgrade ", StringComparison.OrdinalIgnoreCase) ? HandleUpgrade(__instance, text2.Substring("upgrade ".Length).Trim()) : ((text2.Equals("beacon recall", StringComparison.OrdinalIgnoreCase) || text2.Equals("beacon store", StringComparison.OrdinalIgnoreCase)) ? HandleBeaconRecall() : (text2.Equals("beacon", StringComparison.OrdinalIgnoreCase) ? HandleBeacon(__instance) : (text2.Equals("hack", StringComparison.OrdinalIgnoreCase) ? HandleUpgrade(__instance, "hack") : ((!TryMatchGroup(text2, out typeId)) ? HijackManager.RequestHijack(text2) : HijackManager.ListDefenses(typeId))))))) : CommandText.CurrentConfig()) : CommandText.HowItWorks()));
			__result = MakeNode(text3);
			return false;
		}

		private static string HandleUpgrade(Terminal terminal, string sub)
		{
			if (sub.Equals("reset", StringComparison.OrdinalIgnoreCase))
			{
				string result = UpgradeManager.Reset();
				HijackNetworker active = HijackNetworker.Active;
				if ((Object)(object)active != (Object)null)
				{
					foreach (var (id, level) in UpgradeManager.AllRuntimeLevels())
					{
						active.ShareUpgradeLevel(id, level);
					}
				}
				return result;
			}
			HijackNetworker active2 = HijackNetworker.Active;
			if ((Object)(object)active2 != (Object)null && !((NetworkBehaviour)active2).IsServer)
			{
				active2.RequestPurchase("upgrade", sub);
				return "Purchase request sent to the host (shared credits are host-side).";
			}
			int num = ShipCredits.Get(terminal);
			var (result2, num2) = UpgradeManager.Buy(sub, num);
			if (num2 > 0)
			{
				ShipCredits.Set(terminal, num - num2);
				active2?.ShareUpgradeLevel(sub, UpgradeManager.LevelOf(sub));
			}
			return result2;
		}

		private static string HandleBeaconRecall()
		{
			HijackNetworker.Active?.RequestRecall();
			return "Defense Beacon recalled (if one was deployed).";
		}

		private static string HandleBeacon(Terminal terminal)
		{
			HijackNetworker active = HijackNetworker.Active;
			if ((Object)(object)active != (Object)null && !((NetworkBehaviour)active).IsServer)
			{
				active.RequestPurchase("beacon", "");
				return "Beacon request sent to the host (shared credits are host-side).";
			}
			int num = ShipCredits.Get(terminal);
			var (result, num2) = BeaconManager.Purchase(num);
			if (num2 > 0)
			{
				ShipCredits.Set(terminal, num - num2);
				active?.ShareUpgradeLevel("beacon", UpgradeManager.LevelOf("beacon"));
			}
			return result;
		}

		private static bool TryMatchGroup(string arg, out string typeId)
		{
			string text = arg.Trim().ToLowerInvariant();
			foreach (IHijackableDefense item in DefenseRegistry.All)
			{
				string text2 = item.TypeId.ToLowerInvariant();
				string text3 = item.DisplayName.ToLowerInvariant();
				if (text == text2 || text == text2 + "s" || text == text3 || text == text3 + "s")
				{
					typeId = item.TypeId;
					return true;
				}
			}
			typeId = "";
			return false;
		}

		private static string GetTypedText(Terminal terminal)
		{
			try
			{
				object value = Traverse.Create((object)terminal).Field("screenText").GetValue();
				string text = Traverse.Create(value).Property("text", (object[])null).GetValue<string>() ?? "";
				int value2 = Traverse.Create((object)terminal).Field("textAdded").GetValue<int>();
				if (value2 <= 0 || value2 > text.Length)
				{
					return "";
				}
				return text.Substring(text.Length - value2);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not read terminal input: " + ex.Message));
				return "";
			}
		}

		private static TerminalNode MakeNode(string text)
		{
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			val.displayText = text + "\n\n";
			val.clearPreviousText = true;
			val.maxCharactersToType = 50;
			return val;
		}
	}
	[HarmonyPatch(typeof(Turret))]
	public static class TurretPatches
	{
		private static readonly TurretHijack _module = new TurretHijack();

		[HarmonyPrefix]
		[HarmonyPatch("Update")]
		public static bool UpdatePrefix(Turret __instance)
		{
			if (!HijackManager.IsAllied((Component)(object)__instance))
			{
				return true;
			}
			_module.DriveAlliedTurret(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "Start")]
	internal static class UpgradeSaveLoadPatch
	{
		[HarmonyPostfix]
		private static void LoadUpgradesForSave()
		{
			UpgradeManager.LoadForCurrentSave();
		}
	}
	internal static class UpgradeGameOverPatch
	{
		internal static void AfterReset()
		{
			UpgradeManager.OnGameOverReset();
		}
	}
}
namespace AlliedDefenses.Networking
{
	public class HijackNetworker : NetworkBehaviour
	{
		private static bool _warnedRpc;

		public static HijackNetworker? Instance { get; private set; }

		public static HijackNetworker? Active
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return Instance;
				}
				Instance = Object.FindObjectOfType<HijackNetworker>();
				return Instance;
			}
		}

		public override void OnNetworkSpawn()
		{
			Instance = this;
			((NetworkBehaviour)this).OnNetworkSpawn();
			Plugin.Log.LogInfo((object)"HijackNetworker ready (network active).");
			if (!((NetworkBehaviour)this).IsServer)
			{
				Safe(delegate
				{
					RequestAllLevelsServerRpc();
				});
			}
		}

		public override void OnNetworkDespawn()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			((NetworkBehaviour)this).OnNetworkDespawn();
		}

		private static void Safe(Action rpc)
		{
			try
			{
				rpc();
			}
			catch (Exception ex)
			{
				if (!_warnedRpc)
				{
					_warnedRpc = true;
					Plugin.Log.LogWarning((object)("Networking note: an RPC could not be sent. This is harmless in solo and if the build isn't fully netcode-patched; multiplayer sync may be limited. (" + ex.Message + ")"));
				}
			}
		}

		public void RequestHijack(ulong netId, string typeId)
		{
			ApplyHijack(netId, typeId, allied: true);
		}

		public void RequestUnhijack(ulong netId, string typeId)
		{
			ApplyHijack(netId, typeId, allied: false);
		}

		private void ApplyHijack(ulong netId, string typeId, bool allied)
		{
			if (((NetworkBehaviour)this).IsServer)
			{
				HijackManager.ApplyHijack(netId, typeId, allied);
				Safe(delegate
				{
					ApplyHijackClientRpc(netId, typeId, allied);
				});
			}
			else
			{
				Safe(delegate
				{
					RequestHijackServerRpc(netId, typeId, allied);
				});
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void RequestHijackServerRpc(ulong netId, string typeId, bool allied)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val2 = default(ServerRpcParams);
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(946746885u, val2, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val, netId);
				bool flag = typeId != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(typeId, false);
				}
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref allied, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 946746885u, val2, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				base.__rpc_exec_stage = (__RpcExecStage)0;
				ulong netId2 = netId;
				string typeId2 = typeId;
				bool allied2 = allied;
				HijackManager.ApplyHijack(netId2, typeId2, allied2);
				Safe(delegate
				{
					ApplyHijackClientRpc(netId2, typeId2, allied2);
				});
			}
		}

		[ClientRpc]
		private void ApplyHijackClientRpc(ulong netId, string typeId, bool allied)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val2 = default(ClientRpcParams);
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(4088680816u, val2, (RpcDelivery)0);
				BytePacker.WriteValueBitPacked(val, netId);
				bool flag = typeId != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(typeId, false);
				}
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref allied, default(ForPrimitives));
				((NetworkBehaviour)this).__endSendClientRpc(ref val, 4088680816u, val2, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				base.__rpc_exec_stage = (__RpcExecStage)0;
				if (!((NetworkBehaviour)this).IsServer)
				{
					HijackManager.ApplyHijack(netId, typeId, allied);
				}
			}
		}

		public void ShareUpgradeLevel(string id, int level)
		{
			if (((NetworkBehaviour)this).IsServer)
			{
				UpgradeManager.SetRuntimeLevel(id, level, persistOnHost: true);
				OnHostLevelSet(id, level);
				Safe(delegate
				{
					ShareUpgradeLevelClientRpc(id, level);
				});
			}
			else
			{
				Safe(delegate
				{
					ShareUpgradeLevelServerRpc(id, level);
				});
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void ShareUpgradeLevelServerRpc(string id, int level)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val2 = default(ServerRpcParams);
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(2080125155u, val2, (RpcDelivery)0);
				bool flag = id != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(id, false);
				}
				BytePacker.WriteValueBitPacked(val, level);
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 2080125155u, val2, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				base.__rpc_exec_stage = (__RpcExecStage)0;
				string id2 = id;
				int level2 = level;
				UpgradeManager.SetRuntimeLevel(id2, level2, persistOnHost: true);
				OnHostLevelSet(id2, level2);
				Safe(delegate
				{
					ShareUpgradeLevelClientRpc(id2, level2);
				});
			}
		}

		[ClientRpc]
		private void ShareUpgradeLevelClientRpc(string id, int level)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val2 = default(ClientRpcParams);
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendClientRpc(317843578u, val2, (RpcDelivery)0);
				bool flag = id != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(id, false);
				}
				BytePacker.WriteValueBitPacked(val, level);
				((NetworkBehaviour)this).__endSendClientRpc(ref val, 317843578u, val2, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				base.__rpc_exec_stage = (__RpcExecStage)0;
				if (!((NetworkBehaviour)this).IsServer)
				{
					UpgradeManager.SetRuntimeLevel(id, level);
				}
			}
		}

		public void RequestPurchase(string kind, string id)
		{
			if (((NetworkBehaviour)this).IsServer)
			{
				DoHostPurchase(kind, id);
				return;
			}
			Safe(delegate
			{
				RequestPurchaseServerRpc(kind, id ?? "");
			});
		}

		[ServerRpc(RequireOwnership = false)]
		private void RequestPurchaseServerRpc(string kind, string id)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val2 = default(ServerRpcParams);
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(703571770u, val2, (RpcDelivery)0);
				bool flag = kind != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
				if (flag)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(kind, false);
				}
				bool flag2 = id != null;
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives));
				if (flag2)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe(id, false);
				}
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 703571770u, val2, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				base.__rpc_exec_stage = (__RpcExecStage)0;
				DoHostPurchase(kind, id);
			}
		}

		private void DoHostPurchase(string kind, string id)
		{
			Terminal val = ShipCredits.Find();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int num = ShipCredits.Get(val);
			if (kind == "beacon")
			{
				int item = BeaconManager.Purchase(num).spent;
				if (item > 0)
				{
					ShipCredits.Set(val, num - item);
					UpgradeManager.SetRuntimeLevel("beacon", UpgradeManager.LevelOf("beacon"), persistOnHost: true);
					Safe(delegate
					{
						ShareUpgradeLevelClientRpc("beacon", UpgradeManager.LevelOf("beacon"));
					});
				}
				return;
			}
			int item2 = UpgradeManager.Buy(id, num).spent;
			if (item2 > 0)
			{
				ShipCredits.Set(val, num - item2);
				Safe(delegate
				{
					ShareUpgradeLevelClientRpc(id, UpgradeManager.LevelOf(id));
				});
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void RequestAllLevelsServerRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_007c: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val2 = default(ServerRpcParams);
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(1965179607u, val2, (RpcDelivery)0);
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 1965179607u, val2, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return;
			}
			base.__rpc_exec_stage = (__RpcExecStage)0;
			foreach (var item in UpgradeManager.AllRuntimeLevels())
			{
				var (id, level) = item;
				Safe(delegate
				{
					ShareUpgradeLevelClientRpc(id, level);
				});
			}
		}

		private static void OnHostLevelSet(string id, int level)
		{
			if (id == "beacon" && level <= 0)
			{
				BeaconManager.DespawnAll();
			}
		}

		public void RequestDeploy(Vector3 pos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)this).IsServer)
			{
				BeaconManager.DeployAt(pos);
				return;
			}
			Safe(delegate
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				RequestDeployServerRpc(pos);
			});
		}

		[ServerRpc(RequireOwnership = false)]
		private void RequestDeployServerRpc(Vector3 pos)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0089: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val2 = default(ServerRpcParams);
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(2249649619u, val2, (RpcDelivery)0);
					((FastBufferWriter)(ref val)).WriteValueSafe(ref pos);
					((NetworkBehaviour)this).__endSendServerRpc(ref val, 2249649619u, val2, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					base.__rpc_exec_stage = (__RpcExecStage)0;
					BeaconManager.DeployAt(pos);
				}
			}
		}

		public void RequestRecall()
		{
			if (((NetworkBehaviour)this).IsServer)
			{
				BeaconManager.DespawnAll();
				return;
			}
			Safe(delegate
			{
				RequestRecallServerRpc();
			});
		}

		[ServerRpc(RequireOwnership = false)]
		private void RequestRecallServerRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_007c: 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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val2 = default(ServerRpcParams);
					FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(2971233699u, val2, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendServerRpc(ref val, 2971233699u, val2, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					base.__rpc_exec_stage = (__RpcExecStage)0;
					BeaconManager.DespawnAll();
				}
			}
		}

		public void RequestHack(TerminalAccessibleObject tao)
		{
			if ((Object)(object)tao == (Object)null)
			{
				return;
			}
			if (((NetworkBehaviour)this).IsServer)
			{
				DoHack(tao);
				return;
			}
			Safe(delegate
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				RequestHackServerRpc(NetworkBehaviourReference.op_Implicit((NetworkBehaviour)(object)tao));
			});
		}

		[ServerRpc(RequireOwnership = false)]
		private void RequestHackServerRpc(NetworkBehaviourReference taoRef)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
			{
				ServerRpcParams val2 = default(ServerRpcParams);
				FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(613921044u, val2, (RpcDelivery)0);
				((FastBufferWriter)(ref val)).WriteValueSafe<NetworkBehaviourReference>(ref taoRef, default(ForNetworkSerializable));
				((NetworkBehaviour)this).__endSendServerRpc(ref val, 613921044u, val2, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
			{
				base.__rpc_exec_stage = (__RpcExecStage)0;
				TerminalAccessibleObject tao = default(TerminalAccessibleObject);
				if (((NetworkBehaviourReference)(ref taoRef)).TryGet<TerminalAccessibleObject>(ref tao, (NetworkManager)null))
				{
					DoHack(tao);
				}
			}
		}

		private static void DoHack(TerminalAccessibleObject tao)
		{
			try
			{
				tao.CallFunctionFromTerminal();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Hack Tool failed: " + ex.Message));
			}
		}

		protected override void __initializeVariables()
		{
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected override void __initializeRpcs()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			((NetworkBehaviour)this).__registerRpc(946746885u, new RpcReceiveHandler(__rpc_handler_946746885), "RequestHijackServerRpc");
			((NetworkBehaviour)this).__registerRpc(4088680816u, new RpcReceiveHandler(__rpc_handler_4088680816), "ApplyHijackClientRpc");
			((NetworkBehaviour)this).__registerRpc(2080125155u, new RpcReceiveHandler(__rpc_handler_2080125155), "ShareUpgradeLevelServerRpc");
			((NetworkBehaviour)this).__registerRpc(317843578u, new RpcReceiveHandler(__rpc_handler_317843578), "ShareUpgradeLevelClientRpc");
			((NetworkBehaviour)this).__registerRpc(703571770u, new RpcReceiveHandler(__rpc_handler_703571770), "RequestPurchaseServerRpc");
			((NetworkBehaviour)this).__registerRpc(1965179607u, new RpcReceiveHandler(__rpc_handler_1965179607), "RequestAllLevelsServerRpc");
			((NetworkBehaviour)this).__registerRpc(2249649619u, new RpcReceiveHandler(__rpc_handler_2249649619), "RequestDeployServerRpc");
			((NetworkBehaviour)this).__registerRpc(2971233699u, new RpcReceiveHandler(__rpc_handler_2971233699), "RequestRecallServerRpc");
			((NetworkBehaviour)this).__registerRpc(613921044u, new RpcReceiveHandler(__rpc_handler_613921044), "RequestHackServerRpc");
			((NetworkBehaviour)this).__initializeRpcs();
		}

		private static void __rpc_handler_946746885(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong netId = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref netId);
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string typeId = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref typeId, false);
				}
				bool allied = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref allied, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).RequestHijackServerRpc(netId, typeId, allied);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_4088680816(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				ulong netId = default(ulong);
				ByteUnpacker.ReadValueBitPacked(reader, ref netId);
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string typeId = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref typeId, false);
				}
				bool allied = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref allied, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).ApplyHijackClientRpc(netId, typeId, allied);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2080125155(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string id = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref id, false);
				}
				int level = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref level);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).ShareUpgradeLevelServerRpc(id, level);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_317843578(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string id = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref id, false);
				}
				int level = default(int);
				ByteUnpacker.ReadValueBitPacked(reader, ref level);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).ShareUpgradeLevelClientRpc(id, level);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_703571770(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_0067: 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_0099: 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)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				string kind = null;
				if (flag)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref kind, false);
				}
				bool flag2 = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives));
				string id = null;
				if (flag2)
				{
					((FastBufferReader)(ref reader)).ReadValueSafe(ref id, false);
				}
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).RequestPurchaseServerRpc(kind, id);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_1965179607(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: 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)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).RequestAllLevelsServerRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2249649619(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0036: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				Vector3 pos = default(Vector3);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref pos);
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).RequestDeployServerRpc(pos);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_2971233699(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_0029: 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)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).RequestRecallServerRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_613921044(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				NetworkBehaviourReference taoRef = default(NetworkBehaviourReference);
				((FastBufferReader)(ref reader)).ReadValueSafe<NetworkBehaviourReference>(ref taoRef, default(ForNetworkSerializable));
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((HijackNetworker)(object)target).RequestHackServerRpc(taoRef);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "HijackNetworker";
		}
	}
	public static class NetcodePatcher
	{
		[RuntimeInitializeOnLoadMethod]
		private static void Init()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0 && methodInfo.Name != "Init")
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}
	}
	[HarmonyPatch]
	public static class NetworkObjectManager
	{
		private static GameObject? _networkPrefab;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		public static void RegisterPrefab()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			if ((Object)(object)_networkPrefab != (Object)null)
			{
				return;
			}
			try
			{
				if ((Object)(object)NetworkManager.Singleton == (Object)null)
				{
					Plugin.Log.LogError((object)"NetworkObjectManager: NetworkManager.Singleton is null; cannot register prefab.");
					return;
				}
				_networkPrefab = new GameObject("AlliedDefensesNetworkHandler");
				Object.DontDestroyOnLoad((Object)(object)_networkPrefab);
				((Object)_networkPrefab).hideFlags = (HideFlags)61;
				NetworkObject netObj = _networkPrefab.AddComponent<NetworkObject>();
				_networkPrefab.AddComponent<HijackNetworker>();
				AssignStableHash(netObj, "AlliedDefenses.HijackNetworker");
				NetworkManager.Singleton.AddNetworkPrefab(_networkPrefab);
				Plugin.Log.LogInfo((object)"NetworkObjectManager: network prefab registered.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"NetworkObjectManager: failed to register prefab: {arg}");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		public static void SpawnHandler()
		{
			try
			{
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton == (Object)null)
				{
					Plugin.Log.LogWarning((object)"NetworkObjectManager: NetworkManager null at StartOfRound.Start.");
				}
				else if ((singleton.IsHost || singleton.IsServer) && !((Object)(object)HijackNetworker.Instance != (Object)null))
				{
					if ((Object)(object)_networkPrefab == (Object)null)
					{
						Plugin.Log.LogError((object)"NetworkObjectManager: prefab is null (registration failed?); cannot spawn.");
						return;
					}
					GameObject val = Object.Instantiate<GameObject>(_networkPrefab);
					val.GetComponent<NetworkObject>().Spawn(false);
					Plugin.Log.LogInfo((object)"NetworkObjectManager: HijackNetworker spawned by the host.");
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"NetworkObjectManager: failed to spawn handler: {arg}");
			}
		}

		private static void AssignStableHash(NetworkObject netObj, string key)
		{
			uint hashCode = (uint)key.GetHashCode();
			FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				Plugin.Log.LogError((object)"NetworkObjectManager: GlobalObjectIdHash field not found; spawn will likely fail.");
			}
			else
			{
				field.SetValue(netObj, hashCode);
			}
		}
	}
}
namespace AlliedDefenses.Defenses
{
	public class MineHijack : IHijackableDefense
	{
		public string TypeId => "mine";

		public string DisplayName => "Mine";

		public Type ComponentType => typeof(Landmine);

		public bool TryResolveByTerminalCode(string code, out Component? defense)
		{
			defense = TerminalCodeResolver.Resolve(code, typeof(Landmine));
			return (Object)(object)defense != (Object)null;
		}

		public void ApplyAlliedState(Component defense, bool allied)
		{
			if (!allied)
			{
				AlliedLightTint.Apply(defense, allied: false);
			}
		}

		public void TickAlliedTargeting(Component defense)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)defense == (Object)null)
			{
				return;
			}
			Landmine val = (Landmine)(object)((defense is Landmine) ? defense : null);
			if (val == null || val.hasExploded)
			{
				return;
			}
			AlliedLightTint.Apply((Component)(object)val, allied: true);
			if (!((Object)(object)NetworkManager.Singleton != (Object)null) || NetworkManager.Singleton.IsServer)
			{
				EnemyAI val2 = TargetingHelper.FindBestEnemy(((Component)val).transform.position, Vector3.up, UpgradeManager.EffectiveMineRadius(), 180f, requireLineOfSight: false);
				if (!((Object)(object)val2 == (Object)null))
				{
					Detonate(val);
				}
			}
		}

		private static void Detonate(Landmine mine)
		{
			if (mine.hasExploded)
			{
				return;
			}
			try
			{
				Traverse.Create((object)mine).Method("TriggerMineOnLocalClientByExiting", Array.Empty<object>()).GetValue();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to detonate allied mine: " + ex.Message));
			}
		}
	}
	public class SpikeHijack : IHijackableDefense
	{
		public string TypeId => "spike";

		public string DisplayName => "Spike trap";

		public Type ComponentType => typeof(SpikeRoofTrap);

		public bool TryResolveByTerminalCode(string code, out Component? defense)
		{
			defense = TerminalCodeResolver.Resolve(code, typeof(SpikeRoofTrap));
			return (Object)(object)defense != (Object)null;
		}

		public void ApplyAlliedState(Component defense, bool allied)
		{
			AlliedLightTint.Apply(defense, allied);
		}

		public void TickAlliedTargeting(Component defense)
		{
		}
	}
	public class TurretHijack : IHijackableDefense
	{
		private static readonly Dictionary<int, float> _nextFire = new Dictionary<int, float>();

		private static readonly Dictionary<int, Vector3> _baseDir = new Dictionary<int, Vector3>();

		private const float AlignToleranceDeg = 10f;

		public string TypeId => "turret";

		public string DisplayName => "Turret";

		public Type ComponentType => typeof(Turret);

		public bool TryResolveByTerminalCode(string code, out Component? defense)
		{
			defense = TerminalCodeResolver.Resolve(code, typeof(Turret));
			return (Object)(object)defense != (Object)null;
		}

		public void ApplyAlliedState(Component defense, bool allied)
		{
			//IL_001a: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Turret val = (Turret)(object)((defense is Turret) ? defense : null);
			if (val == null)
			{
				return;
			}
			if (allied)
			{
				val.turretActive = true;
				val.turretMode = (TurretMode)0;
				if ((Object)(object)val.turretAnimator != (Object)null)
				{
					val.turretAnimator.SetInteger("TurretMode", 0);
				}
				TurretVisuals.SetAllied(val, allied: true);
				if ((Object)(object)val.aimPoint != (Object)null && (Object)(object)val.centerPoint != (Object)null)
				{
					Dictionary<int, Vector3> baseDir = _baseDir;
					int instanceID = ((Object)val).GetInstanceID();
					Vector3 val2 = val.aimPoint.position - val.centerPoint.position;
					baseDir[instanceID] = ((Vector3)(ref val2)).normalized;
				}
			}
			else
			{
				int instanceID2 = ((Object)val).GetInstanceID();
				_nextFire.Remove(instanceID2);
				_baseDir.Remove(instanceID2);
				TurretVisuals.SetAllied(val, allied: false);
			}
		}

		public void TickAlliedTargeting(Component defense)
		{
		}

		public void DriveAlliedTurret(Turret turret)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00b3: 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_00bd: 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_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_010c: 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_0117: 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_011f: 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)
			if (!GetNodes(turret, out Transform rod, out Transform pivot, out Transform muzzle))
			{
				return;
			}
			Vector3 val = muzzle.position - pivot.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			EnemyAI val2 = TargetingHelper.FindBestEnemy(muzzle.position, normalized, UpgradeManager.EffectiveDetectionRange());
			if ((Object)(object)val2 == (Object)null)
			{
				IdleScan(turret, rod, pivot, muzzle);
				TurretVisuals.HideBeam(turret);
				return;
			}
			if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.IsServer)
			{
				SpringManAI val3 = (SpringManAI)(object)((val2 is SpringManAI) ? val2 : null);
				if (val3 != null && UpgradeManager.NeutralizeEnabled)
				{
					CoilheadNeutralizer.Neutralize(val3, UpgradeManager.NeutralizeLinger());
				}
			}
			Vector3 val4 = ((Component)val2).transform.position + Vector3.up * 0.5f;
			float degPerSec = Mathf.Max(turret.rotationSpeed, 90f);
			AimRodAt(rod, pivot.position, muzzle.position, val4, degPerSec);
			UpdateBeam(turret, pivot, muzzle);
			bool flag = (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.IsServer;
			float num = Vector3.Angle(muzzle.position - pivot.position, val4 - pivot.position);
			if (flag && num <= 10f)
			{
				TryFireAtEnemy(turret, val2);
			}
		}

		private static bool GetNodes(Turret turret, out Transform rod, out Transform pivot, out Transform muzzle)
		{
			rod = turret.turretRod;
			pivot = turret.centerPoint;
			muzzle = turret.aimPoint;
			if ((Object)(object)rod != (Object)null && (Object)(object)pivot != (Object)null)
			{
				return (Object)(object)muzzle != (Object)null;
			}
			return false;
		}

		private static void AimRodAt(Transform rod, Vector3 pivotPos, Vector3 muzzlePos, Vector3 targetPoint, float degPerSec)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//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_0074: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = targetPoint - pivotPos;
			Vector3 val2 = muzzlePos - pivotPos;
			if (!(((Vector3)(ref val)).sqrMagnitude < 1E-05f) && !(((Vector3)(ref val2)).sqrMagnitude < 1E-05f))
			{
				((Vector3)(ref val)).Normalize();
				((Vector3)(ref val2)).Normalize();
				Vector3 val3 = rod.InverseTransformDirection(val2);
				Quaternion val4 = Quaternion.LookRotation(val, Vector3.up) * Quaternion.Inverse(Quaternion.LookRotation(val3, Vector3.up));
				rod.rotation = Quaternion.RotateTowards(rod.rotation, val4, degPerSec * Time.deltaTime);
			}
		}

		private static void IdleScan(Turret turret, Transform rod, Transform pivot, Transform muzzle)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_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_002b: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)turret).GetInstanceID();
			Vector3 val2;
			if (!_baseDir.TryGetValue(instanceID, out var value))
			{
				Vector3 val = muzzle.position - pivot.position;
				val2 = ((Vector3)(ref val)).normalized;
			}
			else
			{
				val2 = value;
			}
			Vector3 val3 = val2;
			float num = Mathf.Sin(Time.time * 0.6f) * 50f;
			Vector3 val4 = Quaternion.AngleAxis(num, Vector3.up) * val3;
			AimRodAt(rod, pivot.position, muzzle.position, pivot.position + val4 * 5f, 60f);
		}

		private static void UpdateBeam(Turret turret, Transform pivot, Transform muzzle)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_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_0028: 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_0047: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			float num = UpgradeManager.EffectiveDetectionRange();
			Vector3 val = muzzle.position - pivot.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			Vector3 position = muzzle.position;
			RaycastHit val2 = default(RaycastHit);
			Vector3 to = (Physics.Raycast(position, normalized, ref val2, num, -1, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point : (position + normalized * num));
			TurretVisuals.DrawBeam(turret, position, to);
		}

		private void TryFireAtEnemy(Turret turret, EnemyAI enemy)
		{
			int instanceID = ((Object)turret).GetInstanceID();
			float time = Time.time;
			if (!_nextFire.TryGetValue(instanceID, out var value) || !(time < value))
			{
				_nextFire[instanceID] = time + UpgradeManager.EffectiveFireInterval();
				enemy.HitEnemy(UpgradeManager.EffectiveTurretDamage(), (PlayerControllerB)null, false, -1);
				MuzzleFlash(turret);
			}
		}

		private static void MuzzleFlash(Turret turret)
		{
			if ((Object)(object)turret.bulletParticles != (Object)null)
			{
				turret.bulletParticles.Emit(2);
			}
		}
	}
}
namespace AlliedDefenses.Config
{
	public enum UpgradeSaveMode
	{
		Persistent,
		PerSave
	}
	public enum Language
	{
		English,
		Francais
	}
	public static class ModConfig
	{
		public static ConfigEntry<string> HijackCommand;

		public static ConfigEntry<Language> TerminalLanguage;

		public static ConfigEntry<float> HijackDuration;

		public static ConfigEntry<float> EnemyDetectionRange;

		public static ConfigEntry<float> MineTriggerRadius;

		public static ConfigEntry<bool> IgnorePlayersWhenAllied;

		public static ConfigEntry<int> HijackCreditCost;

		public static ConfigEntry<int> TurretEnemyDamage;

		public static ConfigEntry<bool> EnableUpgrades;

		public static ConfigEntry<bool> EnableHackTool;

		public static ConfigEntry<int> HackToolPrice;

		public static ConfigEntry<string> HackKey;

		public static ConfigEntry<float> HackRange;

		public static ConfigEntry<bool> EnableBeacon;

		public static ConfigEntry<int> BeaconPrice;

		public static ConfigEntry<bool> BeaconRingOnMonitor;

		public static ConfigEntry<string> BeaconRingColorHex;

		public static ConfigEntry<string> BeaconDeployKey;

		public static ConfigEntry<string> BeaconRecallKey;

		public static ConfigEntry<bool> BeaconRadarTarget;

		public static ConfigEntry<UpgradeSaveMode> UpgradePersistence;

		public static ConfigEntry<bool> ColorAlliedDefenses;

		public static ConfigEntry<string> AlliedColorHex;

		public static ConfigEntry<string> RadarAlliedColorHex;

		public static Color AlliedColor => ParseHex(AlliedColorHex.Value, Color.green);

		public static Color RadarAlliedColor => ParseHex(RadarAlliedColorHex.Value, new Color(0.118f, 0.565f, 1f));

		public static Color BeaconRingColor => ParseHex(BeaconRingColorHex.Value, new Color(1f, 0.176f, 0.816f));

		public static void Init(ConfigFile cfg)
		{
			HijackCommand = cfg.Bind<string>("General", "HijackCommand", "ally", "Keyword typed in the terminal. In-game usage: <command> <id>  (e.g. ally A0)");
			TerminalLanguage = cfg.Bind<Language>("General", "Language", Language.English, "Language of the terminal help text (ally / ally help / ally config): English or Francais.");
			HijackDuration = cfg.Bind<float>("General", "HijackDuration", 60f, "How many seconds a defense stays allied. Set to 0 for unlimited.");
			EnemyDetectionRange = cfg.Bind<float>("Targeting", "EnemyDetectionRange", 30f, "Maximum distance (m) at which a hijacked turret detects an enemy.");
			MineTriggerRadius = cfg.Bind<float>("Targeting", "MineTriggerRadius", 4f, "Radius (m) within which an allied mine detonates on a nearby enemy.");
			IgnorePlayersWhenAllied = cfg.Bind<bool>("Targeting", "IgnorePlayersWhenAllied", true, "If true, an allied defense never fires at a player (recommended).");
			HijackCreditCost = cfg.Bind<int>("Economy", "HijackCreditCost", 0, "Credit cost to hijack a defense. 0 = free.");
			TurretEnemyDamage = cfg.Bind<int>("Economy", "TurretEnemyDamage", 1, "Base turret damage per shot to enemies (before upgrades).");
			EnableUpgrades = cfg.Bind<bool>("Economy", "EnableUpgrades", true, "Enable the buy-with-credits upgrade system (ally upgrades / ally upgrade <id>).");
			EnableHackTool = cfg.Bind<bool>("HackTool", "EnableHackTool", true, "Enable the Hack Tool: after buying it ('ally hack'), aim at a locked big door, turret, mine or spike trap and press the hack key to trigger it - like typing its code, but from inside the facility.");
			HackToolPrice = cfg.Bind<int>("HackTool", "HackToolPrice", 150, "One-time credit cost of the Hack Tool ability (bought with 'ally hack').");
			HackKey = cfg.Bind<string>("HackTool", "HackKey", "H", "Key to use the Hack Tool on the object you're aiming at. Unity Input System key names.");
			HackRange = cfg.Bind<float>("HackTool", "HackRange", 6f, "Maximum distance (m) at which the Hack Tool can trigger the object you aim at.");
			UpgradePersistence = cfg.Bind<UpgradeSaveMode>("Economy", "UpgradePersistence", UpgradeSaveMode.Persistent, "Persistent = upgrades are kept forever on this install (survive death AND game over). PerSave = upgrades are tied to the current save slot: kept through deaths, but wiped on a game over.");
			EnableBeacon = cfg.Bind<bool>("Beacon", "EnableBeacon", true, "Enable the carryable Defense Beacon (two-handed prop bought once with 'ally beacon'). It anchors the protective auras (sanity/seismic/muffle) wherever you set it down.");
			BeaconPrice = cfg.Bind<int>("Beacon", "BeaconPrice", 175, "One-time credit cost of the Defense Beacon. Owned/paid state follows the same Persistent/PerSave rule as the upgrades. Re-delivering a lost beacon is free.");
			BeaconRingOnMonitor = cfg.Bind<bool>("Beacon", "BeaconRingOnMonitor", true, "Also draw the beacon's radius ring on the ship monitor (radar map). It only shows when the monitor is looking at an area near the beacon (the camera follows players).");
			BeaconRingColorHex = cfg.Bind<string>("Beacon", "BeaconRingColorHex", "FF2DD0", "Colour of the beacon radius ring (both in-world and on the monitor), HTML hex without '#'. Default FF2DD0 (magenta/pink) - deliberately a colour the game's map does not use (it is green terrain + blue lines), so the ring can't be mistaken for them.");
			BeaconDeployKey = cfg.Bind<string>("Beacon", "BeaconDeployKey", "B", "Key to deploy (or move) your owned Defense Beacon at your current position. Uses Unity Input System key names (e.g. B, V, N, F, Numpad0). Press again to move it.");
			BeaconRecallKey = cfg.Bind<string>("Beacon", "BeaconRecallKey", "N", "Key to recall (store) the deployed Defense Beacon so it no longer sits in the world. Uses Unity Input System key names. You can also type 'ally beacon recall' at the terminal.");
			BeaconRadarTarget = cfg.Bind<bool>("Beacon", "BeaconRadarTarget", true, "Register the deployed beacon as a selectable target on the ship radar/monitor, so you can find/view it from the ship like a radar booster.");
			ColorAlliedDefenses = cfg.Bind<bool>("Visuals", "ColorAlliedDefenses", true, "Tint allied defenses (turret laser/light and the radar code) so you can tell they're on your side.");
			AlliedColorHex = cfg.Bind<string>("Visuals", "AlliedColorHex", "00FF00", "In-world color for allied turret laser/light, HTML hex without '#'. Default 00FF00 (green).");
			RadarAlliedColorHex = cfg.Bind<string>("Visuals", "RadarAlliedColorHex", "1E90FF", "Radar-map color for allied defenses, HTML hex without '#'. Default 1E90FF (blue). Avoid green here: the game already uses green for active codes.");
		}

		private static Color ParseHex(string hex, Color fallback)
		{
			//IL_0016: 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)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString("#" + hex, ref result))
			{
				return fallback;
			}
			return result;
		}
	}
}
namespace AlliedDefenses.Core
{
	public static class BeaconRegistry
	{
		private static readonly List<Transform> _beacons = new List<Transform>();

		public static int Count => _beacons.Count;

		public static void Register(Transform t)
		{
			if (!((Object)(object)t == (Object)null) && !_beacons.Contains(t))
			{
				_beacons.Add(t);
			}
		}

		public static void Unregister(Transform t)
		{
			if (!((Object)(object)t == (Object)null))
			{
				_beacons.Remove(t);
			}
		}

		public static bool AnyBeaconWithin(Vector3 point, float radius)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (radius <= 0f)
			{
				return false;
			}
			float num = radius * radius;
			for (int num2 = _beacons.Count - 1; num2 >= 0; num2--)
			{
				Transform val = _beacons[num2];
				if ((Object)(object)val == (Object)null)
				{
					_beacons.RemoveAt(num2);
				}
				else
				{
					Vector3 val2 = val.position - point;
					if (((Vector3)(ref val2)).sqrMagnitude <= num)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	public static class AlliedLightTint
	{
		private sealed class Cache
		{
			public Light[] Lights = Array.Empty<Light>();

			public Color[] Colors = Array.Empty<Color>();
		}

		private static readonly Dictionary<int, Cache> _cache = new Dictionary<int, Cache>();

		public static void Apply(Component defense, bool allied)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.ColorAlliedDefenses.Value || (Object)(object)defense == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)defense).GetInstanceID();
			if (allied)
			{
				if (!_cache.TryGetValue(instanceID, out Cache value))
				{
					Light[] componentsInChildren = defense.GetComponentsInChildren<Light>(true);
					Cache cache = new Cache();
					cache.Lights = componentsInChildren;
					cache.Colors = (Color[])(object)new Color[componentsInChildren.Length];
					value = cache;
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						value.Colors[i] = componentsInChildren[i].color;
					}
					_cache[instanceID] = value;
				}
				Color alliedColor = ModConfig.AlliedColor;
				Light[] lights = value.Lights;
				foreach (Light val in lights)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.color = alliedColor;
					}
				}
			}
			else
			{
				if (!_cache.TryGetValue(instanceID, out Cache value2))
				{
					return;
				}
				for (int k = 0; k < value2.Lights.Length; k++)
				{
					if ((Object)(object)value2.Lights[k] != (Object)null)
					{
						value2.Lights[k].color = value2.Colors[k];
					}
				}
				_cache.Remove(instanceID);
			}
		}
	}
	public static class CoilheadNeutralizer
	{
		private static readonly Dictionary<SpringManAI, float> _until = new Dictionary<SpringManAI, float>();

		public static void Neutralize(SpringManAI coil, float linger)
		{
			if (!((Object)(object)coil == (Object)null))
			{
				_until[coil] = Time.time + Mathf.Max(0.1f, linger);
			}
		}

		public static bool IsNeutralized(SpringManAI coil)
		{
			if ((Object)(object)coil == (Object)null)
			{
				return false;
			}
			if (!_until.TryGetValue(coil, out var value))
			{
				return false;
			}
			if (Time.time >= value)
			{
				_until.Remove(coil);
				return false;
			}
			return true;
		}
	}
	public static class DefenseRegistry
	{
		private static readonly List<IHijackableDefense> _defenses = new List<IHijackableDefense>();

		public static IReadOnlyList<IHijackableDefense> All => _defenses;

		public static int Count => _defenses.Count;

		public static void RegisterDefaults()
		{
			Register(new TurretHijack());
			Register(new MineHijack());
			Register(new SpikeHijack());
		}

		public static void Register(IHijackableDefense defense)
		{
			_defenses.Add(defense);
			Plugin.Log.LogInfo((object)("Defense module registered: " + defense.TypeId + " (" + defense.DisplayName + ")"));
		}

		public static bool TryResolve(string code, out IHijackableDefense? module, out Component? defense)
		{
			foreach (IHijackableDefense defense3 in _defenses)
			{
				if (defense3.TryResolveByTerminalCode(code, out Component defense2) && (Object)(object)defense2 != (Object)null)
				{
					module = defense3;
					defense = defense2;
					return true;
				}
			}
			module = null;
			defense = null;
			return false;
		}

		public static IHijackableDefense? FindModule(string typeId)
		{
			foreach (IHijackableDefense defense in _defenses)
			{
				if (defense.TypeId == typeId)
				{
					return defense;
				}
			}
			return null;
		}
	}
	public class HackToolInput : MonoBehaviour
	{
		private Key _key = (Key)22;

		private bool _resolved;

		private float _cooldownUntil;

		private void Update()
		{
			//IL_003f: 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)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableHackTool.Value)
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			if (!_resolved)
			{
				_key = ParseKey(ModConfig.HackKey.Value, (Key)22);
				_resolved = true;
			}
			if (!((ButtonControl)current[_key]).wasPressedThisFrame || Time.unscaledTime < _cooldownUntil)
			{
				return;
			}
			StartOfRound instance = StartOfRound.Instance;
			PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null);
			if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead || val.inTerminalMenu || val.isTypingChat)
			{
				return;
			}
			if (!UpgradeManager.HackToolOwned)
			{
				Tip("You don't own the Hack Tool - buy it with 'ally hack'.");
				return;
			}
			Camera gameplayCamera = val.gameplayCamera;
			if ((Object)(object)gameplayCamera == (Object)null)
			{
				return;
			}
			float num = Mathf.Max(1f, ModConfig.HackRange.Value);
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(((Component)gameplayCamera).transform.position, ((Component)gameplayCamera).transform.forward, ref val2, num, -1, (QueryTriggerInteraction)2))
			{
				TerminalAccessibleObject val3 = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<TerminalAccessibleObject>() ?? ((Component)((RaycastHit)(ref val2)).collider).GetComponentInChildren<TerminalAccessibleObject>();
				if ((Object)(object)val3 != (Object)null)
				{
					_cooldownUntil = Time.unscaledTime + 0.5f;
					HijackNetworker.Active?.RequestHack(val3);
					Tip("Hack Tool: triggered.");
					return;
				}
			}
			Tip("Aim at a locked door, turret, mine or spike trap (in range).");
		}

		private static Key ParseKey(string name, Key fallback)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.TryParse<Key>((name ?? "").Trim(), ignoreCase: true, out Key result))
			{
				return fallback;
			}
			return result;
		}

		private static void Tip(string body)
		{
			try
			{
				HUDManager instance = HUDManager.Instance;
				if (instance != null)
				{
					instance.DisplayTip("Hack Tool", body, false, false, "LC_Tip1");
				}
			}
			catch
			{
			}
		}
	}
	public class HijackEntry
	{
		public ulong NetworkId;

		public string TypeId = "";

		public Component Defense;

		public float ExpireTime;
	}
	public static class HijackManager
	{
		private static readonly Dictionary<ulong, HijackEntry> _active = new Dictionary<ulong, HijackEntry>();

		public static int ActiveCount => _active.Count;

		public static bool IsAllied(ulong networkId)
		{
			return _active.ContainsKey(networkId);
		}

		public static bool IsAllied(Component defense)
		{
			ulong? num = ResolveNetworkId(defense);
			if (num.HasValue)
			{
				return _active.ContainsKey(num.Value);
			}
			return false;
		}

		public static HijackEntry? Get(ulong networkId)
		{
			if (!_active.TryGetValue(networkId, out HijackEntry value))
			{
				return null;
			}
			return value;
		}

		public static string RequestHijack(string code)
		{
			if (!DefenseRegistry.TryResolve(code, out IHijackableDefense module, out Component defense) || (Object)(object)defense == (Object)null || module == null)
			{
				return "No defense found for code '" + code + "'.";
			}
			ulong? num = ResolveNetworkId(defense);
			if (!num.HasValue)
			{
				return "This defense has no network identity (cannot be hijacked).";
			}
			HijackNetworker active = HijackNetworker.Active;
			if ((Object)(object)active == (Object)null)
			{
				return "Network handler not ready yet. Try again in a moment.";
			}
			active.RequestHijack(num.Value, module.TypeId);
			float num2 = UpgradeManager.EffectiveDuration();
			string text = ((num2 > 0f) ? $"for {num2:0} seconds" : "until end of round");
			return "Hijacking " + module.DisplayName + " '" + code + "' " + text + "...";
		}

		public static string ListDefenses(string typeId)
		{
			IHijackableDefense hijackableDefense = DefenseRegistry.FindModule(typeId);
			if (hijackableDefense == null)
			{
				return "Unknown defense type '" + typeId + "'.";
			}
			List<string> list = new List<string>();
			Object[] array = Object.FindObjectsOfType(hijackableDefense.ComponentType);
			foreach (Object val in array)
			{
				Component val2 = (Component)(object)((val is Component) ? val : null);
				if (val2 != null)
				{
					list.Add(TerminalCodeResolver.GetCodeFor(val2));
				}
			}
			list.Sort(Str