Decompiled source of AlliedDefenses v0.4.0

AlliedDefenses.dll

Decompiled 8 hours 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.Config;
using AlliedDefenses.Core;
using AlliedDefenses.Defenses;
using AlliedDefenses.NetcodePatcher;
using AlliedDefenses.Networking;
using AlliedDefenses.UI;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;

[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.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0+10500bfa76dcc5896caacbaa107916fcbd1098bb")]
[assembly: AssemblyProduct("AlliedDefenses")]
[assembly: AssemblyTitle("AlliedDefenses")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.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.4.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.4.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()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			try
			{
				_harmony.PatchAll();
				DefenseRegistry.RegisterDefaults();
				HijackTicker.EnsureExists();
				Log.LogInfo((object)string.Format("{0} v{1} by {2} loaded. {3} defense module(s) active.", "AlliedDefenses", "0.4.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.4.0";
	}
}
namespace AlliedDefenses.UI
{
	public static class CommandText
	{
		private static string Keyword => ModConfig.HijackCommand.Value.Trim();

		public static string Usage()
		{
			string keyword = Keyword;
			return "ALLIED DEFENSES\n-------------------------\n" + keyword + " <id>     : hijack one defense by its id (turret or mine, e.g. " + keyword + " U9)\n" + keyword + " turrets  : list all turrets and their ids\n" + keyword + " mines    : list all mines and their ids\n" + keyword + " help     : how the mod works\n" + keyword + " config   : show the current settings\n";
		}

		public static string HowItWorks()
		{
			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:");
			stringBuilder.AppendLine("  " + keyword + " turrets  list all turrets and their ids.");
			stringBuilder.AppendLine("  " + keyword + " <id>   hijack one turret (same id you'd use to disable it).");
			stringBuilder.AppendLine("  An allied turret stops shooting players and instead aims at");
			stringBuilder.AppendLine("  the nearest visible enemy in range.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("MINES:");
			stringBuilder.AppendLine("  " + keyword + " mines  list all mines and their ids.");
			stringBuilder.AppendLine("  " + keyword + " <id>   hijack one mine (same id you'd use to disable it).");
			stringBuilder.AppendLine("  An allied mine no longer explodes under players; it detonates");
			stringBuilder.AppendLine("  only when an enemy steps close to it.");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("All hijacks last for a set time, then the defense turns hostile");
			stringBuilder.AppendLine("again. Everyone in 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();
		}

		public static string CurrentConfig()
		{
			float value = ModConfig.HijackDuration.Value;
			string text = ((value > 0f) ? $"{value:0} seconds, then it turns hostile again" : "unlimited (stays allied until end of round)");
			bool value2 = ModConfig.IgnorePlayersWhenAllied.Value;
			int value3 = ModConfig.HijackCreditCost.Value;
			string text2 = ((value3 > 0) ? $"{value3} credits per hijack" : "free");
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("ALLIED DEFENSES - CURRENT CONFIG");
			stringBuilder.AppendLine("------------------------------------");
			stringBuilder.AppendLine("Command keyword       : " + Keyword);
			stringBuilder.AppendLine("Allied duration       : " + text);
			stringBuilder.AppendLine($"Turret detect range   : {ModConfig.EnemyDetectionRange.Value:0} meters");
			stringBuilder.AppendLine($"Mine trigger radius   : {ModConfig.MineTriggerRadius.Value:0} meters");
			stringBuilder.AppendLine("Players can be hit    : " + (value2 ? "NO - allied defenses never hurt players" : "yes - friendly fire is ON"));
			stringBuilder.AppendLine("Hijack cost           : " + text2);
			stringBuilder.AppendLine("Allied colour cue     : " + (ModConfig.ColorAlliedDefenses.Value ? "ON (green laser/light in dungeon, blue code on radar)" : "off"));
			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();
		}
	}
}
namespace AlliedDefenses.Patches
{
	[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(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)) ? CommandText.CurrentConfig() : ((!TryMatchGroup(text2, out typeId)) ? HijackManager.RequestHijack(text2) : HijackManager.ListDefenses(typeId))) : CommandText.HowItWorks()));
			__result = MakeNode(text3);
			return false;
		}

		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;
		}
	}
}
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).");
		}

		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);
				}
			}
		}

		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
			((NetworkBehaviour)this).__registerRpc(946746885u, new RpcReceiveHandler(__rpc_handler_946746885), "RequestHijackServerRpc");
			((NetworkBehaviour)this).__registerRpc(4088680816u, new RpcReceiveHandler(__rpc_handler_4088680816), "ApplyHijackClientRpc");
			((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;
			}
		}

		[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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"NetworkObjectManager: GameNetworkManager.Start reached.");
			if ((Object)(object)_networkPrefab != (Object)null)
			{
				Plugin.Log.LogInfo((object)"NetworkObjectManager: prefab already created, skipping.");
				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.");
					return;
				}
				if (!singleton.IsHost && !singleton.IsServer)
				{
					Plugin.Log.LogInfo((object)"NetworkObjectManager: not the host; client will receive the handler from the host.");
					return;
				}
				if ((Object)(object)HijackNetworker.Instance != (Object)null)
				{
					Plugin.Log.LogInfo((object)"NetworkObjectManager: handler already spawned.");
					return;
				}
				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.");
				return;
			}
			field.SetValue(netObj, hashCode);
			Plugin.Log.LogInfo((object)$"NetworkObjectManager: GlobalObjectIdHash set to {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, ModConfig.MineTriggerRadius.Value, 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 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 FireInterval = 0.21f;

		private const int EnemyDamagePerShot = 1;

		private const float AlignToleranceDeg = 10f;

		private static bool _diagLogged;

		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;
				}
				LogHierarchyOnce(val);
			}
			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_0069: 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_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)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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, ModConfig.EnemyDetectionRange.Value);
			if ((Object)(object)val2 == (Object)null)
			{
				IdleScan(turret, rod, pivot, muzzle);
				TurretVisuals.HideBeam(turret);
				return;
			}
			Vector3 val3 = ((Component)val2).transform.position + Vector3.up * 0.5f;
			float degPerSec = Mathf.Max(turret.rotationSpeed, 90f);
			AimRodAt(rod, pivot.position, muzzle.position, val3, degPerSec);
			UpdateBeam(turret, pivot, muzzle);
			bool flag = (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.IsServer;
			float num = Vector3.Angle(muzzle.position - pivot.position, val3 - 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 LogHierarchyOnce(Turret turret)
		{
			if (_diagLogged)
			{
				return;
			}
			_diagLogged = true;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("[Turret diagnostic] PREFAB TREE (R=Renderer L=Light Ln=LineRenderer T=Turret):");
			Transform val = ((Component)turret).transform;
			for (int i = 0; i < 2; i++)
			{
				if (!((Object)(object)val.parent != (Object)null))
				{
					break;
				}
				val = val.parent;
			}
			int count = 0;
			DumpTree(val, 0, stringBuilder, ref count);
			stringBuilder.AppendLine("[Turret diagnostic] Transform fields on Turret:");
			FieldInfo[] fields = typeof(Turret).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (typeof(Transform).IsAssignableFrom(fieldInfo.FieldType))
				{
					object? value = fieldInfo.GetValue(turret);
					Transform val2 = (Transform)((value is Transform) ? value : null);
					stringBuilder.AppendLine("  " + fieldInfo.Name + " -> " + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "null"));
				}
			}
			Plugin.Log.LogInfo((object)stringBuilder.ToString());
		}

		private static void DumpTree(Transform t, int depth, StringBuilder sb, ref int count)
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			if (count++ > 80 || depth > 5)
			{
				return;
			}
			string text = "";
			if ((Object)(object)((Component)t).GetComponent<Renderer>() != (Object)null)
			{
				text += "R";
			}
			if ((Object)(object)((Component)t).GetComponent<Light>() != (Object)null)
			{
				text += "L";
			}
			if ((Object)(object)((Component)t).GetComponent<LineRenderer>() != (Object)null)
			{
				text += "Ln";
			}
			if ((Object)(object)((Component)t).GetComponent<Turret>() != (Object)null)
			{
				text += "T";
			}
			sb.AppendLine(new string(' ', depth * 2) + ((Object)t).name + " [" + text + "]");
			foreach (Transform item in t)
			{
				Transform t2 = item;
				DumpTree(t2, depth + 1, sb, ref count);
			}
		}

		private static void UpdateBeam(Turret turret, Transform pivot, Transform muzzle)
		{
			//IL_000c: 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_001c: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_003b: 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_003e: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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)
			float value = ModConfig.EnemyDetectionRange.Value;
			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, value, -1, (QueryTriggerInteraction)1) ? ((RaycastHit)(ref val2)).point : (position + normalized * value));
			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 + 0.21f;
				enemy.HitEnemy(1, (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.Core
{
	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 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());
		}

		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 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 value = ModConfig.HijackDuration.Value;
			string text = ((value > 0f) ? $"for {value: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(StringComparer.OrdinalIgnoreCase);
			string text = hijackableDefense.DisplayName.ToLower();
			if (list.Count == 0)
			{
				return "No " + text + "s on this level.";
			}
			return string.Format("{0} {1}(s) on this level:\n  {2}\n", list.Count, text, string.Join(", ", list)) + "Use '" + ModConfig.HijackCommand.Value + " <id>' to hijack one.";
		}

		public static void ApplyHijack(ulong networkId, string typeId, bool allied)
		{
			Component val = ResolveComponent(networkId, typeId);
			IHijackableDefense hijackableDefense = DefenseRegistry.FindModule(typeId);
			if ((Object)(object)val == (Object)null || hijackableDefense == null)
			{
				Plugin.Log.LogWarning((object)$"ApplyHijack: could not resolve netId={networkId} type={typeId}");
				return;
			}
			hijackableDefense.ApplyAlliedState(val, allied);
			if (allied)
			{
				float value = ModConfig.HijackDuration.Value;
				_active[networkId] = new HijackEntry
				{
					NetworkId = networkId,
					TypeId = typeId,
					Defense = val,
					ExpireTime = ((value > 0f) ? (Time.time + value) : 0f)
				};
				Plugin.Log.LogInfo((object)$"{hijackableDefense.DisplayName} (net {networkId}) is now ALLIED.");
			}
			else
			{
				RadarTimerDisplay.Restore(val);
				_active.Remove(networkId);
				Plugin.Log.LogInfo((object)$"{hijackableDefense.DisplayName} (net {networkId}) is hostile again.");
			}
		}

		public static void Tick()
		{
			if (_active.Count == 0)
			{
				return;
			}
			bool flag = (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer;
			List<HijackEntry> list = null;
			List<ulong> list2 = null;
			foreach (KeyValuePair<ulong, HijackEntry> item in _active)
			{
				HijackEntry value = item.Value;
				if ((Object)(object)value.Defense == (Object)null)
				{
					(list2 ?? (list2 = new List<ulong>())).Add(value.NetworkId);
					continue;
				}
				try
				{
					DefenseRegistry.FindModule(value.TypeId)?.TickAlliedTargeting(value.Defense);
					RadarTimerDisplay.Update(value);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)$"Tick error for {value.TypeId} (net {value.NetworkId}); dropping it: {ex.Message}");
					(list2 ?? (list2 = new List<ulong>())).Add(value.NetworkId);
					continue;
				}
				if (flag && value.ExpireTime > 0f && Time.time >= value.ExpireTime)
				{
					(list ?? (list = new List<HijackEntry>())).Add(value);
				}
			}
			if (list2 != null)
			{
				foreach (ulong item2 in list2)
				{
					_active.Remove(item2);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (HijackEntry item3 in list)
			{
				HijackNetworker.Active?.RequestUnhijack(item3.NetworkId, item3.TypeId);
			}
		}

		public static void ClearAll()
		{
			foreach (HijackEntry value in _active.Values)
			{
				DefenseRegistry.FindModule(value.TypeId)?.ApplyAlliedState(value.Defense, allied: false);
				RadarTimerDisplay.Restore(value.Defense);
			}
			_active.Clear();
		}

		public static ulong? ResolveNetworkId(Component c)
		{
			NetworkObject componentInParent = c.GetComponentInParent<NetworkObject>();
			if (!((Object)(object)componentInParent != (Object)null))
			{
				return null;
			}
			return componentInParent.NetworkObjectId;
		}

		private static Component? ResolveComponent(ulong networkId, string typeId)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			NetworkSpawnManager val = ((singleton != null) ? singleton.SpawnManager : null);
			if (val == null)
			{
				return null;
			}
			if (!val.SpawnedObjects.TryGetValue(networkId, out var value) || (Object)(object)value == (Object)null)
			{
				return null;
			}
			IHijackableDefense hijackableDefense = DefenseRegistry.FindModule(typeId);
			if (hijackableDefense == null)
			{
				return null;
			}
			return ((Component)value).GetComponentInChildren(hijackableDefense.ComponentType);
		}
	}
	public class HijackTicker : MonoBehaviour
	{
		public static HijackTicker? Instance { get; private set; }

		public static void EnsureExists()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("AlliedDefenses_Ticker");
				Object.DontDestroyOnLoad((Object)(object)val);
				((Object)val).hideFlags = (HideFlags)61;
				Instance = val.AddComponent<HijackTicker>();
			}
		}

		private void Update()
		{
			HijackManager.Tick();
		}
	}
	public interface IHijackableDefense
	{
		string TypeId { get; }

		string DisplayName { get; }

		Type ComponentType { get; }

		bool TryResolveByTerminalCode(string code, out Component? defense);

		void ApplyAlliedState(Component defense, bool allied);

		void TickAlliedTargeting(Component defense);
	}
	public static class RadarTimerDisplay
	{
		private static readonly Dictionary<int, string> _originalText = new Dictionary<int, string>();

		private static readonly Dictionary<int, Color> _originalColor = new Dictionary<int, Color>();

		public static void Update(HijackEntry entry)
		{
			//IL_0058: 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)
			TerminalAccessibleObject val = FindAccessible(entry.Defense);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Component radarText = GetRadarText(val);
			if (!((Object)(object)radarText == (Object)null))
			{
				int instanceID = ((Object)val).GetInstanceID();
				if (!_originalText.ContainsKey(instanceID))
				{
					_originalText[instanceID] = StripTimer(GetText(radarText));
					_originalColor[instanceID] = GetColor(radarText);
				}
				string text = _originalText[instanceID];
				string text2 = ((!(entry.ExpireTime <= 0f)) ? Format(Mathf.Max(0f, entry.ExpireTime - Time.time)) : "ALLY");
				SetText(radarText, text + "\n" + text2);
				if (ModConfig.ColorAlliedDefenses.Value)
				{
					SetColor(radarText, ModConfig.RadarAlliedColor);
				}
			}
		}

		public static void Restore(Component defense)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			TerminalAccessibleObject val = FindAccessible(defense);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)val).GetInstanceID();
			Component radarText = GetRadarText(val);
			if ((Object)(object)radarText != (Object)null)
			{
				if (_originalText.TryGetValue(instanceID, out string value))
				{
					SetText(radarText, value);
				}
				if (_originalColor.TryGetValue(instanceID, out var value2))
				{
					SetColor(radarText, value2);
				}
			}
			_originalText.Remove(instanceID);
			_originalColor.Remove(instanceID);
		}

		private static string Format(float seconds)
		{
			int num = Mathf.CeilToInt(seconds);
			return $"{num / 60}:{num % 60:00}";
		}

		private static string StripTimer(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text ?? "";
			}
			int num = text.IndexOf('\n');
			if (num < 0)
			{
				return text;
			}
			return text.Substring(0, num);
		}

		private static TerminalAccessibleObject? FindAccessible(Component defense)
		{
			if ((Object)(object)defense == (Object)null)
			{
				return null;
			}
			return defense.GetComponentInParent<TerminalAccessibleObject>() ?? defense.GetComponentInChildren<TerminalAccessibleObject>();
		}

		private static Component? GetRadarText(TerminalAccessibleObject tao)
		{
			string[] array = new string[3] { "mapRadarText", "radarText", "codeText" };
			foreach (string text in array)
			{
				try
				{
					Component value = Traverse.Create((object)tao).Field(text).GetValue<Component>();
					if ((Object)(object)value != (Object)null)
					{
						return value;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static string GetText(Component tmp)
		{
			try
			{
				return Traverse.Create((object)tmp).Property("text", (object[])null).GetValue<string>() ?? "";
			}
			catch
			{
				return "";
			}
		}

		private static void SetText(Component tmp, string value)
		{
			try
			{
				Traverse.Create((object)tmp).Property("text", (object[])null).SetValue((object)value);
			}
			catch
			{
			}
		}

		private static Color GetColor(Component tmp)
		{
			//IL_0011: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return Traverse.Create((object)tmp).Property("color", (object[])null).GetValue<Color>();
			}
			catch
			{
				return Color.white;
			}
		}

		private static void SetColor(Component tmp, Color value)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Traverse.Create((object)tmp).Property("color", (object[])null).SetValue((object)value);
			}
			catch
			{
			}
		}
	}
	public static class TargetingHelper
	{
		private const int LineOfSightMask = 1051400;

		public static float Range => ModConfig.EnemyDetectionRange.Value;

		public static EnemyAI? FindBestEnemy(Vector3 origin, Vector3 forward, float range, float coneHalfAngle = 180f, bool requireLineOfSight = true)
		{
			//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_005e: 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_0061: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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)
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null)
			{
				return null;
			}
			EnemyAI result = null;
			float num = float.MaxValue;
			float num2 = range * range;
			foreach (EnemyAI spawnedEnemy in instance.SpawnedEnemies)
			{
				if (!((Object)(object)spawnedEnemy == (Object)null) && !spawnedEnemy.isEnemyDead)
				{
					Vector3 position = ((Component)spawnedEnemy).transform.position;
					Vector3 val = position - origin;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (!(sqrMagnitude > num2) && (!(coneHalfAngle < 180f) || !(Vector3.Angle(forward, val) > coneHalfAngle)) && (!requireLineOfSight || HasLineOfSight(origin, position)) && sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = spawnedEnemy;
					}
				}
			}
			return result;
		}

		public static bool HasLineOfSight(Vector3 from, Vector3 to)
		{
			//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_001a: 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)
			Vector3 val = to - from;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.01f)
			{
				return true;
			}
			return !Physics.Raycast(from, ((Vector3)(ref val)).normalized, magnitude - 0.5f, 1051400, (QueryTriggerInteraction)1);
		}
	}
	public static class TerminalCodeResolver
	{
		public static Component? Resolve(string code, Type componentType)
		{
			if (string.IsNullOrEmpty(code))
			{
				return null;
			}
			TerminalAccessibleObject[] array = Object.FindObjectsOfType<TerminalAccessibleObject>();
			foreach (TerminalAccessibleObject val in array)
			{
				string a = ReadObjectCode(val);
				if (string.Equals(a, code, StringComparison.OrdinalIgnoreCase))
				{
					Component val2 = ((Component)val).GetComponentInChildren(componentType) ?? ((Component)val).GetComponentInParent(componentType);
					if ((Object)(object)val2 != (Object)null)
					{
						return val2;
					}
				}
			}
			return null;
		}

		public static string GetCodeFor(Component c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return "?";
			}
			TerminalAccessibleObject val = c.GetComponentInParent<TerminalAccessibleObject>() ?? c.GetComponentInChildren<TerminalAccessibleObject>();
			string text = (((Object)(object)val != (Object)null) ? ReadObjectCode(val) : "");
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "?";
		}

		public static string ReadObjectCode(TerminalAccessibleObject acc)
		{
			string[] array = new string[3] { "objectCode", "codeString", "code" };
			foreach (string text in array)
			{
				try
				{
					string value = Traverse.Create((object)acc).Field(text).GetValue<string>();
					if (!string.IsNullOrEmpty(value))
					{
						return value;
					}
				}
				catch
				{
				}
			}
			return "";
		}
	}
	public static class TurretVisuals
	{
		private sealed class Cache
		{
			public LineRenderer[] Lines = Array.Empty<LineRenderer>();

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

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

			public Light[] Lights = Array.Empty<Light>();

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

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

		private static readonly Dictionary<int, LineRenderer> _beams = new Dictionary<int, LineRenderer>();

		public static void SetAllied(Turret turret, bool allied)
		{
			//IL_0038: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.ColorAlliedDefenses.Value)
			{
				return;
			}
			int instanceID = ((Object)turret).GetInstanceID();
			if (allied)
			{
				if (!_cache.ContainsKey(instanceID))
				{
					_cache[instanceID] = Capture(turret);
				}
				Color alliedColor = ModConfig.AlliedColor;
				Cache cache = _cache[instanceID];
				LineRenderer[] lines = cache.Lines;
				foreach (LineRenderer val in lines)
				{
					if (!((Object)(object)val == (Object)null))
					{
						val.startColor = alliedColor;
						val.endColor = alliedColor;
					}
				}
				Light[] lights = cache.Lights;
				foreach (Light val2 in lights)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						val2.color = alliedColor;
					}
				}
			}
			else
			{
				if (!_cache.TryGetValue(instanceID, out Cache value))
				{
					return;
				}
				for (int k = 0; k < value.Lines.Length; k++)
				{
					if (!((Object)(object)value.Lines[k] == (Object)null))
					{
						value.Lines[k].startColor = value.LineStart[k];
						value.Lines[k].endColor = value.LineEnd[k];
					}
				}
				for (int l = 0; l < value.Lights.Length; l++)
				{
					if (!((Object)(object)value.Lights[l] == (Object)null))
					{
						value.Lights[l].color = value.LightColors[l];
					}
				}
				_cache.Remove(instanceID);
				if (_beams.TryGetValue(instanceID, out LineRenderer value2))
				{
					if ((Object)(object)value2 != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)value2).gameObject);
					}
					_beams.Remove(instanceID);
				}
			}
		}

		public static void DrawBeam(Turret turret, Vector3 from, Vector3 to)
		{
			//IL_0056: 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)
			if (ModConfig.ColorAlliedDefenses.Value)
			{
				int instanceID = ((Object)turret).GetInstanceID();
				if (!_beams.TryGetValue(instanceID, out LineRenderer value) || (Object)(object)value == (Object)null)
				{
					value = CreateBeam(turret);
					_beams[instanceID] = value;
				}
				((Renderer)value).enabled = true;
				value.useWorldSpace = true;
				value.positionCount = 2;
				value.SetPosition(0, from);
				value.SetPosition(1, to);
			}
		}

		public static void HideBeam(Turret turret)
		{
			if (_beams.TryGetValue(((Object)turret).GetInstanceID(), out LineRenderer value) && (Object)(object)value != (Object)null)
			{
				((Renderer)value).enabled = false;
			}
		}

		private static LineRenderer CreateBeam(Turret turret)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("AlliedDefenses_Beam");
			val.transform.SetParent(((Component)turret).transform, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			LineRenderer componentInChildren = ((Component)turret).GetComponentInChildren<LineRenderer>(true);
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Renderer)componentInChildren).sharedMaterial != (Object)null)
			{
				((Renderer)val2).material = new Material(((Renderer)componentInChildren).sharedMaterial);
			}
			Color color = (val2.endColor = (val2.startColor = ModConfig.AlliedColor));
			try
			{
				if ((Object)(object)((Renderer)val2).material != (Object)null)
				{
					((Renderer)val2).material.color = color;
				}
			}
			catch
			{
			}
			val2.startWidth = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.startWidth : 0.04f);
			val2.endWidth = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.endWidth : 0.04f);
			val2.numCapVertices = 2;
			((Renderer)val2).enabled = false;
			return val2;
		}

		private static Cache Capture(Turret turret)
		{
			//IL_0061: 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_0077: 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_009f: 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)
			LineRenderer[] componentsInChildren = ((Component)turret).GetComponentsInChildren<LineRenderer>(true);
			Light[] componentsInChildren2 = ((Component)turret).GetComponentsInChildren<Light>(true);
			Cache cache = new Cache();
			cache.Lines = componentsInChildren;
			cache.LineStart = (Color[])(object)new Color[componentsInChildren.Length];
			cache.LineEnd = (Color[])(object)new Color[componentsInChildren.Length];
			cache.Lights = componentsInChildren2;
			cache.LightColors = (Color[])(object)new Color[componentsInChildren2.Length];
			Cache cache2 = cache;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				cache2.LineStart[i] = componentsInChildren[i].startColor;
				cache2.LineEnd[i] = componentsInChildren[i].endColor;
			}
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				cache2.LightColors[j] = componentsInChildren2[j].color;
			}
			return cache2;
		}
	}
}
namespace AlliedDefenses.Config
{
	public static class ModConfig
	{
		public static ConfigEntry<string> HijackCommand;

		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<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 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)");
			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.");
			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 __GEN
{
	internal class NetworkVariableSerializationHelper
	{
		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeSerialization()
		{
		}
	}
}
namespace AlliedDefenses.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}