Decompiled source of Hide and PEAK v1.4.0

BepInEx/plugins/hide_and_peak.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using HideAndSeekMod;
using Hide_and_PEAK;
using Hide_and_PEAK.Configuration;
using Hide_and_PEAK.Patches;
using Hide_and_PEAK.UI;
using Hide_and_PEAK.Voice;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("hide_and_peak")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.3.3.0")]
[assembly: AssemblyInformationalVersion("1.3.3+9003cd69e249093bd48b3125ac88077cdb9b4d83")]
[assembly: AssemblyProduct("hide_and_peak")]
[assembly: AssemblyTitle("hide_and_peak")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace HideAndSeekMod
{
	public class HideAndSeekManager : MonoBehaviourPunCallbacks
	{
		[CompilerGenerated]
		private sealed class <CheckGameEndAfterDelay>d__27 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			public HideAndSeekManager <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CheckGameEndAfterDelay>d__27(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>4__this.CheckForGameEnd();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <ClearProcessingAfterDelay>d__26 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public int viewId;

			public float delay;

			public HideAndSeekManager <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ClearProcessingAfterDelay>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>4__this._processingCaught.Remove(viewId);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <EndGameTimer>d__33 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public HideAndSeekManager <>4__this;

			private float <elapsed>5__1;

			private float <duration>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EndGameTimer>d__33(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Plugin.Log.LogInfo((object)"[GameEnd] Starting 30-second countdown...");
					<elapsed>5__1 = 0f;
					<duration>5__2 = 30f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsed>5__1 < <duration>5__2)
				{
					if ((Object)(object)ScoreBoardUI.Instance != (Object)null)
					{
						ScoreBoardUI.Instance.gameOverCountdown = <duration>5__2 - <elapsed>5__1;
					}
					<elapsed>5__1 += Time.deltaTime;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if (<elapsed>5__1 >= <duration>5__2)
				{
					Plugin.Log.LogInfo((object)"[GameEnd] 30 seconds elapsed, restarting game");
					ScoreBoardUI.Instance.IsOpenMode = false;
				}
				if ((Object)(object)ScoreBoardUI.Instance != (Object)null && ScoreBoardUI.Instance.showUI)
				{
					ScoreBoardUI.Instance.isGameOverMode = false;
					ScoreBoardUI.Instance.gameOverCountdown = 0f;
					ScoreBoardUI.Instance.SetScoreBoardUI(visible: false);
				}
				if (<>4__this.IsHost())
				{
					<>4__this.RestartGameForAll();
					<>4__this._gameEndSequenceActive = false;
				}
				<>4__this._endGameCoroutine = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static HideAndSeekManager Instance;

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

		private bool _gameEndSequenceActive = false;

		private Coroutine _endGameCoroutine;

		public PhotonView View;

		public float HiderGracePeriod = Plugin.ConfigurationHandler.ConfigHiderGracePeriod.Value;

		public bool IsGameActive = false;

		public bool IsHider
		{
			get
			{
				object value;
				return ((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"Team", out value) && (Team)value == Team.Hider;
			}
		}

		public bool IsSeeker
		{
			get
			{
				object value;
				return ((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"Team", out value) && (Team)value == Team.Seeker;
			}
		}

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				View = ((Component)((Component)this).transform).GetComponent<PhotonView>();
				if ((Object)(object)View == (Object)null)
				{
					Plugin.Log.LogError((object)"No PhotonView attached!");
				}
				Plugin.Log.LogInfo((object)$"PhotonView ID: {View.ViewID}, IsMine: {View.IsMine}, Owner: {View.Owner}");
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Plugin.Log.LogWarning((object)"[HideAndSeekManager] Instance already exists, destroying old one.");
				Object.Destroy((Object)(object)Instance);
				Instance = this;
			}
		}

		private void Start()
		{
			CheckIfInGame();
		}

		private void CheckIfInGame()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Checking if in game...");
			if (((Dictionary<object, object>)(object)PhotonNetwork.MasterClient.CustomProperties).TryGetValue((object)"IsInGame", out object value) && (bool)value)
			{
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Found game: Starting game...");
				RejoinGame();
			}
		}

		[PunRPC]
		public void RPC_StartGame()
		{
			StartGame();
		}

		[PunRPC]
		public void RPC_RequestCurrentTimeString(int requesterActorNumber)
		{
			if (!((Object)(object)PlayerStats.Instance == (Object)null))
			{
				float currentTime = PlayerStats.Instance._currentTime;
				Player val = PhotonNetwork.CurrentRoom.Players[requesterActorNumber];
				if (val != null)
				{
					View.RPC("RPC_ReceiveCurrentTimeString", val, new object[1] { currentTime });
					Plugin.Log.LogInfo((object)("[RPC_RequestCurrentTimeString] Sent _currentTimeString to " + val.NickName));
				}
			}
		}

		[PunRPC]
		public void RPC_ReceiveCurrentTimeString(float currentTime)
		{
			if ((Object)(object)PlayerStats.Instance != (Object)null)
			{
				PlayerStats.Instance.SetCurrentTimeFromHost(currentTime);
				Plugin.Log.LogInfo((object)$"[RPC_ReceiveCurrentTimeString] Updated _currentTime: {currentTime}");
			}
		}

		public void RejoinGame()
		{
			((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"Team", out object value);
			Team team = (Team)value;
			((Component)this).gameObject.AddComponent<HideAndSeekPlayer>();
			Plugin.Log.LogInfo((object)"InitiatingUI");
			DeathLog.InitiateDeathLog();
			IsGameActive = true;
			View.RPC("RPC_RequestCurrentTimeString", PhotonNetwork.MasterClient, new object[1] { PhotonNetwork.LocalPlayer.ActorNumber });
			Plugin.Log.LogInfo((object)"[RequestCurrentTimeString] Requested _currentTimeString from host");
		}

		public void StartGame()
		{
			((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"Team", out object value);
			Team team = (Team)value;
			((Component)this).gameObject.AddComponent<HideAndSeekPlayer>();
			Plugin.Log.LogInfo((object)"InitiatingUI");
			DeathLog.InitiateDeathLog();
			PlayerStats.InitiatePlayerStats();
			IsGameActive = true;
			if (IsHost())
			{
				View.RPC("RPC_SetHiderGracePeriod", (RpcTarget)1, new object[1] { HiderGracePeriod });
				Plugin.Log.LogInfo((object)$"[HideAndSeekManager] Broadcasting HiderGracePeriod ({HiderGracePeriod}) to clients");
				View.RPC("RPC_SetSoundIntervals", (RpcTarget)1, new object[2]
				{
					SoundPlayer.Instance?.nextSoundTime ?? ((float)Plugin.ConfigurationHandler.ConfigTauntStartTime.Value),
					SoundPlayer.Instance?.soundInterval ?? ((float)Plugin.ConfigurationHandler.ConfigTauntIntervalTime.Value)
				});
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Broadcasting SoundPlayer intervals to clients");
			}
			if ((Object)(object)SoundPlayer.Instance != (Object)null)
			{
				SoundPlayer.Instance.nextSoundTime = PlayerStats.Instance._currentTime + (float)Plugin.ConfigurationHandler.ConfigTauntStartTime.Value;
			}
		}

		[PunRPC]
		public void RPC_SetSoundIntervals(float nextSound, float interval)
		{
			if ((Object)(object)SoundPlayer.Instance != (Object)null)
			{
				SoundPlayer.Instance.nextSoundTime = nextSound;
				SoundPlayer.Instance.soundInterval = interval;
				Plugin.Log.LogInfo((object)$"[HideAndSeekManager] Sound intervals synced from host: nextSound={nextSound}, interval={interval}");
			}
		}

		[PunRPC]
		public void RPC_SetHiderGracePeriod(float gracePeriod)
		{
			HiderGracePeriod = gracePeriod;
			Plugin.Log.LogInfo((object)$"[HideAndSeekManager] HiderGracePeriod set to {gracePeriod} by host.");
		}

		[PunRPC]
		public void RPC_SetFrozenState(int viewId, bool isFrozen, float frozenHeight, float frozenStamina)
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			PhotonView val = PhotonView.Find(viewId);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)$"[FreezeSync] Could not find PhotonView for {viewId}");
				return;
			}
			Character component = ((Component)val).GetComponent<Character>();
			if ((Object)(object)component == (Object)null)
			{
				Plugin.Log.LogWarning((object)$"[FreezeSync] No Character component on PhotonView {viewId}");
				return;
			}
			if (!isFrozen)
			{
				Plugin.Log.LogInfo((object)("[FreezeSync] Unfreezing " + component.characterName));
				return;
			}
			Bodypart bodypart = component.GetBodypart((BodypartType)2);
			if ((Object)(object)((bodypart != null) ? bodypart.Rig : null) != (Object)null)
			{
				Rigidbody rig = bodypart.Rig;
				Vector3 position = bodypart.Rig.position;
				position.y = frozenHeight;
				rig.position = position;
				bodypart.Rig.linearVelocity = Vector3.zero;
				bodypart.Rig.angularVelocity = Vector3.zero;
			}
			component.data.currentStamina = frozenStamina;
			component.input.movementInput = Vector2.zero;
			component.input.jumpIsPressed = false;
			component.input.crouchIsPressed = false;
			Plugin.Log.LogInfo((object)$"[FreezeSync] Applied freeze to {component.characterName}, height={frozenHeight}");
		}

		public void SyncFreezeState(Character character, bool isFrozen, float frozenHeight, float frozenStamina)
		{
			if (!((Object)(object)character?.refs?.view == (Object)null))
			{
				View.RPC("RPC_SetFrozenState", (RpcTarget)1, new object[4]
				{
					character.refs.view.ViewID,
					isFrozen,
					frozenHeight,
					frozenStamina
				});
			}
		}

		[PunRPC]
		public void RPC_RequestCatch(int seekerViewId, int hiderViewId)
		{
			if (IsHost())
			{
				Character val = Character.AllCharacters.Find((Character c) => c.refs.view.ViewID == seekerViewId);
				Character val2 = Character.AllCharacters.Find((Character c) => c.refs.view.ViewID == hiderViewId);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
				{
					Plugin.Log.LogInfo((object)("[HideAndSeekPlayer] Host processing catch: " + val.characterName + " -> " + val2.characterName));
					CatchHider(val, val2);
				}
			}
		}

		public void CatchHider(Character seekerCharacter, Character hiderCharacter)
		{
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			//IL_0197: Expected O, but got Unknown
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Expected O, but got Unknown
			//IL_01da: Expected O, but got Unknown
			if (!IsHost())
			{
				return;
			}
			if (PlayerStats.Instance._currentTime < HiderGracePeriod)
			{
				Plugin.Log.LogInfo((object)"[HideAndSeekPlayer] Catch ignored, hider grace period.");
				return;
			}
			Player controller = hiderCharacter.view.Controller;
			Player controller2 = seekerCharacter.view.Controller;
			((Dictionary<object, object>)(object)controller.CustomProperties).TryGetValue((object)"Team", out object value);
			((Dictionary<object, object>)(object)controller2.CustomProperties).TryGetValue((object)"Team", out object value2);
			if ((Team)value != 0 || (Team)value2 != Team.Seeker)
			{
				return;
			}
			int viewID = hiderCharacter.refs.view.ViewID;
			if (!_processingCaught.Contains(viewID))
			{
				_processingCaught.Add(viewID);
				Plugin.Log.LogInfo((object)"Team swap 1");
				View.RPC("RPC_ResetStamina", controller, Array.Empty<object>());
				View.RPC("RPC_AddDeath", (RpcTarget)0, new object[2]
				{
					seekerCharacter.refs.view.ViewID,
					hiderCharacter.refs.view.ViewID
				});
				Plugin.Log.LogInfo((object)"Team swap 2");
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"Team", (object)Team.Seeker);
				((Dictionary<object, object>)val).Add((object)"OriginalRole", (object)Team.Hider);
				((Dictionary<object, object>)val).Add((object)"Caught_Time", (object)PlayerStats.Instance._currentTimeString);
				Hashtable val2 = val;
				controller.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				((Dictionary<object, object>)(object)controller2.CustomProperties).TryGetValue((object)"Catches", out object value3);
				int num = (int)value3 + 1;
				Hashtable val3 = new Hashtable();
				((Dictionary<object, object>)val3).Add((object)"Catches", (object)num);
				Hashtable val4 = val3;
				controller2.SetCustomProperties(val4, (Hashtable)null, (WebFlags)null);
				Plugin.Log.LogInfo((object)$"{controller2.NickName} now has {num} catches.");
				((MonoBehaviour)this).StartCoroutine(ClearProcessingAfterDelay(viewID, 1f));
				if (IsHost())
				{
					((MonoBehaviour)this).StartCoroutine(CheckGameEndAfterDelay(0.5f));
				}
			}
		}

		[PunRPC]
		public void RPC_ResetStamina()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Resetting local character stamina");
			Character localCharacter = Character.localCharacter;
			if (localCharacter != null)
			{
				localCharacter.AddStamina(1f);
			}
			Character localCharacter2 = Character.localCharacter;
			if (localCharacter2 != null)
			{
				localCharacter2.refs.afflictions.ClearAllStatus(false);
			}
		}

		[IteratorStateMachine(typeof(<ClearProcessingAfterDelay>d__26))]
		private IEnumerator ClearProcessingAfterDelay(int viewId, float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ClearProcessingAfterDelay>d__26(0)
			{
				<>4__this = this,
				viewId = viewId,
				delay = delay
			};
		}

		[IteratorStateMachine(typeof(<CheckGameEndAfterDelay>d__27))]
		public IEnumerator CheckGameEndAfterDelay(float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckGameEndAfterDelay>d__27(0)
			{
				<>4__this = this,
				delay = delay
			};
		}

		private void CheckForGameEnd()
		{
			if (!IsHost() || !IsGameActive || _gameEndSequenceActive)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"OriginalRole", out object value) && (Team)value == Team.Hider)
				{
					num++;
					if (((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"Team", out object value2) && (Team)value2 == Team.Hider)
					{
						num2++;
					}
				}
			}
			Plugin.Log.LogInfo((object)$"[GameEnd Check] Original Hiders: {num}, Remaining: {num2}");
			if (num > 0 && num2 == 0)
			{
				Plugin.Log.LogInfo((object)"[GameEnd] All hiders caught! Ending game...");
				_gameEndSequenceActive = true;
				View.RPC("RPC_ShowEndGameScoreboard", (RpcTarget)0, Array.Empty<object>());
				View.RPC("RPC_ResetInfiniteStamina", (RpcTarget)0, Array.Empty<object>());
			}
		}

		[PunRPC]
		private void RPC_ResetInfiniteStamina()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Resetting local character infinite stamina");
			Character.localCharacter.infiniteStam = false;
		}

		private void SaveCurrentMatch()
		{
			MatchResult matchResult = new MatchResult
			{
				Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm"),
				Duration = (((Object)(object)PlayerStats.Instance != (Object)null) ? PlayerStats.Instance._currentTime : 0f)
			};
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				matchResult.PlayerResults.Add(new PlayerResult
				{
					PlayerName = val.NickName,
					Team = ((!((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"Team", out object value)) ? Team.Seeker : ((Team)value)),
					OriginalRole = ((!((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"OriginalRole", out object value2)) ? Team.Seeker : ((Team)value2)),
					CaughtTime = (((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"Caught_Time", out object value3) ? value3.ToString() : ""),
					Catches = (((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"Catches", out object value4) ? ((int)value4) : 0)
				});
			}
			MatchHistoryManager.SaveMatch(matchResult);
		}

		[PunRPC]
		public void RPC_ShowEndGameScoreboard()
		{
			Plugin.Log.LogInfo((object)"[GameEnd] Received RPC: ShowEndGameScoreboard");
			ShowEndGameScoreboard();
		}

		private void ShowEndGameScoreboard()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_006a: Expected O, but got Unknown
			if ((Object)(object)ScoreBoardUI.Instance != (Object)null)
			{
				ScoreBoardUI.Instance.isGameOverMode = true;
				ScoreBoardUI.Instance.gameOverCountdown = 30f;
				ScoreBoardUI.Instance.SetScoreBoardUI(visible: true);
				ScoreBoardUI.Instance.IsOpenMode = true;
				Plugin.Log.LogInfo((object)"[GameEnd] Scoreboard opened");
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"IsInGame", (object)false);
				Hashtable val2 = val;
				PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
			}
			SaveCurrentMatch();
			if (_endGameCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_endGameCoroutine);
			}
			_endGameCoroutine = ((MonoBehaviour)this).StartCoroutine(EndGameTimer());
		}

		[IteratorStateMachine(typeof(<EndGameTimer>d__33))]
		private IEnumerator EndGameTimer()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EndGameTimer>d__33(0)
			{
				<>4__this = this
			};
		}

		[PunRPC]
		public void RPC_AddDeath(int seekerViewId, int hiderViewId)
		{
			PhotonView val = PhotonView.Find(seekerViewId);
			PhotonView val2 = PhotonView.Find(hiderViewId);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogError((object)$"[DeathLog] Could not resolve PhotonViews! seeker={seekerViewId}, hider={hiderViewId}");
				return;
			}
			if ((Object)(object)DeathLog.Instance == (Object)null)
			{
				DeathLog.InitiateDeathLog();
			}
			DeathLog.Instance?.AddDeath(val, val2);
		}

		private void Update()
		{
			if (!PhotonNetwork.InRoom)
			{
				return;
			}
			if (IsHost() && Plugin.ConfigurationHandler.TeamSelectionUIAction.WasPressedThisFrame())
			{
				View.RPC("RPC_SetTeamSelectionUI", (RpcTarget)0, new object[1] { !TeamSelectionUI.Instance.showUI });
			}
			if (Plugin.ConfigurationHandler.ScoreBoardAction.IsPressed())
			{
				if (!ScoreBoardUI.Instance.showUI)
				{
					ScoreBoardUI.Instance.SetScoreBoardUI(visible: true);
				}
				else if (ScoreBoardUI.Instance.IsOpenMode)
				{
					ScoreBoardUI.Instance.IsOpenMode = false;
					ScoreBoardUI.Instance.SetScoreBoardUI(visible: false);
				}
			}
			else if (!ScoreBoardUI.Instance.IsOpenMode && ScoreBoardUI.Instance.showUI)
			{
				ScoreBoardUI.Instance.SetScoreBoardUI(visible: false);
			}
		}

		[PunRPC]
		public void RPC_SetTeamSelectionUI(bool visible)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)$"Received RPC: SetTeamSelectionUI -> {visible}");
			if ((Object)(object)TeamSelectionUI.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TeamSelectionUI.Instance was null. Creating UI GameObject on demand.");
				GameObject val = new GameObject("Team Selection UI");
				val.AddComponent<TeamSelectionUI>();
			}
			TeamSelectionUI.Instance.SetTeamSelectionUI(visible);
		}

		[PunRPC]
		public void RPC_TestDeath()
		{
			try
			{
				if ((Object)(object)DeathLog.Instance == (Object)null)
				{
					DeathLog.InitiateDeathLog();
				}
				Character localCharacter = Character.localCharacter;
				PhotonView localPV = ((!((Object)(object)localCharacter != (Object)null)) ? null : localCharacter.refs?.view);
				if ((Object)(object)localPV == (Object)null)
				{
					Plugin.Log.LogError((object)"[DeathLog Test] Local PhotonView not found.");
					return;
				}
				PhotonView hider = (from c in Character.AllCharacters
					where (Object)(object)c != (Object)null && (Object)(object)c.refs?.view != (Object)null && c.refs.view.ViewID != localPV.ViewID
					select c.refs.view).FirstOrDefault() ?? localPV;
				DeathLog.Instance?.AddDeath(localPV, hider);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[DeathLog Test] Exception: {arg}");
			}
		}

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

		public bool IsHost()
		{
			return PhotonNetwork.IsMasterClient;
		}

		public void DestroyGame()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00b6: Expected O, but got Unknown
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Destroying game state...");
			IsGameActive = false;
			_processingCaught.Clear();
			HideAndSeekPlayer component = ((Component)this).gameObject.GetComponent<HideAndSeekPlayer>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Removed HideAndSeekPlayer component");
			}
			if (PhotonNetwork.LocalPlayer != null)
			{
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"Team", (object)null);
				((Dictionary<object, object>)val).Add((object)"Ready", (object)false);
				((Dictionary<object, object>)val).Add((object)"OriginalRole", (object)null);
				((Dictionary<object, object>)val).Add((object)"Caught_Time", (object)"");
				((Dictionary<object, object>)val).Add((object)"Catches", (object)0);
				Hashtable val2 = val;
				PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Reset local player properties");
			}
			if ((Object)(object)PlayerStats.Instance != (Object)null)
			{
				PlayerStats.Instance.ResetStats();
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Reset PlayerStats");
			}
			if ((Object)(object)DeathLog.Instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)DeathLog.Instance).gameObject);
				DeathLog.Instance = null;
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Cleared DeathLog");
			}
			if ((Object)(object)TeamSelectionUI.Instance != (Object)null && TeamSelectionUI.Instance.showUI)
			{
				TeamSelectionUI.Instance.SetTeamSelectionUI(visible: false);
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Closed TeamSelectionUI");
			}
			if ((Object)(object)ScoreBoardUI.Instance != (Object)null && ScoreBoardUI.Instance.showUI)
			{
				ScoreBoardUI.Instance.SetScoreBoardUI(visible: false);
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Closed ScoreBoardUI");
			}
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Game destroyed successfully");
		}

		public void InitializeNewGame()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Initializing new game...");
			Plugin.ConfigurationHandler?.PushNameColourToPhoton();
			if ((Object)(object)TeamSelectionUI.Instance != (Object)null)
			{
				TeamSelectionUI.Instance.SetTeamSelectionUI(visible: true);
				Plugin.Log.LogInfo((object)"[HideAndSeekManager] Opened TeamSelectionUI for new game");
			}
			else
			{
				Plugin.Log.LogWarning((object)"[HideAndSeekManager] TeamSelectionUI.Instance is null, cannot open");
			}
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] New game initialized");
		}

		public void RestartGame()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Restarting game...");
			DestroyGame();
			InitializeNewGame();
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Game restarted successfully");
		}

		[PunRPC]
		public void RPC_DestroyGame()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Received RPC: DestroyGame");
			DestroyGame();
		}

		[PunRPC]
		public void RPC_InitializeNewGame()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Received RPC: InitializeNewGame");
			InitializeNewGame();
		}

		[PunRPC]
		public void RPC_RestartGame()
		{
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Received RPC: RestartGame");
			RestartGame();
		}

		public void DestroyGameForAll()
		{
			if (!IsHost())
			{
				Plugin.Log.LogWarning((object)"[HideAndSeekManager] Only host can destroy game for all");
				return;
			}
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Broadcasting destroy to all clients");
			View.RPC("RPC_DestroyGame", (RpcTarget)0, Array.Empty<object>());
		}

		public void InitializeNewGameForAll()
		{
			if (!IsHost())
			{
				Plugin.Log.LogWarning((object)"[HideAndSeekManager] Only host can initialize new game for all");
				return;
			}
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Broadcasting new game initialization to all clients");
			View.RPC("RPC_InitializeNewGame", (RpcTarget)0, Array.Empty<object>());
		}

		public void RestartGameForAll()
		{
			if (!IsHost())
			{
				Plugin.Log.LogWarning((object)"[HideAndSeekManager] Only host can restart game for all");
				return;
			}
			Plugin.Log.LogInfo((object)"[HideAndSeekManager] Broadcasting game restart to all clients");
			View.RPC("RPC_RestartGame", (RpcTarget)0, Array.Empty<object>());
		}
	}
}
namespace Hide_and_PEAK
{
	public class HideAndSeekPlayer : MonoBehaviour
	{
		private Vector3 _lastPosition = Vector3.zero;

		private Camera MainCamera = Camera.main;

		public bool IsHider
		{
			get
			{
				object value;
				return ((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"Team", out value) && (Team)value == Team.Hider;
			}
		}

		public bool IsSeeker
		{
			get
			{
				object value;
				return ((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"Team", out value) && (Team)value == Team.Seeker;
			}
		}

		private void Start()
		{
			GlobalEvents.OnCharacterDied = (Action<Character>)Delegate.Combine(GlobalEvents.OnCharacterDied, new Action<Character>(OnCharacterDied));
		}

		private void OnDestroy()
		{
			GlobalEvents.OnCharacterDied = (Action<Character>)Delegate.Remove(GlobalEvents.OnCharacterDied, new Action<Character>(OnCharacterDied));
		}

		private void OnCharacterDied(Character character)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			//IL_012d: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Character.localCharacter == (Object)null || Character.localCharacter.refs == null || !HideAndSeekManager.Instance.IsGameActive)
			{
				return;
			}
			Plugin.Log.LogInfo((object)("Death event for " + ((Object)character).name));
			if (character.characterName.Equals(Character.localCharacter.characterName) && (Character.localCharacter.data.dead || Character.localCharacter.refs.customization.isDead))
			{
				Plugin.Log.LogInfo((object)"[HideAndSeekPlayer] Local Character is dead :(");
				DeathLog.Instance.AddWorldDeath(Character.localCharacter.view);
				if (IsHider)
				{
					Plugin.Log.LogInfo((object)"[HideAndSeekPlayer] Local Character was a hider, reviving as seeker...");
					Hashtable val = new Hashtable();
					((Dictionary<object, object>)val).Add((object)"Team", (object)Team.Seeker);
					((Dictionary<object, object>)val).Add((object)"OriginalRole", (object)Team.Hider);
					((Dictionary<object, object>)val).Add((object)"Caught_Time", (object)PlayerStats.Instance._currentTimeString);
					((Dictionary<object, object>)val).Add((object)"Catches", (object)0);
					Hashtable val2 = val;
					PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
					((MonoBehaviourPun)Character.localCharacter).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3]
					{
						Plugin.Instance.lastDeathPosition,
						false,
						0
					});
					Character.localCharacter.AddStamina(100f);
					Character.localCharacter.AddIllegalStatus("BLIND", 10f);
					Plugin.Log.LogInfo((object)"[HideAndSeekPlayer] Switched local player to seeker, revived them and applied blind!");
				}
			}
			if (HideAndSeekManager.Instance.IsHost())
			{
				((MonoBehaviour)this).StartCoroutine(HideAndSeekManager.Instance.CheckGameEndAfterDelay(0.5f));
			}
		}

		private void Update()
		{
			if (!((Object)(object)Character.localCharacter == (Object)null) && Character.localCharacter.refs != null && HideAndSeekManager.Instance.IsGameActive)
			{
				Character.localCharacter.refs.afflictions.hungerPerSecond = 0f;
				if (IsSeeker)
				{
					Character.localCharacter.infiniteStam = true;
				}
				if (IsSeeker && (Object)(object)Character.localCharacter.input != (Object)null && Character.localCharacter.input.useSecondaryIsPressed)
				{
					TryRaycastConeCatch(1.4f, 15f);
				}
				else if (IsSeeker)
				{
					TryRaycastConeCatch(0.9f, 35f);
				}
			}
		}

		private void TryRaycastConeCatch(float distance, float spreadAngle)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)MainCamera == (Object)null)
			{
				MainCamera = Camera.main;
				if ((Object)(object)MainCamera == (Object)null)
				{
					Plugin.Log.LogError((object)"[HideAndSeekPlayer] No main camera found for raycast.");
					return;
				}
			}
			if (!Object.op_Implicit((Object)(object)HideAndSeekManager.Instance) || !HideAndSeekManager.Instance.IsGameActive)
			{
				return;
			}
			Vector3 position = ((Component)MainCamera).transform.position;
			Vector3 forward = ((Component)MainCamera).transform.forward;
			Vector3[] array = (Vector3[])(object)new Vector3[5]
			{
				forward,
				Quaternion.Euler(spreadAngle, 0f, 0f) * forward,
				Quaternion.Euler(0f - spreadAngle, 0f, 0f) * forward,
				Quaternion.Euler(0f, spreadAngle, 0f) * forward,
				Quaternion.Euler(0f, 0f - spreadAngle, 0f) * forward
			};
			RaycastHit val2 = default(RaycastHit);
			foreach (Vector3 val in array)
			{
				if (Physics.Raycast(position, val, ref val2, distance))
				{
					Character componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Character>();
					if (!((Object)(object)componentInParent == (Object)null) && (!((Object)(object)Character.localCharacter != (Object)null) || !((Object)(object)componentInParent == (Object)(object)Character.localCharacter)))
					{
						Plugin.Log.LogInfo((object)("[HideAndSeekPlayer] Cone ray hit: " + componentInParent.characterName));
						int viewID = Character.localCharacter.refs.view.ViewID;
						int viewID2 = componentInParent.refs.view.ViewID;
						HideAndSeekManager.Instance.View.RPC("RPC_RequestCatch", (RpcTarget)2, new object[2] { viewID, viewID2 });
						break;
					}
				}
			}
		}
	}
	public static class MatchHistoryManager
	{
		[Serializable]
		private class MatchListWrapper
		{
			public List<MatchResult> Matches;
		}

		private static readonly string savePath = Path.Combine(Application.persistentDataPath, "match_history.json");

		private static List<MatchResult> _matches = new List<MatchResult>();

		public static List<MatchResult> Matches
		{
			get
			{
				if (_matches == null)
				{
					LoadMatches();
				}
				return _matches;
			}
		}

		public static void SaveMatch(MatchResult match)
		{
			_matches.Add(match);
			string contents = JsonUtility.ToJson((object)new MatchListWrapper
			{
				Matches = _matches
			}, true);
			File.WriteAllText(savePath, contents);
			Debug.Log((object)("[MatchHistory] Saved match to " + savePath));
		}

		private static void LoadMatches()
		{
			if (File.Exists(savePath))
			{
				string text = File.ReadAllText(savePath);
				MatchListWrapper matchListWrapper = JsonUtility.FromJson<MatchListWrapper>(text);
				_matches = matchListWrapper.Matches ?? new List<MatchResult>();
			}
			else
			{
				_matches = new List<MatchResult>();
			}
		}
	}
	[Serializable]
	public class MatchResult
	{
		public string Date;

		public float Duration;

		public List<PlayerResult> PlayerResults = new List<PlayerResult>();
	}
	[Serializable]
	public class PlayerResult
	{
		public string PlayerName;

		public Team Team;

		public Team OriginalRole;

		public string CaughtTime;

		public int Catches;
	}
	[BepInPlugin("hide_and_peak", "hide_and_peak", "1.3.3")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		public static ConfigurationHandler ConfigurationHandler;

		private ModConfigurationUI _ui;

		private SoundPlayer _soundPlayer;

		public bool _isInitialised = false;

		private bool _pushedNameColor = false;

		private GameObject _teamSelectionUI;

		private GameObject _scoreBoardUI;

		private HideAndSeekManager _manager;

		private RichPresenceService _richPresenceService = null;

		public static Plugin Instance;

		public Vector3 lastDeathPosition = new Vector3(0f, 0f, 0f);

		private RichPresenceState lastState = (RichPresenceState)0;

		public const string Id = "hide_and_peak";

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "hide_and_peak";

		public static string Version => "1.3.3";

		private void Awake()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)("Plugin " + Name + " v" + Version + " loaded!"));
			_harmony = new Harmony("hide_and_peak");
			_harmony.PatchAll(typeof(BodypartOnCollisionEnterPatch));
			_harmony.PatchAll(typeof(VoiceObscuranceFilterPatch));
			_harmony.PatchAll(typeof(CharacterMovementUpdatePatch));
			_harmony.PatchAll(typeof(RunManagerStartRunPatch));
			_harmony.PatchAll(typeof(CharacterRPCADiePatch));
			_harmony.PatchAll(typeof(WindChillZoneHandleTimePatch));
			ConfigurationHandler = new ConfigurationHandler(((BaseUnityPlugin)this).Config);
			GameObject val = new GameObject("HideAndPEAKConfigUI");
			Object.DontDestroyOnLoad((Object)(object)val);
			_ui = val.AddComponent<ModConfigurationUI>();
			_ui.Init(new List<Option>
			{
				Option.InputAction("Menu Key", ConfigurationHandler.ConfigMenuKey),
				Option.InputAction("Freeze Key", ConfigurationHandler.ConfigFreezeKey),
				Option.InputAction("Team Selection UI Key", ConfigurationHandler.ConfigTeamSelectionUIKey),
				Option.InputAction("Score Board Key", ConfigurationHandler.ConfigScoreBoardKey),
				Option.Int("Taunt Start Time (seconds)", ConfigurationHandler.ConfigTauntStartTime, 1, 900, 10),
				Option.Int("Taunt Interval Time (seconds)", ConfigurationHandler.ConfigTauntIntervalTime, 1, 600, 10),
				Option.Int("Hider Grace Period (seconds)", ConfigurationHandler.ConfigHiderGracePeriod, 1, 60),
				Option.Bool("Taunts Enabled", ConfigurationHandler.ConfigTauntsEnabled),
				Option.Bool("Seeker Voice", ConfigurationHandler.ConfigSeekerVoice),
				Option.Colour("Name Colour", ConfigurationHandler.NameColourR, ConfigurationHandler.NameColourG, ConfigurationHandler.NameColourB),
				Option.Bool("Storms Enabled", ConfigurationHandler.ConfigStormsEnabled)
			});
		}

		private void Update()
		{
			//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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_0083: Invalid comparison between Unknown and I4
			//IL_00dc: 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)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			_richPresenceService = GameHandler.GetService<RichPresenceService>();
			RichPresenceService richPresenceService = _richPresenceService;
			RichPresenceState val = (RichPresenceState)((richPresenceService != null) ? ((int)richPresenceService.m_currentState) : 0);
			if (_richPresenceService != null && lastState != val)
			{
				Log.LogInfo((object)$"[Plugin] Rich presence state changed from {lastState} to {_richPresenceService.m_currentState}");
				RichPresenceState currentState = _richPresenceService.m_currentState;
				RichPresenceState val2 = currentState;
				if ((int)val2 != 0)
				{
					if ((int)val2 == 1 && _isInitialised)
					{
						Log.LogInfo((object)"[Plugin] Players are at the airport. Unloading Hide and PEAK components until next run");
						TeardownMod();
					}
				}
				else if (_isInitialised)
				{
					Log.LogInfo((object)"[Plugin] Player left the game. Unloading current Hide and PEAK components");
					TeardownMod();
				}
				lastState = _richPresenceService.m_currentState;
			}
			if (ConfigurationHandler.MenuAction.WasPerformedThisFrame())
			{
				ModConfigurationUI.Instance.ToggleMenu();
			}
			if (ConfigurationHandler.ReviveAction.WasPerformedThisFrame() && (Object)(object)HideAndSeekManager.Instance != (Object)null && HideAndSeekManager.Instance.IsSeeker && (Character.localCharacter.data._dead || Character.localCharacter.data.passedOut))
			{
				Log.LogInfo((object)"[Plugin] Reviving character");
				if (Character.localCharacter.data._dead)
				{
					((MonoBehaviourPun)Character.localCharacter).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { lastDeathPosition, false, 0 });
				}
				else
				{
					((MonoBehaviourPun)Character.localCharacter).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3]
					{
						((Component)Character.localCharacter.GetBodypart((BodypartType)0)).transform.position + ((Component)Character.localCharacter).transform.up,
						false,
						0
					});
				}
				Character.localCharacter.AddStamina(100f);
			}
			if (!_pushedNameColor && PhotonNetwork.InRoom)
			{
				try
				{
					ConfigurationHandler?.PushNameColourToPhoton();
				}
				catch
				{
				}
				_pushedNameColor = true;
			}
		}

		public void InitialiseMod()
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			if (_isInitialised || (Object)(object)Character.localCharacter == (Object)null)
			{
				return;
			}
			Character.localCharacter.refs.afflictions.hungerPerSecond = 0f;
			Log.LogInfo((object)"[Plugin] Initialising Hide and PEAK mod...");
			Character val = Character.localCharacter;
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (object.Equals(allCharacter.player.view.Controller, PhotonNetwork.MasterClient))
				{
					Log.LogInfo((object)"[Plugin] Found the host character");
					val = allCharacter;
				}
			}
			ConfigurationHandler.PushNameColourToPhoton();
			_teamSelectionUI = new GameObject("Team Selection UI");
			_teamSelectionUI.AddComponent<TeamSelectionUI>();
			Object.DontDestroyOnLoad((Object)(object)_teamSelectionUI);
			_scoreBoardUI = new GameObject("Scoreboard UI");
			_scoreBoardUI.AddComponent<ScoreBoardUI>();
			Object.DontDestroyOnLoad((Object)(object)_scoreBoardUI);
			_manager = ((Component)val).gameObject.AddComponent<HideAndSeekManager>();
			_soundPlayer = ((Component)val).gameObject.AddComponent<SoundPlayer>();
			PlayerStats.InitiatePlayerStats();
			_isInitialised = true;
			Log.LogInfo((object)"[Plugin] Initialisation complete");
		}

		public void TeardownMod()
		{
			if (_isInitialised)
			{
				Log.LogInfo((object)"[Plugin] Tearing down Hide and PEAK mod...");
				if ((Object)(object)_manager != (Object)null)
				{
					Object.Destroy((Object)(object)_manager);
					_manager = null;
				}
				if ((Object)(object)_soundPlayer != (Object)null)
				{
					Object.Destroy((Object)(object)_soundPlayer);
					_soundPlayer = null;
				}
				if ((Object)(object)_teamSelectionUI != (Object)null)
				{
					Object.Destroy((Object)(object)_teamSelectionUI);
				}
				if ((Object)(object)_scoreBoardUI != (Object)null)
				{
					Object.Destroy((Object)(object)_scoreBoardUI);
				}
				_teamSelectionUI = null;
				_scoreBoardUI = null;
				if ((Object)(object)PlayerStats.Instance != (Object)null)
				{
					PlayerStats.Instance.ResetStats();
				}
				_pushedNameColor = false;
				_isInitialised = false;
				Log.LogInfo((object)"[Plugin] Teardown complete, ready to initialise again");
			}
		}

		private void OnDestroy()
		{
			TeardownMod();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		public static bool IsHost()
		{
			return PhotonNetwork.IsMasterClient;
		}
	}
	public enum Team
	{
		Hider,
		Seeker
	}
}
namespace Hide_and_PEAK.Voice
{
	public class SoundPlayer : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <LoadSounds>d__8 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public SoundPlayer <>4__this;

			private string <soundsFolder>5__1;

			private string[] <files>5__2;

			private float <startTime>5__3;

			private float <currentTime>5__4;

			private string[] <>s__5;

			private int <>s__6;

			private string <file>5__7;

			private UnityWebRequest <www>5__8;

			private AudioClip <clip>5__9;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadSounds>d__8(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<soundsFolder>5__1 = null;
				<files>5__2 = null;
				<>s__5 = null;
				<file>5__7 = null;
				<www>5__8 = null;
				<clip>5__9 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				//IL_016b: Invalid comparison between Unknown and I4
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<soundsFolder>5__1 = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "sounds");
						if (!Directory.Exists(<soundsFolder>5__1))
						{
							Plugin.Log.LogWarning((object)("[SoundPlayer] Sounds folder not found: " + <soundsFolder>5__1));
							return false;
						}
						<files>5__2 = Directory.GetFiles(<soundsFolder>5__1, "*.wav");
						if (<files>5__2.Length == 0)
						{
							Plugin.Log.LogWarning((object)("[SoundPlayer] No WAV files found in: " + <soundsFolder>5__1));
							return false;
						}
						Plugin.Log.LogInfo((object)$"[SoundPlayer] Loading {<files>5__2.Length} sound files...");
						<>s__5 = <files>5__2;
						<>s__6 = 0;
						break;
					case 1:
						<>1__state = -3;
						if ((int)<www>5__8.result != 1)
						{
							Plugin.Log.LogError((object)("[SoundPlayer] Failed to load " + Path.GetFileName(<file>5__7) + ": " + <www>5__8.error));
						}
						else
						{
							<clip>5__9 = DownloadHandlerAudioClip.GetContent(<www>5__8);
							((Object)<clip>5__9).name = Path.GetFileNameWithoutExtension(<file>5__7);
							<>4__this.loadedClips.Add(<clip>5__9);
							<>4__this.clipLookup[((Object)<clip>5__9).name] = <clip>5__9;
							Plugin.Log.LogInfo((object)("[SoundPlayer] Loaded: " + ((Object)<clip>5__9).name));
							<clip>5__9 = null;
						}
						<>m__Finally1();
						<www>5__8 = null;
						<file>5__7 = null;
						<>s__6++;
						break;
					}
					if (<>s__6 < <>s__5.Length)
					{
						<file>5__7 = <>s__5[<>s__6];
						<www>5__8 = UnityWebRequestMultimedia.GetAudioClip("file:///" + <file>5__7, (AudioType)20);
						<>1__state = -3;
						<>2__current = <www>5__8.SendWebRequest();
						<>1__state = 1;
						return true;
					}
					<>s__5 = null;
					<>4__this.isLoaded = true;
					<startTime>5__3 = Plugin.ConfigurationHandler.ConfigTauntStartTime.Value;
					<currentTime>5__4 = (((Object)(object)PlayerStats.Instance != (Object)null) ? PlayerStats.Instance._currentTime : 0f);
					<>4__this.nextSoundTime = <currentTime>5__4 + <startTime>5__3;
					Plugin.Log.LogInfo((object)$"[SoundPlayer] Finished loading {<>4__this.loadedClips.Count} sounds. First sound at {<>4__this.nextSoundTime:F2}s");
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<www>5__8 != null)
				{
					((IDisposable)<www>5__8).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private List<AudioClip> loadedClips = new List<AudioClip>();

		private Dictionary<string, AudioClip> clipLookup = new Dictionary<string, AudioClip>();

		private bool isLoaded = false;

		public static SoundPlayer Instance;

		public float nextSoundTime;

		public float soundInterval = Plugin.ConfigurationHandler.ConfigTauntIntervalTime.Value;

		private void Start()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				((MonoBehaviour)this).StartCoroutine(LoadSounds());
			}
			else
			{
				Plugin.Log.LogWarning((object)"[SoundPlayer] Instance already exists, destroying old one.");
				Object.Destroy((Object)(object)Instance);
				Instance = this;
			}
		}

		private void Update()
		{
			if (isLoaded && !((Object)(object)PlayerStats.Instance == (Object)null) && HideAndSeekManager.Instance.IsGameActive && HideAndSeekManager.Instance.IsHost())
			{
				float currentTime = PlayerStats.Instance._currentTime;
				if (currentTime >= nextSoundTime)
				{
					PlayRandomSound();
					nextSoundTime += soundInterval;
					Plugin.Log.LogInfo((object)$"[SoundPlayer] Host triggered sound at {currentTime:F2}s, next at {nextSoundTime:F2}s");
				}
			}
		}

		[IteratorStateMachine(typeof(<LoadSounds>d__8))]
		private IEnumerator LoadSounds()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadSounds>d__8(0)
			{
				<>4__this = this
			};
		}

		public void PlayRandomSound()
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			if (!isLoaded || loadedClips.Count == 0)
			{
				Plugin.Log.LogWarning((object)"[SoundPlayer] No sounds loaded yet!");
				return;
			}
			Plugin.Log.LogInfo((object)"[SoundPlayer: PlayRandomSound] Host triggering random sound");
			if (!HideAndSeekManager.Instance.IsHost() || !Plugin.ConfigurationHandler.ConfigTauntsEnabled.Value)
			{
				return;
			}
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (((Dictionary<object, object>)(object)allCharacter.view.Controller.CustomProperties).TryGetValue((object)"Team", out object value) && (Team)value == Team.Hider)
				{
					AudioClip val = loadedClips[Random.Range(0, loadedClips.Count)];
					Vector3 cameraPos = allCharacter.GetCameraPos(0f);
					HideAndSeekManager.Instance.View.RPC("RPC_PlaySound", (RpcTarget)0, new object[2]
					{
						((Object)val).name,
						cameraPos
					});
					Plugin.Log.LogInfo((object)$"[SoundPlayer: PlayRandomSound] Host broadcasting sound: {((Object)val).name} at {cameraPos}");
				}
			}
		}

		[PunRPC]
		public void RPC_PlaySound(string clipName, Vector3 pos)
		{
			//IL_0049: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_00ab: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if (!clipLookup.TryGetValue(clipName, out AudioClip value))
			{
				Plugin.Log.LogWarning((object)("[SoundPlayer] Clip not found on client: " + clipName));
				return;
			}
			SFX_Instance val = ScriptableObject.CreateInstance<SFX_Instance>();
			val.clips = (AudioClip[])(object)new AudioClip[1] { value };
			val.settings = new SFX_Settings
			{
				volume = 1f,
				pitch = 1f,
				pitch_Variation = 0.2f,
				cooldown = 0.1f,
				spatialBlend = 1f,
				volume_Variation = 0.4f,
				dopplerLevel = 0f,
				range = 450f
			};
			val.Play(pos);
			Plugin.Log.LogInfo((object)$"[SoundPlayer] Playing clip via RPC: {clipName} at {pos}");
		}
	}
}
namespace Hide_and_PEAK.UI
{
	public class DeathLog : MonoBehaviour
	{
		private TMP_Text _text;

		public static DeathLog Instance;

		private readonly List<(string message, float expires)> _deaths = new List<(string, float)>();

		private readonly StringBuilder _sb = new StringBuilder(256);

		private const float Lifetime = 5f;

		private void Start()
		{
			//IL_00b3: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this)
			{
				Plugin.Log.LogWarning((object)"[DeathLog] Instance already exists, replacing.");
				Object.Destroy((Object)(object)((Component)Instance).gameObject);
			}
			Instance = this;
			_text = ((Component)this).GetComponent<TMP_Text>();
			if ((Object)(object)_text == (Object)null)
			{
				Plugin.Log.LogError((object)"[DeathLog] No TMP_Text found!");
				((Behaviour)this).enabled = false;
				return;
			}
			_text.autoSizeTextContainer = true;
			_text.textWrappingMode = (TextWrappingModes)0;
			_text.alignment = (TextAlignmentOptions)260;
			((Graphic)_text).color = Color.white;
			_text.fontSize = 26f;
			_text.outlineColor = Color32.op_Implicit(Color.black);
			_text.outlineWidth = 0.06f;
			_text.lineSpacing = -30f;
			_text.text = "";
		}

		private void Update()
		{
			if ((Object)(object)_text == (Object)null)
			{
				return;
			}
			_sb.Clear();
			_sb.Append("\n ");
			_sb.Append("\n ");
			float time = Time.time;
			for (int num = _deaths.Count - 1; num >= 0; num--)
			{
				(string message, float expires) tuple = _deaths[num];
				string item = tuple.message;
				float item2 = tuple.expires;
				float num2 = item2 - time;
				if (num2 <= 0f)
				{
					_deaths.RemoveAt(num);
				}
				else
				{
					float num3 = Mathf.Clamp01(num2 / 5f);
					int num4 = Mathf.RoundToInt(num3 * 255f);
					_sb.Append(item.Replace("{alpha}", num4.ToString("X2")));
					_sb.Append('\n');
				}
			}
			_text.text = _sb.ToString();
		}

		public void AddDeath(PhotonView seeker, PhotonView hider)
		{
			Plugin.Log.LogInfo((object)"[DeathLog] Adding death");
			string text = "FF5555";
			string text2 = "55AAFF";
			if (seeker.Owner != null && ((Dictionary<object, object>)(object)seeker.Owner.CustomProperties).TryGetValue((object)"NameColour", out object value))
			{
				text = (string)value;
			}
			if (hider.Owner != null && ((Dictionary<object, object>)(object)hider.Owner.CustomProperties).TryGetValue((object)"NameColour", out object value2))
			{
				text2 = (string)value2;
			}
			Player owner = seeker.Owner;
			string text3 = FilterName((owner != null) ? owner.NickName : null);
			Player owner2 = hider.Owner;
			string text4 = FilterName((owner2 != null) ? owner2.NickName : null);
			string text5 = "<color=#" + text + "{alpha}>" + text3 + "</color>";
			string text6 = "<color=#" + text2 + "{alpha}>" + text4 + "</color>";
			string text7 = "<color=#FFFFFF{alpha}> found </color>";
			string item = text5 + text7 + text6;
			_deaths.Add((item, Time.time + 5f));
			Plugin.Log.LogInfo((object)"[DeathLog] Death added");
		}

		public void AddWorldDeath(PhotonView hider)
		{
			Plugin.Log.LogInfo((object)"[DeathLog] Adding world death");
			string text = "FFFFFF";
			string text2 = "55AAFF";
			if (hider.Owner != null && ((Dictionary<object, object>)(object)hider.Owner.CustomProperties).TryGetValue((object)"NameColour", out object value))
			{
				text2 = (string)value;
			}
			Player owner = hider.Owner;
			string text3 = FilterName((owner != null) ? owner.NickName : null);
			string text4 = "<color=#" + text + "{alpha}>Death</color>";
			string text5 = "<color=#" + text2 + "{alpha}>" + text3 + "</color>";
			string text6 = "<color=#FFFFFF{alpha}> found </color>";
			string item = text4 + text6 + text5;
			_deaths.Add((item, Time.time + 5f));
			Plugin.Log.LogInfo((object)"[DeathLog] Death added");
		}

		private string FilterName(string input)
		{
			if (!string.IsNullOrEmpty(input))
			{
				TMP_Text text = _text;
				if (!((Object)(object)((text != null) ? text.font : null) == (Object)null))
				{
					input = input.Replace("<", "").Replace(">", "");
					TMP_FontAsset font = _text.font;
					StringBuilder stringBuilder = new StringBuilder(input.Length);
					string text2 = input;
					foreach (char c in text2)
					{
						if (font.HasCharacter(c, false, false))
						{
							stringBuilder.Append(c);
						}
					}
					return (stringBuilder.Length > 0) ? stringBuilder.ToString() : "Unknown";
				}
			}
			return "Unknown";
		}

		public static void InitiateDeathLog()
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)Instance).gameObject);
				Instance = null;
			}
			AscentUI val = Object.FindAnyObjectByType<AscentUI>();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"[DeathLog] Could not find AscentUI parent!");
				return;
			}
			GameObject val2 = new GameObject("DeathLog UI", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			RectTransform component = val2.GetComponent<RectTransform>();
			((Transform)component).SetParent(((Component)val).transform.parent, false);
			((Transform)component).localScale = Vector3.one;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(1f, 1f);
			component.anchorMax = val3;
			component.anchorMin = val3;
			component.pivot = new Vector2(1f, 1f);
			component.anchoredPosition = new Vector2(-16f, -16f);
			component.sizeDelta = new Vector2(600f, 200f);
			TMP_Text component2 = ((Component)val).GetComponent<TMP_Text>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)component2.font != (Object)null)
			{
				TextMeshProUGUI component3 = val2.GetComponent<TextMeshProUGUI>();
				((TMP_Text)component3).font = component2.font;
				Plugin.Log.LogInfo((object)("[DeathLog] Copied font from AscentUI: " + ((Object)component2.font).name));
			}
			else
			{
				Plugin.Log.LogWarning((object)"[DeathLog] Could not find font on AscentUI, using default");
			}
			val2.AddComponent<DeathLog>();
			((Transform)component).SetAsLastSibling();
		}
	}
	public class ModConfigurationUI : MenuWindow
	{
		private List<Option> _options = new List<Option>();

		public bool _visible;

		private int _selectedIndex;

		private bool _waitingForBinding = false;

		private Option _bindingTarget;

		private Texture2D _whiteTex;

		private Texture2D _rainbowTex;

		private GUIStyle _titleStyle;

		private GUIStyle _rowStyle;

		private GUIStyle _hintStyle;

		private GUIStyle _buttonStyle;

		private string titleText;

		private string hintText;

		private int RowHeight = 32;

		private int PanelWidth = 460;

		private int Pad = 12;

		private int TitleFontSize = 22;

		private int OptionFontSize = 16;

		private int HintFontSize = 14;

		private const int ButtonWidth = 30;

		private const int ButtonHeight = 30;

		private const int ButtonHintSpacing = 4;

		public static ModConfigurationUI Instance;

		private void Awake()
		{
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)Instance);
			}
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			((MenuWindow)this).StartClosed();
			titleText = "Hide and PEAK Settings | v" + Plugin.Version;
			hintText = "Open/Close • Click: Change • Scroll Wheel: Adjust Numerical Values";
		}

		public void Init(List<Option> options)
		{
			_options = options ?? new List<Option>();
			_selectedIndex = 0;
		}

		private void EnsureStyles()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//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_0089: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00ad: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_whiteTex == (Object)null)
			{
				_whiteTex = new Texture2D(1, 1);
				_whiteTex.SetPixel(0, 0, Color.white);
				_whiteTex.Apply();
			}
			_titleStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = TitleFontSize,
				alignment = (TextAnchor)3,
				fontStyle = (FontStyle)1
			};
			_rowStyle = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)3,
				fontSize = OptionFontSize,
				padding = new RectOffset(10, 10, 4, 4)
			};
			_hintStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = HintFontSize,
				alignment = (TextAnchor)3,
				wordWrap = true
			};
			_buttonStyle = new GUIStyle(GUI.skin.button)
			{
				fontSize = OptionFontSize,
				alignment = (TextAnchor)4
			};
		}

		private void CalculatePanelWidth()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			float num = _titleStyle.CalcSize(new GUIContent(titleText)).x;
			foreach (Option option in _options)
			{
				float x = _rowStyle.CalcSize(new GUIContent(option.Label + ": " + option.DisplayValue())).x;
				if (x > num)
				{
					num = x;
				}
			}
			int num2 = CalculateHintWidth();
			num = Mathf.Max(num, (float)num2);
			PanelWidth = Mathf.Clamp((int)num + Pad * 2, 460, Screen.width - Pad * 2);
		}

		private int CalculateHintWidth()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			float num = _hintStyle.CalcHeight(new GUIContent("Test"), 9999f);
			float num2 = num * 2f;
			for (int i = 200; i < Screen.width - Pad * 2; i += 20)
			{
				float num3 = _hintStyle.CalcHeight(new GUIContent(hintText), (float)i);
				if (num3 <= num2)
				{
					return i;
				}
			}
			return Screen.width - Pad * 2;
		}

		private void Scale(int scale)
		{
			if (scale >= 0 || HintFontSize >= 2)
			{
				TitleFontSize += scale * 2;
				OptionFontSize += scale * 2;
				HintFontSize += scale * 2;
				RowHeight = OptionFontSize + 16;
				CalculatePanelWidth();
			}
		}

		public void ToggleMenu()
		{
			_visible = !_visible;
			if (_visible)
			{
				((MenuWindow)this).Open();
			}
			else
			{
				((MenuWindow)this).Close();
			}
		}

		private void Update()
		{
			//IL_0048: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!_visible || _options.Count == 0)
			{
				return;
			}
			if (_waitingForBinding && ((ButtonControl)Keyboard.current.anyKey).wasPressedThisFrame)
			{
				Enumerator<KeyControl> enumerator = Keyboard.current.allKeys.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						KeyControl current = enumerator.Current;
						if (((ButtonControl)current).wasPressedThisFrame)
						{
							_bindingTarget.StringEntry.Value = ((InputControl)current).path;
							_waitingForBinding = false;
							_bindingTarget = null;
							break;
						}
					}
					return;
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
			}
			if (Input.GetKeyDown((KeyCode)9))
			{
				bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				CycleSelection((!flag) ? 1 : (-1));
			}
			if (Input.GetKeyDown((KeyCode)273))
			{
				CycleSelection(-1);
			}
			if (Input.GetKeyDown((KeyCode)274))
			{
				CycleSelection(1);
			}
			if (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271))
			{
				ToggleSelected();
			}
			if (Input.GetKeyDown((KeyCode)276))
			{
				AdjustInt(-1);
			}
			if (Input.GetKeyDown((KeyCode)275))
			{
				AdjustInt(1);
			}
			float axis = Input.GetAxis("Mouse ScrollWheel");
			if (axis > 0f)
			{
				AdjustInt(1);
			}
			else if (axis < 0f)
			{
				AdjustInt(-1);
			}
		}

		private void ToggleSelected()
		{
			Option option = _options[_selectedIndex];
			if (option.IsDisabled())
			{
				return;
			}
			switch (option.Type)
			{
			case Option.OptionType.Bool:
				option.BoolEntry.Value = !option.BoolEntry.Value;
				break;
			case Option.OptionType.Int:
			{
				int num = option.IntEntry.Value + option.Step;
				if (num > option.MaxInt)
				{
					num = option.MinInt;
				}
				option.IntEntry.Value = num;
				break;
			}
			case Option.OptionType.InputAction:
				_waitingForBinding = true;
				_bindingTarget = option;
				break;
			case Option.OptionType.String:
				break;
			}
		}

		private void AdjustInt(int delta)
		{
			Option option = _options[_selectedIndex];
			if (!option.IsDisabled() && option.Type == Option.OptionType.Int)
			{
				option.IntEntry.Value = Mathf.Clamp(option.IntEntry.Value + delta * option.Step, option.MinInt, option.MaxInt);
			}
		}

		private void CycleSelection(int delta)
		{
			if (_options.Count == 0)
			{
				return;
			}
			int selectedIndex = _selectedIndex;
			do
			{
				_selectedIndex = (_selectedIndex + delta) % _options.Count;
				if (_selectedIndex < 0)
				{
					_selectedIndex += _options.Count;
				}
			}
			while (_options[_selectedIndex].IsDisabled() && _selectedIndex != selectedIndex);
		}

		private void OnGUI()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0478: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			if (!_visible)
			{
				return;
			}
			EnsureStyles();
			CalculatePanelWidth();
			float num = _titleStyle.CalcHeight(new GUIContent(titleText), (float)(PanelWidth - Pad * 2));
			float num2 = _hintStyle.CalcHeight(new GUIContent(hintText), (float)(PanelWidth - Pad * 2));
			List<float> list = new List<float>();
			float num3 = 0f;
			foreach (Option option2 in _options)
			{
				float num4 = RowHeight;
				if (option2.Type == Option.OptionType.Colour)
				{
					float num5 = _rowStyle.CalcHeight(new GUIContent("Name Color"), (float)(PanelWidth - Pad * 2));
					float num6 = 16f;
					num4 = num5 + num6 + 4f;
				}
				list.Add(num4);
				num3 += num4 + 4f;
			}
			int num7 = Pad + (int)num + 8 + (int)num3 + RowHeight * 2 + 16 + Pad + (int)num2 + 30 + 4;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(20f, 20f, (float)PanelWidth, (float)num7);
			GUI.color = new Color(0f, 0f, 0f, 0.75f);
			GUI.DrawTexture(val, (Texture)(object)_whiteTex);
			GUI.color = Color.white;
			GUI.Label(new Rect(((Rect)(ref val)).x + (float)Pad, ((Rect)(ref val)).y + (float)Pad, ((Rect)(ref val)).width - (float)(Pad * 2), num), titleText, _titleStyle);
			float num8 = ((Rect)(ref val)).y + (float)Pad + num + 8f;
			Rect val2 = default(Rect);
			for (int i = 0; i < _options.Count; i++)
			{
				Option option = _options[i];
				float num9 = list[i];
				((Rect)(ref val2))..ctor(((Rect)(ref val)).x + (float)Pad, num8, ((Rect)(ref val)).width - (float)(Pad * 2), num9);
				if (((Rect)(ref val2)).Contains(Event.current.mousePosition) && !option.IsDisabled())
				{
					GUI.color = new Color(1f, 1f, 1f, 0.24f);
					GUI.DrawTexture(val2, (Texture)(object)_whiteTex);
					GUI.color = Color.white;
					_selectedIndex = i;
				}
				switch (option.Type)
				{
				case Option.OptionType.Bool:
					DrawBoolOption(option, val2);
					break;
				case Option.OptionType.Int:
					DrawIntOption(option, val2);
					break;
				case Option.OptionType.InputAction:
					DrawInputActionOption(option, val2);
					break;
				case Option.OptionType.Colour:
					DrawColourOption(option, val2);
					break;
				}
				num8 += num9 + 4f;
			}
			float num10 = RowHeight;
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref val)).x + (float)Pad, num8, ((Rect)(ref val)).width - (float)(Pad * 2), num10);
			GUI.Label(val3, "Jump to Segment", _titleStyle);
			num8 += num10 + 4f;
			string[] names = Enum.GetNames(typeof(Segment));
			List<string> list2 = new List<string>();
			string[] array = names;
			foreach (string text in array)
			{
				if (!text.Equals("Peak", StringComparison.OrdinalIgnoreCase))
				{
					list2.Add(text);
				}
			}
			int count = list2.Count;
			float num11 = (float)RowHeight * 1.1f;
			float num12 = 10f;
			float num13 = ((Rect)(ref val)).width - (float)(Pad * 2);
			float num14 = (num13 - (float)(count - 1) * num12) / (float)count;
			float num15 = ((Rect)(ref val)).x + (float)Pad;
			float num16 = num8;
			Rect val4 = default(Rect);
			for (int k = 0; k < count; k++)
			{
				((Rect)(ref val4))..ctor(num15, num16, num14, num11);
				GUI.color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
				GUI.DrawTexture(val4, (Texture)(object)_whiteTex);
				GUI.color = Color.white;
				if (GUI.Button(val4, list2[k], _buttonStyle))
				{
					try
					{
						if (PhotonNetwork.IsMasterClient)
						{
							Segment val5 = (Segment)Enum.Parse(typeof(Segment), list2[k]);
							MapHandler.JumpToSegment(val5);
						}
					}
					catch (Exception arg)
					{
						Plugin.Log.LogError((object)$"Failed to jump to segment {list2[k]}: {arg}");
					}
				}
				num15 += num14 + num12;
			}
			num8 = num16 + num11 + 8f;
			Rect val6 = default(Rect);
			((Rect)(ref val6))..ctor(((Rect)(ref val)).x + (float)Pad, num8, ((Rect)(ref val)).width - (float)(Pad * 2), num2);
			GUI.Label(val6, hintText, _hintStyle);
			num16 = ((Rect)(ref val6)).yMax + 4f;
			if (GUI.Button(new Rect(((Rect)(ref val)).xMax - 60f - (float)Pad, num16, 30f, 30f), "+", _buttonStyle))
			{
				Scale(1);
			}
			if (GUI.Button(new Rect(((Rect)(ref val)).xMax - 30f - (float)Pad, num16, 30f, 30f), "-", _buttonStyle))
			{
				Scale(-1);
			}
		}

		private void DrawBoolOption(Option option, Rect rect)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
			GUI.DrawTexture(rect, (Texture)(object)_whiteTex);
			GUI.color = Color.white;
			if (GUI.Button(rect, option.Label + ": " + (option.BoolEntry.Value ? "On" : "Off"), _rowStyle))
			{
				option.BoolEntry.Value = !option.BoolEntry.Value;
			}
		}

		private void DrawIntOption(Option option, Rect rect)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
			GUI.DrawTexture(rect, (Texture)(object)_whiteTex);
			GUI.color = Color.white;
			if (GUI.Button(rect, $"{option.Label}: {option.IntEntry.Value}", _rowStyle))
			{
				ConfigEntry<int> intEntry = option.IntEntry;
				intEntry.Value += option.Step;
			}
		}

		private void DrawInputActionOption(Option option, Rect rect)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
			GUI.DrawTexture(rect, (Texture)(object)_whiteTex);
			GUI.color = Color.white;
			string text = ((_waitingForBinding && option == _bindingTarget) ? "Press any key..." : option.StringEntry.Value.Split("/")[^1].ToUpper());
			if (GUI.Button(rect, option.Label + ": " + text, _rowStyle) && !_waitingForBinding)
			{
				_waitingForBinding = true;
				_bindingTarget = option;
			}
		}

		private void DrawColourOption(Option option, Rect rowRect)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Invalid comparison between Unknown and I4
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<int> nameColourR = Plugin.ConfigurationHandler.NameColourR;
			ConfigEntry<int> nameColourG = Plugin.ConfigurationHandler.NameColourG;
			ConfigEntry<int> nameColourB = Plugin.ConfigurationHandler.NameColourB;
			GUI.color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
			GUI.DrawTexture(rowRect, (Texture)(object)_whiteTex);
			GUI.color = Color.white;
			float num = _rowStyle.CalcHeight(new GUIContent("Name Colour"), ((Rect)(ref rowRect)).width);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref rowRect)).x + 4f, ((Rect)(ref rowRect)).y + 2f, ((Rect)(ref rowRect)).width - 8f, num);
			GUI.Label(val, "Name Colour", _rowStyle);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref rowRect)).x + 4f, ((Rect)(ref rowRect)).y + num + 2f, ((Rect)(ref rowRect)).width - 48f, 16f);
			EnsureRainbowTexture((int)((Rect)(ref val2)).width);
			GUI.DrawTexture(val2, (Texture)(object)_rainbowTex);
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref rowRect)).x + ((Rect)(ref rowRect)).width - 40f, ((Rect)(ref val2)).y, 36f, ((Rect)(ref val2)).height);
			GUI.color = new Color((float)nameColourR.Value / 255f, (float)nameColourG.Value / 255f, (float)nameColourB.Value / 255f);
			GUI.DrawTexture(val3, (Texture)(object)_whiteTex);
			GUI.color = Color.white;
			Event current = Event.current;
			if (((int)current.type == 0 || (int)current.type == 3) && ((Rect)(ref val2)).Contains(current.mousePosition))
			{
				float t = Mathf.Clamp01((current.mousePosition.x - ((Rect)(ref val2)).x) / ((Rect)(ref val2)).width);
				Color val4 = ColourFromRainbow(t);
				nameColourR.Value = Mathf.RoundToInt(val4.r * 255f);
				nameColourG.Value = Mathf.RoundToInt(val4.g * 255f);
				nameColourB.Value = Mathf.RoundToInt(val4.b * 255f);
				current.Use();
			}
		}

		private void EnsureRainbowTexture(int width = 256)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_rainbowTex != (Object)null))
			{
				_rainbowTex = new Texture2D(width, 1);
				for (int i = 0; i < width; i++)
				{
					float t = (float)i / (float)(width - 1);
					_rainbowTex.SetPixel(i, 0, ColourFromRainbow(t));
				}
				_rainbowTex.Apply();
			}
		}

		private Color ColourFromRainbow(float t)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			return Color.HSVToRGB(t, 1f, 1f);
		}

		private void OnDestroy()
		{
			if ((Object)(object)_whiteTex != (Object)null)
			{
				Object.Destroy((Object)(object)_whiteTex);
			}
			if ((Object)(object)_rainbowTex != (Object)null)
			{
				Object.Destroy((Object)(object)_rainbowTex);
			}
		}
	}
	public class PlayerStats : MonoBehaviour
	{
		private TMP_Text _text;

		private float _deathTime = 0f;

		public float _currentTime = 0f;

		public float _startTime = 0f;

		public static PlayerStats Instance;

		public string _currentTimeString = "";

		private string FormatTime(float totalSeconds)
		{
			int num = Mathf.FloorToInt(totalSeconds);
			return $"{num / 3600}:{num % 3600 / 60:00}:{num % 60:00}";
		}

		private void Start()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				_text = ((Component)this).GetComponent<TMP_Text>();
				if ((Object)(object)_text == (Object)null)
				{
					Plugin.Log.LogError((object)"[PlayerStats] No TMP_Text found on object!");
					((Behaviour)this).enabled = false;
					return;
				}
				_text.autoSizeTextContainer = true;
				_text.textWrappingMode = (TextWrappingModes)0;
				_text.alignment = (TextAlignmentOptions)258;
				((Graphic)_text).color = Color.white;
				_text.fontSize = 34f;
				_text.outlineColor = Color32.op_Implicit(Color.black);
				_text.outlineWidth = 0.06f;
				_text.lineSpacing = -30f;
				ResetTimer();
			}
			else
			{
				Plugin.Log.LogWarning((object)"[PlayerStats] Instance already exists, destroying old one.");
				Object.Destroy((Object)(object)Instance);
				Instance = this;
			}
		}

		public void ResetStats()
		{
			ResetTimer();
		}

		private void ResetTimer()
		{
			_startTime = Time.time;
		}

		public void SetCurrentTimeFromHost(float currentTimeFromHost)
		{
			_startTime = Time.time - currentTimeFromHost;
			_currentTime = currentTimeFromHost;
			_currentTimeString = FormatTime(_currentTime);
			Plugin.Log.LogInfo((object)("[PlayerStats] Synced _currentTime from host: " + _currentTimeString));
		}

		private void Update()
		{
			if (!((Object)(object)_text == (Object)null) && !((Object)(object)Character.localCharacter == (Object)null))
			{
				CharacterStats stats = Character.localCharacter.refs.stats;
				_currentTime = Time.time - _startTime;
				_currentTimeString = FormatTime(_currentTime);
				if (HideAndSeekManager.Instance.IsGameActive)
				{
					_text.text = $"{_currentTimeString}\n{stats.heightInMeters}m";
				}
				else
				{
					_text.text = $"{stats.heightInMeters}m";
				}
			}
		}

		public static void InitiatePlayerStats()
		{
			//IL_008e: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance == (Object)null)
			{
				AscentUI val = Object.FindAnyObjectByType<AscentUI>();
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogError((object)"[Plugin] Could not find AscentUI to clone!");
					return;
				}
				Transform obj = Object.Instantiate<Transform>(((Component)val).transform, ((Component)val).transform.parent);
				RectTransform val2 = (RectTransform)(object)((obj is RectTransform) ? obj : null);
				((Object)val2).name = "Player Stats UI";
				Object.Destroy((Object)(object)((Component)val2).GetComponent<AscentUI>());
				((Component)val2).gameObject.AddComponent<PlayerStats>();
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(0.5f, 1f);
				val2.anchorMax = val3;
				val2.anchorMin = val3;
				val2.pivot = new Vector2(0.5f, 1f);
				val2.anchoredPosition = Vector2.zero;
			}
			else
			{
				Instance.ResetStats();
			}
		}
	}
	public class ScoreBoardUI : MenuWindow
	{
		public bool showUI = false;

		public bool isGameOverMode = false;

		public float gameOverCountdown = 0f;

		private int _currentMatchIndex = -1;

		private GUIStyle panelStyle;

		private GUIStyle headerStyle;

		private GUIStyle teamHeaderStyle;

		private GUIStyle playerStyle;

		private GUIStyle buttonStyle;

		private bool stylesCreated = false;

		public bool IsOpenMode = false;

		private Vector2 scrollPos;

		private string elapsedTime = "00:00";

		public static ScoreBoardUI Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				((MenuWindow)this).StartClosed();
				Plugin.Log.LogInfo((object)"[ScoreBoardUI] Awake: Scoreboard UI initialized.");
			}
			else
			{
				Plugin.Log.LogWarning((object)"[ScoreBoardUI] Instance already exists, destroying old one.");
				Object.Destroy((Object)(object)Instance);
				Instance = this;
			}
		}

		private void OnGUI()
		{
			if (showUI)
			{
				if (!stylesCreated)
				{
					CreateGUIStyles();
					stylesCreated = true;
				}
				UpdateElapsedTime();
				DrawScoreBoard();
			}
		}

		public void SetScoreBoardUI(bool visible)
		{
			showUI = visible;
			if (visible)
			{
				((MenuWindow)this).Open();
			}
			else
			{
				((MenuWindow)this).Close();
			}
		}

		public void UpdateElapsedTime()
		{
			if ((Object)(object)PlayerStats.Instance != (Object)null)
			{
				elapsedTime = PlayerStats.Instance._currentTimeString;
			}
		}

		private void CreateGUIStyles()
		{
			panelStyle = UIHelper.CreatePanelStyle();
			headerStyle = UIHelper.CreateLabelStyle(28, (TextAnchor)4, bold: true);
			teamHeaderStyle = UIHelper.CreateLabelStyle(18, (TextAnchor)3, bold: true);
			playerStyle = UIHelper.CreateLabelStyle(16, (TextAnchor)3, bold: true);
			buttonStyle = UIHelper.CreateLabelStyle(16, (TextAnchor)4);
		}

		private void DrawScoreBoard()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)Screen.width * 0.75f;
			float num2 = (float)Screen.height * 0.8f;
			float num3 = (float)Screen.width / 2f - num / 2f;
			float num4 = (float)Screen.height * 0.1f;
			GUILayout.BeginArea(new Rect(num3, num4, num, num2), panelStyle);
			float num5 = num2 * 0.12f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(0f, 0f, num, num5 * 0.6f);
			string text;
			if (_currentMatchIndex >= 0 && _currentMatchIndex < MatchHistoryManager.Matches.Count)
			{
				MatchResult matchResult = MatchHistoryManager.Matches[_currentMatchIndex];
				text = "Match: " + matchResult.Date + " | Duration: " + FormatTime(matchResult.Duration);
			}
			else
			{
				text = (isGameOverMode ? "GAME OVER!" : "Hide & Seek Scoreboard");
			}
			GUI.Label(val, text, headerStyle);
			string text2 = (isGameOverMode ? $"Restarting: {Mathf.CeilToInt(gameOverCountdown)}s" : ((_currentMatchIndex >= 0) ? "" : ("Time: " + elapsedTime)));
			Vector2 val2 = headerStyle.CalcSize(new GUIContent(text2));
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(num - val2.x - 10f, 0f, val2.x, num5 * 0.6f);
			GUI.Label(val3, text2, headerStyle);
			GUILayout.Space(num5 * 0.65f);
			scrollPos = GUILayout.BeginScrollView(scrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			float rowHeight = num2 * 0.05f;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (DrawFlatButton("< Previous", new Color(0.25f, 0.5f, 1f)))
			{
				ShowPreviousMatch();
			}
			GUILayout.FlexibleSpace();
			if (DrawFlatButton("Next >", new Color(1f, 0.55f, 0.2f)))
			{
				ShowNextMatch();
			}
			GUILayout.EndHorizontal();
			if (_currentMatchIndex >= 0 && _currentMatchIndex < MatchHistoryManager.Matches.Count)
			{
				DrawMatch(MatchHistoryManager.Matches[_currentMatchIndex], rowHeight);
			}
			else
			{
				DrawLiveGame(rowHeight);
			}
			GUILayout.EndScrollView();
			GUILayout.EndArea();
		}

		private bool DrawFlatButton(string text, Color baseColor)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_000d: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = buttonStyle.CalcSize(new GUIContent(text));
			Rect rect = GUILayoutUtility.GetRect(val.x + 20f, val.y + 8f);
			Color val2 = baseColor;
			if (((Rect)(ref rect)).Contains(Event.current.mousePosition))
			{
				val2 *= 1.2f;
			}
			UIHelper.DrawBackground(rect, val2);
			GUI.Label(rect, text, buttonStyle);
			return GUI.Button(rect, GUIContent.none, GUIStyle.none);
		}

		private void DrawMatch(MatchResult match, float rowHeight)
		{
			DrawTeamHeaderFromHistory(match.PlayerResults, Team.Hider);
			foreach (PlayerResult playerResult in match.PlayerResults)
			{
				if (playerResult.Team == Team.Hider)
				{
					DrawPlayerRowFromHistory(playerResult, rowHeight);
				}
			}
			DrawTeamHeaderFromHistory(match.PlayerResults, Team.Seeker);
			foreach (PlayerResult playerResult2 in match.PlayerResults)
			{
				if (playerResult2.Team == Team.Seeker)
				{
					DrawPlayerRowFromH