Decompiled source of NeverAlone v1.0.2

BepInEx/plugins/NeverAlone/Never Alone.dll

Decompiled 2 weeks 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.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using Peak;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Inversion")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Inversion")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f9d0f724-364b-47e0-bbc8-5382cf448217")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[DefaultExecutionOrder(10000)]
[BepInPlugin("com.saphir.neveraloneheartbeat", "NeverAloneHeartbeat", "1.0.0")]
public sealed class NeverAloneHeartbeat : BaseUnityPlugin
{
	private const float SafeDistance = 60f;

	private const float BaseBpm = 52f;

	private const float ScoutmasterFarBpm = 72f;

	private const float ScoutmasterNearBpm = 240f;

	private const float BaseHeartbeatVolume = 1f;

	private const float MaximumHeartbeatVolume = 2f;

	private const float BreathOutVolume = 1f;

	private const float BreathInVolume = 1f;

	private const float ScoutmasterEffectStartDistance = 50f;

	private const float ScoutmasterMaximumEffectDistance = 5f;

	private AudioSource heartbeatSource;

	private AudioSource breathOutSource;

	private AudioSource breathInSource;

	private AudioClip heartbeatClip;

	private AudioClip breathOutClip;

	private AudioClip breathInClip;

	private Scoutmaster scoutmaster;

	private Character scoutmasterCharacter;

	private float nextBeatTime;

	private float currentBpm = 52f;

	private float currentHeartbeatVolume = 1f;

	private bool hasDistanceState;

	private bool wasOutsideSafeZone;

	private bool wasGameplayActive;

	private bool mixerReady;

	private void Awake()
	{
		heartbeatSource = CreateLocalAudioSource(loop: false);
		breathOutSource = CreateLocalAudioSource(loop: true);
		breathInSource = CreateLocalAudioSource(loop: false);
		((MonoBehaviour)this).StartCoroutine(LoadAllAudio());
		nextBeatTime = Time.unscaledTime + 0.5f;
	}

	private AudioSource CreateLocalAudioSource(bool loop)
	{
		AudioSource val = ((Component)this).gameObject.AddComponent<AudioSource>();
		val.playOnAwake = false;
		val.loop = loop;
		val.spatialBlend = 0f;
		val.dopplerLevel = 0f;
		val.priority = 32;
		val.ignoreListenerPause = false;
		val.ignoreListenerVolume = false;
		val.bypassEffects = false;
		val.bypassListenerEffects = false;
		val.bypassReverbZones = true;
		val.outputAudioMixerGroup = null;
		return val;
	}

	private IEnumerator LoadAllAudio()
	{
		string heartbeatPath = FindAudioFile("Heartbeat.wav");
		string breathOutPath = FindAudioFile("breathsoundout.wav");
		string breathInPath = FindAudioFile("breathsoundin.wav");
		if (!string.IsNullOrEmpty(heartbeatPath))
		{
			yield return LoadWav(heartbeatPath, delegate(AudioClip clip)
			{
				heartbeatClip = clip;
			});
		}
		if (!string.IsNullOrEmpty(breathOutPath))
		{
			yield return LoadWav(breathOutPath, delegate(AudioClip clip)
			{
				breathOutClip = clip;
				if ((Object)(object)breathOutSource != (Object)null)
				{
					breathOutSource.clip = clip;
				}
			});
		}
		if (!string.IsNullOrEmpty(breathInPath))
		{
			yield return LoadWav(breathInPath, delegate(AudioClip clip)
			{
				breathInClip = clip;
			});
		}
	}

	private string FindAudioFile(string fileName)
	{
		string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		if (!string.IsNullOrEmpty(directoryName))
		{
			string text = Path.Combine(directoryName, fileName);
			if (File.Exists(text))
			{
				return text;
			}
		}
		string pluginPath = Paths.PluginPath;
		if (string.IsNullOrEmpty(pluginPath) || !Directory.Exists(pluginPath))
		{
			return null;
		}
		string text2 = Path.Combine(pluginPath, fileName);
		if (File.Exists(text2))
		{
			return text2;
		}
		try
		{
			string[] files = Directory.GetFiles(pluginPath, fileName, SearchOption.AllDirectories);
			if (files != null && files.Length != 0)
			{
				return files[0];
			}
		}
		catch
		{
		}
		return null;
	}

	private static IEnumerator LoadWav(string path, Action<AudioClip> onLoaded)
	{
		if (string.IsNullOrEmpty(path) || !File.Exists(path))
		{
			yield break;
		}
		string uri = new Uri(Path.GetFullPath(path)).AbsoluteUri;
		UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(uri, (AudioType)20);
		try
		{
			DownloadHandler downloadHandler = request.downloadHandler;
			DownloadHandlerAudioClip handler = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null);
			if (handler != null)
			{
				handler.streamAudio = false;
				handler.compressed = false;
			}
			yield return request.SendWebRequest();
			if ((int)request.result == 1)
			{
				AudioClip clip = DownloadHandlerAudioClip.GetContent(request);
				if ((Object)(object)clip != (Object)null)
				{
					onLoaded(clip);
				}
				yield break;
			}
		}
		finally
		{
			((IDisposable)request)?.Dispose();
		}
	}

	private void Update()
	{
		UpdateSfxMixer();
		if (!IsGameplayActive() || !mixerReady)
		{
			DisableGameplayAudio();
			return;
		}
		if (!wasGameplayActive)
		{
			wasGameplayActive = true;
			currentBpm = 52f;
			currentHeartbeatVolume = 1f;
			nextBeatTime = Time.unscaledTime + 0.25f;
			hasDistanceState = false;
			wasOutsideSafeZone = false;
		}
		CacheScoutmaster();
		UpdateDistanceAudio();
		UpdateHeartbeatState();
		PlayHeartbeatWhenReady();
	}

	private void UpdateSfxMixer()
	{
		if ((Object)(object)SFX_Player.instance == (Object)null || (Object)(object)SFX_Player.instance.defaultMixerGroup == (Object)null)
		{
			mixerReady = false;
			return;
		}
		AudioMixerGroup defaultMixerGroup = SFX_Player.instance.defaultMixerGroup;
		if ((Object)(object)heartbeatSource != (Object)null && (Object)(object)heartbeatSource.outputAudioMixerGroup != (Object)(object)defaultMixerGroup)
		{
			heartbeatSource.outputAudioMixerGroup = defaultMixerGroup;
		}
		if ((Object)(object)breathOutSource != (Object)null && (Object)(object)breathOutSource.outputAudioMixerGroup != (Object)(object)defaultMixerGroup)
		{
			breathOutSource.outputAudioMixerGroup = defaultMixerGroup;
		}
		if ((Object)(object)breathInSource != (Object)null && (Object)(object)breathInSource.outputAudioMixerGroup != (Object)(object)defaultMixerGroup)
		{
			breathInSource.outputAudioMixerGroup = defaultMixerGroup;
		}
		mixerReady = (Object)(object)heartbeatSource != (Object)null && (Object)(object)breathOutSource != (Object)null && (Object)(object)breathInSource != (Object)null && (Object)(object)heartbeatSource.outputAudioMixerGroup == (Object)(object)defaultMixerGroup && (Object)(object)breathOutSource.outputAudioMixerGroup == (Object)(object)defaultMixerGroup && (Object)(object)breathInSource.outputAudioMixerGroup == (Object)(object)defaultMixerGroup;
	}

	private bool IsGameplayActive()
	{
		if (!MapHandler.ExistsAndInitialized)
		{
			return false;
		}
		Character localCharacter = Character.localCharacter;
		return (Object)(object)localCharacter != (Object)null && localCharacter.IsPlayerControlled && (Object)(object)localCharacter.data != (Object)null && !localCharacter.data.dead;
	}

	private void UpdateDistanceAudio()
	{
		Character localCharacter = Character.localCharacter;
		float nearestPlayerDistance = GetNearestPlayerDistance(localCharacter);
		if (nearestPlayerDistance < 0f)
		{
			StopOutsideBreathing();
			hasDistanceState = false;
			wasOutsideSafeZone = false;
			return;
		}
		bool flag = nearestPlayerDistance > 60f;
		if (!hasDistanceState)
		{
			hasDistanceState = true;
			wasOutsideSafeZone = flag;
			if (flag)
			{
				StartOutsideBreathing();
			}
			return;
		}
		if (flag)
		{
			StartOutsideBreathing();
		}
		else
		{
			StopOutsideBreathing();
			if (wasOutsideSafeZone)
			{
				PlayInsideBreathingOnce();
			}
		}
		wasOutsideSafeZone = flag;
	}

	private void StartOutsideBreathing()
	{
		if (!((Object)(object)breathOutSource == (Object)null) && !((Object)(object)breathOutClip == (Object)null))
		{
			if ((Object)(object)breathOutSource.clip != (Object)(object)breathOutClip)
			{
				breathOutSource.clip = breathOutClip;
			}
			breathOutSource.volume = 1f;
			if (!breathOutSource.isPlaying)
			{
				breathOutSource.Play();
			}
		}
	}

	private void StopOutsideBreathing()
	{
		if ((Object)(object)breathOutSource != (Object)null && breathOutSource.isPlaying)
		{
			breathOutSource.Stop();
		}
	}

	private void PlayInsideBreathingOnce()
	{
		if (!((Object)(object)breathInSource == (Object)null) && !((Object)(object)breathInClip == (Object)null))
		{
			breathInSource.Stop();
			breathInSource.volume = 1f;
			breathInSource.pitch = 1f;
			breathInSource.PlayOneShot(breathInClip, 1f);
		}
	}

	private void PlayHeartbeatWhenReady()
	{
		if (!((Object)(object)heartbeatSource == (Object)null) && !((Object)(object)heartbeatClip == (Object)null) && !(Time.unscaledTime < nextBeatTime))
		{
			heartbeatSource.pitch = 1f;
			heartbeatSource.volume = 1f;
			heartbeatSource.PlayOneShot(heartbeatClip, currentHeartbeatVolume);
			float num = 60f / Mathf.Max(1f, currentBpm);
			nextBeatTime = Time.unscaledTime + num;
		}
	}

	private void UpdateHeartbeatState()
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		float num = 52f;
		float num2 = 1f;
		Character localCharacter = Character.localCharacter;
		if ((Object)(object)localCharacter != (Object)null && (Object)(object)scoutmaster != (Object)null && (Object)(object)scoutmasterCharacter != (Object)null && (Object)(object)scoutmaster.currentTarget == (Object)(object)localCharacter)
		{
			float num3 = Vector3.Distance(scoutmasterCharacter.Center, localCharacter.Center);
			float num4 = Mathf.InverseLerp(50f, 5f, num3);
			num4 = Mathf.Pow(num4, 1.18f);
			num = Mathf.Lerp(72f, 240f, num4);
			num2 = Mathf.Lerp(1.2f, 2f, num4);
		}
		currentBpm = Mathf.MoveTowards(currentBpm, num, Time.unscaledDeltaTime * 95f);
		currentHeartbeatVolume = Mathf.MoveTowards(currentHeartbeatVolume, num2, Time.unscaledDeltaTime * 1.2f);
	}

	private void CacheScoutmaster()
	{
		Scoutmaster val = default(Scoutmaster);
		if ((Object)(object)scoutmaster != (Object)null)
		{
			if ((Object)(object)scoutmasterCharacter == (Object)null)
			{
				scoutmasterCharacter = ((Component)scoutmaster).GetComponent<Character>();
			}
		}
		else if (Scoutmaster.GetPrimaryScoutmaster(ref val) && (Object)(object)val != (Object)null)
		{
			scoutmaster = val;
			scoutmasterCharacter = ((Component)scoutmaster).GetComponent<Character>();
		}
		else
		{
			scoutmaster = null;
			scoutmasterCharacter = null;
		}
	}

	private static float GetNearestPlayerDistance(Character source)
	{
		//IL_0054: 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)
		if (!IsValidPlayer(source))
		{
			return -1f;
		}
		float num = float.MaxValue;
		bool flag = false;
		for (int i = 0; i < Character.AllCharacters.Count; i++)
		{
			Character val = Character.AllCharacters[i];
			if (IsValidPlayer(val) && !((Object)(object)val == (Object)(object)source))
			{
				float num2 = Vector3.Distance(source.Center, val.Center);
				if (num2 < num)
				{
					num = num2;
				}
				flag = true;
			}
		}
		return flag ? num : (-1f);
	}

	private static bool IsValidPlayer(Character character)
	{
		return (Object)(object)character != (Object)null && character.IsPlayerControlled && (Object)(object)character.data != (Object)null && !character.data.dead && !character.data.fullyPassedOut;
	}

	private void DisableGameplayAudio()
	{
		if ((Object)(object)heartbeatSource != (Object)null)
		{
			heartbeatSource.Stop();
		}
		StopOutsideBreathing();
		if ((Object)(object)breathInSource != (Object)null)
		{
			breathInSource.Stop();
		}
		currentBpm = 52f;
		currentHeartbeatVolume = 1f;
		nextBeatTime = Time.unscaledTime + 0.5f;
		hasDistanceState = false;
		wasOutsideSafeZone = false;
		wasGameplayActive = false;
		scoutmaster = null;
		scoutmasterCharacter = null;
	}

	private void OnDisable()
	{
		DisableGameplayAudio();
	}
}
[BepInPlugin("com.saphir.neveralonecompass", "NeverAloneCompass", "1.0.0")]
public sealed class Compass : BaseUnityPlugin
{
	private const ushort CompassItemId = 23;

	private const string CompassPrefabName = "Compass";

	private readonly HashSet<Segment> spawnedSegments = new HashSet<Segment>();

	private Segment lastObservedSegment = (Segment)6;

	private Segment pendingSegment = (Segment)6;

	private void Update()
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Invalid comparison between Unknown and I4
		//IL_0021: 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_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Invalid comparison between Unknown and I4
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Invalid comparison between Unknown and I4
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || !MapHandler.ExistsAndInitialized)
		{
			lastObservedSegment = (Segment)6;
			pendingSegment = (Segment)6;
			spawnedSegments.Clear();
			return;
		}
		Segment currentSegmentNumber = MapHandler.CurrentSegmentNumber;
		if ((int)lastObservedSegment == 6)
		{
			lastObservedSegment = currentSegmentNumber;
			if ((int)currentSegmentNumber != 0 && (int)currentSegmentNumber != 6 && !spawnedSegments.Contains(currentSegmentNumber))
			{
				BeginSpawn(currentSegmentNumber);
			}
		}
		else if (currentSegmentNumber != lastObservedSegment)
		{
			lastObservedSegment = currentSegmentNumber;
			if ((int)currentSegmentNumber != 0 && (int)currentSegmentNumber != 6 && !spawnedSegments.Contains(currentSegmentNumber))
			{
				BeginSpawn(currentSegmentNumber);
			}
		}
	}

	private void BeginSpawn(Segment segment)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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)
		if (pendingSegment != segment)
		{
			pendingSegment = segment;
			((MonoBehaviour)this).StartCoroutine(SpawnCompassAtPreviousCampfire(segment));
		}
	}

	private IEnumerator SpawnCompassAtPreviousCampfire(Segment segment)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		Campfire previousCampfire = null;
		while (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && MapHandler.ExistsAndInitialized && MapHandler.CurrentSegmentNumber == segment)
		{
			previousCampfire = MapHandler.PreviousCampfire;
			if ((Object)(object)previousCampfire != (Object)null && ((Component)previousCampfire).gameObject.activeInHierarchy)
			{
				break;
			}
			yield return null;
		}
		if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || !MapHandler.ExistsAndInitialized || MapHandler.CurrentSegmentNumber != segment || (Object)(object)previousCampfire == (Object)null)
		{
			pendingSegment = (Segment)6;
			yield break;
		}
		Item compassPrefab = default(Item);
		if (!ItemDatabase.TryGetItem("Compass", ref compassPrefab) && !ItemDatabase.TryGetItem((ushort)23, ref compassPrefab))
		{
			pendingSegment = (Segment)6;
			yield break;
		}
		Vector3 spawnPosition = GetSpawnPosition(previousCampfire);
		Quaternion spawnRotation = Quaternion.Euler(0f, ((Component)previousCampfire).transform.eulerAngles.y, 0f);
		PhotonNetwork.InstantiateItemRoom(((Object)compassPrefab).name, spawnPosition, spawnRotation);
		spawnedSegments.Add(segment);
		pendingSegment = (Segment)6;
	}

	private static Vector3 GetSpawnPosition(Campfire campfire)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)campfire).transform;
		Vector3 val = transform.position + transform.right * 1.5f + transform.forward * 0.6f + Vector3.up * 1.5f;
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(val, Vector3.down, ref val2, 5f, -1, (QueryTriggerInteraction)1))
		{
			return ((RaycastHit)(ref val2)).point + Vector3.up * 0.25f;
		}
		return transform.position + transform.right * 1.5f + transform.forward * 0.6f + Vector3.up * 0.5f;
	}

	private void OnDisable()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		((MonoBehaviour)this).StopAllCoroutines();
		spawnedSegments.Clear();
		lastObservedSegment = (Segment)6;
		pendingSegment = (Segment)6;
	}
}
[BepInPlugin("com.saphir.gloomfog", "GloomFog", "1.0.0")]
public sealed class GloomFog : BaseUnityPlugin
{
	private static readonly int ExtraFogProperty = Shader.PropertyToID("EXTRAFOG");

	private static readonly int FogSafeZoneProperty = Shader.PropertyToID("FogSafeZone");

	private static readonly int GloomVisibilityOffsetProperty = Shader.PropertyToID("GloomVisibiltyOffset");

	private static readonly int HeightFogHeightProperty = Shader.PropertyToID("HeightFogHeight");

	private static readonly int FogTextureProperty = Shader.PropertyToID("FogTexture");

	private static readonly Color LonelyFogColor = new Color(0.38f, 0.42f, 0.41f, 1f);

	private MapHandler cachedMapHandler;

	private DayNightProfile gloomProfile;

	private FogShaderParams gloomFogShaderParams;

	private ForceFogShaderHeight gloomHeightSource;

	private void LateUpdate()
	{
		if (!MapHandler.ExistsAndInitialized || (Object)(object)DayNightManager.instance == (Object)null)
		{
			ClearCache();
			return;
		}
		MapHandler instance = Singleton<MapHandler>.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			ClearCache();
			return;
		}
		if ((Object)(object)cachedMapHandler != (Object)(object)instance || (Object)(object)gloomProfile == (Object)null)
		{
			CacheGloomSources(instance);
		}
		if (!((Object)(object)gloomProfile == (Object)null))
		{
			ApplyGloomFog();
			ApplyLonelyFogColor();
			if ((Object)(object)FogSafeZoneManager.instance == (Object)null || !((Behaviour)FogSafeZoneManager.instance).isActiveAndEnabled)
			{
				Shader.SetGlobalFloat(FogSafeZoneProperty, 0f);
				Shader.SetGlobalFloat(GloomVisibilityOffsetProperty, 0f);
			}
		}
	}

	private void CacheGloomSources(MapHandler mapHandler)
	{
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Invalid comparison between Unknown and I4
		cachedMapHandler = mapHandler;
		gloomProfile = null;
		gloomFogShaderParams = null;
		gloomHeightSource = null;
		MapSegment val = FindGloomSegment(mapHandler.segments);
		if (val == null)
		{
			val = FindGloomSegment(mapHandler.variantSegments);
		}
		if (val == null)
		{
			return;
		}
		gloomProfile = val.dayNightProfile;
		GameObject segmentParent = val.segmentParent;
		if ((Object)(object)segmentParent == (Object)null)
		{
			return;
		}
		gloomFogShaderParams = segmentParent.GetComponentInChildren<FogShaderParams>(true);
		ForceFogShaderHeight[] componentsInChildren = segmentParent.GetComponentsInChildren<ForceFogShaderHeight>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null && (int)componentsInChildren[i].fogType == 0)
			{
				gloomHeightSource = componentsInChildren[i];
				break;
			}
		}
	}

	private static MapSegment FindGloomSegment(MapSegment[] segments)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Invalid comparison between Unknown and I4
		if (segments == null)
		{
			return null;
		}
		foreach (MapSegment val in segments)
		{
			if (val != null && (int)val.biome == 8)
			{
				return val;
			}
		}
		return null;
	}

	private void ApplyGloomFog()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		float timeOfDayNormalized = DayNightManager.instance.timeOfDayNormalized;
		if (gloomProfile.fogGradient != null)
		{
			Shader.SetGlobalFloat(ExtraFogProperty, gloomProfile.fogGradient.Evaluate(timeOfDayNormalized).r);
		}
		ApplyShaderFloats(gloomProfile.globalShaderFloats);
		ApplyShaderFloats(gloomProfile.globalStaticShaderFloats);
		ApplyAnimatedShaderFloats(gloomProfile.animatedGlobalShaderFloats, timeOfDayNormalized);
		if ((Object)(object)gloomFogShaderParams != (Object)null && (Object)(object)gloomFogShaderParams.fogTexture != (Object)null)
		{
			Shader.SetGlobalTexture(FogTextureProperty, gloomFogShaderParams.fogTexture);
		}
		if ((Object)(object)gloomHeightSource != (Object)null)
		{
			Shader.SetGlobalFloat(HeightFogHeightProperty, ((Component)gloomHeightSource).transform.position.y);
		}
	}

	private static void ApplyLonelyFogColor()
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		string shaderValue = DayNightManager.instance.getShaderValue((ShaderParams)7);
		if (!string.IsNullOrEmpty(shaderValue))
		{
			Shader.SetGlobalColor(shaderValue, LonelyFogColor);
		}
	}

	private static void ApplyShaderFloats(ShaderParameters[] parameters)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		if (parameters == null || (Object)(object)DayNightManager.instance == (Object)null)
		{
			return;
		}
		foreach (ShaderParameters val in parameters)
		{
			if (val != null && IsFogFloatParameter(val.parameter))
			{
				string shaderValue = DayNightManager.instance.getShaderValue(val.parameter);
				if (!string.IsNullOrEmpty(shaderValue))
				{
					Shader.SetGlobalFloat(shaderValue, val.paramValue);
				}
			}
		}
	}

	private static void ApplyAnimatedShaderFloats(AnimatedShaderParameters[] parameters, float time)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if (parameters == null || (Object)(object)DayNightManager.instance == (Object)null)
		{
			return;
		}
		foreach (AnimatedShaderParameters val in parameters)
		{
			if (val != null && val.paramValue != null && IsFogFloatParameter(val.parameter))
			{
				string shaderValue = DayNightManager.instance.getShaderValue(val.parameter);
				if (!string.IsNullOrEmpty(shaderValue))
				{
					Shader.SetGlobalFloat(shaderValue, val.paramValue.Evaluate(time));
				}
			}
		}
	}

	private static bool IsFogFloatParameter(ShaderParams parameter)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Invalid comparison between Unknown and I4
		return (int)parameter == 3 || (int)parameter == 5 || (int)parameter == 6 || (int)parameter == 8;
	}

	private void ClearCache()
	{
		cachedMapHandler = null;
		gloomProfile = null;
		gloomFogShaderParams = null;
		gloomHeightSource = null;
	}
}
[BepInPlugin("com.saphir.scoutmasterdamage", "ScoutMasterDamage", "1.0.0")]
public sealed class ScoutMasterDamage : BaseUnityPlugin
{
	private const float OriginalScoutmasterThrowDamage = 0.3f;

	private const float AdditionalThrowDamage = 0.7f;

	private const float DamageTolerance = 0.001f;

	private Character localCharacter;

	private CharacterAfflictions localAfflictions;

	private Scoutmaster scoutmaster;

	private bool applyingAdditionalDamage;

	private void Update()
	{
		CacheLocalPlayer();
		CacheScoutmaster();
	}

	private void CacheLocalPlayer()
	{
		Character val = Character.localCharacter;
		if (!((Object)(object)val == (Object)(object)localCharacter))
		{
			UnsubscribeLocalAfflictions();
			localCharacter = val;
			if (!((Object)(object)localCharacter == (Object)null) && localCharacter.refs != null && !((Object)(object)localCharacter.refs.afflictions == (Object)null))
			{
				localAfflictions = localCharacter.refs.afflictions;
				CharacterAfflictions obj = localAfflictions;
				obj.OnAddedStatus = (Action<STATUSTYPE, float>)Delegate.Combine(obj.OnAddedStatus, new Action<STATUSTYPE, float>(OnStatusAdded));
			}
		}
	}

	private void CacheScoutmaster()
	{
		Scoutmaster val = default(Scoutmaster);
		if (Scoutmaster.GetPrimaryScoutmaster(ref val))
		{
			scoutmaster = val;
		}
		else
		{
			scoutmaster = null;
		}
	}

	private void OnStatusAdded(STATUSTYPE statusType, float amount)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Invalid comparison between Unknown and I4
		if (!applyingAdditionalDamage && (int)statusType <= 0 && !(Mathf.Abs(amount - 0.3f) > 0.001f) && !((Object)(object)localCharacter == (Object)null) && !((Object)(object)localAfflictions == (Object)null) && !((Object)(object)scoutmaster == (Object)null) && !((Object)(object)scoutmaster.currentTarget != (Object)(object)localCharacter))
		{
			float currentStatus = localAfflictions.GetCurrentStatus((STATUSTYPE)0);
			applyingAdditionalDamage = true;
			localAfflictions.SetStatus((STATUSTYPE)0, currentStatus + 0.7f, true);
			applyingAdditionalDamage = false;
		}
	}

	private void UnsubscribeLocalAfflictions()
	{
		if ((Object)(object)localAfflictions != (Object)null)
		{
			CharacterAfflictions obj = localAfflictions;
			obj.OnAddedStatus = (Action<STATUSTYPE, float>)Delegate.Remove(obj.OnAddedStatus, new Action<STATUSTYPE, float>(OnStatusAdded));
		}
		localAfflictions = null;
	}

	private void OnDisable()
	{
		UnsubscribeLocalAfflictions();
		localCharacter = null;
		scoutmaster = null;
		applyingAdditionalDamage = false;
	}
}
[DefaultExecutionOrder(10000)]
[BepInPlugin("com.saphir.scoutmasterdarkness", "ScoutmasterDarkness", "1.0.0")]
public sealed class ScoutmasterDarkness : BaseUnityPlugin
{
	private const float SafeDistance = 60f;

	private const float ScoutmasterCallDistance = 60f;

	private const float ForcedChaseDuration = 0.75f;

	private const float ForcedChaseRefreshInterval = 0.35f;

	private static readonly int ExtraFogProperty = Shader.PropertyToID("EXTRAFOG");

	private static readonly int FogSafeZoneProperty = Shader.PropertyToID("FogSafeZone");

	private static readonly int GloomVisibilityOffsetProperty = Shader.PropertyToID("GloomVisibiltyOffset");

	private static readonly int HeightFogHeightProperty = Shader.PropertyToID("HeightFogHeight");

	private static readonly int FogTextureProperty = Shader.PropertyToID("FogTexture");

	private static readonly Color LonelyFogColor = new Color(0.38f, 0.42f, 0.41f, 1f);

	private Scoutmaster controlledScoutmaster;

	private PhotonView controlledScoutmasterView;

	private bool scoutmasterSuppressed;

	private bool scoutmasterCalledByDistance;

	private int lastForcedTargetViewId = -1;

	private float lastForcedTargetTime = -100f;

	private float nextForcedTargetRefreshTime;

	private MapHandler cachedMapHandler;

	private DayNightProfile gloomProfile;

	private FogShaderParams gloomFogShaderParams;

	private ForceFogShaderHeight gloomHeightSource;

	private void LateUpdate()
	{
		CacheScoutmasterReference();
		if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
		{
			UpdateScoutmasterCallState();
		}
		ApplyPersistentGloomFog();
	}

	private void UpdateScoutmasterCallState()
	{
		Character isolatedPlayer;
		float isolatedDistance;
		if ((Object)(object)controlledScoutmaster == (Object)null || (Object)(object)controlledScoutmasterView == (Object)null)
		{
			scoutmasterCalledByDistance = false;
		}
		else if (!TryGetMostIsolatedPlayer(out isolatedPlayer, out isolatedDistance) || (Object)(object)isolatedPlayer == (Object)null)
		{
			scoutmasterCalledByDistance = false;
			SuppressScoutmaster();
		}
		else if (!scoutmasterCalledByDistance)
		{
			if (isolatedDistance >= 60f)
			{
				scoutmasterCalledByDistance = true;
				ActivateScoutmaster(isolatedPlayer);
			}
			else
			{
				SuppressScoutmaster();
			}
		}
		else if (isolatedDistance <= 60f)
		{
			scoutmasterCalledByDistance = false;
			SuppressScoutmaster();
		}
		else
		{
			ActivateScoutmaster(isolatedPlayer);
		}
	}

	private void ActivateScoutmaster(Character target)
	{
		if (!((Object)(object)target == (Object)null) && !((Object)(object)((MonoBehaviourPun)target).photonView == (Object)null) && !((Object)(object)controlledScoutmaster == (Object)null) && !((Object)(object)controlledScoutmasterView == (Object)null) && controlledScoutmasterView.IsMine)
		{
			if (scoutmasterSuppressed)
			{
				((Behaviour)controlledScoutmaster).enabled = true;
				scoutmasterSuppressed = false;
			}
			int viewID = ((MonoBehaviourPun)target).photonView.ViewID;
			bool flag = lastForcedTargetViewId != viewID;
			bool flag2 = Time.time >= nextForcedTargetRefreshTime;
			if ((flag || flag2) && (!flag || lastForcedTargetViewId == -1 || !(Time.time < lastForcedTargetTime + 0.75f)))
			{
				controlledScoutmasterView.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { viewID, 0.75f });
				lastForcedTargetViewId = viewID;
				lastForcedTargetTime = Time.time;
				nextForcedTargetRefreshTime = Time.time + 0.35f;
			}
		}
	}

	private void SuppressScoutmaster()
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)controlledScoutmaster == (Object)null) && !((Object)(object)controlledScoutmasterView == (Object)null) && controlledScoutmasterView.IsMine)
		{
			if (!scoutmasterSuppressed)
			{
				controlledScoutmasterView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2]
				{
					(object)new Vector3(0f, 0f, 5000f),
					false
				});
				controlledScoutmasterView.RPC("StopClimbingRpc", (RpcTarget)0, new object[1] { 0f });
				((Behaviour)controlledScoutmaster).enabled = false;
				scoutmasterSuppressed = true;
			}
			if (Time.time >= lastForcedTargetTime + 0.75f)
			{
				controlledScoutmasterView.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { -1, 0f });
				lastForcedTargetViewId = -1;
				nextForcedTargetRefreshTime = 0f;
			}
		}
	}

	private void CacheScoutmasterReference()
	{
		if (!((Object)(object)controlledScoutmaster != (Object)null))
		{
			Scoutmaster val = default(Scoutmaster);
			if (!Scoutmaster.GetPrimaryScoutmaster(ref val) || (Object)(object)val == (Object)null)
			{
				controlledScoutmasterView = null;
				scoutmasterSuppressed = false;
				scoutmasterCalledByDistance = false;
				lastForcedTargetViewId = -1;
				lastForcedTargetTime = -100f;
				nextForcedTargetRefreshTime = 0f;
			}
			else
			{
				controlledScoutmaster = val;
				controlledScoutmasterView = ((Component)controlledScoutmaster).GetComponent<PhotonView>();
				scoutmasterSuppressed = false;
			}
		}
	}

	private static bool TryGetMostIsolatedPlayer(out Character isolatedPlayer, out float isolatedDistance)
	{
		//IL_006e: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		isolatedPlayer = null;
		isolatedDistance = -1f;
		for (int i = 0; i < Character.AllCharacters.Count; i++)
		{
			Character val = Character.AllCharacters[i];
			if (!IsValidPlayer(val))
			{
				continue;
			}
			float num = float.MaxValue;
			bool flag = false;
			for (int j = 0; j < Character.AllCharacters.Count; j++)
			{
				Character val2 = Character.AllCharacters[j];
				if (IsValidPlayer(val2) && !((Object)(object)val2 == (Object)(object)val))
				{
					float num2 = Vector3.Distance(val.Center, val2.Center);
					if (num2 < num)
					{
						num = num2;
					}
					flag = true;
				}
			}
			if (flag && ((Object)(object)isolatedPlayer == (Object)null || num > isolatedDistance || (Mathf.Approximately(num, isolatedDistance) && val.Center.y > isolatedPlayer.Center.y)))
			{
				isolatedPlayer = val;
				isolatedDistance = num;
			}
		}
		return (Object)(object)isolatedPlayer != (Object)null;
	}

	private static bool IsValidPlayer(Character character)
	{
		return (Object)(object)character != (Object)null && character.IsPlayerControlled && (Object)(object)character.data != (Object)null && !character.data.dead && !character.data.fullyPassedOut;
	}

	private void ApplyPersistentGloomFog()
	{
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		if (!MapHandler.ExistsAndInitialized || (Object)(object)DayNightManager.instance == (Object)null)
		{
			ClearGloomCache();
			return;
		}
		MapHandler instance = Singleton<MapHandler>.Instance;
		if ((Object)(object)instance == (Object)null)
		{
			ClearGloomCache();
			return;
		}
		if ((Object)(object)cachedMapHandler != (Object)(object)instance || (Object)(object)gloomProfile == (Object)null)
		{
			CacheGloomSources(instance);
		}
		if (!((Object)(object)gloomProfile == (Object)null))
		{
			float timeOfDayNormalized = DayNightManager.instance.timeOfDayNormalized;
			if (gloomProfile.fogGradient != null)
			{
				Shader.SetGlobalFloat(ExtraFogProperty, gloomProfile.fogGradient.Evaluate(timeOfDayNormalized).r);
			}
			ApplyGloomShaderFloats(gloomProfile.globalShaderFloats);
			ApplyGloomShaderFloats(gloomProfile.globalStaticShaderFloats);
			ApplyGloomAnimatedShaderFloats(gloomProfile.animatedGlobalShaderFloats, timeOfDayNormalized);
			if ((Object)(object)gloomFogShaderParams != (Object)null && (Object)(object)gloomFogShaderParams.fogTexture != (Object)null)
			{
				Shader.SetGlobalTexture(FogTextureProperty, gloomFogShaderParams.fogTexture);
			}
			if ((Object)(object)gloomHeightSource != (Object)null)
			{
				Shader.SetGlobalFloat(HeightFogHeightProperty, ((Component)gloomHeightSource).transform.position.y);
			}
			string shaderValue = DayNightManager.instance.getShaderValue((ShaderParams)7);
			if (!string.IsNullOrEmpty(shaderValue))
			{
				Shader.SetGlobalColor(shaderValue, LonelyFogColor);
			}
			Shader.SetGlobalFloat(FogSafeZoneProperty, 0f);
			Shader.SetGlobalFloat(GloomVisibilityOffsetProperty, 0f);
		}
	}

	private void CacheGloomSources(MapHandler mapHandler)
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Invalid comparison between Unknown and I4
		cachedMapHandler = mapHandler;
		gloomProfile = null;
		gloomFogShaderParams = null;
		gloomHeightSource = null;
		MapSegment val = FindGloomSegment(mapHandler.segments);
		if (val == null)
		{
			val = FindGloomSegment(mapHandler.variantSegments);
		}
		if (val == null)
		{
			return;
		}
		gloomProfile = val.dayNightProfile;
		GameObject segmentParent = val.segmentParent;
		if ((Object)(object)segmentParent == (Object)null)
		{
			return;
		}
		gloomFogShaderParams = segmentParent.GetComponentInChildren<FogShaderParams>(true);
		ForceFogShaderHeight[] componentsInChildren = segmentParent.GetComponentsInChildren<ForceFogShaderHeight>(true);
		foreach (ForceFogShaderHeight val2 in componentsInChildren)
		{
			if ((Object)(object)val2 != (Object)null && (int)val2.fogType == 0)
			{
				gloomHeightSource = val2;
				break;
			}
		}
	}

	private static MapSegment FindGloomSegment(MapSegment[] segments)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Invalid comparison between Unknown and I4
		if (segments == null)
		{
			return null;
		}
		foreach (MapSegment val in segments)
		{
			if (val != null && (int)val.biome == 8)
			{
				return val;
			}
		}
		return null;
	}

	private static void ApplyGloomShaderFloats(ShaderParameters[] parameters)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		if (parameters == null || (Object)(object)DayNightManager.instance == (Object)null)
		{
			return;
		}
		foreach (ShaderParameters val in parameters)
		{
			if (val != null && IsGloomFogFloatParameter(val.parameter))
			{
				string shaderValue = DayNightManager.instance.getShaderValue(val.parameter);
				if (!string.IsNullOrEmpty(shaderValue))
				{
					Shader.SetGlobalFloat(shaderValue, val.paramValue);
				}
			}
		}
	}

	private static void ApplyGloomAnimatedShaderFloats(AnimatedShaderParameters[] parameters, float time)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if (parameters == null || (Object)(object)DayNightManager.instance == (Object)null)
		{
			return;
		}
		foreach (AnimatedShaderParameters val in parameters)
		{
			if (val != null && val.paramValue != null && IsGloomFogFloatParameter(val.parameter))
			{
				string shaderValue = DayNightManager.instance.getShaderValue(val.parameter);
				if (!string.IsNullOrEmpty(shaderValue))
				{
					Shader.SetGlobalFloat(shaderValue, val.paramValue.Evaluate(time));
				}
			}
		}
	}

	private static bool IsGloomFogFloatParameter(ShaderParams parameter)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Invalid comparison between Unknown and I4
		return (int)parameter == 3 || (int)parameter == 5 || (int)parameter == 6 || (int)parameter == 8;
	}

	private void ClearGloomCache()
	{
		cachedMapHandler = null;
		gloomProfile = null;
		gloomFogShaderParams = null;
		gloomHeightSource = null;
	}

	private void OnDisable()
	{
		if ((Object)(object)controlledScoutmaster != (Object)null && (Object)(object)controlledScoutmasterView != (Object)null && controlledScoutmasterView.IsMine)
		{
			if (scoutmasterSuppressed)
			{
				((Behaviour)controlledScoutmaster).enabled = true;
			}
			controlledScoutmasterView.RPC("RPCA_SetCurrentTarget", (RpcTarget)0, new object[2] { -1, 0f });
		}
		controlledScoutmaster = null;
		controlledScoutmasterView = null;
		scoutmasterSuppressed = false;
		scoutmasterCalledByDistance = false;
		lastForcedTargetViewId = -1;
		lastForcedTargetTime = -100f;
		nextForcedTargetRefreshTime = 0f;
		ClearGloomCache();
	}
}
[DefaultExecutionOrder(10000)]
[BepInPlugin("com.saphir.neveralonevoice", "NeverAloneVoice", "1.0.0")]
public sealed class Voice : BaseUnityPlugin
{
	private sealed class VoiceState
	{
		public AudioSource Source;

		public float BaseVolume;

		public float LastAppliedVolume;

		public bool HasAppliedVolume;
	}

	private const float FullVolumeDistance = 10f;

	private const float MuteDistance = 30f;

	private readonly Dictionary<Character, VoiceState> voiceStates = new Dictionary<Character, VoiceState>();

	private readonly List<Character> staleCharacters = new List<Character>();

	private void LateUpdate()
	{
		Character localCharacter = Character.localCharacter;
		if (!IsValidPlayer(localCharacter))
		{
			RestoreAll();
			return;
		}
		UpdateRemoteVoices(localCharacter);
		RemoveStaleCharacters();
	}

	private void UpdateRemoteVoices(Character localCharacter)
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < Character.AllCharacters.Count; i++)
		{
			Character val = Character.AllCharacters[i];
			if (!IsValidPlayer(val) || (Object)(object)val == (Object)(object)localCharacter)
			{
				continue;
			}
			VoiceState voiceState = GetVoiceState(val);
			if (voiceState != null && !((Object)(object)voiceState.Source == (Object)null))
			{
				AudioSource source = voiceState.Source;
				float num = Vector3.Distance(localCharacter.Center, val.Center);
				UpdateBaseVolume(voiceState);
				if (num >= 30f)
				{
					source.volume = voiceState.BaseVolume;
					source.mute = true;
					voiceState.LastAppliedVolume = voiceState.BaseVolume;
					voiceState.HasAppliedVolume = true;
				}
				else
				{
					source.mute = false;
					float num2 = ((!(num <= 10f)) ? Mathf.InverseLerp(30f, 10f, num) : 1f);
					float lastAppliedVolume = (source.volume = voiceState.BaseVolume * num2);
					voiceState.LastAppliedVolume = lastAppliedVolume;
					voiceState.HasAppliedVolume = true;
				}
			}
		}
	}

	private static void UpdateBaseVolume(VoiceState state)
	{
		if (state != null && !((Object)(object)state.Source == (Object)null))
		{
			float volume = state.Source.volume;
			if (!state.HasAppliedVolume)
			{
				state.BaseVolume = volume;
			}
			else if (!Mathf.Approximately(volume, state.LastAppliedVolume))
			{
				state.BaseVolume = volume;
			}
		}
	}

	private VoiceState GetVoiceState(Character character)
	{
		if (voiceStates.TryGetValue(character, out var value))
		{
			if (value != null && (Object)(object)value.Source != (Object)null)
			{
				return value;
			}
			voiceStates.Remove(character);
		}
		if (character.refs == null || (Object)(object)character.refs.voice == (Object)null)
		{
			return null;
		}
		AudioSource component = ((Component)character.refs.voice).GetComponent<AudioSource>();
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		VoiceState voiceState = new VoiceState
		{
			Source = component,
			BaseVolume = component.volume,
			LastAppliedVolume = component.volume,
			HasAppliedVolume = false
		};
		voiceStates[character] = voiceState;
		return voiceState;
	}

	private void RemoveStaleCharacters()
	{
		staleCharacters.Clear();
		foreach (KeyValuePair<Character, VoiceState> voiceState in voiceStates)
		{
			Character key = voiceState.Key;
			VoiceState value = voiceState.Value;
			if ((Object)(object)key == (Object)null || !Character.AllCharacters.Contains(key))
			{
				RestoreVoiceState(value);
				staleCharacters.Add(key);
			}
		}
		for (int i = 0; i < staleCharacters.Count; i++)
		{
			voiceStates.Remove(staleCharacters[i]);
		}
	}

	private static bool IsValidPlayer(Character character)
	{
		return (Object)(object)character != (Object)null && character.IsPlayerControlled && !character.isBot;
	}

	private static void RestoreVoiceState(VoiceState state)
	{
		if (state != null && !((Object)(object)state.Source == (Object)null))
		{
			state.Source.mute = false;
			state.Source.volume = state.BaseVolume;
			state.HasAppliedVolume = false;
		}
	}

	private void RestoreAll()
	{
		foreach (KeyValuePair<Character, VoiceState> voiceState in voiceStates)
		{
			RestoreVoiceState(voiceState.Value);
		}
	}

	private void OnDisable()
	{
		RestoreAll();
		voiceStates.Clear();
		staleCharacters.Clear();
	}
}
[DefaultExecutionOrder(20000)]
[BepInPlugin("com.saphir.neveralonebinoculars", "NeverAloneBinoculars", "1.0.0")]
public sealed class Binoculars : BaseUnityPlugin
{
	private const ushort BinocularItemId = 14;

	private const float MaximumVisibilityBoost = 4.5f;

	private const float MaximumFarFogReduction = 0.15f;

	private const float VisibilityRiseSpeed = 5.5f;

	private const float VisibilityFallSpeed = 8f;

	private static readonly int GloomVisibilityOffsetProperty = Shader.PropertyToID("GloomVisibiltyOffset");

	private static readonly int ExtraFogProperty = Shader.PropertyToID("EXTRAFOG");

	private Item cachedBinocularItem;

	private Action_ShowBinocularOverlay cachedBinocularOverlay;

	private float currentVisibilityBoost;

	private void LateUpdate()
	{
		Character localCharacter = Character.localCharacter;
		if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || localCharacter.data.dead)
		{
			ClearState();
			return;
		}
		bool flag = IsLocalPlayerUsingBinoculars(localCharacter);
		float num = (flag ? 4.5f : 0f);
		float num2 = (flag ? 5.5f : 8f);
		currentVisibilityBoost = Mathf.MoveTowards(currentVisibilityBoost, num, Time.deltaTime * num2);
		if (currentVisibilityBoost <= 0.001f)
		{
			currentVisibilityBoost = 0f;
			return;
		}
		float strength = Mathf.Clamp01(currentVisibilityBoost / 4.5f);
		ApplyNearAndMidVisibility();
		ApplyFarSilhouetteVisibility(strength);
	}

	private void ApplyNearAndMidVisibility()
	{
		float globalFloat = Shader.GetGlobalFloat(GloomVisibilityOffsetProperty);
		Shader.SetGlobalFloat(GloomVisibilityOffsetProperty, Mathf.Max(globalFloat, currentVisibilityBoost));
	}

	private void ApplyFarSilhouetteVisibility(float strength)
	{
		float num = 0.15f * strength;
		float globalFloat = Shader.GetGlobalFloat(ExtraFogProperty);
		Shader.SetGlobalFloat(ExtraFogProperty, globalFloat * (1f - num));
		if (!((Object)(object)DayNightManager.instance == (Object)null))
		{
			string shaderValue = DayNightManager.instance.getShaderValue((ShaderParams)5);
			if (!string.IsNullOrEmpty(shaderValue))
			{
				int num2 = Shader.PropertyToID(shaderValue);
				float globalFloat2 = Shader.GetGlobalFloat(num2);
				Shader.SetGlobalFloat(num2, globalFloat2 * (1f - num));
			}
			string shaderValue2 = DayNightManager.instance.getShaderValue((ShaderParams)3);
			if (!string.IsNullOrEmpty(shaderValue2))
			{
				int num3 = Shader.PropertyToID(shaderValue2);
				float globalFloat3 = Shader.GetGlobalFloat(num3);
				Shader.SetGlobalFloat(num3, globalFloat3 * (1f - num * 0.5f));
			}
		}
	}

	private bool IsLocalPlayerUsingBinoculars(Character localCharacter)
	{
		Item currentItem = localCharacter.data.currentItem;
		if ((Object)(object)currentItem == (Object)null || currentItem.itemID != 14)
		{
			cachedBinocularItem = null;
			cachedBinocularOverlay = null;
			return false;
		}
		if ((Object)(object)cachedBinocularItem != (Object)(object)currentItem || (Object)(object)cachedBinocularOverlay == (Object)null)
		{
			cachedBinocularItem = currentItem;
			cachedBinocularOverlay = ((Component)currentItem).GetComponentInChildren<Action_ShowBinocularOverlay>(true);
		}
		return (Object)(object)cachedBinocularOverlay != (Object)null && cachedBinocularOverlay.binocularsActive;
	}

	private void ClearState()
	{
		cachedBinocularItem = null;
		cachedBinocularOverlay = null;
		currentVisibilityBoost = 0f;
	}

	private void OnDisable()
	{
		ClearState();
	}
}