Decompiled source of InsanityRemastered v1.2.1

InsanityRemastered.dll

Decompiled 9 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance;
using DunGen.Graph;
using GameNetcodeStuff;
using HarmonyLib;
using InsanityRemastered.General;
using InsanityRemastered.Hallucinations;
using InsanityRemastered.ModIntegration;
using InsanityRemastered.Patches;
using InsanityRemastered.Utilities;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
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("Epicool")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("MIT License")]
[assembly: AssemblyDescription("Fork of InsanityRemastered (Original by BudgetAirpods)")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1")]
[assembly: AssemblyProduct("InsanityRemastered")]
[assembly: AssemblyTitle("InsanityRemastered")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Toimis/InsanityRemastered")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public enum InsanityLevel
{
	Low,
	Medium,
	High,
	Max
}
public enum SceneNames
{
	InitSceneLaunchOptions,
	MainMenu,
	SampleSceneRelay
}
namespace InsanityRemastered
{
	internal class AnimationID
	{
		public const string PlayerWalking = "Walking";

		public const string PlayerCrouching = "Crouching";

		public const string SpiderMoving = "Moving";

		public const string BrackenMoving = "Sneaking";
	}
	public enum HallucinationType
	{
		Staring,
		Wandering,
		Approaching
	}
	[BepInPlugin("Epicool.InsanityRemastered", "Insanity Remastered", "1.2.0")]
	public class InsanityRemasteredBase : BaseUnityPlugin
	{
		public static InsanityRemasteredBase Instance;

		public const string modGUID = "Epicool.InsanityRemastered";

		public const string modName = "Insanity Remastered";

		public const string modVersion = "1.2.0";

		private readonly Harmony harmony = new Harmony("Epicool.InsanityRemastered");

		internal static GameObject SanityModObject;

		private static string logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads", "log.txt");

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
			AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
			InsanityRemasteredLogger.Initialize("Epicool.InsanityRemastered");
			InsanityRemasteredConfiguration.Initialize(((BaseUnityPlugin)this).Config);
			InsanityRemasteredConfiguration.ValidateSettings();
			InsanityRemasteredContent.LoadContent();
			harmony.PatchAll();
		}

		private void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
		{
			ModIntegrator.BeginIntegrations(args.LoadedAssembly);
		}

		private void SetupModManager()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			GameObject val = new GameObject("Sanity Mod");
			val.AddComponent<InsanityGameManager>();
			val.AddComponent<InsanitySoundManager>();
			((Behaviour)val.AddComponent<HallucinationManager>()).enabled = false;
			SanityModObject = val;
			((Object)SanityModObject).hideFlags = (HideFlags)61;
		}

		private void OnSceneLoaded(Scene level, LoadSceneMode loadEnum)
		{
			if (((Scene)(ref level)).name == SceneNames.SampleSceneRelay.ToString() && !SanityModObject.activeInHierarchy)
			{
				SanityModObject.SetActive(true);
			}
			if (((Scene)(ref level)).name == SceneNames.MainMenu.ToString())
			{
				if (Object.op_Implicit((Object)(object)SanityModObject))
				{
					InsanitySoundManager.Instance.StopModSounds();
					((Object)SanityModObject).hideFlags = (HideFlags)61;
				}
				else
				{
					SetupModManager();
					((Object)SanityModObject).hideFlags = (HideFlags)61;
				}
			}
		}

		public static void Log(string message)
		{
			using StreamWriter streamWriter = new StreamWriter(logFilePath, append: true);
			streamWriter.WriteLine(message);
		}
	}
	internal class InsanityRemasteredContent
	{
		internal static Material[] Materials { get; set; }

		internal static GameObject[] EnemyModels { get; set; }

		internal static Texture2D[] Textures { get; set; }

		internal static AudioClip[] AuditoryHallucinations { get; set; }

		internal static AudioClip[] Stingers { get; set; }

		internal static AudioClip[] PlayerHallucinationSounds { get; set; }

		internal static AudioClip[] LCGameSFX { get; set; }

		internal static AudioClip[] Drones { get; set; }

		private static string DataFolder => Path.GetFullPath(Paths.PluginPath);

		public static void LoadContent()
		{
			LoadSounds();
		}

		public static GameObject GetEnemyModel(string name)
		{
			for (int i = 0; i < EnemyModels.Length; i++)
			{
				if (((Object)EnemyModels[i]).name == name)
				{
					return EnemyModels[i];
				}
			}
			return null;
		}

		public static Material GetMaterial(string name)
		{
			for (int i = 0; i < EnemyModels.Length; i++)
			{
				if (((Object)Materials[i]).name == name)
				{
					InsanityRemasteredLogger.Log("Successfully loaded material: " + name);
					return Materials[i];
				}
			}
			return null;
		}

		public static Texture2D GetTexture(string name)
		{
			for (int i = 0; i < EnemyModels.Length; i++)
			{
				if (((Object)Textures[i]).name == name)
				{
					InsanityRemasteredLogger.Log("Successfully loaded texture: " + name);
					return Textures[i];
				}
			}
			return null;
		}

		private static void LoadEnemy()
		{
			string text = Path.Combine(DataFolder, "insanityremastered_enemies");
			InsanityRemasteredLogger.Log(text);
			AssetBundle obj = AssetBundle.LoadFromFile(text);
			if (!Object.op_Implicit((Object)(object)obj))
			{
				InsanityRemasteredLogger.LogWarning("Failed to load enemies.");
			}
			EnemyModels = obj.LoadAllAssets<GameObject>();
		}

		private static void LoadMaterials()
		{
			string text = Path.Combine(DataFolder, "insanityremastered_materials");
			InsanityRemasteredLogger.Log(text);
			AssetBundle obj = AssetBundle.LoadFromFile(text);
			if (!Object.op_Implicit((Object)(object)obj))
			{
				InsanityRemasteredLogger.LogWarning("Failed to load materials.");
			}
			Materials = obj.LoadAllAssets<Material>();
			Textures = obj.LoadAllAssets<Texture2D>();
			EnemyModels = obj.LoadAllAssets<GameObject>();
		}

		private static void LoadSounds()
		{
			string text = ((!InsanityRemasteredConfiguration.useThunderstoreFolderPath) ? "InsanityRemastered" : "Epicool-InsanityRemastered");
			string text2 = Path.Combine(DataFolder, text, "soundresources_sfx");
			string text3 = Path.Combine(DataFolder, text, "soundresources_stingers");
			string text4 = Path.Combine(DataFolder, text, "soundresources_hallucination");
			string text5 = Path.Combine(DataFolder, text, "soundresources_drones");
			string text6 = Path.Combine(DataFolder, text, "soundresources_lc");
			AssetBundle val = AssetBundle.LoadFromFile(text2);
			AssetBundle val2 = AssetBundle.LoadFromFile(text3);
			AssetBundle val3 = AssetBundle.LoadFromFile(text4);
			AssetBundle val4 = AssetBundle.LoadFromFile(text5);
			AssetBundle val5 = AssetBundle.LoadFromFile(text6);
			if (InsanityRemasteredConfiguration.logDebugVariables)
			{
				InsanityRemasteredLogger.LogVariables(new string[11]
				{
					"modFolder", "sfxPath", "ambiencePath", "fakePlayerPath", "dronePath", "lcGamePath", "sfx", "ambience", "fakePlayer", "drone",
					"lcGame"
				}, new object[11]
				{
					text, text2, text3, text4, text5, text6, val, val2, val3, val4,
					val5
				});
			}
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)val5))
			{
				InsanityRemasteredLogger.Log("Successfully loaded audio assets!");
				AuditoryHallucinations = val.LoadAllAssets<AudioClip>();
				Stingers = val2.LoadAllAssets<AudioClip>();
				PlayerHallucinationSounds = val3.LoadAllAssets<AudioClip>();
				Drones = val4.LoadAllAssets<AudioClip>();
				LCGameSFX = val5.LoadAllAssets<AudioClip>();
			}
			else
			{
				InsanityRemasteredLogger.LogError("Failed to load audio assets!");
			}
		}
	}
	internal class InsanityRemasteredDebug
	{
		public static void QuickHotkeyTesting()
		{
			if (UnityInput.Current.GetKeyDown("f"))
			{
				SpawnFakePlayer();
			}
			if (UnityInput.Current.GetKeyDown("v"))
			{
				HallucinationManager.Instance.Hallucinate("LightsOff");
			}
		}

		public static void SpawnFakePlayer()
		{
			HallucinationManager.Instance.PanicAttackLevel = 1f;
			PlayerPatcher.LocalPlayer.insanityLevel = 100f;
			HallucinationManager.Instance.Hallucinate("FakePlayer");
		}

		public static void SpawnItem(string itemName)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			foreach (Item items in StartOfRound.Instance.allItemsList.itemsList)
			{
				if (((Object)items).name == itemName)
				{
					GrabbableObject component = Object.Instantiate<GameObject>(items.spawnPrefab, ((Component)PlayerPatcher.LocalPlayer).transform.position + ((Component)PlayerPatcher.LocalPlayer).transform.forward * 2f, ((Component)PlayerPatcher.LocalPlayer).transform.rotation, RoundManager.Instance.spawnedScrapContainer).GetComponent<GrabbableObject>();
					component.fallTime = 1f;
					component.scrapPersistedThroughRounds = false;
					component.grabbable = true;
					if (items.isScrap)
					{
						component.SetScrapValue(Random.Range(items.minValue, items.maxValue));
						((NetworkBehaviour)component).NetworkObject.Spawn(false);
					}
				}
			}
		}

		public static void SpawnObserver()
		{
			HallucinationManager.Instance.Hallucinate("Observer");
		}
	}
	internal static class InsanityRemasteredLogger
	{
		internal static ManualLogSource logSource;

		public static float logTimer;

		public static void Initialize(string modGUID)
		{
			logSource = Logger.CreateLogSource(modGUID);
		}

		public static void Log(object message)
		{
			logSource.LogMessage(message);
		}

		public static void LogError(object message)
		{
			logSource.LogError(message);
		}

		public static void LogWarning(object message)
		{
			logSource.LogWarning(message);
		}

		public static void LogVariables(string[] variableNames, object[] variables)
		{
			if (variableNames.Length != variables.Length)
			{
				throw new ArgumentException("The number of variable names and variables must match.");
			}
			for (int i = 0; i < variables.Length; i++)
			{
				string text = ((variables[i] != null) ? variables[i].ToString() : "null");
				logSource.LogMessage((object)(variableNames[i] + ": " + text));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "InsanityRemastered";

		public const string PLUGIN_NAME = "InsanityRemastered";

		public const string PLUGIN_VERSION = "1.2.1";
	}
}
namespace InsanityRemastered.Utilities
{
	[HarmonyPatch]
	internal class GameEvents
	{
		public static event Action<bool> OnEnterOrLeaveFacility;

		public static event Action OnGameStart;

		public static event Action OnLateGameStart;

		public static event Action OnGameEnd;

		public static event Action OnEnemySpawned;

		public static event Action OnShipLanded;

		public static event Action<GrabbableObject> OnItemSwitch;

		public static event Action OnPlayerJoin;

		public static event Action OnPlayerLeave;

		public static event Action OnPlayerDied;

		public static event Action<int> OnTakeDamage;

		public static event Action<EnemyAI> OnKillEnemy;

		[HarmonyPatch(typeof(EntranceTeleport), "TeleportPlayer")]
		[HarmonyPrefix]
		private static void OnEnterLeaveFacility(EntranceTeleport __instance)
		{
			GameEvents.OnEnterOrLeaveFacility?.Invoke(__instance.isEntranceToBuilding);
		}

		[HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")]
		[HarmonyPostfix]
		private static void GameStart()
		{
			GameEvents.OnGameStart?.Invoke();
		}

		[HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")]
		[HarmonyPostfix]
		private static void LateGameStart()
		{
			GameEvents.OnLateGameStart?.Invoke();
		}

		[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
		[HarmonyPostfix]
		private static void GameEnd()
		{
			GameEvents.OnGameEnd?.Invoke();
		}

		[HarmonyPatch(typeof(StartOfRound), "OnShipLandedMiscEvents")]
		[HarmonyPostfix]
		private static void ShipLanded()
		{
			GameEvents.OnShipLanded?.Invoke();
		}

		[HarmonyPatch(typeof(RoundManager), "SpawnEnemyGameObject")]
		[HarmonyPostfix]
		private static void SpawnEnemy()
		{
			GameEvents.OnEnemySpawned?.Invoke();
		}

		[HarmonyPatch(typeof(StartOfRound), "OnClientDisconnect")]
		[HarmonyPostfix]
		private static void PlayerLeave()
		{
			GameEvents.OnPlayerLeave?.Invoke();
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")]
		[HarmonyPostfix]
		private static void SwitchItem(ref GrabbableObject ___currentlyHeldObjectServer)
		{
			if ((Object)(object)___currentlyHeldObjectServer != (Object)null)
			{
				GameEvents.OnItemSwitch?.Invoke(___currentlyHeldObjectServer);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
		[HarmonyPostfix]
		private static void OnPlayerDeath(ref PlayerControllerB __instance)
		{
			GameEvents.OnPlayerDied?.Invoke();
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
		[HarmonyPostfix]
		private static void TakeDamage(int damageNumber)
		{
			GameEvents.OnTakeDamage?.Invoke(damageNumber);
		}

		[HarmonyPatch(typeof(EnemyAI), "KillEnemy")]
		[HarmonyPostfix]
		private static void KillEnemy(EnemyAI __instance)
		{
			GameEvents.OnKillEnemy?.Invoke(__instance);
		}
	}
}
namespace InsanityRemastered.Patches
{
	[HarmonyPatch]
	internal class HUDPatcher
	{
		private static bool hudOn;

		private static bool wasWarned;

		private static void ResetWarningFacility(bool outside)
		{
			if (outside)
			{
				wasWarned = false;
			}
		}

		private static void ResetWarning()
		{
		}

		[HarmonyPatch(typeof(HUDManager), "Awake")]
		[HarmonyPostfix]
		private static void _Awake()
		{
			HallucinationManager.OnUIHallucination += PlayUISFX;
			GameEvents.OnEnterOrLeaveFacility += ResetWarningFacility;
			GameEvents.OnGameEnd += ResetWarning;
			GameEvents.OnPlayerDied += ResetWarning;
		}

		[HarmonyPatch(typeof(HUDManager), "Update")]
		[HarmonyPostfix]
		private static void _Update()
		{
			if (UnityInput.Current.GetKeyDown((KeyCode)48))
			{
				ToggleHUD();
			}
			if (InsanityRemasteredConfiguration.sanityRemindersEnabled && !wasWarned)
			{
				if (PlayerPatcher.CurrentInsanityLevel >= InsanityLevel.High)
				{
					HUDManager.Instance.DisplayTip("WARNING!", "Heartrate is . Please exercise caution.", true, false, "LC_Tip1");
					wasWarned = true;
				}
				else if (PlayerPatcher.CurrentInsanityLevel == InsanityLevel.Medium)
				{
					HUDManager.Instance.DisplayTip("WARNING!", "Heartrate level is above normal. Please exercise caution.", true, false, "LC_Tip1");
					wasWarned = true;
				}
			}
		}

		private static void PlayUISFX()
		{
			InsanitySoundManager.Instance.PlayUISound(HUDManager.Instance.warningSFX[Random.Range(0, HUDManager.Instance.warningSFX.Length)]);
		}

		private static void ToggleHUD()
		{
			if (hudOn)
			{
				HUDManager.Instance.HideHUD(false);
				hudOn = false;
			}
			else
			{
				HUDManager.Instance.HideHUD(true);
				hudOn = true;
			}
		}
	}
	[HarmonyPatch(typeof(FlashlightItem))]
	internal class ItemPatcher
	{
		private static float walkieRNGFrequency = 35f;

		private static float walkieRNGTimer;

		[HarmonyPatch(typeof(FlashlightItem), "SwitchFlashlight")]
		[HarmonyPostfix]
		private static void OnUse(bool on)
		{
			PlayerPatcher.FlashlightOn = on;
		}

		[HarmonyPatch(typeof(GrabbableObject), "EquipItem")]
		[HarmonyPostfix]
		private static void SetControlTipForPills(ref GrabbableObject __instance)
		{
			if (((Object)__instance.itemProperties).name == "PillBottle")
			{
				HUDManager.Instance.ChangeControlTip(1, "Consume pills: [LMB]", false);
			}
		}

		[HarmonyPatch(typeof(WalkieTalkie), "Update")]
		[HarmonyPostfix]
		private static void WalkieEffects(ref WalkieTalkie __instance)
		{
			if (!GameNetworkManager.Instance.gameHasStarted || !InsanityRemasteredConfiguration.skinwalkerWalkiesEnabled || !PlayerPatcher.LocalPlayer.isInsideFactory)
			{
				return;
			}
			walkieRNGTimer += Time.deltaTime;
			if (walkieRNGTimer > walkieRNGFrequency && ((GrabbableObject)__instance).isBeingUsed)
			{
				walkieRNGTimer = 0f;
				if (SkinwalkerModIntegration.IsInstalled && InsanityGameManager.AreOtherPlayersConnected && Random.Range(0f, 1f) < 0.35f)
				{
					__instance.thisAudio.PlayOneShot(SkinwalkerModIntegration.GetRandomClip());
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerPatcher
	{
		public static InsanityLevel CurrentInsanityLevel;

		public static int PlayersConnected;

		internal static bool lookingAtModelHallucination;

		private static bool holdingPills;

		public static PlayerControllerB LocalPlayer => GameNetworkManager.Instance.localPlayerController;

		public static bool FlashlightOn { get; set; }

		public static event Action OnInteractWithFakeItem;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void _Awake(ref PlayerControllerB __instance)
		{
			InsanityRemasteredAI.OnHallucinationEnded += LoseSanity;
			GameEvents.OnItemSwitch += OnItemSwitch;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Start")]
		[HarmonyPostfix]
		private static void _Start(PlayerControllerB __instance)
		{
			__instance.maxInsanityLevel = 100f;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SetPlayerSanityLevel")]
		[HarmonyPrefix]
		private static bool PlayerInsanityPatch()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Invalid comparison between Unknown and I4
			if (GameNetworkManager.Instance.gameHasStarted)
			{
				if (StartOfRound.Instance.inShipPhase || !TimeOfDay.Instance.currentDayTimeStarted)
				{
					LocalPlayer.insanityLevel = 0f;
					return false;
				}
				if (PlayersConnected > 1)
				{
					LocalPlayer.isPlayerAlone = !InsanityGameManager.Instance.IsNearOtherPlayers;
				}
				else
				{
					LocalPlayer.isPlayerAlone = true;
				}
				if (LocalPlayer.isInsideFactory)
				{
					LocalPlayer.insanitySpeedMultiplier = InsanityRemasteredConfiguration.sanityLossInsideFactory;
				}
				else if (LocalPlayer.isInHangarShipRoom)
				{
					LocalPlayer.insanitySpeedMultiplier = 0f - InsanityRemasteredConfiguration.sanityGainInsideShip;
				}
				else if ((int)TimeOfDay.Instance.dayMode > 1)
				{
					LocalPlayer.insanitySpeedMultiplier = InsanityRemasteredConfiguration.sanityLossDarkOutside;
				}
				else
				{
					LocalPlayer.insanitySpeedMultiplier = 0f - InsanityRemasteredConfiguration.sanityGainLightOutside;
				}
				if (LocalPlayer.insanitySpeedMultiplier > 0f)
				{
					if (InsanityGameManager.Instance.IsNearLightSource || FlashlightOn || AdvancedCompanyCompatibility.nightVision)
					{
						PlayerControllerB localPlayer = LocalPlayer;
						localPlayer.insanitySpeedMultiplier -= InsanityRemasteredConfiguration.sanityGainLight;
					}
					if (InsanityGameManager.Instance.IsHearingPlayersThroughWalkie && LocalPlayer.isPlayerAlone)
					{
						PlayerControllerB localPlayer2 = LocalPlayer;
						localPlayer2.insanitySpeedMultiplier -= InsanityRemasteredConfiguration.sanityGainHearingWalkies;
					}
				}
				if (InsanityGameManager.Instance.LightsOff)
				{
					PlayerControllerB localPlayer3 = LocalPlayer;
					localPlayer3.insanitySpeedMultiplier += InsanityRemasteredConfiguration.sanityLossLightsOffEvent;
				}
				if (lookingAtModelHallucination)
				{
					PlayerControllerB localPlayer4 = LocalPlayer;
					localPlayer4.insanitySpeedMultiplier += InsanityRemasteredConfiguration.sanityLossLookingAtModelHallucination;
				}
				if (CurrentInsanityLevel == InsanityLevel.Max)
				{
					PlayerControllerB localPlayer5 = LocalPlayer;
					localPlayer5.insanitySpeedMultiplier += InsanityRemasteredConfiguration.sanityLossPanicAttack;
				}
				if (LocalPlayer.insanitySpeedMultiplier < 0f)
				{
					LocalPlayer.insanityLevel = Mathf.MoveTowards(LocalPlayer.insanityLevel, 0f, Time.deltaTime * (0f - LocalPlayer.insanitySpeedMultiplier));
					return false;
				}
				if (LocalPlayer.insanityLevel > LocalPlayer.maxInsanityLevel)
				{
					LocalPlayer.insanityLevel = Mathf.MoveTowards(LocalPlayer.insanityLevel, LocalPlayer.maxInsanityLevel, Time.deltaTime * 2f);
					return false;
				}
				if (PlayersConnected == 1)
				{
					PlayerControllerB localPlayer6 = LocalPlayer;
					localPlayer6.insanitySpeedMultiplier *= InsanityRemasteredConfiguration.sanityLossSoloReduction;
				}
				else
				{
					PlayerControllerB localPlayer7 = LocalPlayer;
					localPlayer7.insanitySpeedMultiplier *= InsanityRemasteredConfiguration.sanityLossNearPlayersReduction;
				}
				LocalPlayer.insanityLevel = Mathf.MoveTowards(LocalPlayer.insanityLevel, LocalPlayer.maxInsanityLevel, Time.deltaTime * LocalPlayer.insanitySpeedMultiplier);
				return false;
			}
			return false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		[HarmonyPostfix]
		private static void _Update()
		{
			PlayersConnected = StartOfRound.Instance.connectedPlayersAmount + 1;
			PlayersConnected = Math.Clamp(PlayersConnected, 1, 4);
			if (GameNetworkManager.Instance.gameHasStarted && LocalPlayer.isPlayerControlled && !LocalPlayer.isPlayerDead)
			{
				UpdateStatusEffects();
				if (HallucinationManager.Instance.PanicAttackLevel > 0.9f)
				{
					CurrentInsanityLevel = InsanityLevel.Max;
				}
				else if (LocalPlayer.insanityLevel > 90f)
				{
					CurrentInsanityLevel = InsanityLevel.High;
				}
				else if (LocalPlayer.insanityLevel > 45f)
				{
					CurrentInsanityLevel = InsanityLevel.Medium;
				}
				else
				{
					CurrentInsanityLevel = InsanityLevel.Low;
				}
			}
		}

		private static void UpdateStatusEffects()
		{
			if (HallucinationManager.slowness)
			{
				LocalPlayer.movementSpeed = Mathf.MoveTowards(LocalPlayer.movementSpeed, 2.3f, 5f * Time.deltaTime);
			}
			else if (!HallucinationManager.slowness && !LocalPlayer.isSprinting && !LocalPlayer.isCrouching)
			{
				LocalPlayer.movementSpeed = Mathf.MoveTowards(LocalPlayer.movementSpeed, 4.6f, 5f * Time.deltaTime);
			}
			if (HallucinationManager.reduceVision)
			{
				HUDManager.Instance.increaseHelmetCondensation = true;
			}
		}

		private static void OnItemSwitch(GrabbableObject item)
		{
			if (((Object)item.itemProperties).name == "PillBottle")
			{
				holdingPills = true;
			}
			else
			{
				holdingPills = false;
			}
		}

		private static void LoseSanity(bool touched)
		{
			if (touched)
			{
				PlayerControllerB localPlayer = LocalPlayer;
				localPlayer.insanityLevel += 15f;
				LocalPlayer.JumpToFearLevel(1f, true);
			}
		}

		private static void OnHeardHallucinationSound()
		{
			if (CurrentInsanityLevel >= InsanityLevel.Medium)
			{
				PlayerControllerB localPlayer = LocalPlayer;
				localPlayer.insanityLevel += 2.5f;
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ActivateItem_performed")]
		[HarmonyPostfix]
		private static void _UseItem(PlayerControllerB __instance)
		{
			if (holdingPills)
			{
				LocalPlayer.ItemSlots[LocalPlayer.currentItemSlot].DestroyObjectInHand(LocalPlayer);
				holdingPills = false;
				LocalPlayer.insanityLevel = 0f;
				HallucinationManager.Instance.AdjustPanic(reset: true);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")]
		[HarmonyPostfix]
		private static void InteractPatch(PlayerControllerB __instance)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Ray(((Component)LocalPlayer.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward), ref val, __instance.grabDistance, 832) && ((Component)((RaycastHit)(ref val)).collider).gameObject.layer != 8 && ((Component)((RaycastHit)(ref val)).collider).tag == "PhysicsProp" && !LocalPlayer.twoHanded && !(__instance.sinkingValue > 0.73f) && Object.op_Implicit((Object)(object)((Component)((Component)((RaycastHit)(ref val)).collider).transform).gameObject.GetComponent<FakeItem>()))
			{
				PlayerControllerB localPlayer = LocalPlayer;
				localPlayer.insanityLevel += 13f;
				LocalPlayer.JumpToFearLevel(0.4f, true);
				PlayerPatcher.OnInteractWithFakeItem?.Invoke();
			}
		}
	}
}
namespace InsanityRemastered.ModIntegration
{
	public class AdvancedCompanyCompatibility
	{
		public static bool nightVision;

		internal static void UnequipHeadLightUtility()
		{
			nightVision = false;
		}

		internal static void HeadLightUtilityUse(bool on)
		{
			nightVision = on;
		}
	}
	public class ModIntegrator
	{
		public static void BeginIntegrations(Assembly assembly)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Expected O, but got Unknown
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Expected O, but got Unknown
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Expected O, but got Unknown
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Expected O, but got Unknown
			if (InsanityRemasteredConfiguration.useExperimentalSkinwalkerVersion)
			{
				SkinwalkerModIntegration.IsInstalled = true;
				InsanityRemasteredLogger.Log("Skinwalker mod installed, starting integration.");
				Harmony val = new Harmony("skinwalker");
				Type[] types = assembly.GetTypes();
				for (int i = 0; i < types.Length; i++)
				{
					if (types[i].Name == "AudioAggregator")
					{
						MethodInfo method = types[i].GetMethod("AddAudioRecording", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
						HarmonyMethod val2 = new HarmonyMethod(typeof(SkinwalkerModIntegration).GetMethod("AddRecording"));
						val.Patch((MethodBase)method, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
			}
			else if (assembly.FullName.StartsWith("SkinwalkerMod"))
			{
				SkinwalkerModIntegration.IsInstalled = true;
				InsanityRemasteredLogger.Log("Skinwalker mod installed, starting integration.");
				Harmony val3 = new Harmony("skinwalker");
				Type[] types2 = assembly.GetTypes();
				for (int j = 0; j < types2.Length; j++)
				{
					if (types2[j].Name == "SkinwalkerModPersistent")
					{
						MethodInfo method2 = types2[j].GetMethod("Update", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
						HarmonyMethod val4 = new HarmonyMethod(typeof(SkinwalkerModIntegration).GetMethod("UpdateClips"));
						val3.Patch((MethodBase)method2, val4, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
			}
			if (!assembly.FullName.StartsWith("AdvancedCompany"))
			{
				return;
			}
			InsanityRemasteredLogger.LogError("AdvancedCompany mod installed, starting integration.");
			Harmony val5 = new Harmony("AdvancedCompany");
			Type[] types3 = assembly.GetTypes();
			for (int k = 0; k < types3.Length; k++)
			{
				if (types3[k].Name == "NightVision" && types3[k].Namespace == "AdvancedCompany.Objects")
				{
					InsanityRemasteredLogger.Log("Vision Enhancer object found, starting method patching.");
					MethodInfo method3 = types3[k].GetMethod("SwitchFlashlight", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
					MethodInfo method4 = types3[k].GetMethod("Unequipped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
					HarmonyMethod val6 = new HarmonyMethod(typeof(AdvancedCompanyCompatibility).GetMethod("HeadLightUtilityUse"));
					HarmonyMethod val7 = new HarmonyMethod(typeof(AdvancedCompanyCompatibility).GetMethod("UnequipHeadLightUtility"));
					val5.Patch((MethodBase)method3, val6, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					val5.Patch((MethodBase)method4, val7, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (types3[k].Name == "HelmetLamp" && types3[k].Namespace == "AdvancedCompany.Objects")
				{
					InsanityRemasteredLogger.Log("Helmet Lamp object found, starting fix.");
					MethodInfo method5 = types3[k].GetMethod("SwitchFlashlight", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
					MethodInfo method6 = types3[k].GetMethod("Unequipped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
					HarmonyMethod val8 = new HarmonyMethod(typeof(AdvancedCompanyCompatibility).GetMethod("HeadLightUtilityUse"));
					HarmonyMethod val9 = new HarmonyMethod(typeof(AdvancedCompanyCompatibility).GetMethod("UnequipHeadLightUtility"));
					val5.Patch((MethodBase)method5, val8, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					val5.Patch((MethodBase)method6, val9, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (types3[k].Name == "TacticalHelmet" && types3[k].Namespace == "AdvancedCompany.Objects")
				{
					InsanityRemasteredLogger.Log("Tactical Helmet object found, starting fix.");
					MethodInfo method7 = types3[k].GetMethod("SwitchFlashlight", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
					MethodInfo method8 = types3[k].GetMethod("Unequipped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
					HarmonyMethod val10 = new HarmonyMethod(typeof(AdvancedCompanyCompatibility).GetMethod("HeadLightUtilityUse"));
					HarmonyMethod val11 = new HarmonyMethod(typeof(AdvancedCompanyCompatibility).GetMethod("UnequipHeadLightUtility"));
					val5.Patch((MethodBase)method7, val10, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					val5.Patch((MethodBase)method8, val11, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}
	}
	public class SkinwalkerModIntegration
	{
		private static List<AudioClip> skinwalkerClips = new List<AudioClip>();

		public static bool IsInstalled { get; set; }

		internal static void UpdateClips(ref List<AudioClip> ___cachedAudio)
		{
			skinwalkerClips = ___cachedAudio;
		}

		public static AudioClip GetRandomClip()
		{
			return skinwalkerClips[Random.Range(0, skinwalkerClips.Count)];
		}

		internal static void AddRecording(object recording)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			skinwalkerClips.Add((AudioClip)recording.GetType().GetField("clip").GetValue(recording));
		}

		public static void ClearRecordings()
		{
			skinwalkerClips.Clear();
		}
	}
}
namespace InsanityRemastered.Hallucinations
{
	internal class FakeItem : MonoBehaviour
	{
		private float stayTimer = 50f;

		private void Update()
		{
			stayTimer -= Time.deltaTime;
			if (stayTimer <= 0f)
			{
				((Component)this).gameObject.SetActive(false);
			}
		}

		private void Interaction()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			float num = Random.Range(0f, 1f);
			if (num < 0.7f)
			{
				HUDManager.Instance.DisplayTip("", InsanityRemasteredConfiguration.tipMessageTexts[7], true, false, "LC_Tip1");
			}
			if (num < 0.4f)
			{
				GameNetworkManager.Instance.localPlayerController.DamagePlayer(Random.Range(1, 8), false, true, (CauseOfDeath)0, 0, false, default(Vector3));
				PlayerPatcher.LocalPlayer.DropBlood(default(Vector3), true, false);
			}
			else if (num < 0.001f)
			{
				PlayerPatcher.LocalPlayer.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0);
			}
			InsanitySoundManager.Instance.PlayStinger();
			((Component)this).gameObject.SetActive(false);
		}

		private void OnEnable()
		{
			PlayerPatcher.OnInteractWithFakeItem += Interaction;
		}

		private void OnDisable()
		{
			PlayerPatcher.OnInteractWithFakeItem -= Interaction;
		}
	}
	public enum HallucinationSpawnType
	{
		NotLooking,
		Visible
	}
	internal class InsanityRemasteredAI : MonoBehaviour
	{
		protected float duration = 30f;

		private float agentStoppingDistance = 3f;

		private float durationTimer;

		private bool notSeenYet = true;

		protected bool wanderSpot;

		private bool isSetUp;

		public HallucinationType hallucinationType;

		public HallucinationSpawnType hallucinationSpawnType;

		protected AudioSource soundSource;

		protected AudioClip[] sound;

		protected GameObject[] aiNodes;

		protected Animator hallucinationAnimator;

		protected NavMeshAgent agent;

		protected PlayerControllerB LocalPlayer => GameNetworkManager.Instance.localPlayerController;

		public static event Action OnFailedToSpawn;

		public static event Action<bool> OnHallucinationEnded;

		public virtual void Start()
		{
			SetupVariables();
		}

		public virtual void Spawn()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			LoadAINodes();
			Vector3 val = FindSpawnPosition();
			_ = val != Vector3.zero;
			((Component)this).transform.position = val;
			wanderSpot = false;
			notSeenYet = true;
			((Behaviour)agent).enabled = true;
		}

		public virtual bool HasLineOfSightToPosition(Transform eye, Vector3 pos, float width = 45f, int range = 60, float proximityAwareness = -1f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			if (Vector3.Distance(eye.position, pos) < (float)range && !Physics.Linecast(eye.position, pos, StartOfRound.Instance.collidersAndRoomMaskAndDefault))
			{
				Vector3 val = pos - eye.position;
				if (Vector3.Angle(eye.forward, val) < width || Vector3.Distance(((Component)this).transform.position, pos) < proximityAwareness)
				{
					return true;
				}
			}
			return false;
		}

		public virtual void LookingAtHallucination()
		{
		}

		public virtual void LookAtHallucinationFirstTime()
		{
			notSeenYet = false;
			LocalPlayer.JumpToFearLevel(0.5f, true);
		}

		public virtual void FinishHallucination(bool touched)
		{
			if (touched)
			{
				LocalPlayer.JumpToFearLevel(1f, true);
				if (Random.Range(0f, 1f) < 0.4f)
				{
					InsanitySoundManager.Instance.PlayJumpscare();
				}
			}
			else
			{
				LocalPlayer.insanityLevel = Mathf.Max(LocalPlayer.insanityLevel - 5f, 0f);
			}
			InsanityRemasteredAI.OnHallucinationEnded?.Invoke(touched);
			PoolForLater();
		}

		public virtual void Wander()
		{
			//IL_0058: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!wanderSpot)
			{
				agent.SetDestination(RoundManager.Instance.GetRandomNavMeshPositionInRadius(aiNodes[Random.Range(0, aiNodes.Length)].transform.position, 12f, default(NavMeshHit)));
				wanderSpot = true;
			}
			if (Vector3.Distance(((Component)this).transform.position, agent.destination) <= agentStoppingDistance)
			{
				PoolForLater();
				InsanityRemasteredAI.OnHallucinationEnded?.Invoke(obj: false);
			}
		}

		public virtual void TimerTick()
		{
			durationTimer += Time.deltaTime;
			if (durationTimer > duration)
			{
				durationTimer = 0f;
				FinishHallucination(touched: false);
			}
		}

		public virtual void ChasePlayer()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			TimerTick();
			if (Vector3.Distance(((Component)this).transform.position, ((Component)LocalPlayer).transform.position) <= agentStoppingDistance)
			{
				FinishHallucination(touched: true);
			}
			agent.SetDestination(((Component)LocalPlayer).transform.position);
		}

		public virtual void PoolForLater()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			((Behaviour)agent).enabled = false;
			((Component)this).transform.position = Vector3.zero;
			((Component)this).gameObject.SetActive(false);
		}

		private void LoadAINodes()
		{
		}

		public virtual void Update()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (LocalPlayer.HasLineOfSightToPosition(((Component)this).transform.position, 45f, 60, -1f))
			{
				if (notSeenYet)
				{
					LookAtHallucinationFirstTime();
				}
				PlayerPatcher.lookingAtModelHallucination = true;
			}
			else
			{
				PlayerPatcher.lookingAtModelHallucination = false;
			}
		}

		public virtual void SetupVariables()
		{
			if (!isSetUp)
			{
				aiNodes = GameObject.FindGameObjectsWithTag("AINode");
				agent = ((Component)this).GetComponent<NavMeshAgent>();
				hallucinationAnimator = ((Component)this).GetComponentInChildren<Animator>();
				soundSource = ((Component)this).gameObject.AddComponent<AudioSource>();
				soundSource.spatialBlend = 1f;
				agent.angularSpeed = float.PositiveInfinity;
				agent.speed = 3f;
				agent.stoppingDistance = agentStoppingDistance;
				agent.areaMask = StartOfRound.Instance.walkableSurfacesMask;
				isSetUp = true;
			}
		}

		private Vector3 FindSpawnPosition()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			if (hallucinationSpawnType == HallucinationSpawnType.NotLooking)
			{
				for (int i = 0; i < aiNodes.Length; i++)
				{
					if (!Physics.Linecast(((Component)LocalPlayer.gameplayCamera).transform.position, aiNodes[i].transform.position, StartOfRound.Instance.collidersAndRoomMaskAndDefault) && !LocalPlayer.HasLineOfSightToPosition(aiNodes[i].transform.position, 45f, 20, 8f))
					{
						return aiNodes[i].transform.position;
					}
				}
			}
			return Vector3.zero;
		}

		private void OnEnable()
		{
			if (isSetUp)
			{
				Spawn();
				return;
			}
			SetupVariables();
			isSetUp = true;
		}
	}
	internal class PlayerHallucination : InsanityRemasteredAI
	{
		private float stareTimer = 5f;

		private float waitTimeForNewWander = 5f;

		private float wanderTimer;

		private float stareDuration;

		private float rotationSpeed = 0.95f;

		private float footstepDistance = 1.5f;

		private int minWanderPoints = 3;

		private int maxWanderPoints = 5;

		private int currentFootstepSurfaceIndex;

		private List<Vector3> wanderPositions = new List<Vector3>();

		private Vector3 lastStepPosition;

		private AudioSource footstepSource;

		private bool spoken;

		private bool seenPlayer;

		public static SkinnedMeshRenderer suitRenderer;

		private void StopAndStare()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			soundSource.Stop();
			seenPlayer = true;
			agent.isStopped = true;
			hallucinationAnimator.SetBool("Walking", false);
			Stare(((Component)base.LocalPlayer).transform.position);
			if (SkinwalkerModIntegration.IsInstalled && InsanityGameManager.AreOtherPlayersConnected && !spoken)
			{
				soundSource.PlayOneShot(SkinwalkerModIntegration.GetRandomClip());
				spoken = true;
			}
			stareDuration += Time.deltaTime;
			if (stareDuration > stareTimer)
			{
				agent.isStopped = false;
				((Behaviour)hallucinationAnimator).enabled = true;
				hallucinationAnimator.SetBool("Walking", true);
				hallucinationType = HallucinationType.Approaching;
			}
		}

		private void Stare(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			Quaternion val = Quaternion.LookRotation(position - ((Component)this).transform.position);
			((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, val, rotationSpeed * Time.deltaTime);
		}

		private void GenerateNewDestination()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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)
			hallucinationAnimator.SetBool("Walking", true);
			Vector3 val = wanderPositions[Random.Range(0, wanderPositions.Count)];
			wanderPositions.Remove(val);
			agent.SetDestination(val);
			agent.isStopped = false;
			wanderSpot = true;
		}

		private void ReachDestination()
		{
			if (wanderPositions.Count == 0)
			{
				FinishHallucination(touched: false);
			}
			hallucinationAnimator.SetBool("Walking", false);
			agent.isStopped = true;
			wanderTimer += Time.deltaTime;
			if (wanderTimer > waitTimeForNewWander)
			{
				wanderTimer = 0f;
				wanderSpot = false;
			}
		}

		private void GenerateWanderPoints()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (wanderPositions.Count > 0)
			{
				wanderPositions.Clear();
			}
			for (int i = 0; i < Random.Range(minWanderPoints, maxWanderPoints); i++)
			{
				wanderPositions.Add(RoundManager.Instance.GetRandomNavMeshPositionInRadius(((Component)this).transform.position, 20f, default(NavMeshHit)));
			}
		}

		private void PlayFootstepSound()
		{
			GetCurrentMaterialStandingOn();
			int num = Random.Range(0, StartOfRound.Instance.footstepSurfaces[currentFootstepSurfaceIndex].clips.Length);
			footstepSource.pitch = Random.Range(0.93f, 1.07f);
			footstepSource.PlayOneShot(StartOfRound.Instance.footstepSurfaces[currentFootstepSurfaceIndex].clips[num], 5.5f);
		}

		private void GetCurrentMaterialStandingOn()
		{
			//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)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(new Ray(((Component)this).transform.position + Vector3.up, -Vector3.up), ref val, 6f, StartOfRound.Instance.walkableSurfacesMask, (QueryTriggerInteraction)1) || ((Component)((RaycastHit)(ref val)).collider).CompareTag(StartOfRound.Instance.footstepSurfaces[currentFootstepSurfaceIndex].surfaceTag))
			{
				return;
			}
			for (int i = 0; i < StartOfRound.Instance.footstepSurfaces.Length; i++)
			{
				if (((Component)((RaycastHit)(ref val)).collider).CompareTag(StartOfRound.Instance.footstepSurfaces[i].surfaceTag))
				{
					currentFootstepSurfaceIndex = i;
					break;
				}
			}
		}

		private void Footstep()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (Vector3.Distance(((Component)this).transform.position, lastStepPosition) > footstepDistance)
			{
				lastStepPosition = ((Component)this).transform.position;
				PlayFootstepSound();
			}
		}

		private int GetRandomPlayerSuitID()
		{
			PlayerControllerB val;
			do
			{
				val = StartOfRound.Instance.allPlayerScripts[Random.Range(0, StartOfRound.Instance.allPlayerScripts.Length)];
			}
			while (!val.isPlayerControlled);
			return val.currentSuitID;
		}

		private void SetSuit(int id)
		{
			Material suitMaterial = StartOfRound.Instance.unlockablesList.unlockables[id].suitMaterial;
			((Renderer)suitRenderer).material = suitMaterial;
		}

		public override void Start()
		{
			base.Start();
			sound = InsanityRemasteredContent.PlayerHallucinationSounds;
			hallucinationAnimator.runtimeAnimatorController = StartOfRound.Instance.localClientAnimatorController;
			footstepSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			footstepSource.spatialBlend = 1f;
		}

		public override void Update()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			base.Update();
			if (hallucinationType == HallucinationType.Wandering)
			{
				if (HasLineOfSightToPosition(((Component)this).transform, ((Component)base.LocalPlayer).transform.position, 45f, 45) || Vector3.Distance(((Component)this).transform.position, ((Component)base.LocalPlayer).transform.position) < 3f || seenPlayer)
				{
					StopAndStare();
				}
				else
				{
					Wander();
				}
			}
			else if (hallucinationType == HallucinationType.Approaching)
			{
				ChasePlayer();
			}
			if (hallucinationType == HallucinationType.Staring)
			{
				Stare(((Component)base.LocalPlayer).transform.position);
				TimerTick();
			}
			Footstep();
		}

		public override void LookAtHallucinationFirstTime()
		{
			base.LookAtHallucinationFirstTime();
		}

		public override void FinishHallucination(bool touched)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (touched)
			{
				float num = Random.Range(0f, 1f);
				if (num < 0.3f)
				{
					base.LocalPlayer.DamagePlayer(Random.Range(2, 16), false, true, (CauseOfDeath)5, 0, false, default(Vector3));
					PlayerPatcher.LocalPlayer.DropBlood(default(Vector3), true, false);
					base.FinishHallucination(touched);
					return;
				}
				if (num < 0.6f)
				{
					HallucinationManager.Instance.PanicAttackSymptom(canKill: true);
				}
				base.FinishHallucination(touched);
			}
			else
			{
				base.FinishHallucination(touched);
			}
		}

		public override void Wander()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (wanderPositions.Count != 0 && !wanderSpot)
			{
				GenerateNewDestination();
			}
			if (Vector3.Distance(((Component)this).transform.position, agent.destination) <= agent.stoppingDistance && wanderSpot)
			{
				ReachDestination();
			}
		}

		public override void Spawn()
		{
			base.Spawn();
			seenPlayer = false;
			SetSuit(GetRandomPlayerSuitID());
			hallucinationType = HallucinationType.Staring;
			if (PlayerPatcher.CurrentInsanityLevel >= InsanityLevel.Medium)
			{
				GenerateWanderPoints();
				hallucinationType = HallucinationType.Wandering;
			}
			if (SkinwalkerModIntegration.IsInstalled && InsanityGameManager.AreOtherPlayersConnected && Random.Range(0f, 1f) < 0.5f)
			{
				soundSource.clip = SkinwalkerModIntegration.GetRandomClip();
			}
			else
			{
				soundSource.clip = InsanitySoundManager.Instance.LoadFakePlayerSound();
			}
			if (Random.Range(0f, 1f) < 0.7f)
			{
				HUDManager.Instance.DisplayTip("", InsanityRemasteredConfiguration.tipMessageTexts[0], true, false, "LC_Tip1");
			}
			spoken = false;
			soundSource.Play();
			hallucinationAnimator.SetBool("Walking", false);
			stareDuration = 0f;
		}

		public override void SetupVariables()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			base.SetupVariables();
			agent.obstacleAvoidanceType = (ObstacleAvoidanceType)0;
			suitRenderer = ((Component)this).GetComponentInChildren<SkinnedMeshRenderer>(false);
			duration = 30f;
			hallucinationAnimator.runtimeAnimatorController = StartOfRound.Instance.localClientAnimatorController;
			hallucinationSpawnType = HallucinationSpawnType.NotLooking;
			lastStepPosition = ((Component)this).transform.position;
		}
	}
}
namespace InsanityRemastered.General
{
	public class HallucinationID
	{
		public const string Observer = "Observer";

		public const string CrypticStatus = "CrypticStatus";

		public const string Auditory = "Auditory";

		public const string CrypticMessage = "CrypticMessage";

		public const string FakeItem = "FakeItem";

		public const string FakePlayer = "FakePlayer";

		public const string LightsOff = "LightsOff";
	}
	internal class HallucinationManager : MonoBehaviour
	{
		public static HallucinationManager Instance;

		private float droneRNGTimer;

		private float droneRNGFrequency = 60f;

		private float hallucinationRNGTimer;

		private float hallucinationRNGFrequency = 2000f;

		private float panicAttackLevel;

		public static bool slowness;

		public static bool reduceVision;

		private readonly Dictionary<string, InsanityLevel> hallucinations = new Dictionary<string, InsanityLevel>
		{
			{
				"Auditory",
				InsanityLevel.Low
			},
			{
				"CrypticStatus",
				InsanityLevel.Low
			},
			{
				"CrypticMessage",
				InsanityLevel.Low
			},
			{
				"FakePlayer",
				InsanityLevel.Medium
			},
			{
				"FakeItem",
				InsanityLevel.Medium
			},
			{
				"LightsOff",
				InsanityLevel.High
			}
		};

		private PlayerControllerB LocalPlayer => GameNetworkManager.Instance.localPlayerController;

		private InsanityLevel InsanityLevel => PlayerPatcher.CurrentInsanityLevel;

		public float PanicAttackLevel
		{
			get
			{
				return panicAttackLevel;
			}
			set
			{
				panicAttackLevel = value;
			}
		}

		public Dictionary<string, InsanityLevel> Hallucinations => hallucinations;

		public static event Action<bool> OnPowerHallucination;

		public static event Action OnPlayerHallucinationStarted;

		public static event Action OnSpawnFakeItem;

		public static event Action OnSoundPlayed;

		public static event Action OnSanityRecovered;

		public static event Action OnExperiencePanicAttack;

		public static event Action OnUIHallucination;

		private void Start()
		{
			hallucinationRNGFrequency *= InsanityRemasteredConfiguration.hallucinationRNGMultiplier;
		}

		private void Awake()
		{
			Instance = this;
		}

		private void Update()
		{
			if (!LocalPlayer.isPlayerDead && LocalPlayer.isPlayerControlled && LocalPlayer.isInsideFactory)
			{
				if (LocalPlayer.insanityLevel < 20f)
				{
					hallucinationRNGTimer += Time.deltaTime * 20f;
				}
				else
				{
					hallucinationRNGTimer += Time.deltaTime * LocalPlayer.insanityLevel;
				}
				if (hallucinationRNGTimer > hallucinationRNGFrequency)
				{
					hallucinationRNGTimer = 0f;
					if (InsanityRemasteredConfiguration.logDebugVariables)
					{
						InsanityRemasteredLogger.LogError("hallucinationRNGTimer = 0f");
					}
					if (Random.Range(0f, 300f) < LocalPlayer.insanityLevel + 100f)
					{
						Hallucinate(GetRandomHallucination());
					}
				}
				if (PlayerPatcher.CurrentInsanityLevel >= InsanityLevel.High)
				{
					droneRNGTimer += Time.deltaTime;
					if (droneRNGTimer > droneRNGFrequency)
					{
						droneRNGTimer = 0f;
						if (Random.Range(0f, 1f) < 0.4f)
						{
							InsanitySoundManager.Instance.PlayDrone();
							if (PlayerPatcher.CurrentInsanityLevel == InsanityLevel.Max)
							{
								PanicAttackSymptom();
							}
						}
					}
				}
			}
			if (GameNetworkManager.Instance.gameHasStarted)
			{
				AdjustPanic();
			}
			else
			{
				AdjustPanic(reset: true);
			}
			if (InsanityRemasteredConfiguration.logDebugVariables)
			{
				if (InsanityRemasteredLogger.logTimer < 10f)
				{
					InsanityRemasteredLogger.logTimer += Time.deltaTime;
					return;
				}
				InsanityRemasteredLogger.logTimer = 0f;
				InsanityRemasteredLogger.LogVariables(new string[9] { "insanitySpeedMultiplier", "insanityLevel", "panicAttackLevel", "CurrentInsanityLevel", "hallucinationRNGTimer", "isPlayerAlone", "IsNearLightSource", "connectedPlayersAmount", "PlayersConnected" }, new object[9]
				{
					LocalPlayer.insanitySpeedMultiplier,
					LocalPlayer.insanityLevel,
					panicAttackLevel,
					PlayerPatcher.CurrentInsanityLevel,
					hallucinationRNGTimer,
					LocalPlayer.isPlayerAlone,
					InsanityGameManager.Instance.IsNearLightSource,
					StartOfRound.Instance.connectedPlayersAmount,
					PlayerPatcher.PlayersConnected
				});
			}
		}

		public void AdjustPanic(bool reset = false)
		{
			if (!InsanityRemasteredConfiguration.panicAttacksEnabled)
			{
				return;
			}
			if (reset)
			{
				panicAttackLevel = 0f;
				SoundManager.Instance.SetDiageticMixerSnapshot(0, 1f);
				HallucinationManager.OnSanityRecovered?.Invoke();
			}
			else if (!LocalPlayer.isInsideFactory || !LocalPlayer.isPlayerAlone)
			{
				panicAttackLevel = Mathf.MoveTowards(panicAttackLevel, 0f, 0.25f * Time.deltaTime);
				if (InsanityRemasteredConfiguration.panicAttackFXEnabled)
				{
					HUDManager.Instance.insanityScreenFilter.weight = Mathf.MoveTowards(HUDManager.Instance.insanityScreenFilter.weight, 0f, Time.deltaTime);
					SoundManager.Instance.SetDiageticMixerSnapshot(0, 16f);
				}
			}
			else if (PlayerPatcher.CurrentInsanityLevel >= InsanityLevel.High && !InsanityGameManager.Instance.IsNearLightSource)
			{
				panicAttackLevel = Mathf.MoveTowards(panicAttackLevel, 1f, 0.5f * Time.deltaTime);
				if (InsanityRemasteredConfiguration.panicAttackFXEnabled)
				{
					HUDManager.Instance.insanityScreenFilter.weight = Mathf.MoveTowards(HUDManager.Instance.insanityScreenFilter.weight, 0.5f, Time.deltaTime);
					SoundManager.Instance.SetDiageticMixerSnapshot(1, 64f);
				}
			}
			if (panicAttackLevel == 0f)
			{
				slowness = false;
				reduceVision = false;
			}
		}

		public void PanicAttackSymptom(bool canKill = false)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			LocalPlayer.JumpToFearLevel(0.6f, true);
			if (!InsanityRemasteredConfiguration.panicAttacksEnabled)
			{
				return;
			}
			InsanityRemasteredLogger.Log("Applying panic attack symptom.");
			if (PanicAttackLevel < 0.9f)
			{
				panicAttackLevel = 0.9f;
			}
			if (InsanityRemasteredConfiguration.panicAttackDebuffsEnabled)
			{
				switch (Random.Range(0, 6))
				{
				case 1:
				case 2:
					slowness = true;
					break;
				case 3:
				case 4:
					reduceVision = true;
					break;
				case 5:
					if (InsanityRemasteredConfiguration.panicAttackDeathsEnabled && canKill)
					{
						LocalPlayer.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0);
						break;
					}
					slowness = true;
					reduceVision = true;
					break;
				}
			}
			if (InsanityRemasteredConfiguration.sanityRemindersEnabled)
			{
				HUDManager.Instance.DisplayTip("WARNING!", "Heartrate is at dangerous levels. Please seek help immediately.", true, false, "LC_Tip1");
			}
			HallucinationManager.OnExperiencePanicAttack?.Invoke();
		}

		public void Hallucinate(string id)
		{
			InsanityRemasteredLogger.Log("Performing hallucination with ID: " + id);
			switch (id)
			{
			case "CrypticStatus":
				HallucinateStatusEffect();
				break;
			case "CrypticMessage":
				HallucinateTipMessage();
				break;
			case "FakePlayer":
				HallucinatePlayerModel(InsanityGameManager.Instance.currentHallucinationModel);
				break;
			case "Auditory":
				HallucinateSound();
				break;
			case "FakeItem":
				HallucinateFakeItem();
				break;
			case "LightsOff":
				HallucinateLightsOff();
				break;
			default:
				InsanityRemasteredLogger.LogWarning("No such hallucination with ID: " + id);
				break;
			}
		}

		public string GetRandomHallucination()
		{
			KeyValuePair<string, InsanityLevel> keyValuePair;
			do
			{
				keyValuePair = hallucinations.ElementAt(Random.Range(0, hallucinations.Count()));
			}
			while (keyValuePair.Value > InsanityLevel);
			return keyValuePair.Key;
		}

		public string GetRandomHallucination(string excludedHallucination)
		{
			KeyValuePair<string, InsanityLevel> keyValuePair;
			do
			{
				keyValuePair = hallucinations.ElementAt(Random.Range(0, hallucinations.Count()));
			}
			while (keyValuePair.Value > InsanityLevel || keyValuePair.Key.Equals(excludedHallucination));
			return keyValuePair.Key;
		}

		private void HallucinateStatusEffect()
		{
			if (!InsanityRemasteredConfiguration.messageHallucinationsEnabled)
			{
				return;
			}
			int num = Random.Range(0, InsanityRemasteredConfiguration.statusEffectTexts.Length);
			string text = InsanityRemasteredConfiguration.statusEffectTexts[num];
			HUDManager.Instance.DisplayStatusEffect(text);
			if (Random.Range(0f, 100f) < 20f + LocalPlayer.insanityLevel / 2f)
			{
				switch (num)
				{
				case 0:
				case 1:
					PanicAttackSymptom();
					break;
				case 2:
				case 4:
					Hallucinate("FakePlayer");
					break;
				case 3:
					Hallucinate("LightsOff");
					break;
				}
			}
			HallucinationManager.OnUIHallucination?.Invoke();
		}

		private void HallucinateTipMessage()
		{
			if (!InsanityRemasteredConfiguration.messageHallucinationsEnabled)
			{
				return;
			}
			int num = Random.Range(0, InsanityRemasteredConfiguration.tipMessageTexts.Length);
			string text = InsanityRemasteredConfiguration.tipMessageTexts[num];
			HUDManager.Instance.DisplayTip("", text, true, false, "LC_Tip1");
			HallucinationManager.OnUIHallucination?.Invoke();
			if (Random.Range(0f, 100f) < 10f + LocalPlayer.insanityLevel / 4f)
			{
				switch (num)
				{
				case 1:
				case 5:
					Hallucinate("FakePlayer");
					break;
				case 6:
					Hallucinate("FakeItem");
					break;
				case 7:
					Hallucinate("Auditory");
					break;
				case 2:
				case 3:
				case 4:
					break;
				}
			}
		}

		private void HallucinateLightsOff(bool reset = false)
		{
			if (!InsanityRemasteredConfiguration.lightsOffEventEnabled || RoundManager.Instance.powerOffPermanently)
			{
				return;
			}
			if (reset && InsanityGameManager.Instance.LightsOff)
			{
				foreach (Animator bunkerLightsAnimator in InsanityGameManager.Instance.BunkerLightsAnimators)
				{
					bunkerLightsAnimator.SetBool("on", true);
				}
				HallucinationManager.OnPowerHallucination?.Invoke(obj: true);
			}
			else
			{
				if (reset || InsanityGameManager.Instance.LightsOff)
				{
					return;
				}
				foreach (Animator bunkerLightsAnimator2 in InsanityGameManager.Instance.BunkerLightsAnimators)
				{
					bunkerLightsAnimator2.SetBool("on", false);
				}
				PlayerPatcher.LocalPlayer.JumpToFearLevel(0.4f, true);
				HallucinationManager.OnPowerHallucination?.Invoke(obj: false);
			}
		}

		public void ResetLightsOff()
		{
			HallucinateLightsOff(reset: true);
		}

		private void HallucinatePlayerModel(GameObject model)
		{
			if (InsanityRemasteredConfiguration.modelHallucinationsEnabled)
			{
				if (!model.activeInHierarchy)
				{
					model.SetActive(true);
				}
				HallucinationManager.OnPlayerHallucinationStarted?.Invoke();
			}
		}

		private void HallucinateSound()
		{
			if (InsanityRemasteredConfiguration.auditoryHallucinationsEnabled)
			{
				InsanitySoundManager.Instance.PlayHallucinationSound();
				HallucinationManager.OnSoundPlayed?.Invoke();
			}
		}

		private void HallucinateFakeItem()
		{
			//IL_0048: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			if (InsanityRemasteredConfiguration.itemHallucinationsEnabled)
			{
				SpawnableItemWithRarity val = RoundManager.Instance.currentLevel.spawnableScrap[Random.Range(0, RoundManager.Instance.currentLevel.spawnableScrap.Count)];
				Vector3 val2 = RoundManager.Instance.GetRandomNavMeshPositionInRadiusSpherical(((Component)PlayerPatcher.LocalPlayer).transform.position, 10f, default(NavMeshHit)) + Vector3.up * val.spawnableItem.verticalOffset;
				GameObject obj = Object.Instantiate<GameObject>(val.spawnableItem.spawnPrefab, val2, Quaternion.identity);
				obj.GetComponent<GrabbableObject>().SetScrapValue(Random.Range(val.spawnableItem.minValue, val.spawnableItem.maxValue + 50));
				obj.AddComponent<FakeItem>();
				HallucinationManager.OnSpawnFakeItem?.Invoke();
			}
		}
	}
	internal class InsanityGameManager : MonoBehaviour
	{
		public static InsanityGameManager Instance;

		private List<Light> bunkerLights = new List<Light>();

		private List<Animator> bunkerLightsAnimators = new List<Animator>();

		private float deletionTimer;

		private float deletionFrequency = 10f;

		public GameObject currentHallucinationModel;

		private PlayerControllerB LocalPlayer => GameNetworkManager.Instance.localPlayerController;

		public static DungeonFlow MapFlow => RoundManager.Instance.dungeonGenerator.Generator.DungeonFlow;

		public static bool AreOtherPlayersConnected => StartOfRound.Instance.connectedPlayersAmount > 0;

		public bool IsNearOtherPlayers => NearOtherPlayers();

		public bool IsNearLightSource => NearLightSource();

		public bool IsHearingPlayersThroughWalkie => PlayerIsHearingOthersThroughWalkieTalkie();

		public bool IsTalking => PlayerTalking();

		public bool LightsOff { get; private set; }

		public List<Light> BunkerLights => bunkerLights;

		public List<Animator> BunkerLightsAnimators => bunkerLightsAnimators;

		private void Awake()
		{
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			GameEvents.OnGameEnd += OnRoundEnd;
			GameEvents.OnShipLanded += GameEvents_OnShipLanded;
			GameEvents.OnPlayerDied += GameEvents_OnPlayerDied;
			GameEvents.OnEnterOrLeaveFacility += OnEnterOrLeaveFacility;
			HallucinationManager.OnPowerHallucination += PowerHallucination;
			SceneManager.sceneLoaded += SceneLoaded;
		}

		private void GameEvents_OnShipLanded()
		{
			CacheLights();
		}

		private void Update()
		{
			if (InsanityRemasteredConfiguration.useExperimentalSkinwalkerVersion && SkinwalkerModIntegration.IsInstalled)
			{
				deletionTimer += Time.deltaTime;
				if (deletionTimer > deletionFrequency)
				{
					deletionTimer = 0f;
					SkinwalkerModIntegration.ClearRecordings();
				}
			}
			if (GameNetworkManager.Instance.gameHasStarted && RoundManager.Instance.powerOffPermanently)
			{
				LightsOff = true;
			}
		}

		private void PowerHallucination(bool on)
		{
			LightsOff = !on;
		}

		private void SceneLoaded(Scene scene, LoadSceneMode arg1)
		{
			if (((Scene)(ref scene)).name == SceneNames.SampleSceneRelay.ToString())
			{
				SavePlayerModel();
				((Behaviour)HallucinationManager.Instance).enabled = true;
			}
			else if (((Scene)(ref scene)).name == SceneNames.MainMenu.ToString() || ((Scene)(ref scene)).name == SceneNames.InitSceneLaunchOptions.ToString())
			{
				((Behaviour)HallucinationManager.Instance).enabled = false;
			}
		}

		private void GameEvents_OnPlayerDied()
		{
			InsanitySoundManager.Instance.StopModSounds();
			HallucinationManager.Instance.AdjustPanic(reset: true);
			HallucinationManager.Instance.ResetLightsOff();
		}

		private void OnRoundEnd()
		{
			currentHallucinationModel.SetActive(false);
			LocalPlayer.insanityLevel = 0f;
		}

		private void OnEnterOrLeaveFacility(bool outside)
		{
			if (outside)
			{
				HallucinationManager.Instance.ResetLightsOff();
			}
		}

		private bool NearOtherPlayers(PlayerControllerB playerScript = null, float checkRadius = 16f)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)playerScript == (Object)null)
			{
				playerScript = LocalPlayer;
			}
			((Component)LocalPlayer).gameObject.layer = 0;
			bool result = Physics.CheckSphere(((Component)playerScript).transform.position, checkRadius, 8, (QueryTriggerInteraction)1);
			((Component)LocalPlayer).gameObject.layer = 3;
			return result;
		}

		private bool PlayerIsHearingOthersThroughWalkieTalkie(PlayerControllerB playerScript = null)
		{
			if ((Object)(object)playerScript == (Object)null)
			{
				playerScript = LocalPlayer;
			}
			if (!playerScript.holdingWalkieTalkie)
			{
				return false;
			}
			for (int i = 0; i < WalkieTalkie.allWalkieTalkies.Count; i++)
			{
				if (WalkieTalkie.allWalkieTalkies[i].clientIsHoldingAndSpeakingIntoThis && (Object)(object)WalkieTalkie.allWalkieTalkies[i] != (Object)/*isinst with value type is only supported in some contexts*/)
				{
					return true;
				}
			}
			return false;
		}

		private bool PlayerTalking()
		{
			VoicePlayerState obj = StartOfRound.Instance.voiceChatModule.FindPlayer(StartOfRound.Instance.voiceChatModule.LocalPlayerName);
			float num = Mathf.Clamp(obj.Amplitude, 0f, 1f);
			if (obj.IsSpeaking)
			{
				return num > 0.85f;
			}
			return false;
		}

		private bool NearLightSource(float checkRadius = 10f)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < bunkerLights.Count; i++)
			{
				if (Vector3.Distance(((Component)bunkerLights[i]).transform.position, ((Component)LocalPlayer).transform.position) < checkRadius && RoundManager.Instance.allPoweredLightsAnimators[i].GetBool("on"))
				{
					return true;
				}
			}
			return false;
		}

		private void SavePlayerModel()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(GameObject.Find("ScavengerModel"));
			foreach (Transform item in val.transform)
			{
				Transform val2 = item;
				if (((Object)val2).name == "LOD2" || ((Object)val2).name == "LOD3")
				{
					((Component)val2).gameObject.SetActive(false);
				}
				if (((Object)val2).name == "LOD1")
				{
					((Component)val2).gameObject.SetActive(true);
				}
				if (!(((Object)val2).name == "metarig"))
				{
					continue;
				}
				foreach (Transform item2 in ((Component)val2).transform)
				{
					Transform val3 = item2;
					if (((Object)val3).name == "ScavengerModelArmsOnly")
					{
						((Component)val3).gameObject.SetActive(false);
					}
					if (((Object)val3).name == "CameraContainer")
					{
						((Component)val3).gameObject.SetActive(false);
					}
				}
			}
			val.SetActive(false);
			val.AddComponent<PlayerHallucination>();
			val.AddComponent<NavMeshAgent>();
			val.GetComponent<LODGroup>().enabled = false;
			currentHallucinationModel = val;
		}

		private void CacheLights()
		{
			bunkerLights.Clear();
			bunkerLightsAnimators.Clear();
			foreach (Light allPoweredLight in RoundManager.Instance.allPoweredLights)
			{
				bunkerLights.Add(allPoweredLight);
			}
			foreach (Animator allPoweredLightsAnimator in RoundManager.Instance.allPoweredLightsAnimators)
			{
				bunkerLightsAnimators.Add(allPoweredLightsAnimator);
			}
			if (bunkerLights.Count != bunkerLightsAnimators.Count)
			{
				InsanityRemasteredLogger.LogError("The lights and light animators are not equal. Please report this bug.");
			}
		}
	}
	internal class InsanityRemasteredConfiguration
	{
		public static string[] tipMessageTexts = new string[8] { "I'm always watching.", "behind you.", "did you see that?", "Time is running out.", "You will never make it out of here.", "you are the only one alive", "The company is just using you. This is all pointless.", "You will regret that." };

		public static string[] statusEffectTexts = new string[6] { "WARNING:\n\nMultiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected. Multiple organ failures detected.", "WARNING:\n\nLife support systems compromised.\nLie down and hope it ends quickly.", "SYSTEM ERROR: SECURITY BREACH.\n\nAvoid all other crew members.", "SYSTEM ERROR: CRITICAL RADIATION EXPOSURE.\n\nImmediately discard all flashlights.", "Unknown lifeform detected nearby.", "Biological anomaly detected." };

		public static float SFXVolume { get; set; }

		public static string configPreset { get; set; }

		public static bool panicAttacksEnabled { get; set; }

		public static bool panicAttackDeathsEnabled { get; set; }

		public static bool panicAttackFXEnabled { get; set; }

		public static bool panicAttackDebuffsEnabled { get; set; }

		public static bool sanityRemindersEnabled { get; set; }

		public static int insanityMaxPlayerAmountScaling { get; set; }

		public static float sanityLossSoloReduction { get; set; }

		public static float sanityLossNearPlayersReduction { get; set; }

		public static float sanityLossLightsOffEvent { get; set; }

		public static float sanityLossLookingAtModelHallucination { get; set; }

		public static float sanityLossPanicAttack { get; set; }

		public static float sanityLossInsideFactory { get; set; }

		public static float sanityLossDarkOutside { get; set; }

		public static float sanityGainLight { get; set; }

		public static float sanityGainHearingWalkies { get; set; }

		public static float sanityGainInsideShip { get; set; }

		public static float sanityGainLightOutside { get; set; }

		public static float hallucinationRNGMultiplier { get; set; }

		public static bool messageHallucinationsEnabled { get; set; }

		public static bool itemHallucinationsEnabled { get; set; }

		public static bool modelHallucinationsEnabled { get; set; }

		public static bool lightsOffEventEnabled { get; set; }

		public static bool auditoryHallucinationsEnabled { get; set; }

		public static bool customSFXEnabled { get; set; }

		public static bool skinwalkerWalkiesEnabled { get; set; }

		public static float skinwalkerWalkiesFrequency { get; set; }

		public static bool useThunderstoreFolderPath { get; set; }

		public static bool useExperimentalSkinwalkerVersion { get; set; }

		public static bool logDebugVariables { get; set; }

		public static void Initialize(ConfigFile Config)
		{
			SFXVolume = Config.Bind<float>("Volume", "Stinger/drone volume", 0.5f, "Sets the volume of the stinger and drone sounds.\nValue Constraints: 0.0 - 1.0").Value;
			configPreset = Config.Bind<string>("General", "Configures sanity gain/loss values to", "Custom", "\"Slow\" will allow you to set your own values. \"Slow\" is the recommended preset. \"Fast\" is the alternative preset.").Value;
			panicAttacksEnabled = Config.Bind<bool>("General", "Enable panic attacks", true, "Enables panic attacks.").Value;
			panicAttackDeathsEnabled = Config.Bind<bool>("General", "Enable deaths from panic attacks", false, "Enables the possibility to die when having a panic attack.").Value;
			panicAttackFXEnabled = Config.Bind<bool>("General", "Enable panic attack effects", true, "Enables the auditory and visual effects from panic attacks.").Value;
			panicAttackDebuffsEnabled = Config.Bind<bool>("General", "Enable panic attack debuffs", true, "Enables all panic attack debuffs. (e.g. slowness, cloudy vision)").Value;
			sanityRemindersEnabled = Config.Bind<bool>("General", "Enable sanity level notifications", true, "Enables notifications as your insanity begins to increase.").Value;
			sanityLossSoloReduction = Config.Bind<float>("Sanity Loss", "Solo sanity scaling", 0.7f, "Sets the scaling of sanity loss when playing solo. \nValue Constraints: 0.1 - 1.0").Value;
			sanityLossNearPlayersReduction = Config.Bind<float>("Sanity Loss", "Reduction when near other players", 0.65f, "Multiplies the final sanity loss by this amount when near other players. Lower values reduce sanity loss.\nValue Constraints: 0.1 - 1.0").Value;
			sanityLossLightsOffEvent = Config.Bind<float>("Sanity Loss", "Sanity loss during Lights Off event", 0.11f, "Sets the sanity loss during the Lights Off event.\nValue Constraints: 0.0 - 1.0").Value;
			sanityLossLookingAtModelHallucination = Config.Bind<float>("Sanity Loss", "Sanity loss looking at a model hallucination", 0f, "Sets the sanity loss when looking at a model hallucination.\nValue Constraints: 0.0 - 1.0").Value;
			sanityLossPanicAttack = Config.Bind<float>("Sanity Loss", "Sanity loss during a panic attack", 0.22f, "Sets the sanity loss during a panic attack.\nValue Constraints: 0.0 - 1.0").Value;
			sanityLossInsideFactory = Config.Bind<float>("Sanity Loss", "Sanity loss inside the factory", 0.22f, "Sets the base sanity loss when you are inside the factory.\nValue Constraints: 0.0 - 1.0").Value;
			sanityLossDarkOutside = Config.Bind<float>("Sanity Loss", "Sanity loss outside during nighttime", 0.08f, "Sets the base sanity loss when you are outside at night.\nValue Constraints: 0.0 - 1.0").Value;
			sanityGainLight = Config.Bind<float>("Sanity Gain", "Sanity gain near light or using flashlights", 0.11f, "Sets the sanity gain when near a light source or when using a flashlight.\nValue Constraints: 0.0 - 1.0").Value;
			sanityGainHearingWalkies = Config.Bind<float>("Sanity Gain", "Sanity gain hearing walkies", 0.02f, "Sets the sanity gain when hearing other players through walkie talkies.\nValue Constraints: 0.0 - 1.0").Value;
			sanityGainInsideShip = Config.Bind<float>("Sanity Gain", "Sanity gain inside ship", 0.32f, "Sets the base sanity gain when inside the ship.\nValue Constraints: 0.0 - 1.0").Value;
			sanityGainLightOutside = Config.Bind<float>("Sanity Gain", "Sanity gain outside during daytime", 0.08f, "Sets the base sanity gain when you are outside during day.\nValue Constraints: 0.0 - 1.0").Value;
			hallucinationRNGMultiplier = Config.Bind<float>("Hallucinations", "Multiplier for hallucination RNG check", 1f, "A multiplier that affects the frequency of hallucinations. Lower values increase the frequency.\nValue Constraints: 0.1 - 4.0").Value;
			messageHallucinationsEnabled = Config.Bind<bool>("Hallucinations", "Enable message hallucinations", true, "Enables cryptic hallucination messages from the system.").Value;
			itemHallucinationsEnabled = Config.Bind<bool>("Hallucinations", "Enable item hallucinations", true, "Enables hallucinations of fake items.").Value;
			modelHallucinationsEnabled = Config.Bind<bool>("Hallucinations", "Enable model hallucinations", true, "Enables hallucinations of fake players or enemy models.").Value;
			lightsOffEventEnabled = Config.Bind<bool>("Hallucinations", "Enable Lights Off event", true, "Enables a hallucination event in which the lights are shut off.").Value;
			auditoryHallucinationsEnabled = Config.Bind<bool>("Hallucinations", "Enable auditory hallucinations", true, "Enables auditory hallucinations.").Value;
			customSFXEnabled = Config.Bind<bool>("Misc", "Enable custom SFX", true, "Use custom sound effects for auditory hallucinations.").Value;
			skinwalkerWalkiesEnabled = Config.Bind<bool>("Hallucinations", "Enable skinwalker walkies", false, "Enables walkie talkies to play skinwalker clips.").Value;
			skinwalkerWalkiesFrequency = Config.Bind<float>("Hallucinations", "Multiplier for skinwalker walkie frequency", 0.35f, "Enables walkie talkies to play skinwalker clips.\nValue Constraints: 0.1 - 1.0").Value;
			useThunderstoreFolderPath = Config.Bind<bool>("Misc", "Use Thunderstore plugin path", true, "This uses the folder path for Thunderstore plugins to load the assets.").Value;
			useExperimentalSkinwalkerVersion = Config.Bind<bool>("Misc", "Use experimental skinwalker version", false, "Allows InsanityRemastered to load the experimental version of Skinwalker.").Value;
			logDebugVariables = Config.Bind<bool>("Misc", "Log variables for debugging", false, "Logs variables intended for debugging and balancing.").Value;
		}

		public static void ValidateSettings()
		{
			if (configPreset.Equals("Slow", StringComparison.OrdinalIgnoreCase))
			{
				sanityLossNearPlayersReduction = 0.65f;
				sanityLossLightsOffEvent = 0.11f;
				sanityLossLookingAtModelHallucination = 0f;
				sanityLossPanicAttack = 0.22f;
				sanityLossInsideFactory = 0.22f;
				sanityLossDarkOutside = 0.08f;
				sanityGainLight = 0.11f;
				sanityGainHearingWalkies = 0.02f;
				sanityGainInsideShip = 0.32f;
				sanityGainLightOutside = 0.08f;
			}
			if (configPreset.Equals("Fast", StringComparison.OrdinalIgnoreCase))
			{
				sanityLossNearPlayersReduction = 0.85f;
				sanityLossLightsOffEvent = 0.15f;
				sanityLossLookingAtModelHallucination = 0.15f;
				sanityLossPanicAttack = 0.4f;
				sanityLossInsideFactory = 0.35f;
				sanityLossDarkOutside = 0.15f;
				sanityGainLight = 0.35f;
				sanityGainHearingWalkies = 0.05f;
				sanityGainInsideShip = 0.6f;
				sanityGainLightOutside = 0.3f;
			}
			SFXVolume = Math.Clamp(SFXVolume, 0f, 1f);
			sanityLossSoloReduction = Math.Clamp(sanityLossSoloReduction, 0.1f, 1f);
			sanityLossNearPlayersReduction = Math.Clamp(sanityLossNearPlayersReduction, 0.1f, 1f);
			sanityLossLightsOffEvent = Math.Clamp(sanityLossLightsOffEvent, 0f, 1f);
			sanityLossLookingAtModelHallucination = Math.Clamp(sanityLossLookingAtModelHallucination, 0f, 1f);
			sanityLossPanicAttack = Math.Clamp(sanityLossPanicAttack, 0f, 1f);
			sanityLossInsideFactory = Math.Clamp(sanityLossInsideFactory, 0f, 1f);
			sanityLossDarkOutside = Math.Clamp(sanityLossDarkOutside, 0f, 1f);
			sanityGainLight = Math.Clamp(sanityGainLight, 0f, 1f);
			sanityGainHearingWalkies = Math.Clamp(sanityGainHearingWalkies, 0f, 1f);
			sanityGainInsideShip = Math.Clamp(sanityGainInsideShip, 0f, 1f);
			sanityGainLightOutside = Math.Clamp(sanityGainLightOutside, 0f, 1f);
			hallucinationRNGMultiplier = Math.Clamp(hallucinationRNGMultiplier, 0.1f, 4f);
			skinwalkerWalkiesFrequency = Math.Clamp(skinwalkerWalkiesFrequency, 0.1f, 1f);
		}
	}
	internal class InsanitySoundManager : MonoBehaviour
	{
		public static InsanitySoundManager Instance;

		public AudioClip[] hallucinationSFX;

		public AudioClip[] drones;

		public AudioClip[] playerHallucinationSounds;

		public AudioClip[] vanillaSFX;

		public AudioClip[] stingers;

		public AudioSource hallucinationSource;

		private AudioSource droneSource;

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

		private void Start()
		{
			hallucinationSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			hallucinationSource.spatialBlend = 0f;
			droneSource = ((Component)this).gameObject.AddComponent<AudioSource>();
			droneSource.spatialBlend = 0f;
			droneSource.volume = InsanityRemasteredConfiguration.SFXVolume;
			CacheSFX();
		}

		private void CacheSFX()
		{
			vanillaSFX = InsanityRemasteredContent.LCGameSFX;
			stingers = InsanityRemasteredContent.Stingers;
			drones = InsanityRemasteredContent.Drones;
			hallucinationSFX = InsanityRemasteredContent.AuditoryHallucinations;
			playerHallucinationSounds = InsanityRemasteredContent.PlayerHallucinationSounds;
		}

		public AudioClip LoadFakePlayerSound()
		{
			int num = Random.Range(0, playerHallucinationSounds.Length);
			if (Object.op_Implicit((Object)(object)playerHallucinationSounds[num]) && ((Object)playerHallucinationSounds[num]).name != "JumpScare")
			{
				return playerHallucinationSounds[num];
			}
			return null;
		}

		public void PlayJumpscare()
		{
			AudioClip[] array = playerHallucinationSounds;
			for (int i = 0; i < array.Length; i++)
			{
				if (((Object)array[i]).name == "JumpScare")
				{
					hallucinationSource.PlayOneShot(hallucinationSource.clip, 0.7f);
				}
			}
		}

		public void PlayStinger(bool mono = true)
		{
			if (mono)
			{
				droneSource.clip = LoadStingerSound();
				droneSource.Play();
			}
		}

		public void PlayHallucinationSound()
		{
			if (SkinwalkerModIntegration.IsInstalled && StartOfRound.Instance.connectedPlayersAmount > 0 && Random.Range(0f, 1f) < 0.4f)
			{
				SoundManager.Instance.PlaySoundAroundLocalPlayer(SkinwalkerModIntegration.GetRandomClip(), 2.5f);
			}
			else
			{
				SoundManager.Instance.PlaySoundAroundLocalPlayer(LoadHallucinationSound(), 0.9f);
			}
		}

		public void PlayUISound(AudioClip sfx)
		{
			hallucinationSource.PlayOneShot(sfx, 0.8f);
		}

		public void PlayDrone()
		{
			if (!droneSource.isPlaying)
			{
				droneSource.clip = LoadDroneSound();
				droneSource.Play();
			}
		}

		public void StopModSounds()
		{
			hallucinationSource.Stop();
			droneSource.Stop();
		}

		public AudioClip LoadHallucinationSound()
		{
			if (InsanityRemasteredConfiguration.customSFXEnabled && Random.Range(0f, 1f) < 0.8f)
			{
				int num = Random.Range(0, hallucinationSFX.Length);
				if (Object.op_Implicit((Object)(object)hallucinationSFX[num]))
				{
					return hallucinationSFX[num];
				}
			}
			else
			{
				int num2 = Random.Range(0, vanillaSFX.Length);
				if (Object.op_Implicit((Object)(object)vanillaSFX[num2]))
				{
					return vanillaSFX[num2];
				}
			}
			return null;
		}

		private AudioClip LoadStingerSound()
		{
			int num = Random.Range(0, stingers.Length);
			if (Object.op_Implicit((Object)(object)stingers[num]))
			{
				return stingers[num];
			}
			return null;
		}

		private AudioClip LoadDroneSound()
		{
			int num = Random.Range(0, drones.Length);
			if (Object.op_Implicit((Object)(object)drones[num]))
			{
				return drones[num];
			}
			return null;
		}
	}
}