Decompiled source of FacilityOvercharge v1.1.0

FacilityOvercharge.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 StaticNetcodeLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering.HighDefinition;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FacilityOvercharge
{
	public static class AudioLoader
	{
		public static AudioClip Load(string resourceName, AudioType audioType = 13)
		{
			//IL_0052: 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_006f: Invalid comparison between Unknown and I4
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Invalid comparison between Unknown and I4
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				throw new FileNotFoundException("Embedded resource not found: " + resourceName);
			}
			string text = Path.Combine(Path.GetTempPath(), resourceName);
			using (FileStream destination = File.Create(text))
			{
				stream.CopyTo(destination);
			}
			try
			{
				UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file://" + text, audioType);
				audioClip.SendWebRequest();
				while (!audioClip.isDone)
				{
				}
				if ((int)audioClip.result == 2 || (int)audioClip.result == 3)
				{
					throw new IOException("Failed to load audio " + resourceName + ": " + audioClip.error);
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
				((Object)content).name = Path.GetFileNameWithoutExtension(resourceName);
				return content;
			}
			finally
			{
				File.Delete(text);
			}
		}
	}
	public class OverchargeController : MonoBehaviour
	{
		private struct LightSnapshot
		{
			public Light Light;

			public float Intensity;

			public float Range;

			public Color Color;
		}

		private struct AudioCache
		{
			public AudioClip PowerSwitch;

			public AudioClip ElectricalHum;

			public AudioClip Alarm;

			public AudioClip FacilityAlarm;
		}

		private float lastActivation = float.NegativeInfinity;

		private bool usedThisMoon;

		private Coroutine activeSequence;

		internal InteractTrigger ButtonTrigger;

		private AudioSource sfxSource;

		private AudioSource humSource;

		private AudioSource panicSource;

		private const float SURGE_INTENSITY = 4f;

		private const float SURGE_RANGE = 1.5f;

		private const float OVERCHARGE_INTENSITY = 8f;

		private const float OVERCHARGE_RANGE = 3.5f;

		private static AudioClip facilityAlarmClip;

		internal static OverchargeController Instance { get; private set; }

		internal bool CanActivate
		{
			get
			{
				if (activeSequence == null && Time.time - lastActivation >= Plugin.CooldownSeconds.Value)
				{
					if (Plugin.SingleUsePerMoon.Value)
					{
						return !usedThisMoon;
					}
					return true;
				}
				return false;
			}
		}

		private void Awake()
		{
			Instance = this;
			sfxSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			sfxSource.spatialBlend = 0f;
			sfxSource.playOnAwake = false;
			humSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			humSource.spatialBlend = 0f;
			humSource.playOnAwake = false;
			humSource.loop = true;
			panicSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			panicSource.spatialBlend = 0f;
			panicSource.playOnAwake = false;
			panicSource.loop = true;
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal void Activate()
		{
			if (activeSequence == null)
			{
				lastActivation = Time.time;
				usedThisMoon = true;
				Plugin.Logger.LogInfo((object)"Overcharge sequence started");
				activeSequence = ((MonoBehaviour)this).StartCoroutine(Sequence());
			}
		}

		internal void ResetMoon()
		{
			usedThisMoon = false;
		}

		private void Update()
		{
			if (!((Object)(object)ButtonTrigger == (Object)null))
			{
				ButtonTrigger.interactable = CanActivate;
				if (!CanActivate)
				{
					ButtonTrigger.disabledHoverTip = ((usedThisMoon && Plugin.SingleUsePerMoon.Value) ? "[BURNED OUT]" : ((activeSequence != null) ? "[ACTIVE]" : "[RECHARGING...]"));
				}
			}
		}

		private IEnumerator Sequence()
		{
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				activeSequence = null;
				yield break;
			}
			LightSnapshot[] snapshots = CacheLights(instance.allPoweredLights);
			List<Animator> animators = instance.allPoweredLightsAnimators;
			ToggleAllLightsInContainer[] bulbs = Object.FindObjectsOfType<ToggleAllLightsInContainer>();
			AudioCache audio = GatherAudio();
			float savedSunDimmer = CaptureAmbientDimmer();
			float savedNightVisionIntensity = CaptureNightVisionIntensity();
			SetAnimatorsEnabled(animators, enabled: false);
			if (Plugin.CreatureStun.Value)
			{
				StunIndoorEnemies(Plugin.CreatureStunDuration.Value);
			}
			yield return Surge(snapshots, bulbs, audio, 1f);
			yield return Overcharge(snapshots, bulbs, audio, Plugin.OverchargeDuration.Value);
			yield return Collapse(snapshots, bulbs, audio, 1f);
			ToggleBulbs(bulbs, on: false);
			SetAmbientDimmer(0f);
			SetNightVisionIntensity(savedNightVisionIntensity * 0.1f);
			SetShipEmergencyLighting(emergency: true);
			yield return Blackout(snapshots, Plugin.BlackoutDuration.Value);
			ToggleBulbs(bulbs, on: true);
			yield return Recovery(snapshots, audio, savedSunDimmer, savedNightVisionIntensity, 3f);
			SetShipEmergencyLighting(emergency: false);
			RestoreLights(snapshots);
			SetAmbientDimmer(savedSunDimmer);
			SetNightVisionIntensity(savedNightVisionIntensity);
			SetAnimatorsEnabled(animators, enabled: true);
			Plugin.Logger.LogInfo((object)"Overcharge sequence complete");
			activeSequence = null;
		}

		private static LightSnapshot[] CacheLights(List<Light> lights)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			LightSnapshot[] array = new LightSnapshot[lights.Count];
			for (int i = 0; i < lights.Count; i++)
			{
				Light val = lights[i];
				if (!((Object)(object)val == (Object)null))
				{
					array[i] = new LightSnapshot
					{
						Light = val,
						Intensity = val.intensity,
						Range = val.range,
						Color = val.color
					};
				}
			}
			return array;
		}

		private static AudioCache GatherAudio()
		{
			AudioCache result = default(AudioCache);
			BreakerBox val = Object.FindObjectOfType<BreakerBox>();
			if ((Object)(object)val != (Object)null)
			{
				result.PowerSwitch = val.switchPowerSFX;
				if ((Object)(object)val.breakerBoxHum != (Object)null)
				{
					result.ElectricalHum = val.breakerBoxHum.clip;
				}
			}
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				result.Alarm = instance.shipAlarmHornSFX;
			}
			if ((Object)(object)result.Alarm == (Object)null)
			{
				StartOfRound instance2 = StartOfRound.Instance;
				if ((Object)(object)instance2 != (Object)null)
				{
					result.Alarm = instance2.alarmSFX;
				}
			}
			if ((Object)(object)facilityAlarmClip == (Object)null)
			{
				try
				{
					facilityAlarmClip = AudioLoader.Load("FacilityOvercharge.alarm.mp3", (AudioType)13);
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogWarning((object)("Failed to load facility alarm: " + ex.Message));
				}
			}
			result.FacilityAlarm = facilityAlarmClip;
			return result;
		}

		private static void SetAnimatorsEnabled(List<Animator> animators, bool enabled)
		{
			foreach (Animator animator in animators)
			{
				if ((Object)(object)animator != (Object)null)
				{
					((Behaviour)animator).enabled = enabled;
				}
			}
		}

		private static void ToggleBulbs(ToggleAllLightsInContainer[] containers, bool on)
		{
			foreach (ToggleAllLightsInContainer val in containers)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.ToggleLights(on);
				}
			}
		}

		private static void SetBulbEmissiveIntensity(ToggleAllLightsInContainer[] containers, float intensity)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			foreach (ToggleAllLightsInContainer val in containers)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>();
				foreach (Renderer val2 in componentsInChildren)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						Material[] materials = val2.materials;
						if (val.materialIndex < materials.Length)
						{
							materials[val.materialIndex].SetColor("_EmissiveColor", Color.white * intensity);
						}
					}
				}
			}
		}

		private static float CaptureAmbientDimmer()
		{
			TimeOfDay instance = TimeOfDay.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.sunIndirect == (Object)null)
			{
				return 1f;
			}
			HDAdditionalLightData component = ((Component)instance.sunIndirect).GetComponent<HDAdditionalLightData>();
			if (!((Object)(object)component != (Object)null))
			{
				return 1f;
			}
			return component.lightDimmer;
		}

		private static void SetAmbientDimmer(float value)
		{
			TimeOfDay instance = TimeOfDay.Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.sunIndirect == (Object)null))
			{
				HDAdditionalLightData component = ((Component)instance.sunIndirect).GetComponent<HDAdditionalLightData>();
				if ((Object)(object)component != (Object)null)
				{
					component.lightDimmer = value;
				}
			}
		}

		private static float CaptureNightVisionIntensity()
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null || (Object)(object)val.nightVision == (Object)null)
			{
				return 0f;
			}
			return val.nightVision.intensity;
		}

		private static void SetNightVisionIntensity(float value)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val != (Object)null && (Object)(object)val.nightVision != (Object)null)
			{
				val.nightVision.intensity = value;
			}
		}

		private static void RestoreLights(LightSnapshot[] snapshots)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < snapshots.Length; i++)
			{
				LightSnapshot lightSnapshot = snapshots[i];
				if (!((Object)(object)lightSnapshot.Light == (Object)null))
				{
					lightSnapshot.Light.intensity = lightSnapshot.Intensity;
					lightSnapshot.Light.range = lightSnapshot.Range;
					lightSnapshot.Light.color = lightSnapshot.Color;
					((Behaviour)lightSnapshot.Light).enabled = true;
				}
			}
		}

		private IEnumerator Surge(LightSnapshot[] snapshots, ToggleAllLightsInContainer[] bulbs, AudioCache audio, float duration)
		{
			if ((Object)(object)audio.PowerSwitch != (Object)null)
			{
				sfxSource.PlayOneShot(audio.PowerSwitch);
			}
			StartHum(audio.ElectricalHum, 0f, 1.3f);
			StartPanic(audio, 0.6f, 1.2f);
			float elapsed = 0f;
			while (elapsed < duration)
			{
				float num = elapsed / duration;
				humSource.volume = num * 0.6f;
				humSource.pitch = 1.3f - num * 0.4f;
				panicSource.pitch = 1.2f - num * 0.15f;
				for (int i = 0; i < snapshots.Length; i++)
				{
					LightSnapshot lightSnapshot = snapshots[i];
					if (!((Object)(object)lightSnapshot.Light == (Object)null))
					{
						float num2 = Mathf.PerlinNoise(Time.time * 25f + (float)((Object)lightSnapshot.Light).GetInstanceID() * 0.17f, 0f);
						lightSnapshot.Light.intensity = lightSnapshot.Intensity * num2 * num * 4f;
						lightSnapshot.Light.range = lightSnapshot.Range * (1f + num * 0.5f);
					}
				}
				SetBulbEmissiveIntensity(bulbs, num * 4f);
				elapsed += Time.deltaTime;
				yield return null;
			}
		}

		private IEnumerator Overcharge(LightSnapshot[] snapshots, ToggleAllLightsInContainer[] bulbs, AudioCache audio, float duration)
		{
			humSource.volume = 1f;
			humSource.pitch = 0.9f;
			panicSource.volume = 0.8f;
			panicSource.pitch = 1.05f;
			float elapsed = 0f;
			while (elapsed < duration)
			{
				float num = elapsed / duration;
				float num2 = 1f + 0.15f * Mathf.Sin(Time.time * 8f);
				humSource.pitch = 0.9f - 0.1f * Mathf.Sin(Time.time * 4f);
				panicSource.pitch = Mathf.Lerp(1.05f, 0.8f, num);
				for (int i = 0; i < snapshots.Length; i++)
				{
					LightSnapshot lightSnapshot = snapshots[i];
					if (!((Object)(object)lightSnapshot.Light == (Object)null))
					{
						lightSnapshot.Light.intensity = lightSnapshot.Intensity * 8f * num2;
						lightSnapshot.Light.range = lightSnapshot.Range * 3.5f;
						lightSnapshot.Light.color = Color.Lerp(lightSnapshot.Color, Color.white, 0.7f);
					}
				}
				SetBulbEmissiveIntensity(bulbs, 8f * num2);
				elapsed += Time.deltaTime;
				yield return null;
			}
		}

		private IEnumerator Collapse(LightSnapshot[] snapshots, ToggleAllLightsInContainer[] bulbs, AudioCache audio, float duration)
		{
			float elapsed = 0f;
			LightSnapshot[] array;
			while (elapsed < duration)
			{
				float num = 1f - elapsed / duration;
				humSource.volume = num * 0.8f;
				humSource.pitch = Mathf.Lerp(0.3f, 0.8f, num);
				panicSource.volume = num * 0.6f;
				panicSource.pitch = Mathf.Lerp(0.4f, 0.8f, num);
				array = snapshots;
				for (int i = 0; i < array.Length; i++)
				{
					LightSnapshot lightSnapshot = array[i];
					if (!((Object)(object)lightSnapshot.Light == (Object)null))
					{
						float num2 = ((Random.value < 0.3f) ? 0f : 1f);
						lightSnapshot.Light.intensity = lightSnapshot.Intensity * num2 * num;
						lightSnapshot.Light.range = lightSnapshot.Range * (0.5f + 0.5f * num);
					}
				}
				SetBulbEmissiveIntensity(bulbs, num);
				elapsed += Time.deltaTime;
				yield return null;
			}
			StopHum();
			StopPanic();
			if ((Object)(object)audio.PowerSwitch != (Object)null)
			{
				sfxSource.PlayOneShot(audio.PowerSwitch, 1.5f);
			}
			array = snapshots;
			for (int i = 0; i < array.Length; i++)
			{
				LightSnapshot lightSnapshot2 = array[i];
				if ((Object)(object)lightSnapshot2.Light != (Object)null)
				{
					((Behaviour)lightSnapshot2.Light).enabled = false;
				}
			}
		}

		private static IEnumerator Blackout(LightSnapshot[] snapshots, float duration)
		{
			for (int i = 0; i < snapshots.Length; i++)
			{
				LightSnapshot lightSnapshot = snapshots[i];
				if ((Object)(object)lightSnapshot.Light != (Object)null)
				{
					((Behaviour)lightSnapshot.Light).enabled = false;
				}
			}
			yield return (object)new WaitForSeconds(duration);
		}

		private IEnumerator Recovery(LightSnapshot[] snapshots, AudioCache audio, float targetDimmer, float targetNightVision, float duration)
		{
			if ((Object)(object)audio.PowerSwitch != (Object)null)
			{
				sfxSource.PlayOneShot(audio.PowerSwitch);
			}
			LightSnapshot[] array = snapshots;
			for (int i = 0; i < array.Length; i++)
			{
				LightSnapshot lightSnapshot = array[i];
				if (!((Object)(object)lightSnapshot.Light == (Object)null))
				{
					((Behaviour)lightSnapshot.Light).enabled = true;
					lightSnapshot.Light.intensity = 0f;
					lightSnapshot.Light.range = lightSnapshot.Range * 0.3f;
				}
			}
			StartHum(audio.ElectricalHum, 0f, 1.1f);
			float elapsed = 0f;
			while (elapsed < duration)
			{
				float num = elapsed / duration;
				humSource.volume = num * 0.4f;
				humSource.pitch = 1.1f - num * 0.2f;
				SetAmbientDimmer(Mathf.Lerp(0f, targetDimmer, num));
				SetNightVisionIntensity(Mathf.Lerp(targetNightVision * 0.1f, targetNightVision, num));
				array = snapshots;
				for (int i = 0; i < array.Length; i++)
				{
					LightSnapshot lightSnapshot2 = array[i];
					if (!((Object)(object)lightSnapshot2.Light == (Object)null))
					{
						bool flag = Random.value < num;
						lightSnapshot2.Light.intensity = (flag ? (lightSnapshot2.Intensity * Random.Range(0.4f, 1f)) : 0f);
						lightSnapshot2.Light.range = (flag ? (lightSnapshot2.Range * Random.Range(0.6f, 1f)) : (lightSnapshot2.Range * 0.3f));
						lightSnapshot2.Light.color = lightSnapshot2.Color;
					}
				}
				elapsed += Time.deltaTime;
				yield return null;
			}
			StopHum();
		}

		private void StartHum(AudioClip clip, float volume, float pitch)
		{
			if (!((Object)(object)clip == (Object)null))
			{
				humSource.clip = clip;
				humSource.volume = volume;
				humSource.pitch = pitch;
				humSource.Play();
			}
		}

		private void StopHum()
		{
			humSource.Stop();
			humSource.clip = null;
		}

		private void StartPanic(AudioCache audio, float volume, float pitch)
		{
			AudioClip val = audio.FacilityAlarm ?? audio.Alarm ?? audio.ElectricalHum;
			if (!((Object)(object)val == (Object)null))
			{
				panicSource.clip = val;
				panicSource.volume = volume;
				panicSource.pitch = pitch;
				panicSource.Play();
			}
		}

		private void StopPanic()
		{
			panicSource.Stop();
			panicSource.clip = null;
		}

		private static void StunIndoorEnemies(float duration)
		{
			foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies)
			{
				if ((Object)(object)spawnedEnemy != (Object)null && !spawnedEnemy.isEnemyDead && !spawnedEnemy.isOutside)
				{
					spawnedEnemy.SetEnemyStunned(true, duration, (PlayerControllerB)null);
				}
			}
		}

		private static void SetShipEmergencyLighting(bool emergency)
		{
			StartOfRound instance = StartOfRound.Instance;
			if (instance != null)
			{
				ShipLights shipRoomLights = instance.shipRoomLights;
				if (shipRoomLights != null)
				{
					shipRoomLights.SetShipLightsOnLocalClientOnly(!emergency);
				}
			}
		}
	}
	[StaticNetcode]
	public static class OverchargeNetwork
	{
		[ServerRpc]
		public static void RequestOverchargeServerRpc()
		{
			OverchargeController instance = OverchargeController.Instance;
			if ((Object)(object)instance == (Object)null || !instance.CanActivate)
			{
				Plugin.Logger.LogDebug((object)"Overcharge request denied (cooldown or unavailable)");
				return;
			}
			Plugin.Logger.LogInfo((object)"Overcharge approved — broadcasting to all clients");
			StartOverchargeClientRpc();
		}

		[ClientRpc]
		public static void StartOverchargeClientRpc()
		{
			OverchargeController.Instance?.Activate();
		}
	}
	[BepInPlugin("keo.lethalcompany.facilityovercharge", "FacilityOvercharge", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "keo.lethalcompany.facilityovercharge";

		public const string NAME = "FacilityOvercharge";

		public const string VERSION = "1.0.0";

		internal static ManualLogSource Logger { get; private set; }

		internal static ConfigEntry<float> OverchargeDuration { get; private set; }

		internal static ConfigEntry<float> BlackoutDuration { get; private set; }

		internal static ConfigEntry<float> CooldownSeconds { get; private set; }

		internal static ConfigEntry<bool> SingleUsePerMoon { get; private set; }

		internal static ConfigEntry<bool> CreatureStun { get; private set; }

		internal static ConfigEntry<float> CreatureStunDuration { get; private set; }

		internal static ConfigEntry<bool> DisableCaveSignalLoss { get; private set; }

		private void Awake()
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			OverchargeDuration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "OverchargeDuration", 3f, "Seconds the facility lights stay at max brightness.");
			BlackoutDuration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BlackoutDuration", 10f, "Seconds of total darkness after the overcharge.");
			CooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CooldownSeconds", 60f, "Minimum seconds between uses.");
			SingleUsePerMoon = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SingleUsePerMoon", false, "If true, the overcharge can only be used once per landing.");
			CreatureStun = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "CreatureStun", true, "Whether the overcharge stuns indoor creatures.");
			CreatureStunDuration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CreatureStunDuration", 2f, "Seconds creatures remain stunned.");
			DisableCaveSignalLoss = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisableCaveSignalLoss", true, "Prevents cave/mine signal loss so the ship monitor always shows the player feed.");
			new Harmony("keo.lethalcompany.facilityovercharge").PatchAll();
			Logger.LogInfo((object)"FacilityOvercharge v1.0.0 loaded");
		}
	}
}
namespace FacilityOvercharge.Patches
{
	[HarmonyPatch]
	public static class ShipPatch
	{
		private static readonly Vector3 BUTTON_POSITION = new Vector3(9.79f, 2.21f, -6f);

		private static readonly Vector3 BUTTON_ROTATION = new Vector3(0f, 270f, 90f);

		private const float BUTTON_SCALE = 1f;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		private static void CreateOverchargeButton(StartOfRound __instance)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			var (val, name) = FindTeleporterButtonPrefab(__instance);
			GameObject val2;
			InteractTrigger val3;
			if ((Object)(object)val != (Object)null)
			{
				val2 = Object.Instantiate<GameObject>(val, __instance.elevatorTransform);
				((Object)val2).name = "OverchargeButton";
				val2.transform.localPosition = BUTTON_POSITION;
				val2.transform.localEulerAngles = BUTTON_ROTATION;
				val2.transform.localScale = Vector3.one * 1f;
				RecolorRenderers(val2, new Color(0.7f, 0.1f, 0.1f));
				val3 = FindTriggerByName(val2, name);
			}
			else
			{
				Plugin.Logger.LogWarning((object)"No teleporter prefab in unlockables — using fallback button");
				val2 = CreateFallbackButton(__instance.elevatorTransform);
				val3 = val2.GetComponent<InteractTrigger>();
			}
			if ((Object)(object)val3 == (Object)null)
			{
				Plugin.Logger.LogError((object)"Overcharge button has no InteractTrigger — aborting");
				Object.Destroy((Object)(object)val2);
				return;
			}
			val3.hoverTip = "Overcharge : [LMB]";
			val3.disabledHoverTip = "[RECHARGING...]";
			val3.onInteract = new InteractEvent();
			((UnityEvent<PlayerControllerB>)(object)val3.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate
			{
				OverchargeNetwork.RequestOverchargeServerRpc();
			});
			val2.AddComponent<OverchargeController>().ButtonTrigger = val3;
			Plugin.Logger.LogInfo((object)$"Overcharge button local position: {val2.transform.localPosition} rotation: {val2.transform.localEulerAngles}");
		}

		private static (GameObject prefab, string triggerName) FindTeleporterButtonPrefab(StartOfRound startOfRound)
		{
			foreach (UnlockableItem unlockable in startOfRound.unlockablesList.unlockables)
			{
				if (!((Object)(object)unlockable.prefabObject == (Object)null))
				{
					ShipTeleporter componentInChildren = unlockable.prefabObject.GetComponentInChildren<ShipTeleporter>();
					if (!((Object)(object)componentInChildren?.buttonAnimator == (Object)null))
					{
						GameObject gameObject = ((Component)componentInChildren.buttonAnimator).gameObject;
						InteractTrigger buttonTrigger = componentInChildren.buttonTrigger;
						return (gameObject, (buttonTrigger != null) ? ((Object)((Component)buttonTrigger).gameObject).name : null);
					}
				}
			}
			return (null, null);
		}

		private static InteractTrigger FindTriggerByName(GameObject root, string name)
		{
			if (name != null)
			{
				InteractTrigger[] componentsInChildren = root.GetComponentsInChildren<InteractTrigger>();
				foreach (InteractTrigger val in componentsInChildren)
				{
					if (((Object)((Component)val).gameObject).name == name)
					{
						return val;
					}
				}
			}
			return root.GetComponentInChildren<InteractTrigger>();
		}

		private static GameObject CreateFallbackButton(Transform parent)
		{
			//IL_0025: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = "OverchargeButton";
			val.transform.SetParent(parent, false);
			val.transform.localPosition = BUTTON_POSITION;
			val.transform.localEulerAngles = BUTTON_ROTATION;
			val.transform.localScale = new Vector3(0.3f, 0.3f, 0.1f);
			val.layer = 9;
			MeshRenderer componentInChildren = ((Component)parent).GetComponentInChildren<MeshRenderer>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				Material val2 = new Material(((Renderer)componentInChildren).sharedMaterial);
				val2.color = new Color(0.7f, 0.1f, 0.1f);
				((Renderer)val.GetComponent<MeshRenderer>()).material = val2;
			}
			InteractTrigger obj = val.AddComponent<InteractTrigger>();
			obj.interactable = true;
			obj.oneHandedItemAllowed = true;
			obj.twoHandedItemAllowed = true;
			return val;
		}

		private static void RecolorRenderers(GameObject root, Color color)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer obj in componentsInChildren)
			{
				Material val = new Material(((Renderer)obj).sharedMaterial);
				val.color = color;
				((Renderer)obj).material = val;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundManager), "GenerateNewFloor")]
		private static void ResetMoonUsage()
		{
			OverchargeController.Instance?.ResetMoon();
		}
	}
	[HarmonyPatch(typeof(ManualCameraRenderer))]
	public static class SignalPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("CheckIfPlayerIsInCaves")]
		private static bool SuppressCaveSignalLoss()
		{
			return !Plugin.DisableCaveSignalLoss.Value;
		}
	}
}