Decompiled source of TurnOffTurrets v1.0.0

BepInEx/plugins/TurnOffTurrets/TurnOffTurrets.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

[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("erockuli")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2026 erockuli")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TurnOffTurrets")]
[assembly: AssemblyTitle("TurnOffTurrets")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TurnOffTurrets
{
	[BepInPlugin("com.turnoffturrets.plugin", "Turn Off Turrets", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class SpecialBerserkState
		{
			public Turret Turret;

			public float RequestedAt;

			public bool RampageStarted;

			public float RampageStartedAt;

			public float OriginalRotationSpeed;

			public bool OriginalRotationSpeedCaptured;

			public bool GracePeriodActive;

			public float GracePeriodStartedAt;

			public bool ShutdownRequested;

			public float DurationSeconds;

			public float RotationSpeed;

			public float FireRateMultiplier;

			public bool TurnOffAfterBurst;

			public bool Authorized;
		}

		private sealed class TurretInteraction
		{
			public Turret Turret;

			public int InstanceId;

			public Vector3 BaseForward;

			public GameObject ZoneObject;

			public BoxCollider ZoneCollider;

			public InteractTrigger Trigger;
		}

		public const string ModGuid = "com.turnoffturrets.plugin";

		public const string ModName = "Turn Off Turrets";

		public const string ModVersion = "1.0.0";

		private static Plugin _instance;

		private Harmony _spawnCompatibilityHarmony;

		private Harmony _customBerserkHarmony;

		private NetworkManager _registeredNetworkManager;

		private bool _networkMessageHandlersRegistered;

		private const string SpecialBerserkRequestMessage = "TurnOffTurrets.SpecialBerserkRequest.v2";

		private const string SpecialBerserkBroadcastMessage = "TurnOffTurrets.SpecialBerserkBroadcast.v2";

		private const string SpecialBerserkEndRequestMessage = "TurnOffTurrets.SpecialBerserkEndRequest.v1";

		private const string SpecialBerserkEndBroadcastMessage = "TurnOffTurrets.SpecialBerserkEndBroadcast.v1";

		private const string BerserkWarningText = "FAILURE, RUN.";

		private const float PostBerserkNormalPeriodSeconds = 1f;

		private ConfigEntry<bool> _repairExplicitHazardMarkers;

		private string _lastTargetedSpawnRepairKey = string.Empty;

		private const float ScanInterval = 0.2f;

		private const float DiscoveryInterval = 1.25f;

		private const float IdleMaintenanceInterval = 0.75f;

		private const float RearOffset = 0.72f;

		private const float InteractionHeight = 0.78f;

		private const float InteractionHoldDuration = 0.45f;

		private const float RearDotDefault = -0.75f;

		private ConfigEntry<bool> _modEnabled;

		private ConfigEntry<float> _interactionDistance;

		private ConfigEntry<float> _rearDotThreshold;

		private ConfigEntry<bool> _berserkEnabled;

		private ConfigEntry<float> _berserkChance;

		private ConfigEntry<bool> _customBerserkEnabled;

		private ConfigEntry<float> _customBerserkDuration;

		private ConfigEntry<float> _customBerserkRotationSpeed;

		private ConfigEntry<float> _customBerserkFireRateMultiplier;

		private ConfigEntry<bool> _customBerserkTurnOff;

		private const float MinCustomBerserkDuration = 0.1f;

		private const float MaxCustomBerserkDuration = 30f;

		private const float MinCustomBerserkRotationSpeed = 77f;

		private const float MaxCustomBerserkRotationSpeed = 1440f;

		private const float MinCustomBerserkFireRateMultiplier = 0.5f;

		private const float MaxCustomBerserkFireRateMultiplier = 5f;

		private readonly Dictionary<int, TurretInteraction> _turretInteractions = new Dictionary<int, TurretInteraction>();

		private readonly Dictionary<ulong, SpecialBerserkState> _specialBerserkStates = new Dictionary<ulong, SpecialBerserkState>();

		private readonly HashSet<int> _seenTurretIds = new HashSet<int>();

		private readonly List<int> _staleTurretIds = new List<int>();

		private float _nextTurretDiscoveryTime;

		private Turret[] _cachedTurrets;

		private Coroutine _maintenanceCoroutine;

		private Sprite _vanillaInteractionIcon;

		private int _vanillaInteractionLayer = -1;

		private float _nextIconScanTime;

		private bool _roundWasActive;

		private string _lastLoggedSceneName = string.Empty;

		private string _lastDiscoverySceneName = string.Empty;

		private int _lastLoggedTurretCount = -1;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			try
			{
				if (((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Custom Berserk Burst", "DelaySeconds")))
				{
					((BaseUnityPlugin)this).Config.Save();
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Could not remove obsolete Custom Berserk Burst/DelaySeconds config entry: " + ex.Message));
			}
			_modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable or disable the Turn Off Turrets interaction entirely. This does not alter turret spawning.");
			_interactionDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "InteractionDistance", 2.2f, "Maximum horizontal distance to the turret base while using the rear controls.");
			_rearDotThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RearDotThreshold", -0.75f, "How directly behind the turret you must stand. Lower/more negative values require a more direct rear approach.");
			_berserkEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Berserk", "Enabled", true, "If enabled, a successful chance roll makes the turret enter berserk instead of shutting down.");
			_berserkChance = ((BaseUnityPlugin)this).Config.Bind<float>("Berserk", "ChancePercent", 15f, "Percent chance from 0 to 100 that a rear-panel interaction enters berserk instead of shutting down. Set to 0 to disable.");
			_customBerserkEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Custom Berserk Burst", "Enabled", true, "Use the fast-spin burst ONLY for berserk triggered by this mod's rear-panel interaction. The game controls the native berserk wind-up; vanilla berserk from hits is not modified.");
			_customBerserkDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Custom Berserk Burst", "DurationSeconds", 4.8f, new ConfigDescription("Duration of the custom high-speed rampage after the game's native berserk firing state starts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f), Array.Empty<object>()));
			_customBerserkRotationSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Custom Berserk Burst", "RotationSpeed", 720f, new ConfigDescription("Turret head rotation speed during the custom rampage. Vanilla berserk is approximately 77; 720 is intentionally extreme.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(77f, 1440f), Array.Empty<object>()));
			_customBerserkFireRateMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Custom Berserk Burst", "FireRateMultiplier", 1.5f, new ConfigDescription("Multiplier for native berserk firing interval. 1 = vanilla firing rate; higher values shoot more often.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), Array.Empty<object>()));
			_customBerserkTurnOff = ((BaseUnityPlugin)this).Config.Bind<bool>("Custom Berserk Burst", "TurnOffAfterBurst", true, "If true, the host turns the turret off when the custom burst ends. If false, the turret returns to vanilla rotation speed and its ordinary berserk timer continues.");
			bool flag = false;
			if (Mathf.Abs(_interactionDistance.Value - 3.25f) < 0.001f)
			{
				_interactionDistance.Value = 2.2f;
				flag = true;
			}
			if (Mathf.Abs(_rearDotThreshold.Value - -0.1f) < 0.001f)
			{
				_rearDotThreshold.Value = -0.75f;
				flag = true;
			}
			if (flag)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			_instance = this;
			_repairExplicitHazardMarkers = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawn Compatibility", "RepairExplicitHazardMarkers", true, "Only add a missing RandomMapObject component on exact MapHazardSpawnType<number> placeholders when at least one matching active-level spawn-table entry has a positive curve at the current time. Checks all duplicate matching entries. Existing marker components/lists and vanilla spawn counts are preserved.");
			InstallSpawnCompatibilityPatch();
			InstallCustomBerserkPatch();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Turn Off Turrets v1.0.0 loaded. Enabled=" + _modEnabled.Value + ". Custom rear-interaction burst=" + _customBerserkEnabled.Value + " (duration=" + _customBerserkDuration.Value.ToString("0.##") + "s after native berserk startup, spin=" + _customBerserkRotationSpeed.Value.ToString("0.##") + ", fire rate=" + _customBerserkFireRateMultiplier.Value.ToString("0.##") + "x, turn off=" + _customBerserkTurnOff.Value + ", post-berserk normal grace=" + 1f.ToString("0.##") + "s). This affects only berserk caused by this mod's rear interaction; vanilla berserk from hits is unchanged."));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Performance: interaction refresh runs every " + 0.2f.ToString("0.##") + "s, turret discovery is cached for " + 1.25f.ToString("0.##") + "s, and idle/game-readiness checks run every " + 0.75f.ToString("0.##") + "s (no plugin Update polling)."));
			_maintenanceCoroutine = ((MonoBehaviour)this).StartCoroutine(MaintenanceLoop());
		}

		private void InstallCustomBerserkPatch()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00e1: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Turret), "Update", (Type[])null, (Type[])null);
				MethodInfo method = typeof(Plugin).GetMethod("TurretUpdatePrefix", BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo method2 = typeof(Plugin).GetMethod("TurretUpdatePostfix", BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Turret), "ToggleTurretEnabled", new Type[1] { typeof(bool) }, (Type[])null);
				MethodInfo method3 = typeof(Plugin).GetMethod("TurretTogglePostfix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo == null || method == null || method2 == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Custom berserk hooks unavailable; vanilla turret behaviour remains unchanged.");
					return;
				}
				_customBerserkHarmony = new Harmony("com.turnoffturrets.plugin.CustomBerserkBurst");
				_customBerserkHarmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				if (methodInfo2 != null && method3 != null)
				{
					_customBerserkHarmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Turret-off cleanup hook unavailable; custom shutdown will still reset the berserk state explicitly.");
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom berserk timing and off-state cleanup hooks installed; the custom sequence remains limited to explicitly marked turrets.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not install custom berserk hooks; vanilla behaviour remains unchanged: " + ex));
			}
		}

		private static bool TurretUpdatePrefix(Turret __instance)
		{
			if ((Object)(object)_instance != (Object)null && (Object)(object)__instance != (Object)null && _instance._specialBerserkStates.Count > 0)
			{
				_instance.PrepareNormalModeDuringGrace(__instance);
				_instance.ApplyCustomFireRateBoost(__instance);
			}
			return true;
		}

		private static void TurretUpdatePostfix(Turret __instance)
		{
			if ((Object)(object)_instance != (Object)null && (Object)(object)__instance != (Object)null && _instance._specialBerserkStates.Count > 0)
			{
				_instance.MaintainCustomBerserk(__instance);
			}
		}

		private static void TurretTogglePostfix(Turret __instance, object[] __args)
		{
			if (!((Object)(object)_instance == (Object)null) && !((Object)(object)__instance == (Object)null) && __args != null && __args.Length != 0)
			{
				object obj = __args[0];
				if (obj is bool && !(bool)obj)
				{
					_instance.CleanUpDisabledTurret(__instance);
				}
			}
		}

		private void PrepareNormalModeDuringGrace(Turret turret)
		{
			if (!((Object)(object)turret == (Object)null) && TryGetNetworkObjectId(turret, out var id) && _specialBerserkStates.TryGetValue(id, out var value) && value != null && value.GracePeriodActive)
			{
				bool value2;
				bool flag = TryGetBoolMember(turret, "enteringBerserkMode", out value2) && value2;
				if (!IsTurretDetectionMode(turret) || flag)
				{
					ResetTurretToNormalDetectionMode(turret);
					return;
				}
				TrySetMember(turret, "enteringBerserkMode", false);
				TrySetMember(turret, "berserkTimer", 0f);
			}
		}

		private void CleanUpDisabledTurret(Turret turret)
		{
			if (!((Object)(object)turret == (Object)null))
			{
				if (TryGetNetworkObjectId(turret, out var id) && _specialBerserkStates.TryGetValue(id, out var value))
				{
					RestoreOriginalRotationSpeed(value);
					_specialBerserkStates.Remove(id);
				}
				turret.turretActive = false;
				ResetTurretToNormalDetectionMode(turret);
			}
		}

		private static void StopTurretAudio(Turret turret)
		{
			if ((Object)(object)turret == (Object)null)
			{
				return;
			}
			try
			{
				AudioSource[] componentsInChildren = ((Component)turret).GetComponentsInChildren<AudioSource>(true);
				foreach (AudioSource val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)null)
					{
						val.Stop();
					}
				}
			}
			catch
			{
			}
			try
			{
				object memberDeep = GetMemberDeep(turret, "bulletParticles");
				ParticleSystem val2 = (ParticleSystem)((memberDeep is ParticleSystem) ? memberDeep : null);
				if (val2 != null)
				{
					val2.Stop(true, (ParticleSystemStopBehavior)0);
				}
			}
			catch
			{
			}
		}

		private void ApplyCustomFireRateBoost(Turret turret)
		{
			if (TryGetNetworkObjectId(turret, out var id) && _specialBerserkStates.TryGetValue(id, out var value) && value != null && value.Authorized && value.RampageStarted && !value.GracePeriodActive && turret.turretActive && IsTurretBerserk(turret))
			{
				float num = Mathf.Clamp(value.FireRateMultiplier, 0.5f, 5f);
				if (!(Mathf.Abs(num - 1f) < 0.001f) && TryGetFloatMember(turret, "turretInterval", out var value2))
				{
					TrySetMember(turret, "turretInterval", Mathf.Max(0f, value2 + Time.deltaTime * (num - 1f)));
				}
			}
		}

		private void MaintainCustomBerserk(Turret turret)
		{
			if ((Object)(object)turret == (Object)null || !TryGetNetworkObjectId(turret, out var id) || !_specialBerserkStates.TryGetValue(id, out var value) || value == null)
			{
				return;
			}
			if (!turret.turretActive)
			{
				CleanUpDisabledTurret(turret);
			}
			else if (value.GracePeriodActive)
			{
				MaintainPostBerserkGracePeriod(turret, id, value);
			}
			else
			{
				if (!value.Authorized)
				{
					return;
				}
				if (!IsTurretBerserk(turret))
				{
					if (!value.RampageStarted && Time.time - value.RequestedAt > Mathf.Max(10f, value.DurationSeconds + 5f))
					{
						RestoreOriginalRotationSpeed(value);
						_specialBerserkStates.Remove(id);
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Custom burst marker expired before turret " + id + " entered native berserk; the game's native state was left unchanged."));
					}
					return;
				}
				if (!value.RampageStarted)
				{
					if (TryGetBoolMember(turret, "enteringBerserkMode", out var value2) && value2)
					{
						return;
					}
					if (!value.OriginalRotationSpeedCaptured)
					{
						if (!TryGetFloatMember(turret, "rotationSpeed", out var value3))
						{
							_specialBerserkStates.Remove(id);
							((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not capture the native rotation speed for custom burst " + id + "; leaving the game's berserk behaviour unchanged."));
							return;
						}
						value.OriginalRotationSpeed = value3;
						value.OriginalRotationSpeedCaptured = true;
					}
					if (!TrySetMember(turret, "rotationSpeed", Mathf.Clamp(value.RotationSpeed, 77f, 1440f)))
					{
						RestoreOriginalRotationSpeed(value);
						_specialBerserkStates.Remove(id);
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not set custom rotation speed on turret " + id + "; abandoning custom burst safely."));
						return;
					}
					value.RampageStarted = true;
					value.RampageStartedAt = Time.time;
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Custom berserk rampage started for turret " + id + " after the game's native berserk wind-up: speed=" + value.RotationSpeed.ToString("0.##") + ", duration=" + value.DurationSeconds.ToString("0.##") + "s, fire multiplier=" + value.FireRateMultiplier.ToString("0.##") + "x."));
				}
				TrySetMember(turret, "rotationSpeed", Mathf.Clamp(value.RotationSpeed, 77f, 1440f));
				float num = Time.time - value.RampageStartedAt;
				float num2 = Mathf.Clamp(value.DurationSeconds, 0.1f, 30f);
				if (TryGetBoolMember(turret, "enteringBerserkMode", out var value4) && !value4)
				{
					float num3 = Mathf.Max(0f, num2 - num) + Mathf.Max(0.1f, Time.deltaTime * 2f);
					if (TryGetFloatMember(turret, "berserkTimer", out var value5))
					{
						TrySetMember(turret, "berserkTimer", Mathf.Max(value5, num3));
					}
				}
				if (num < num2)
				{
					return;
				}
				NetworkManager singleton = NetworkManager.Singleton;
				if (value.TurnOffAfterBurst)
				{
					if (!((Object)(object)singleton != (Object)null) || !singleton.IsListening || singleton.IsServer)
					{
						BeginPostBerserkGracePeriod(id, turret, value, broadcastToClients: true);
					}
				}
				else
				{
					RestoreOriginalRotationSpeed(value);
					_specialBerserkStates.Remove(id);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Custom spin ended for turret " + id + "; native berserk timer continues."));
				}
			}
		}

		private void BeginPostBerserkGracePeriod(ulong id, Turret turret, SpecialBerserkState state, bool broadcastToClients)
		{
			if ((Object)(object)turret == (Object)null || state == null || state.GracePeriodActive)
			{
				return;
			}
			state.Turret = turret;
			state.GracePeriodActive = true;
			state.GracePeriodStartedAt = Time.time;
			state.ShutdownRequested = false;
			RestoreOriginalRotationSpeed(state);
			ResetTurretToNormalDetectionMode(turret);
			NetworkManager singleton = NetworkManager.Singleton;
			bool flag = (Object)(object)singleton != (Object)null && singleton.IsListening && singleton.IsServer;
			if (broadcastToClients && flag)
			{
				try
				{
					turret.SetToModeClientRpc(0);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not broadcast normal detection mode for turret " + id + ": " + ex.Message));
				}
				SendSpecialBerserkEndBroadcastToClients(singleton, id);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Custom berserk ended for turret " + id + "; restored normal detection mode for a fixed " + 1f.ToString("0.##") + "s grace period before shutdown. End broadcast=" + (broadcastToClients && flag) + "."));
		}

		private void ResetTurretToNormalDetectionMode(Turret turret, bool clearTargets = true)
		{
			if ((Object)(object)turret == (Object)null)
			{
				return;
			}
			if (!TrySwitchTurretMode(turret, 0))
			{
				TrySetMember(turret, "turretMode", 0);
			}
			TrySetMember(turret, "enteringBerserkMode", false);
			TrySetMember(turret, "berserkTimer", 0f);
			TrySetMember(turret, "turretInterval", 0f);
			TrySetMember(turret, "lostLOSTimer", 0f);
			TrySetMember(turret, "switchRotationTimer", 0f);
			if (clearTargets)
			{
				ClearTurretTargetingState(turret);
			}
			try
			{
				object memberDeep = GetMemberDeep(turret, "turretAnimator");
				Animator val = (Animator)((memberDeep is Animator) ? memberDeep : null);
				if (val != null)
				{
					val.SetInteger("TurretMode", 0);
				}
			}
			catch
			{
			}
			StopTurretAudio(turret);
		}

		private static void ClearTurretTargetingState(Turret turret)
		{
			if (!((Object)(object)turret == (Object)null))
			{
				TrySetMember(turret, "targetPlayerWithRotation", null);
				TrySetMember(turret, "targetTransform", null);
				TrySetMember(turret, "wasTargetingPlayerLastFrame", false);
				TrySetMember(turret, "targetingDeadPlayer", true);
				TrySetMember(turret, "hasLineOfSight", false);
				TrySetMember(turret, "lostLOSTimer", 0f);
			}
		}

		private void MaintainPostBerserkGracePeriod(Turret turret, ulong id, SpecialBerserkState state)
		{
			PrepareNormalModeDuringGrace(turret);
			if (Time.time - state.GracePeriodStartedAt < 1f)
			{
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((!((Object)(object)singleton != (Object)null) || !singleton.IsListening || singleton.IsServer) && !state.ShutdownRequested)
			{
				state.ShutdownRequested = true;
				bool flag = TryInvokeToggleTurretServerRpc(turret, enabled: false);
				if (!flag)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("ToggleTurretServerRpc unavailable after grace period for turret " + id + "; using local shutdown fallback."));
					turret.ToggleTurretEnabled(false);
					CleanUpDisabledTurret(turret);
				}
				else
				{
					CleanUpDisabledTurret(turret);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Custom berserk grace period completed for turret " + id + " after " + (Time.time - state.GracePeriodStartedAt).ToString("0.00") + "s; off RPC invoked=" + flag + "."));
			}
		}

		private unsafe void SendSpecialBerserkEndBroadcastToClients(NetworkManager manager, ulong id)
		{
			//IL_0051: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)manager == (Object)null || !manager.IsServer || manager.CustomMessagingManager == null || manager.ConnectedClientsIds == null)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			foreach (ulong item in new List<ulong>(manager.ConnectedClientsIds))
			{
				if (item == 0L)
				{
					continue;
				}
				try
				{
					((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
					try
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
						manager.CustomMessagingManager.SendNamedMessage("TurnOffTurrets.SpecialBerserkEndBroadcast.v1", item, val, (NetworkDelivery)3);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not send custom-berserk end state to client " + item + ": " + ex.Message));
				}
			}
		}

		private unsafe bool TrySendSpecialBerserkEndRequest(ulong id)
		{
			//IL_0058: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.IsServer || singleton.CustomMessagingManager == null)
			{
				return false;
			}
			EnsureNetworkMessageHandlers();
			if (!_networkMessageHandlersRegistered || (Object)(object)_registeredNetworkManager != (Object)(object)singleton)
			{
				return false;
			}
			try
			{
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
				try
				{
					((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
					singleton.CustomMessagingManager.SendNamedMessage("TurnOffTurrets.SpecialBerserkEndRequest.v1", 0uL, val, (NetworkDelivery)3);
				}
				finally
				{
					((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
				}
				return true;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not request a graceful end for custom berserk turret " + id + ": " + ex.Message));
				return false;
			}
		}

		private unsafe bool TryQueueCustomBerserk(Turret turret)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetNetworkObjectId(turret, out var id))
			{
				return false;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Custom burst could not synchronise; retaining existing vanilla berserk handling.");
				return false;
			}
			EnsureNetworkMessageHandlers();
			if (!_networkMessageHandlersRegistered || (Object)(object)_registeredNetworkManager != (Object)(object)singleton)
			{
				return false;
			}
			try
			{
				if (singleton.IsServer)
				{
					if (!_customBerserkEnabled.Value)
					{
						return false;
					}
					ApplySpecialBerserkLocally(id, turret);
					SendSpecialBerserkBroadcastToClients(singleton, id, null, enabledByHost: true);
				}
				else
				{
					ApplySpecialBerserkPending(id, turret);
					FastBufferWriter val = default(FastBufferWriter);
					((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
					try
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
						singleton.CustomMessagingManager.SendNamedMessage("TurnOffTurrets.SpecialBerserkRequest.v2", 0uL, val, (NetworkDelivery)3);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				RestoreAndRemoveSpecialBerserk(id);
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not queue custom burst; using the existing vanilla berserk handling: " + ex.Message));
				return false;
			}
		}

		private void ApplySpecialBerserkLocally(ulong id, Turret turret)
		{
			if (!((Object)(object)turret == (Object)null))
			{
				if (!_specialBerserkStates.TryGetValue(id, out var value) || value == null)
				{
					value = new SpecialBerserkState
					{
						Turret = turret
					};
					_specialBerserkStates[id] = value;
				}
				value.Turret = turret;
				value.RequestedAt = Time.time;
				value.Authorized = true;
				value.RampageStarted = false;
				value.RampageStartedAt = 0f;
				value.GracePeriodActive = false;
				value.GracePeriodStartedAt = 0f;
				value.ShutdownRequested = false;
				value.DurationSeconds = Mathf.Clamp(_customBerserkDuration.Value, 0.1f, 30f);
				value.RotationSpeed = Mathf.Clamp(_customBerserkRotationSpeed.Value, 77f, 1440f);
				value.FireRateMultiplier = Mathf.Clamp(_customBerserkFireRateMultiplier.Value, 0.5f, 5f);
				value.TurnOffAfterBurst = _customBerserkTurnOff.Value;
				ShowBerserkWarning();
			}
		}

		private void ApplySpecialBerserkPending(ulong id, Turret turret)
		{
			if (!((Object)(object)turret == (Object)null))
			{
				if (!_specialBerserkStates.TryGetValue(id, out var value) || value == null)
				{
					value = new SpecialBerserkState
					{
						Turret = turret
					};
					_specialBerserkStates[id] = value;
				}
				value.Turret = turret;
				value.RequestedAt = Time.time;
				value.Authorized = false;
				value.RampageStarted = false;
				value.RampageStartedAt = 0f;
				value.GracePeriodActive = false;
				value.GracePeriodStartedAt = 0f;
				value.ShutdownRequested = false;
				value.DurationSeconds = Mathf.Clamp(_customBerserkDuration.Value, 0.1f, 30f);
				value.RotationSpeed = Mathf.Clamp(_customBerserkRotationSpeed.Value, 77f, 1440f);
				value.FireRateMultiplier = Mathf.Clamp(_customBerserkFireRateMultiplier.Value, 0.5f, 5f);
				value.TurnOffAfterBurst = _customBerserkTurnOff.Value;
			}
		}

		private void ApplySpecialBerserkFromHost(ulong id, Turret turret, float duration, float rotationSpeed, float fireRateMultiplier, bool turnOff)
		{
			if ((Object)(object)turret == (Object)null)
			{
				return;
			}
			if (_specialBerserkStates.TryGetValue(id, out var value) && value != null && value.GracePeriodActive)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Ignored late custom-berserk start settings for turret " + id + " because its normal-mode grace period has already begun."));
				return;
			}
			if (value != null && value.Authorized && !value.ShutdownRequested && Time.time - value.RequestedAt <= Mathf.Max(10f, value.DurationSeconds + 1f + 3f))
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Ignored duplicate custom-berserk settings broadcast for turret " + id + "; elapsed time was preserved."));
				return;
			}
			if (!_specialBerserkStates.TryGetValue(id, out var value2) || value2 == null)
			{
				value2 = new SpecialBerserkState
				{
					Turret = turret
				};
				_specialBerserkStates[id] = value2;
			}
			value2.Turret = turret;
			value2.RequestedAt = Time.time;
			value2.Authorized = true;
			value2.DurationSeconds = Mathf.Clamp(duration, 0.1f, 30f);
			value2.RotationSpeed = Mathf.Clamp(rotationSpeed, 77f, 1440f);
			value2.FireRateMultiplier = Mathf.Clamp(fireRateMultiplier, 0.5f, 5f);
			value2.TurnOffAfterBurst = turnOff;
			value2.RampageStarted = false;
			value2.RampageStartedAt = 0f;
			value2.GracePeriodActive = false;
			value2.GracePeriodStartedAt = 0f;
			value2.ShutdownRequested = false;
			ShowBerserkWarning();
		}

		private void ShowBerserkWarning()
		{
			try
			{
				if ((Object)(object)HUDManager.Instance != (Object)null)
				{
					HUDManager.Instance.DisplayTip("FAILURE, RUN.", string.Empty, true, false, "LC_Tip1");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Could not display the custom berserk warning: " + ex.Message));
			}
		}

		private void ShowBerserkWarningForFallback(Turret turret)
		{
			ShowBerserkWarning();
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && singleton.IsListening && singleton.IsServer && TryGetNetworkObjectId(turret, out var id))
			{
				SendSpecialBerserkBroadcastToClients(singleton, id, null, enabledByHost: false);
			}
		}

		private void EnsureNetworkMessageHandlers()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null || (_networkMessageHandlersRegistered && (Object)(object)_registeredNetworkManager == (Object)(object)singleton))
			{
				return;
			}
			UnregisterNetworkMessageHandlers();
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			bool flag4 = false;
			try
			{
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkRequest.v2", new HandleNamedMessageDelegate(HandleSpecialBerserkRequest));
				flag = true;
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkBroadcast.v2", new HandleNamedMessageDelegate(HandleSpecialBerserkBroadcast));
				flag2 = true;
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkEndRequest.v1", new HandleNamedMessageDelegate(HandleSpecialBerserkEndRequest));
				flag3 = true;
				singleton.CustomMessagingManager.RegisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkEndBroadcast.v1", new HandleNamedMessageDelegate(HandleSpecialBerserkEndBroadcast));
				flag4 = true;
				_registeredNetworkManager = singleton;
				_networkMessageHandlersRegistered = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom berserk start/end network messages registered.");
			}
			catch (Exception ex)
			{
				try
				{
					if (flag4)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkEndBroadcast.v1");
					}
					if (flag3)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkEndRequest.v1");
					}
					if (flag2)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkBroadcast.v2");
					}
					if (flag)
					{
						singleton.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkRequest.v2");
					}
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Could not clean up partial custom-berserk handler registration: " + ex2.Message));
				}
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not register custom berserk network messages; partial handlers were rolled back: " + ex.Message));
				_registeredNetworkManager = null;
				_networkMessageHandlersRegistered = false;
			}
		}

		private void UnregisterNetworkMessageHandlers()
		{
			if (!_networkMessageHandlersRegistered || (Object)(object)_registeredNetworkManager == (Object)null)
			{
				return;
			}
			try
			{
				if (_registeredNetworkManager.CustomMessagingManager != null)
				{
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkRequest.v2");
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkBroadcast.v2");
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkEndRequest.v1");
					_registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("TurnOffTurrets.SpecialBerserkEndBroadcast.v1");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Could not unregister custom berserk messages: " + ex.Message));
			}
			_registeredNetworkManager = null;
			_networkMessageHandlersRegistered = false;
		}

		private void HandleSpecialBerserkRequest(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0035: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.ConnectedClients == null || !singleton.ConnectedClients.ContainsKey(senderClientId))
			{
				return;
			}
			try
			{
				ulong num = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
				if (!TryGetSpawnedTurret(singleton, num, out var turret))
				{
					return;
				}
				if (_specialBerserkStates.TryGetValue(num, out var value) && value != null)
				{
					float num2 = Mathf.Max(10f, value.DurationSeconds + 1f + 3f);
					if (Time.time - value.RequestedAt <= num2)
					{
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Ignored duplicate host request for custom berserk on turret " + num + "; existing host-authoritative burst timer was preserved."));
						return;
					}
					RestoreAndRemoveSpecialBerserk(num);
				}
				if (!_customBerserkEnabled.Value)
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Rejected custom berserk request for turret " + num + " because the host has Custom Berserk Burst disabled; native berserk will continue."));
					ShowBerserkWarning();
					SendSpecialBerserkBroadcastToClients(singleton, num, null, enabledByHost: false);
				}
				else
				{
					ApplySpecialBerserkLocally(num, turret);
					SendSpecialBerserkBroadcastToClients(singleton, num, null, enabledByHost: true);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed custom berserk request: " + ex.Message));
			}
		}

		private void HandleSpecialBerserkEndRequest(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0035: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.ConnectedClients == null || !singleton.ConnectedClients.ContainsKey(senderClientId))
			{
				return;
			}
			try
			{
				ulong num = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
				if (TryGetSpawnedTurret(singleton, num, out var turret) && !((Object)(object)turret == (Object)null) && turret.turretActive)
				{
					if (!_specialBerserkStates.TryGetValue(num, out var value) || value == null || !value.Authorized || value.GracePeriodActive || !IsTurretBerserk(turret))
					{
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Ignored graceful-end request for turret " + num + " because no active custom berserk burst matched it."));
						return;
					}
					BeginPostBerserkGracePeriod(num, turret, value, broadcastToClients: true);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Accepted client request to end custom berserk gracefully for turret " + num + "."));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed custom-berserk end request: " + ex.Message));
			}
		}

		private void HandleSpecialBerserkEndBroadcast(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0022: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.IsServer || senderClientId != 0L)
			{
				return;
			}
			try
			{
				ulong num = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
				if (!TryGetSpawnedTurret(singleton, num, out var turret) || (Object)(object)turret == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Custom berserk end broadcast referred to missing turret NetworkObject " + num + "."));
					return;
				}
				if (!_specialBerserkStates.TryGetValue(num, out var value) || value == null)
				{
					value = new SpecialBerserkState
					{
						Turret = turret,
						RequestedAt = Time.time,
						Authorized = true,
						RampageStarted = true,
						RampageStartedAt = Time.time,
						DurationSeconds = 0.1f,
						RotationSpeed = _customBerserkRotationSpeed.Value,
						FireRateMultiplier = 1f,
						TurnOffAfterBurst = true
					};
					_specialBerserkStates[num] = value;
				}
				BeginPostBerserkGracePeriod(num, turret, value, broadcastToClients: false);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed custom-berserk end broadcast: " + ex.Message));
			}
		}

		private void HandleSpecialBerserkBroadcast(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0022: 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_0035: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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)
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || singleton.IsServer || senderClientId != 0L)
			{
				return;
			}
			try
			{
				ulong id = default(ulong);
				((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives));
				bool flag = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
				if (!flag)
				{
					ShowBerserkWarning();
					RestoreAndRemoveSpecialBerserk(id);
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Host declined the custom-burst override for turret " + id + "; native berserk is allowed to continue."));
					return;
				}
				float duration = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref duration, default(ForPrimitives));
				float rotationSpeed = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref rotationSpeed, default(ForPrimitives));
				float fireRateMultiplier = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref fireRateMultiplier, default(ForPrimitives));
				bool turnOff = default(bool);
				((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref turnOff, default(ForPrimitives));
				if (TryGetSpawnedTurret(singleton, id, out var turret))
				{
					ApplySpecialBerserkFromHost(id, turret, duration, rotationSpeed, fireRateMultiplier, turnOff);
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Custom berserk broadcast referred to missing turret NetworkObject " + id + "."));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored malformed custom berserk broadcast: " + ex.Message));
			}
		}

		private unsafe void SendSpecialBerserkBroadcastToClients(NetworkManager manager, ulong id, ulong? excludedClientId, bool enabledByHost)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)manager == (Object)null || !manager.IsServer || manager.CustomMessagingManager == null)
			{
				return;
			}
			List<ulong> list = new List<ulong>();
			try
			{
				foreach (ulong connectedClientsId in manager.ConnectedClientsIds)
				{
					if (connectedClientsId != manager.LocalClientId && (!excludedClientId.HasValue || connectedClientsId != excludedClientId.Value))
					{
						list.Add(connectedClientsId);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not snapshot clients for custom berserk broadcast: " + ex.Message));
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			foreach (ulong item in list)
			{
				try
				{
					((FastBufferWriter)(ref val))..ctor(32, (Allocator)2, -1);
					try
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref id, default(ForPrimitives));
						((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref enabledByHost, default(ForPrimitives));
						if (enabledByHost)
						{
							if (_specialBerserkStates.TryGetValue(id, out var value) && value != null && value.Authorized)
							{
								((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref value.DurationSeconds, default(ForPrimitives));
								((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref value.RotationSpeed, default(ForPrimitives));
								((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref value.FireRateMultiplier, default(ForPrimitives));
								((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value.TurnOffAfterBurst, default(ForPrimitives));
							}
							else
							{
								float num = Mathf.Clamp(_customBerserkDuration.Value, 0.1f, 30f);
								((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref num, default(ForPrimitives));
								num = Mathf.Clamp(_customBerserkRotationSpeed.Value, 77f, 1440f);
								((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref num, default(ForPrimitives));
								num = Mathf.Clamp(_customBerserkFireRateMultiplier.Value, 0.5f, 5f);
								((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref num, default(ForPrimitives));
								bool value2 = _customBerserkTurnOff.Value;
								((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref value2, default(ForPrimitives));
							}
						}
						manager.CustomMessagingManager.SendNamedMessage("TurnOffTurrets.SpecialBerserkBroadcast.v2", item, val, (NetworkDelivery)3);
					}
					finally
					{
						((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
					}
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not send custom berserk settings to client " + item + ": " + ex2.Message));
				}
			}
		}

		private static bool TryGetSpawnedTurret(NetworkManager manager, ulong id, out Turret turret)
		{
			turret = null;
			if ((Object)(object)manager == (Object)null || manager.SpawnManager == null || manager.SpawnManager.SpawnedObjects == null || !manager.SpawnManager.SpawnedObjects.TryGetValue(id, out var value) || (Object)(object)value == (Object)null)
			{
				return false;
			}
			turret = ((Component)value).GetComponent<Turret>();
			if ((Object)(object)turret == (Object)null)
			{
				turret = ((Component)value).GetComponentInChildren<Turret>(true);
			}
			return (Object)(object)turret != (Object)null;
		}

		private static bool TryGetNetworkObjectId(Turret turret, out ulong id)
		{
			id = 0uL;
			if ((Object)(object)turret == (Object)null)
			{
				return false;
			}
			NetworkObject val = ((Component)turret).GetComponent<NetworkObject>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)turret).GetComponentInParent<NetworkObject>();
			}
			if ((Object)(object)val == (Object)null || !val.IsSpawned)
			{
				return false;
			}
			id = val.NetworkObjectId;
			return true;
		}

		private static bool IsTurretBerserk(Turret turret)
		{
			object memberDeep = GetMemberDeep(turret, "turretMode");
			if (memberDeep == null)
			{
				memberDeep = GetMemberDeep(turret, "currentMode");
			}
			try
			{
				return memberDeep != null && Convert.ToInt32(memberDeep) == 3;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsTurretDetectionMode(Turret turret)
		{
			object memberDeep = GetMemberDeep(turret, "turretMode");
			if (memberDeep == null)
			{
				memberDeep = GetMemberDeep(turret, "currentMode");
			}
			try
			{
				return memberDeep != null && Convert.ToInt32(memberDeep) == 0;
			}
			catch
			{
				return false;
			}
		}

		private void RestoreAndRemoveSpecialBerserk(ulong id)
		{
			if (_specialBerserkStates.TryGetValue(id, out var value))
			{
				RestoreOriginalRotationSpeed(value);
			}
			_specialBerserkStates.Remove(id);
		}

		private static void RestoreOriginalRotationSpeed(SpecialBerserkState state)
		{
			if (state != null && (Object)(object)state.Turret != (Object)null && state.OriginalRotationSpeedCaptured)
			{
				TrySetMember(state.Turret, "rotationSpeed", state.OriginalRotationSpeed);
			}
		}

		private static bool TryGetFloatMember(object instance, string name, out float value)
		{
			object memberDeep = GetMemberDeep(instance, name);
			try
			{
				if (memberDeep != null)
				{
					value = Convert.ToSingle(memberDeep);
					return true;
				}
			}
			catch
			{
			}
			value = 0f;
			return false;
		}

		private static bool TryGetBoolMember(object instance, string name, out bool value)
		{
			if (GetMemberDeep(instance, name) is bool flag)
			{
				value = flag;
				return true;
			}
			value = false;
			return false;
		}

		private static object GetMemberDeep(object instance, string name)
		{
			if (instance == null)
			{
				return null;
			}
			BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			Type type = instance.GetType();
			while (type != null)
			{
				FieldInfo field = type.GetField(name, bindingAttr);
				if (field != null)
				{
					try
					{
						return field.GetValue(instance);
					}
					catch
					{
						return null;
					}
				}
				PropertyInfo property = type.GetProperty(name, bindingAttr);
				if (property != null)
				{
					try
					{
						return property.GetValue(instance, null);
					}
					catch
					{
						return null;
					}
				}
				type = type.BaseType;
			}
			return null;
		}

		private static bool TrySetMember(object instance, string name, object value)
		{
			if (instance == null)
			{
				return false;
			}
			BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			Type type = instance.GetType();
			while (type != null)
			{
				FieldInfo field = type.GetField(name, bindingAttr);
				if (field != null)
				{
					try
					{
						if (!TryConvertMemberValue(value, field.FieldType, out var converted))
						{
							return false;
						}
						field.SetValue(instance, converted);
						return true;
					}
					catch
					{
						return false;
					}
				}
				PropertyInfo property = type.GetProperty(name, bindingAttr);
				if (property != null && property.CanWrite)
				{
					try
					{
						if (!TryConvertMemberValue(value, property.PropertyType, out var converted2))
						{
							return false;
						}
						property.SetValue(instance, converted2, null);
						return true;
					}
					catch
					{
						return false;
					}
				}
				type = type.BaseType;
			}
			return false;
		}

		private static bool TryConvertMemberValue(object value, Type destinationType, out object converted)
		{
			converted = null;
			if (destinationType == null)
			{
				return false;
			}
			Type underlyingType = Nullable.GetUnderlyingType(destinationType);
			Type type = underlyingType ?? destinationType;
			if (value == null)
			{
				if (destinationType.IsValueType)
				{
					return underlyingType != null;
				}
				return true;
			}
			if (type.IsInstanceOfType(value))
			{
				converted = value;
				return true;
			}
			try
			{
				converted = ((!type.IsEnum) ? Convert.ChangeType(value, type) : ((value is string value2) ? Enum.Parse(type, value2, ignoreCase: true) : Enum.ToObject(type, value)));
				return true;
			}
			catch
			{
				return false;
			}
		}

		private void InstallSpawnCompatibilityPatch()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(RoundManager), "SpawnMapObjects", (Type[])null, (Type[])null);
				MethodInfo method = typeof(Plugin).GetMethod("RepairExplicitHazardMarkersPrefix", BindingFlags.Static | BindingFlags.NonPublic);
				if (methodInfo == null || method == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)"Targeted spawn compatibility patch not installed: RoundManager.SpawnMapObjects or its prefix was not found.");
					return;
				}
				_spawnCompatibilityHarmony = new Harmony("com.turnoffturrets.plugin.TargetedSpawnCompatibility");
				HarmonyMethod val = new HarmonyMethod(method);
				val.priority = 0;
				_spawnCompatibilityHarmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Targeted spawn compatibility installed. It repairs only exact MapHazardSpawnType<number> placeholders missing RandomMapObject, and only if at least one matching active-level spawn-table entry has a positive curve at the current time. It checks every duplicate matching entry; existing marker lists and vanilla counts are preserved.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not install targeted hazard-spawner compatibility: " + ex));
			}
		}

		private static void RepairExplicitHazardMarkersPrefix(RoundManager __instance)
		{
			Plugin instance = _instance;
			if ((Object)(object)instance == (Object)null || instance._repairExplicitHazardMarkers == null || !instance._repairExplicitHazardMarkers.Value)
			{
				return;
			}
			try
			{
				instance.RepairExplicitHazardMarkers(__instance, "TurretContainer");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)("Targeted spawn-marker repair failed for TurretContainer: " + ex));
			}
		}

		private void RepairExplicitHazardMarkers(RoundManager roundManager, string targetPrefabName)
		{
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)roundManager == (Object)null || (Object)(object)roundManager.currentLevel == (Object)null || roundManager.currentLevel.spawnableMapObjects == null || (Object)(object)TimeOfDay.Instance == (Object)null)
			{
				return;
			}
			GameObject val = null;
			int num = 0;
			List<string> list = new List<string>();
			float normalizedTimeOfDay = TimeOfDay.Instance.normalizedTimeOfDay;
			SpawnableMapObject[] spawnableMapObjects = roundManager.currentLevel.spawnableMapObjects;
			foreach (SpawnableMapObject val2 in spawnableMapObjects)
			{
				if (val2 == null || (Object)(object)val2.prefabToSpawn == (Object)null || !NamesMatch(((Object)val2.prefabToSpawn).name, targetPrefabName))
				{
					continue;
				}
				num++;
				if (val2.numberToSpawn == null)
				{
					list.Add("unavailable");
					continue;
				}
				float num2 = val2.numberToSpawn.Evaluate(normalizedTimeOfDay);
				list.Add(num2.ToString("0.###"));
				if (!(num2 <= 0f) && (Object)(object)val == (Object)null)
				{
					val = val2.prefabToSpawn;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				if (num > 0)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Targeted spawn repair skipped for " + targetPrefabName + ": all " + num + " matching active-level spawn-table entry/entries had no positive curve at normalized time " + normalizedTimeOfDay.ToString("0.###") + " (evaluated values: " + string.Join(", ", list.ToArray()) + "). No spawn markers or spawn rates were changed."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Targeted spawn repair skipped for " + targetPrefabName + ": the active level does not list it in spawnableMapObjects."));
				}
				return;
			}
			if (num > 1)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Targeted spawn repair found " + num + " matching " + targetPrefabName + " spawn-table entries at normalized time " + normalizedTimeOfDay.ToString("0.###") + " (evaluated values: " + string.Join(", ", list.ToArray()) + "); at least one is positive, so normal targeted-marker checks may continue."));
			}
			RandomMapObject[] array = Object.FindObjectsOfType<RandomMapObject>();
			foreach (RandomMapObject val3 in array)
			{
				if ((Object)(object)val3 == (Object)null || val3.spawnablePrefabs == null)
				{
					continue;
				}
				foreach (GameObject spawnablePrefab in val3.spawnablePrefabs)
				{
					if ((Object)(object)spawnablePrefab != (Object)null && NamesMatch(((Object)spawnablePrefab).name, targetPrefabName))
					{
						return;
					}
				}
			}
			List<GameObject> eligibleVanillaHazardPrefabs = GetEligibleVanillaHazardPrefabs(roundManager.currentLevel);
			GameObject[] array2 = Object.FindObjectsOfType<GameObject>();
			int num3 = 0;
			int num4 = 0;
			GameObject[] array3 = array2;
			foreach (GameObject val4 in array3)
			{
				if (!((Object)(object)val4 == (Object)null) && IsExplicitHazardSpawnMarker(((Object)val4).name))
				{
					num3++;
					if (!((Object)(object)val4.GetComponent<RandomMapObject>() != (Object)null))
					{
						val4.AddComponent<RandomMapObject>().spawnablePrefabs = new List<GameObject>(eligibleVanillaHazardPrefabs);
						num4++;
					}
				}
			}
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			string name2 = ((Object)roundManager.currentLevel).name;
			if (num3 == 0)
			{
				string text = name + "|" + name2 + "|" + targetPrefabName;
				if (_lastTargetedSpawnRepairKey != text)
				{
					_lastTargetedSpawnRepairKey = text;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Targeted spawn repair found no exact MapHazardSpawnType<number> placeholder for " + targetPrefabName + " in scene '" + name + "' / level '" + name2 + "'. No other objects or spawn lists were changed."));
				}
			}
			else if (num4 == 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Targeted spawn repair found " + num3 + " explicit placeholder(s), but each already had a RandomMapObject component and no compatible spawner exists for " + targetPrefabName + ". Existing marker lists were intentionally left unchanged to preserve interior/event restrictions."));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Targeted spawn repair on level '" + name2 + "': added RandomMapObject to " + num4 + " missing component(s) on explicitly named MapHazardSpawnType<number> placeholders. Added prefab links only for hazards already in the active level's spawn table with positive vanilla spawn curves; table entries/curves/counts were not changed."));
			}
		}

		private List<GameObject> GetEligibleVanillaHazardPrefabs(SelectableLevel level)
		{
			List<GameObject> list = new List<GameObject>();
			if ((Object)(object)level == (Object)null || level.spawnableMapObjects == null || (Object)(object)TimeOfDay.Instance == (Object)null)
			{
				return list;
			}
			SpawnableMapObject[] spawnableMapObjects = level.spawnableMapObjects;
			foreach (SpawnableMapObject val in spawnableMapObjects)
			{
				if (val == null || (Object)(object)val.prefabToSpawn == (Object)null || val.numberToSpawn == null)
				{
					continue;
				}
				string name = ((Object)val.prefabToSpawn).name;
				if ((!NamesMatch(name, "Landmine") && !NamesMatch(name, "TurretContainer")) || val.numberToSpawn.Evaluate(TimeOfDay.Instance.normalizedTimeOfDay) <= 0f)
				{
					continue;
				}
				bool flag = false;
				foreach (GameObject item in list)
				{
					if ((Object)(object)item != (Object)null && NamesMatch(((Object)item).name, name))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					list.Add(val.prefabToSpawn);
				}
			}
			return list;
		}

		private static bool IsExplicitHazardSpawnMarker(string objectName)
		{
			if (string.IsNullOrEmpty(objectName))
			{
				return false;
			}
			string text = objectName.Replace("(Clone)", string.Empty).Trim();
			if (!text.StartsWith("MapHazardSpawnType", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			string text2 = text.Substring("MapHazardSpawnType".Length);
			if (text2.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < text2.Length; i++)
			{
				if (text2[i] < '0' || text2[i] > '9')
				{
					return false;
				}
			}
			return true;
		}

		private static bool NamesMatch(string actual, string expected)
		{
			if (string.IsNullOrEmpty(actual) || string.IsNullOrEmpty(expected))
			{
				return false;
			}
			return string.Equals(actual.Replace("(Clone)", string.Empty).Trim(), expected, StringComparison.OrdinalIgnoreCase);
		}

		private IEnumerator MaintenanceLoop()
		{
			WaitForSecondsRealtime activeWait = new WaitForSecondsRealtime(0.2f);
			WaitForSecondsRealtime idleWait = new WaitForSecondsRealtime(0.75f);
			while (true)
			{
				EnsureNetworkMessageHandlers();
				if (!IsGameplayReady())
				{
					if (_roundWasActive || _turretInteractions.Count > 0)
					{
						ClearTurretInteractions();
					}
					_roundWasActive = false;
					_cachedTurrets = null;
					_lastDiscoverySceneName = string.Empty;
					_nextTurretDiscoveryTime = 0f;
					yield return idleWait;
					continue;
				}
				if (!_roundWasActive)
				{
					_roundWasActive = true;
					_lastLoggedSceneName = string.Empty;
					_lastLoggedTurretCount = -1;
					_cachedTurrets = null;
					_lastDiscoverySceneName = string.Empty;
					_nextTurretDiscoveryTime = 0f;
				}
				if (!_modEnabled.Value)
				{
					if (_turretInteractions.Count > 0)
					{
						ClearTurretInteractions();
					}
					yield return idleWait;
					continue;
				}
				try
				{
					RefreshTurretInteractions();
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Turret interaction refresh failed: " + ex));
				}
				yield return activeWait;
			}
		}

		private static bool IsGameplayReady()
		{
			try
			{
				Type type = Type.GetType("StartOfRound, Assembly-CSharp");
				object obj = ((type != null) ? GetStaticMember(type, "Instance") : null);
				if (obj == null)
				{
					return false;
				}
				object member = GetMember(obj, "shipHasLanded");
				if (!(member is bool) || !(bool)member)
				{
					return false;
				}
				object member2 = GetMember(obj, "inShipPhase");
				if (member2 is bool && (bool)member2)
				{
					return false;
				}
				Type type2 = Type.GetType("RoundManager, Assembly-CSharp");
				object obj2 = ((type2 != null) ? GetStaticMember(type2, "Instance") : null);
				return obj2 != null && GetMember(obj2, "currentLevel") != null;
			}
			catch
			{
				return false;
			}
		}

		private void RefreshTurretInteractions()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			RefreshVanillaInteractionIconIfNeeded();
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (_cachedTurrets == null || name != _lastDiscoverySceneName || Time.unscaledTime >= _nextTurretDiscoveryTime)
			{
				_cachedTurrets = Object.FindObjectsOfType<Turret>();
				_lastDiscoverySceneName = name;
				_nextTurretDiscoveryTime = Time.unscaledTime + 1.25f;
			}
			Turret[] array = _cachedTurrets ?? Array.Empty<Turret>();
			if (name != _lastLoggedSceneName || array.Length != _lastLoggedTurretCount)
			{
				_lastLoggedSceneName = name;
				_lastLoggedTurretCount = array.Length;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Spawn-safe scan in scene '" + name + "': found " + array.Length + " active Turret component(s). This mod does not register or spawn turret prefabs."));
			}
			_seenTurretIds.Clear();
			PlayerControllerB eligibleLocalPlayer = GetEligibleLocalPlayer();
			string turnOffPrompt = GetTurnOffPrompt();
			Turret[] array2 = array;
			foreach (Turret val in array2)
			{
				if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled)
				{
					continue;
				}
				int instanceID = ((Object)val).GetInstanceID();
				_seenTurretIds.Add(instanceID);
				if (!val.turretActive)
				{
					if (_turretInteractions.TryGetValue(instanceID, out var value) && (Object)(object)value.ZoneObject != (Object)null && value.ZoneObject.activeSelf)
					{
						value.ZoneObject.SetActive(false);
					}
					continue;
				}
				if (!_turretInteractions.TryGetValue(instanceID, out var value2) || (Object)(object)value2.Turret == (Object)null)
				{
					value2 = CreateTurretInteraction(val, instanceID);
					_turretInteractions[instanceID] = value2;
				}
				if (value2 != null && !((Object)(object)value2.ZoneObject == (Object)null) && !((Object)(object)value2.Trigger == (Object)null))
				{
					UpdateZonePlacement(value2);
					if ((Object)(object)value2.Trigger.hoverIcon == (Object)null && (Object)(object)_vanillaInteractionIcon != (Object)null)
					{
						value2.Trigger.hoverIcon = _vanillaInteractionIcon;
					}
					if (value2.Trigger.hoverTip != turnOffPrompt)
					{
						value2.Trigger.hoverTip = turnOffPrompt;
					}
					float distance;
					float alignment;
					bool flag = IsPlayerAtRear(value2, eligibleLocalPlayer, out distance, out alignment);
					bool flag2 = val.turretActive && flag;
					value2.Trigger.interactable = flag2;
					if (value2.ZoneObject.activeSelf != flag2)
					{
						value2.ZoneObject.SetActive(flag2);
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Rear interaction " + (flag2 ? "enabled" : "hidden") + " for turret " + instanceID + "; player rear alignment=" + alignment.ToString("0.00") + ", distance=" + distance.ToString("0.00") + "m."));
					}
					value2.Trigger.disabledHoverTip = string.Empty;
					value2.Trigger.holdTip = "Turning off...";
				}
			}
			_staleTurretIds.Clear();
			foreach (KeyValuePair<int, TurretInteraction> turretInteraction2 in _turretInteractions)
			{
				if (!_seenTurretIds.Contains(turretInteraction2.Key) || turretInteraction2.Value == null || (Object)(object)turretInteraction2.Value.Turret == (Object)null)
				{
					_staleTurretIds.Add(turretInteraction2.Key);
				}
			}
			foreach (int staleTurretId in _staleTurretIds)
			{
				TurretInteraction turretInteraction = _turretInteractions[staleTurretId];
				if (turretInteraction != null && (Object)(object)turretInteraction.ZoneObject != (Object)null)
				{
					Object.Destroy((Object)(object)turretInteraction.ZoneObject);
				}
				_turretInteractions.Remove(staleTurretId);
			}
		}

		private unsafe TurretInteraction CreateTurretInteraction(Turret turret, int id)
		{
			//IL_0026: 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_0035: 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_009f: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected O, but got Unknown
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: 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_008c: 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_0057: 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_0073: 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)
			Vector3 val = -Flatten(((Component)turret).transform.forward);
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = -Flatten(((Object)(object)turret.forwardFacingPos != (Object)null) ? turret.forwardFacingPos.forward : Vector3.forward);
			}
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = Vector3.forward;
			}
			((Vector3)(ref val)).Normalize();
			GameObject val2 = new GameObject("TurnOffTurrets_RearInteraction");
			EnsureNativeInteractionObject(val2);
			val2.SetActive(false);
			BoxCollider val3 = val2.AddComponent<BoxCollider>();
			((Collider)val3).isTrigger = true;
			val3.center = Vector3.zero;
			val3.size = new Vector3(0.78f, 1.12f, 0.34f);
			EnsureNativeInteractionObject(val2);
			InteractTrigger val4 = val2.AddComponent<InteractTrigger>();
			val4.hoverTip = GetTurnOffPrompt();
			val4.disabledHoverTip = string.Empty;
			val4.holdTip = "Turning off...";
			val4.animationString = string.Empty;
			val4.interactable = false;
			val4.oneHandedItemAllowed = true;
			val4.twoHandedItemAllowed = true;
			val4.holdInteraction = true;
			val4.timeToHold = 0.45f;
			val4.timeToHoldSpeedMultiplier = 1f;
			val4.interactCooldown = true;
			val4.cooldownTime = 0.5f;
			val4.triggerOnce = false;
			val4.stopAnimationString = "SA_stopAnimation";
			val4.animationWaitTime = 2f;
			val4.lockPlayerPosition = true;
			val4.disableTriggerMesh = true;
			val4.hoverIcon = _vanillaInteractionIcon;
			val4.holdingInteractEvent = new InteractEventFloat();
			val4.onInteract = new InteractEvent();
			val4.onInteractEarly = new InteractEvent();
			val4.onStopInteract = new InteractEvent();
			val4.onCancelAnimation = new InteractEvent();
			((UnityEvent<PlayerControllerB>)(object)val4.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate(PlayerControllerB interactingPlayer)
			{
				DisableTurretFromRear(turret, id, interactingPlayer);
			});
			TurretInteraction turretInteraction = new TurretInteraction();
			turretInteraction.Turret = turret;
			turretInteraction.InstanceId = id;
			turretInteraction.BaseForward = val;
			turretInteraction.ZoneObject = val2;
			turretInteraction.ZoneCollider = val3;
			turretInteraction.Trigger = val4;
			UpdateZonePlacement(turretInteraction);
			val2.SetActive(false);
			ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
			string[] obj = new string[15]
			{
				"Created native rear interaction for turret instance ",
				id.ToString(),
				". Root forward=",
				((object)Flatten(((Component)turret).transform.forward)/*cast due to .constrained prefix*/).ToString(),
				", corrected front axis=",
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			Vector3 val5 = val;
			obj[5] = ((object)(*(Vector3*)(&val5))/*cast due to .constrained prefix*/).ToString();
			obj[6] = ", zone position=";
			obj[7] = ((object)val2.transform.position/*cast due to .constrained prefix*/).ToString();
			obj[8] = ", tag=";
			obj[9] = val2.tag;
			obj[10] = ", layer=";
			obj[11] = LayerMask.LayerToName(val2.layer);
			obj[12] = " (";
			obj[13] = val2.layer.ToString();
			obj[14] = ").";
			logger.LogDebug((object)string.Concat(obj));
			return turretInteraction;
		}

		private void UpdateZonePlacement(TurretInteraction state)
		{
			//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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0078: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (state != null && !((Object)(object)state.Turret == (Object)null) && !((Object)(object)state.ZoneObject == (Object)null))
			{
				EnsureNativeInteractionObject(state.ZoneObject);
				if ((Object)(object)state.ZoneCollider != (Object)null)
				{
					((Collider)state.ZoneCollider).isTrigger = true;
				}
				Vector3 position = ((Component)state.Turret).transform.position;
				state.ZoneObject.transform.position = position + Vector3.up * 0.78f - state.BaseForward * 0.72f;
				state.ZoneObject.transform.rotation = Quaternion.LookRotation(state.BaseForward, Vector3.up);
			}
		}

		private bool IsPlayerAtRear(TurretInteraction state, PlayerControllerB player, out float distance, out float alignment)
		{
			//IL_0031: 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_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)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			distance = float.MaxValue;
			alignment = 1f;
			if (state == null || (Object)(object)state.Turret == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			Vector3 val = ((Component)player).transform.position - ((Component)state.Turret).transform.position;
			val.y = 0f;
			distance = ((Vector3)(ref val)).magnitude;
			if (distance > Mathf.Max(0.75f, _interactionDistance.Value) || ((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				return false;
			}
			alignment = Vector3.Dot(state.BaseForward, ((Vector3)(ref val)).normalized);
			return alignment <= _rearDotThreshold.Value;
		}

		private void DisableTurretFromRear(Turret turret, int id, PlayerControllerB interactingPlayer)
		{
			try
			{
				if ((Object)(object)turret == (Object)null || !turret.turretActive)
				{
					return;
				}
				GameNetworkManager instance = GameNetworkManager.Instance;
				PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null);
				if ((Object)(object)val == (Object)null || (Object)(object)interactingPlayer != (Object)(object)val || !IsEligibleLocalPlayer(interactingPlayer) || !_turretInteractions.TryGetValue(id, out var value) || value == null || (Object)(object)value.Turret != (Object)(object)turret)
				{
					return;
				}
				if (!IsPlayerAtRear(value, interactingPlayer, out var distance, out var alignment))
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)("Rejected turret interaction because the player was outside the rear panel. Distance=" + distance.ToString("0.00") + "m, alignment=" + alignment.ToString("0.00") + "."));
					return;
				}
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Native InteractTrigger callback fired for turret " + id + "."));
				if (TryGetNetworkObjectId(turret, out var id2) && _specialBerserkStates.TryGetValue(id2, out var value2) && value2 != null)
				{
					if (value2.RampageStarted && IsTurretBerserk(turret) && !value2.GracePeriodActive)
					{
						NetworkManager singleton = NetworkManager.Singleton;
						if ((Object)(object)singleton != (Object)null && singleton.IsListening && !singleton.IsServer)
						{
							bool flag = TrySendSpecialBerserkEndRequest(id2);
							((BaseUnityPlugin)this).Logger.LogInfo((object)("Manual rear-panel graceful shutdown requested during custom berserk for turret " + id2 + "; host request sent=" + flag + "."));
							if (!flag)
							{
								((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not request the host's one-second normal-mode grace; leaving the custom burst under host control.");
							}
						}
						else
						{
							BeginPostBerserkGracePeriod(id2, turret, value2, broadcastToClients: true);
							((BaseUnityPlugin)this).Logger.LogInfo((object)("Manual rear-panel shutdown started a one-second normal-mode grace period for custom-berserk turret " + id2 + "."));
						}
					}
					else
					{
						((BaseUnityPlugin)this).Logger.LogDebug((object)("Ignored duplicate rear-panel interaction for turret " + id2 + " while its custom burst was pending/ending; its timer was not reset."));
					}
					return;
				}
				float num = Mathf.Clamp(_berserkChance.Value, 0f, 100f);
				if (_berserkEnabled.Value && num > 0f && Random.Range(0f, 100f) < num)
				{
					bool flag2 = TryQueueCustomBerserk(turret);
					if (!flag2)
					{
						ShowBerserkWarningForFallback(turret);
					}
					((MonoBehaviour)this).StartCoroutine(BerserkTurretForEightSeconds(turret, id, (int)val.playerClientId, flag2));
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Berserk chance succeeded for turret " + id + " (" + num.ToString("0.##") + "%). Custom burst queued=" + flag2 + "."));
					return;
				}
				bool flag3 = TryInvokeToggleTurretServerRpc(turret, enabled: false);
				if (!flag3)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("ToggleTurretServerRpc was unavailable for turret " + id + "; falling back to local ToggleTurretEnabled(false), which may not replicate to other clients."));
					turret.ToggleTurretEnabled(false);
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Requested turret shutdown from its rear panel. Instance=" + id + ", distance=" + distance.ToString("0.00") + "m, alignment=" + alignment.ToString("0.00") + ", vanilla server RPC invoked=" + flag3 + "."));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to disable turret from rear interaction: " + ex));
			}
		}

		private IEnumerator BerserkTurretForEightSeconds(Turret turret, int id, int playerId, bool customBurstQueued)
		{
			if ((Object)(object)turret == (Object)null)
			{
				yield break;
			}
			Exception ex = null;
			try
			{
				turret.turretActive = true;
				if (!TrySwitchTurretMode(turret, 3))
				{
					throw new MissingMethodException("Turret.SwitchTurretMode was not found via reflection.");
				}
				turret.EnterBerserkModeServerRpc(playerId);
			}
			catch (Exception ex2)
			{
				ex = ex2;
			}
			if (ex != null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not start berserk mode for turret " + id + ": " + ex));
				try
				{
					if ((Object)(object)turret != (Object)null && turret.turretActive)
					{
						if (!TryInvokeToggleTurretServerRpc(turret, enabled: false))
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("ToggleTurretServerRpc was unavailable during berserk fallback for turret " + id + "; using a local shutdown that may not replicate."));
							turret.ToggleTurretEnabled(false);
						}
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Fell back to a server-RPC turret shutdown for turret " + id + "."));
					}
					yield break;
				}
				catch (Exception ex3)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Fallback turret shutdown failed for " + id + ": " + ex3));
					yield break;
				}
			}
			if (customBurstQueued)
			{
				float waitLimit = 10f;
				float waited = 0f;
				bool customMarkerWasSeen = false;
				for (; waited < waitLimit; waited += Time.deltaTime)
				{
					if (!((Object)(object)turret != (Object)null))
					{
						break;
					}
					if (!turret.turretActive)
					{
						break;
					}
					if (TryGetNetworkObjectId(turret, out var id2) && _specialBerserkStates.TryGetValue(id2, out var value) && value != null)
					{
						customMarkerWasSeen = true;
						if (value.RampageStarted || value.GracePeriodActive || value.ShutdownRequested)
						{
							yield break;
						}
					}
					else if (customMarkerWasSeen)
					{
						break;
					}
					yield return null;
				}
				if ((Object)(object)turret == (Object)null || !turret.turretActive)
				{
					yield break;
				}
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Custom burst did not reach its rampage phase for turret " + id + "; falling back to the previous 8-second vanilla berserk handling."));
				if (TryGetNetworkObjectId(turret, out var id3))
				{
					RestoreAndRemoveSpecialBerserk(id3);
				}
			}
			yield return (object)new WaitForSeconds(8f);
			if ((Object)(object)turret == (Object)null)
			{
				yield break;
			}
			if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Turret " + id + " berserk duration is server-controlled for this client."));
				yield break;
			}
			try
			{
				if (!TrySwitchTurretMode(turret, 0))
				{
					throw new MissingMethodException("Turret.SwitchTurretMode was not found via reflection.");
				}
				turret.SetToModeClientRpc(0);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Returned turret " + id + " to detection mode after 8 seconds of berserk."));
			}
			catch (Exception ex4)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not reset turret " + id + " after berserk: " + ex4));
			}
		}

		private static bool TryInvokeToggleTurretServerRpc(Turret turret, bool enabled)
		{
			if ((Object)(object)turret == (Object)null)
			{
				return false;
			}
			Type type = ((object)turret).GetType();
			while (type != null)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "ToggleTurretServerRpc")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length == 0 || parameters[0].ParameterType != typeof(bool))
					{
						continue;
					}
					object[] array = new object[parameters.Length];
					array[0] = enabled;
					bool flag = true;
					for (int j = 1; j < parameters.Length; j++)
					{
						if (parameters[j].IsOptional)
						{
							array[j] = parameters[j].DefaultValue;
						}
						else if (parameters[j].ParameterType.IsValueType)
						{
							array[j] = Activator.CreateInstance(parameters[j].ParameterType);
						}
						else
						{
							array[j] = null;
						}
					}
					try
					{
						methodInfo.Invoke(turret, array);
						return true;
					}
					catch
					{
						flag = false;
					}
				}
				type = type.BaseType;
			}
			return false;
		}

		private static bool TrySwitchTurretMode(Turret turret, int mode)
		{
			if ((Object)(object)turret == (Object)null)
			{
				return false;
			}
			Type type = ((object)turret).GetType();
			while (type != null)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "SwitchTurretMode")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length == 1)
					{
						try
						{
							Type parameterType = parameters[0].ParameterType;
							object obj = (parameterType.IsEnum ? Enum.ToObject(parameterType, mode) : Convert.ChangeType(mode, parameterType));
							methodInfo.Invoke(turret, new object[1] { obj });
							return true;
						}
						catch
						{
						}
					}
				}
				type = type.BaseType;
			}
			return false;
		}

		private PlayerControllerB GetEligibleLocalPlayer()
		{
			GameNetworkManager instance = GameNetworkManager.Instance;
			PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null);
			if (!IsEligibleLocalPlayer(val))
			{
				return null;
			}
			return val;
		}

		private static bool IsEligibleLocalPlayer(PlayerControllerB player)
		{
			if ((Object)(object)player != (Object)null && player.isPlayerControlled && !player.isPlayerDead && !player.isTypingChat)
			{
				return !player.inTerminalMenu;
			}
			return false;
		}

		private string GetTurnOffPrompt()
		{
			string text = GetInteractBindingDisplayName();
			if (string.IsNullOrWhiteSpace(text))
			{
				text = "E";
			}
			text = text.Trim().Trim('[', ']');
			return "Turn off : [" + text + "]";
		}

		private string GetInteractBindingDisplayName()
		{
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Type type = Type.GetType("IngamePlayerSettings, Assembly-CSharp");
				if (type == null)
				{
					return "E";
				}
				object staticMember = GetStaticMember(type, "Instance");
				if (staticMember == null)
				{
					return "E";
				}
				object member = GetMember(GetMember(staticMember, "playerInput"), "actions");
				InputActionAsset val = (InputActionAsset)((member is InputActionAsset) ? member : null);
				if ((Object)(object)val == (Object)null)
				{
					return "E";
				}
				InputAction val2 = val.FindAction("Interact", false);
				if (val2 == null)
				{
					val2 = val.FindAction("Movement/Interact", false);
				}
				if (val2 == null)
				{
					return "E";
				}
				int num = -1;
				if (val2.activeControl != null)
				{
					num = InputActionRebindingExtensions.GetBindingIndexForControl(val2, val2.activeControl);
				}
				if (num < 0)
				{
					bool flag = Gamepad.current != null && (Keyboard.current == null || ((InputDevice)Gamepad.current).lastUpdateTime > ((InputDevice)Keyboard.current).lastUpdateTime);
					for (int i = 0; i < val2.bindings.Count; i++)
					{
						InputBinding val3 = val2.bindings[i];
						object obj = ((InputBinding)(ref val3)).effectivePath;
						if (obj == null)
						{
							val3 = val2.bindings[i];
							obj = ((InputBinding)(ref val3)).path ?? string.Empty;
						}
						string text = (string)obj;
						if (flag && text.IndexOf("<Gamepad>/", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							num = i;
							break;
						}
						if (!flag && text.IndexOf("<Keyboard>/", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							num = i;
							break;
						}
					}
				}
				string text2 = ((num >= 0) ? InputActionRebindingExtensions.GetBindingDisplayString(val2, num, (DisplayStringOptions)0) : InputActionRebindingExtensions.GetBindingDisplayString(val2, (DisplayStringOptions)0, (string)null));
				return string.IsNullOrWhiteSpace(text2) ? "E" : text2;
			}
			catch
			{
				return "E";
			}
		}

		private static object GetStaticMember(Type type, string name)
		{
			BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = type.GetField(name, bindingAttr);
			if (field != null)
			{
				return field.GetValue(null);
			}
			PropertyInfo property = type.GetProperty(name, bindingAttr);
			if (!(property != null))
			{
				return null;
			}
			return property.GetValue(null, null);
		}

		private static object GetMember(object instance, string name)
		{
			if (instance == null)
			{
				return null;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = instance.GetType().GetField(name, bindingAttr);
			if (field != null)
			{
				return field.GetValue(instance);
			}
			PropertyInfo property = instance.GetType().GetProperty(name, bindingAttr);
			if (!(property != null))
			{
				return null;
			}
			return property.GetValue(instance, null);
		}

		private void RefreshVanillaInteractionIconIfNeeded()
		{
			if ((Object)(object)_vanillaInteractionIcon != (Object)null || Time.unscaledTime < _nextIconScanTime)
			{
				return;
			}
			_nextIconScanTime = Time.unscaledTime + 1f;
			InteractTrigger[] array = Object.FindObjectsOfType<InteractTrigger>();
			InteractTrigger[] array2 = array;
			foreach (InteractTrigger val in array2)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.hoverIcon == (Object)null) && !(((Object)((Component)val).gameObject).name == "TurnOffTurrets_RearInteraction"))
				{
					string text = val.hoverTip ?? string.Empty;
					if (text.IndexOf("open", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("door", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						ApplyVanillaInteractionStyle(val);
						break;
					}
				}
			}
			if (!((Object)(object)_vanillaInteractionIcon == (Object)null))
			{
				return;
			}
			array2 = array;
			foreach (InteractTrigger val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.hoverIcon != (Object)null && ((Object)((Component)val2).gameObject).name != "TurnOffTurrets_RearInteraction")
				{
					ApplyVanillaInteractionStyle(val2);
					break;
				}
			}
		}

		private void ApplyVanillaInteractionStyle(InteractTrigger source)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)source.hoverIcon == (Object)null)
			{
				return;
			}
			_vanillaInteractionIcon = source.hoverIcon;
			_vanillaInteractionLayer = ((Component)source).gameObject.layer;
			foreach (TurretInteraction value in _turretInteractions.Values)
			{
				if (value != null && !((Object)(object)value.ZoneObject == (Object)null) && !((Object)(object)value.Trigger == (Object)null))
				{
					EnsureNativeInteractionObject(value.ZoneObject);
					value.Trigger.hoverIcon = _vanillaInteractionIcon;
				}
			}
		}

		private void EnsureNativeInteractionObject(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return;
			}
			try
			{
				if (!string.Equals(obj.tag, "InteractTrigger", StringComparison.Ordinal))
				{
					obj.tag = "InteractTrigger";
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not assign the InteractTrigger tag to rear panel: " + ex.Message));
			}
			int num = LayerMask.NameToLayer("InteractableObject");
			if (num < 0)
			{
				num = LayerMask.NameToLayer("Interactable");
			}
			if (num >= 0)
			{
				obj.layer = num;
			}
			else if (_vanillaInteractionLayer >= 0)
			{
				obj.layer = _vanillaInteractionLayer;
			}
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				component.isTrigger = true;
			}
		}

		private static Vector3 Flatten(Vector3 value)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			value.y = 0f;
			return value;
		}

		private void ClearTurretInteractions()
		{
			foreach (TurretInteraction value in _turretInteractions.Values)
			{
				if (value != null && (Object)(object)value.ZoneObject != (Object)null)
				{
					Object.Destroy((Object)(object)value.ZoneObject);
				}
			}
			_turretInteractions.Clear();
		}

		private void OnDestroy()
		{
			if (_maintenanceCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_maintenanceCoroutine);
				_maintenanceCoroutine = null;
			}
			ClearTurretInteractions();
			_cachedTurrets = null;
			UnregisterNetworkMessageHandlers();
			foreach (KeyValuePair<ulong, SpecialBerserkState> specialBerserkState in _specialBerserkStates)
			{
				RestoreOriginalRotationSpeed(specialBerserkState.Value);
			}
			_specialBerserkStates.Clear();
		}
	}
}