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(); 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 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(); } } else if (Scoutmaster.GetPrimaryScoutmaster(ref val) && (Object)(object)val != (Object)null) { scoutmaster = val; scoutmasterCharacter = ((Component)scoutmaster).GetComponent(); } 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 spawnedSegments = new HashSet(); 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.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(true); ForceFogShaderHeight[] componentsInChildren = segmentParent.GetComponentsInChildren(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)Delegate.Combine(obj.OnAddedStatus, new Action(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)Delegate.Remove(obj.OnAddedStatus, new Action(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(); 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.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(true); ForceFogShaderHeight[] componentsInChildren = segmentParent.GetComponentsInChildren(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 voiceStates = new Dictionary(); private readonly List staleCharacters = new List(); 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(); 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 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 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(true); } return (Object)(object)cachedBinocularOverlay != (Object)null && cachedBinocularOverlay.binocularsActive; } private void ClearState() { cachedBinocularItem = null; cachedBinocularOverlay = null; currentVisibilityBoost = 0f; } private void OnDisable() { ClearState(); } }