Decompiled source of STRAFTAT Gun Game Plus v1.1.3

GunGamePlus.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Object;
using GunGamePlus.Config;
using GunGamePlus.Core;
using GunGamePlus.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("AshenDemon")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.3.0")]
[assembly: AssemblyInformationalVersion("1.1.3")]
[assembly: AssemblyProduct("GunGamePlus")]
[assembly: AssemblyTitle("GunGamePlus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 GunGamePlus
{
	[BepInPlugin("com.ashendemon.gungameplus", "Gun Game Plus", "1.1.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class GunGamePlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.ashendemon.gungameplus";

		public const string PluginName = "Gun Game Plus";

		public const string PluginAuthor = "AshenDemon";

		public const string PluginVersion = "1.1.3";

		private Harmony _harmony;

		private float _lastDeadCheckTime;

		public static GunGamePlugin Instance { get; private set; }

		public static ManualLogSource LogSource { get; private set; }

		private void Awake()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			Instance = this;
			LogSource = ((BaseUnityPlugin)this).Logger;
			LogSource.LogInfo((object)"[GunGamePlus] Initializing Gun Game Plus v1.1.3 by AshenDemon...");
			GunGameConfig.Initialize(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.ashendemon.gungameplus");
			try
			{
				PatchManager.ApplyPatches(_harmony);
				LogSource.LogInfo((object)"[GunGamePlus] All Harmony patches successfully verified and applied.");
			}
			catch (Exception arg)
			{
				LogSource.LogError((object)$"[GunGamePlus] Error applying patches: {arg}");
			}
			WeaponPool.RefreshWeaponPrefabs();
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			GunGameManager.ResetMatchState();
			if (GunGameConfig.IsProgressiveMode)
			{
				GunGameConfig.GenerateProgressiveLadder(announce: false);
			}
			else if (GunGameConfig.IsRandomMode)
			{
				GunGameConfig.RandomizeLadder(announce: false);
			}
		}

		private void Update()
		{
			//IL_0043: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (!GunGameConfig.Enabled.Value)
			{
				return;
			}
			GunGameRespawnManager.ServerCheckAllPlayersAlive();
			MaintainWeaponAmmo();
			RecoverStuckCameraWatchdog();
			if (GunGameConfig.EnableDebugKeys == null || !GunGameConfig.EnableDebugKeys.Value)
			{
				return;
			}
			KeyboardShortcut value;
			if (GunGameConfig.DebugNextTierShortcut != null)
			{
				value = GunGameConfig.DebugNextTierShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					GunGameManager.SimulateLocalKill(GetLocalPlayerId());
				}
			}
			if (GunGameConfig.DebugPrevTierShortcut != null)
			{
				value = GunGameConfig.DebugPrevTierShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					GunGameManager.SimulateLocalDemote(GetLocalPlayerId());
				}
			}
			if (GunGameConfig.DebugKillShortcut != null)
			{
				value = GunGameConfig.DebugKillShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					TriggerLocalSuicide();
				}
			}
			if (GunGameConfig.DebugRandomizeShortcut == null)
			{
				return;
			}
			value = GunGameConfig.DebugRandomizeShortcut.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				if (GunGameConfig.IsProgressiveMode)
				{
					GunGameConfig.GenerateProgressiveLadder();
				}
				else
				{
					GunGameConfig.RandomizeLadder();
				}
			}
		}

		private void RecoverStuckCameraWatchdog()
		{
			if (GunGameManager.IsMatchOver || ((Object)(object)PauseManager.Instance != (Object)null && (PauseManager.Instance.inMainMenu || PauseManager.Instance.inVictoryMenu)))
			{
				return;
			}
			int num = GetLocalPlayerId();
			ClientInstance val = null;
			foreach (KeyValuePair<int, ClientInstance> playerInstance in ClientInstance.playerInstances)
			{
				if ((Object)(object)playerInstance.Value != (Object)null && ((NetworkBehaviour)playerInstance.Value).IsOwner)
				{
					num = playerInstance.Key;
					val = playerInstance.Value;
					break;
				}
			}
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			PlayerManager component = ((Component)val).GetComponent<PlayerManager>();
			FirstPersonController val2 = component?.player;
			if ((Object)(object)val2 == (Object)null)
			{
				FirstPersonController[] array = Object.FindObjectsOfType<FirstPersonController>();
				foreach (FirstPersonController val3 in array)
				{
					if ((Object)(object)val3 != (Object)null && ((NetworkBehaviour)val3).IsOwner)
					{
						val2 = val3;
						if ((Object)(object)component != (Object)null)
						{
							component.player = val3;
						}
						break;
					}
				}
			}
			if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeInHierarchy)
			{
				PlayerHealth component2 = ((Component)val2).GetComponent<PlayerHealth>();
				if ((Object)(object)component2 != (Object)null && !component2.sync___get_value_isKilled() && component2.sync___get_value_health() > 0f)
				{
					_lastDeadCheckTime = 0f;
					GameObject val4 = GameObject.Find("Main Camera");
					if ((Object)(object)val4 != (Object)null)
					{
						Camera component3 = val4.GetComponent<Camera>();
						if ((Object)(object)component3 != (Object)null && ((Behaviour)component3).enabled)
						{
							((Behaviour)component3).enabled = false;
						}
						AudioListener component4 = val4.GetComponent<AudioListener>();
						if ((Object)(object)component4 != (Object)null && ((Behaviour)component4).enabled)
						{
							((Behaviour)component4).enabled = false;
						}
						KillCam component5 = val4.GetComponent<KillCam>();
						if ((Object)(object)component5 != (Object)null && (component5.isDead || component5.ragdollCam))
						{
							component5.isDead = false;
							component5.ragdollCam = false;
							component5.enemy = null;
							component5.ragdoll = null;
						}
					}
					if ((Object)(object)val2.playerCamera != (Object)null && !((Behaviour)val2.playerCamera).enabled)
					{
						((Behaviour)val2.playerCamera).enabled = true;
						((Component)val2.playerCamera).gameObject.SetActive(true);
						AudioListener component6 = ((Component)val2.playerCamera).GetComponent<AudioListener>();
						if ((Object)(object)component6 != (Object)null && !((Behaviour)component6).enabled)
						{
							((Behaviour)component6).enabled = true;
						}
					}
					if (!val2.sync___get_value_canMove())
					{
						val2.sync___set_value_canMove(true, true);
					}
					val2.startOfRound = false;
					return;
				}
			}
			if (_lastDeadCheckTime == 0f)
			{
				_lastDeadCheckTime = Time.time;
			}
			else
			{
				if (!(Time.time - _lastDeadCheckTime > 3f))
				{
					return;
				}
				_lastDeadCheckTime = Time.time;
				if ((Object)(object)InstanceFinder.NetworkManager != (Object)null && InstanceFinder.NetworkManager.IsServer)
				{
					ManualLogSource logSource = LogSource;
					if (logSource != null)
					{
						logSource.LogWarning((object)$"[GunGamePlus] Watchdog triggering delayed respawn for stuck player {num}");
					}
					GunGameRespawnManager.ScheduleRespawn(num);
				}
			}
		}

		private void MaintainWeaponAmmo()
		{
			if (GunGameConfig.UnlimitedAmmo == null || !GunGameConfig.UnlimitedAmmo.Value)
			{
				return;
			}
			try
			{
				PlayerPickup val = FindPickupForPlayer(GetLocalPlayerId());
				if ((Object)(object)val != (Object)null)
				{
					RefillWeapon(val.sync___get_value_objInHand());
					if (val.sync___get_value_hasObjectInLeftHand())
					{
						RefillWeapon(val.sync___get_value_objInLeftHand());
					}
				}
			}
			catch
			{
			}
		}

		private void RefillWeapon(GameObject weaponObj)
		{
			if ((Object)(object)weaponObj == (Object)null)
			{
				return;
			}
			Weapon component = weaponObj.GetComponent<Weapon>();
			if (!((Object)(object)component != (Object)null))
			{
				return;
			}
			string weaponName = WeaponPool.CleanWeaponName(((Object)weaponObj).name);
			if (WeaponPool.IsThrowable(weaponName) || WeaponPool.IsPlaceable(weaponName))
			{
				return;
			}
			component.needsAmmo = false;
			if (component.currentAmmo > 1)
			{
				return;
			}
			component.currentAmmo = 100;
			try
			{
				component.sync___set_value_currentAmmo(100, true);
			}
			catch
			{
			}
		}

		private int GetLocalPlayerId()
		{
			try
			{
				foreach (KeyValuePair<int, ClientInstance> playerInstance in ClientInstance.playerInstances)
				{
					if ((Object)(object)playerInstance.Value != (Object)null && ((NetworkBehaviour)playerInstance.Value).IsOwner)
					{
						return playerInstance.Key;
					}
				}
			}
			catch
			{
			}
			return 0;
		}

		private void TriggerLocalSuicide()
		{
			try
			{
				PlayerHealth[] array = Object.FindObjectsOfType<PlayerHealth>();
				foreach (PlayerHealth val in array)
				{
					if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).IsOwner)
					{
						val.RemoveHealth(99999f);
						LogSource.LogInfo((object)"[GunGamePlus] Debug suicide triggered.");
						break;
					}
				}
			}
			catch (Exception arg)
			{
				LogSource.LogError((object)$"[GunGamePlus] Debug suicide error: {arg}");
			}
		}

		public static PlayerPickup FindPickupForPlayer(int playerId)
		{
			try
			{
				if (ClientInstance.playerInstances.TryGetValue(playerId, out var value) && (Object)(object)value != (Object)null)
				{
					PlayerManager component = ((Component)value).GetComponent<PlayerManager>();
					if ((Object)(object)component?.player != (Object)null)
					{
						PlayerPickup componentInChildren = ((Component)component.player).GetComponentInChildren<PlayerPickup>(true);
						if ((Object)(object)componentInChildren != (Object)null)
						{
							return componentInChildren;
						}
					}
					PlayerPickup componentInChildren2 = ((Component)value).GetComponentInChildren<PlayerPickup>(true);
					if ((Object)(object)componentInChildren2 != (Object)null)
					{
						return componentInChildren2;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		public static PlayerHealth FindPlayerHealth(int playerId)
		{
			try
			{
				if (ClientInstance.playerInstances.TryGetValue(playerId, out var value) && (Object)(object)value != (Object)null)
				{
					PlayerManager component = ((Component)value).GetComponent<PlayerManager>();
					if ((Object)(object)component?.player != (Object)null)
					{
						PlayerHealth component2 = ((Component)component.player).GetComponent<PlayerHealth>();
						if ((Object)(object)component2 != (Object)null)
						{
							return component2;
						}
					}
					PlayerHealth componentInChildren = ((Component)value).GetComponentInChildren<PlayerHealth>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						return componentInChildren;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace GunGamePlus.UI
{
	public static class ModMenuIntegration
	{
		public static void Initialize()
		{
		}
	}
}
namespace GunGamePlus.Patches
{
	public static class GameManagerPatches
	{
		public static bool RecordPlayerDeathPrefix(int playerId, uint spawnGeneration)
		{
			if (!GunGameConfig.Enabled.Value)
			{
				return true;
			}
			try
			{
				GunGameManager.HandlePlayerDeath(playerId);
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] RecordPlayerDeathPrefix error: {arg}");
				}
			}
			return false;
		}

		public static bool PlayerDiedPrefix(int playerId)
		{
			if (!GunGameConfig.Enabled.Value)
			{
				return true;
			}
			try
			{
				GunGameManager.HandlePlayerDeath(playerId);
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] PlayerDiedPrefix error: {arg}");
				}
			}
			return false;
		}

		public static bool WaitForDrawPrefix(ref IEnumerator __result)
		{
			if (GunGameConfig.Enabled.Value && !GunGameManager.IsMatchOver)
			{
				__result = EmptyCoroutine();
				return false;
			}
			return true;
		}

		public static void SetStartTimePrefix(ref float serverTimeTillStart)
		{
			if (GunGameConfig.Enabled.Value && !GunGameManager.IsMatchOver)
			{
				serverTimeTillStart = 0f;
			}
		}

		public static bool CmdEndRoundPrefix()
		{
			if (GunGameConfig.Enabled.Value && !GunGameManager.IsMatchOver)
			{
				return false;
			}
			return true;
		}

		public static bool StartRoundDelayPrefix()
		{
			if (GunGameConfig.Enabled.Value && !GunGameManager.IsMatchOver)
			{
				PauseManager.BetweenRounds = false;
				return false;
			}
			return true;
		}

		public static bool InvokeBeforeSpawnPrefix()
		{
			if (GunGameConfig.Enabled.Value && !GunGameManager.IsMatchOver)
			{
				PauseManager.BetweenRounds = false;
				return false;
			}
			return true;
		}

		public static bool KillCamUpdatePrefix()
		{
			if (GunGameConfig.Enabled.Value)
			{
				return false;
			}
			return true;
		}

		public static void ResetGamePostfix()
		{
			if (GunGameConfig.Enabled.Value)
			{
				GunGameManager.ResetMatchState();
				if (GunGameConfig.IsProgressiveMode)
				{
					GunGameConfig.GenerateProgressiveLadder();
				}
				else if (GunGameConfig.IsRandomMode)
				{
					GunGameConfig.RandomizeLadder();
				}
			}
		}

		private static IEnumerator EmptyCoroutine()
		{
			yield break;
		}
	}
	public static class PatchManager
	{
		public static void ApplyPatches(Harmony harmony)
		{
			try
			{
				harmony.PatchAll(typeof(SpawnerPatches));
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] SpawnerPatches error: {arg}");
				}
			}
			PatchGameManager(harmony);
			PatchPlayerSystems(harmony);
		}

		private static void PatchGameManager(Harmony harmony)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Expected O, but got Unknown
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Expected O, but got Unknown
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Expected O, but got Unknown
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Expected O, but got Unknown
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Expected O, but got Unknown
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Expected O, but got Unknown
			MethodInfo method = typeof(GameManager).GetMethod("RecordPlayerDeath", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				MethodInfo method2 = typeof(GameManagerPatches).GetMethod("RecordPlayerDeathPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)("[GunGamePlus] Patched GameManager death hook: " + method.Name));
				}
			}
			else
			{
				MethodInfo methodInfo = typeof(GameManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.StartsWith("RpcLogic___PlayerDied"));
				if (methodInfo != null)
				{
					MethodInfo method3 = typeof(GameManagerPatches).GetMethod("RecordPlayerDeathPrefix", BindingFlags.Static | BindingFlags.Public);
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					ManualLogSource logSource2 = GunGamePlugin.LogSource;
					if (logSource2 != null)
					{
						logSource2.LogInfo((object)("[GunGamePlus] Patched GameManager death hook: " + methodInfo.Name));
					}
				}
				else
				{
					ManualLogSource logSource3 = GunGamePlugin.LogSource;
					if (logSource3 != null)
					{
						logSource3.LogError((object)"[GunGamePlus] Failed to locate RecordPlayerDeath method on GameManager!");
					}
				}
			}
			MethodInfo method4 = typeof(GameManager).GetMethod("WaitForDraw", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method4 != null)
			{
				MethodInfo method5 = typeof(GameManagerPatches).GetMethod("WaitForDrawPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method4, new HarmonyMethod(method5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method6 = typeof(GameManager).GetMethod("SetStartTime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method6 != null)
			{
				MethodInfo method7 = typeof(GameManagerPatches).GetMethod("SetStartTimePrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method6, new HarmonyMethod(method7), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method8 = typeof(RoundManager).GetMethod("CmdEndRound", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method8 != null)
			{
				MethodInfo method9 = typeof(GameManagerPatches).GetMethod("CmdEndRoundPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method8, new HarmonyMethod(method9), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method10 = typeof(PauseManager).GetMethod("StartRoundDelay", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method10 != null)
			{
				MethodInfo method11 = typeof(GameManagerPatches).GetMethod("StartRoundDelayPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method10, new HarmonyMethod(method11), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method12 = typeof(PauseManager).GetMethod("InvokeBeforeSpawn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method12 != null)
			{
				MethodInfo method13 = typeof(GameManagerPatches).GetMethod("InvokeBeforeSpawnPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method12, new HarmonyMethod(method13), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method14 = typeof(KillCam).GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method14 != null)
			{
				MethodInfo method15 = typeof(GameManagerPatches).GetMethod("KillCamUpdatePrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method14, new HarmonyMethod(method15), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method16 = typeof(GameManager).GetMethod("ResetGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method16 != null)
			{
				MethodInfo method17 = typeof(GameManagerPatches).GetMethod("ResetGamePostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method16, (HarmonyMethod)null, new HarmonyMethod(method17), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method18 = typeof(GameManager).GetMethod("StartGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method18 != null)
			{
				MethodInfo method19 = typeof(GameManagerPatches).GetMethod("ResetGamePostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method18, (HarmonyMethod)null, new HarmonyMethod(method19), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static void PatchPlayerSystems(Harmony harmony)
		{
			//IL_0076: 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_008a: Expected O, but got Unknown
			//IL_008a: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Expected O, but got Unknown
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Expected O, but got Unknown
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Expected O, but got Unknown
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Expected O, but got Unknown
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Expected O, but got Unknown
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Expected O, but got Unknown
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Expected O, but got Unknown
			//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b0: Expected O, but got Unknown
			//IL_0610: Unknown result type (might be due to invalid IL or missing references)
			//IL_061d: Expected O, but got Unknown
			//IL_069e: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ab: Expected O, but got Unknown
			//IL_072c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0739: Expected O, but got Unknown
			MethodInfo method = typeof(PlayerManager).GetMethod("SpawnPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
			{
				typeof(int),
				typeof(int)
			}, null);
			if (method != null)
			{
				MethodInfo method2 = typeof(PlayerPatches).GetMethod("SpawnPlayer2Prefix", BindingFlags.Static | BindingFlags.Public);
				MethodInfo method3 = typeof(PlayerPatches).GetMethod("SpawnPlayerPostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method, new HarmonyMethod(method2), new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method4 = typeof(PlayerManager).GetMethod("SpawnPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[4]
			{
				typeof(int),
				typeof(int),
				typeof(Vector3),
				typeof(Quaternion)
			}, null);
			if (method4 != null)
			{
				MethodInfo method5 = typeof(PlayerPatches).GetMethod("SpawnPlayerPostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method4, (HarmonyMethod)null, new HarmonyMethod(method5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo = typeof(PlayerManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.StartsWith("RpcLogic___SetPlayerMove") || m.Name == "SetPlayerMove");
			if (methodInfo != null)
			{
				MethodInfo method6 = typeof(PlayerPatches).GetMethod("SetPlayerMovePrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)("[GunGamePlus] Patched SetPlayerMove hook: " + methodInfo.Name));
				}
			}
			MethodInfo method7 = typeof(PlayerManager).GetMethod("WaitForRoundStartCoroutineStart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method7 != null)
			{
				MethodInfo method8 = typeof(PlayerPatches).GetMethod("WaitForRoundStartCoroutineStartPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method7, new HarmonyMethod(method8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource2 = GunGamePlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogInfo((object)"[GunGamePlus] Patched WaitForRoundStartCoroutineStart hook");
				}
			}
			MethodInfo method9 = typeof(PlayerManager).GetMethod("WaitForRoundStart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method9 != null)
			{
				MethodInfo method10 = typeof(PlayerPatches).GetMethod("WaitForRoundStartPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method9, new HarmonyMethod(method10), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource3 = GunGamePlugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogInfo((object)"[GunGamePlus] Patched WaitForRoundStart hook");
				}
			}
			MethodInfo method11 = typeof(PlayerSetup).GetMethod("OnStartClient", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method11 != null)
			{
				MethodInfo method12 = typeof(PlayerPatches).GetMethod("PlayerSetupOnStartClientPostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method11, (HarmonyMethod)null, new HarmonyMethod(method12), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource4 = GunGamePlugin.LogSource;
				if (logSource4 != null)
				{
					logSource4.LogInfo((object)"[GunGamePlus] Patched PlayerSetup.OnStartClient hook");
				}
			}
			MethodInfo method13 = typeof(HUDTween).GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method13 != null)
			{
				MethodInfo method14 = typeof(PlayerPatches).GetMethod("HUDTweenUpdatePostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method13, (HarmonyMethod)null, new HarmonyMethod(method14), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method15 = typeof(FirstPersonController).GetMethod("OnTriggerEnter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method15 != null)
			{
				MethodInfo method16 = typeof(PlayerPatches).GetMethod("FirstPersonControllerOnTriggerEnterPrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method15, new HarmonyMethod(method16), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method17 = typeof(FirstPersonController).GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method17 != null)
			{
				MethodInfo method18 = typeof(PlayerPatches).GetMethod("FirstPersonControllerUpdatePostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method17, (HarmonyMethod)null, new HarmonyMethod(method18), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo method19 = typeof(DamageZone).GetMethod("OnEnable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method19 != null)
			{
				MethodInfo method20 = typeof(PlayerPatches).GetMethod("DamageZoneOnEnablePrefix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)method19, new HarmonyMethod(method20), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			PatchPickupMethod(harmony, "RightHandFix", "RightHandFixPrefix");
			PatchPickupMethod(harmony, "LeftHandFix", "LeftHandFixPrefix");
			PatchPickupMethod(harmony, "HandsReconstruct", "HandsReconstructPrefix");
			PatchPickupMethod(harmony, "RightHandDrop", "RightHandDropPrefix");
			PatchPickupMethod(harmony, "RightHandPickup", "RightHandPickupPrefix");
			PatchPickupMethod(harmony, "LeftHandPickup", "LeftHandPickupPrefix");
			PatchPickupMethod(harmony, "SwitchWeapons", "SwitchWeaponsPrefix");
			MethodInfo methodInfo2 = typeof(PlayerPickup).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.StartsWith("RpcLogic___SetObjectInHandObserver"));
			if (methodInfo2 != null)
			{
				MethodInfo method21 = typeof(PlayerPatches).GetMethod("SetObjectInHandObserverPostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method21), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo3 = typeof(PlayerPickup).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.Contains("RpcLogic___DropObjectServer"));
			if (methodInfo3 != null)
			{
				MethodInfo method22 = typeof(PlayerPatches).GetMethod("HandleDropObjectServer", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(method22), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo4 = typeof(PlayerPickup).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.Contains("RpcLogic___DropObjectObserver"));
			if (methodInfo4 != null)
			{
				MethodInfo method23 = typeof(PlayerPatches).GetMethod("HandleDropObjectObserver", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(method23), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			MethodInfo methodInfo5 = typeof(PlayerHealth).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.StartsWith("RpcLogic___SetKiller") || m.Name == "SetKiller");
			if (methodInfo5 != null)
			{
				MethodInfo method24 = typeof(PlayerPatches).GetMethod("SetKillerServerPostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(method24), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource5 = GunGamePlugin.LogSource;
				if (logSource5 != null)
				{
					logSource5.LogInfo((object)("[GunGamePlus] Patched PlayerHealth SetKiller hook: " + methodInfo5.Name));
				}
			}
			MethodInfo methodInfo6 = typeof(PlayerHealth).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.StartsWith("RpcLogic___RemoveHealth") || m.Name == "RemoveHealth");
			if (methodInfo6 != null)
			{
				MethodInfo method25 = typeof(PlayerPatches).GetMethod("RemoveHealthServerPostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(method25), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource6 = GunGamePlugin.LogSource;
				if (logSource6 != null)
				{
					logSource6.LogInfo((object)("[GunGamePlus] Patched PlayerHealth RemoveHealth hook: " + methodInfo6.Name));
				}
			}
			MethodInfo methodInfo7 = typeof(PlayerHealth).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.StartsWith("RpcLogic___ExplodeServer") || m.Name == "ExplodeServer");
			if (methodInfo7 != null)
			{
				MethodInfo method26 = typeof(PlayerPatches).GetMethod("ExplodeServerPostfix", BindingFlags.Static | BindingFlags.Public);
				harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(method26), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ManualLogSource logSource7 = GunGamePlugin.LogSource;
				if (logSource7 != null)
				{
					logSource7.LogInfo((object)("[GunGamePlus] Patched PlayerHealth ExplodeServer hook: " + methodInfo7.Name));
				}
			}
		}

		private static void PatchPickupMethod(Harmony harmony, string targetMethodName, string patchMethodName)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			MethodInfo method = typeof(PlayerPickup).GetMethod(targetMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				MethodInfo method2 = typeof(PlayerPatches).GetMethod(patchMethodName, BindingFlags.Static | BindingFlags.Public);
				if (method2 != null)
				{
					harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}
	}
	public static class PlayerPatches
	{
		private static readonly FieldInfo _fiRoundHasStarted = typeof(FirstPersonController).GetField("roundHasStarted", BindingFlags.Instance | BindingFlags.NonPublic);

		public static bool SpawnPlayer2Prefix(PlayerManager __instance, int suitIndex, int cigIndex)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			try
			{
				ClientInstance component = ((Component)__instance).GetComponent<ClientInstance>();
				int playerId = (((Object)(object)component != (Object)null) ? component.PlayerId : 0);
				(Vector3 position, Quaternion rotation) distinctSpawnPoint = GunGameRespawnManager.GetDistinctSpawnPoint(__instance, playerId);
				Vector3 item = distinctSpawnPoint.position;
				Quaternion item2 = distinctSpawnPoint.rotation;
				MethodInfo method = typeof(PlayerManager).GetMethod("SpawnPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[4]
				{
					typeof(int),
					typeof(int),
					typeof(Vector3),
					typeof(Quaternion)
				}, null);
				if (method != null)
				{
					method.Invoke(__instance, new object[4] { suitIndex, cigIndex, item, item2 });
					return false;
				}
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] SpawnPlayer2Prefix error: {arg}");
				}
			}
			return true;
		}

		public static void SpawnPlayerPostfix(PlayerManager __instance)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			ClientInstance component = ((Component)__instance).GetComponent<ClientInstance>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			int playerId = component.PlayerId;
			if (playerId < 0)
			{
				return;
			}
			if ((Object)(object)InstanceFinder.NetworkManager != (Object)null && InstanceFinder.NetworkManager.IsServer)
			{
				if (GameManager.Instance?.alivePlayers != null && !GameManager.Instance.alivePlayers.Contains(playerId))
				{
					GameManager.Instance.alivePlayers.Add(playerId);
				}
				int currentTierIndex = GunGameManager.GetCurrentTierIndex(playerId);
				GunGameWeaponManager.GiveWeaponTierToPlayer(playerId, currentTierIndex);
				if (currentTierIndex == 0)
				{
					GunGameManager.AnnounceRoundOne();
				}
			}
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				PauseManager.BetweenRounds = false;
				if ((Object)(object)PauseManager.Instance != (Object)null)
				{
					PauseManager.Instance.startRound = false;
					PauseManager.Instance.pause = false;
					PauseManager.Instance.otherPauseBools = false;
				}
				GunGameRespawnManager.UnfreezePlayerControls(playerId);
			}
		}

		public static bool WaitForRoundStartCoroutineStartPrefix(PlayerManager __instance)
		{
			if (GunGameConfig.Enabled.Value && !GunGameManager.IsMatchOver)
			{
				try
				{
					if ((Object)(object)__instance != (Object)null)
					{
						__instance.SetPlayerMove(true);
						if ((Object)(object)__instance.player != (Object)null)
						{
							__instance.player.sync___set_value_canMove(true, true);
							__instance.player.startOfRound = false;
						}
					}
					PauseManager.BetweenRounds = false;
					if ((Object)(object)PauseManager.Instance != (Object)null)
					{
						PauseManager.Instance.startRound = false;
						PauseManager.Instance.pause = false;
						PauseManager.Instance.otherPauseBools = false;
					}
				}
				catch
				{
				}
				return false;
			}
			return true;
		}

		public static bool WaitForRoundStartPrefix(PlayerManager __instance, ref IEnumerator __result)
		{
			if (GunGameConfig.Enabled.Value && !GunGameManager.IsMatchOver)
			{
				try
				{
					if ((Object)(object)__instance != (Object)null)
					{
						__instance.SetPlayerMove(true);
						if ((Object)(object)__instance.player != (Object)null)
						{
							__instance.player.sync___set_value_canMove(true, true);
							__instance.player.startOfRound = false;
						}
					}
					PauseManager.BetweenRounds = false;
					if ((Object)(object)PauseManager.Instance != (Object)null)
					{
						PauseManager.Instance.startRound = false;
						PauseManager.Instance.pause = false;
						PauseManager.Instance.otherPauseBools = false;
					}
				}
				catch
				{
				}
				__result = EmptyCoroutine();
				return false;
			}
			return true;
		}

		public static void PlayerSetupOnStartClientPostfix(PlayerSetup __instance)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner)
			{
				return;
			}
			try
			{
				FirstPersonController component = ((Component)__instance).GetComponent<FirstPersonController>();
				if ((Object)(object)component != (Object)null)
				{
					Settings.Instance.localPlayer = component;
					Crosshair.Instance.player = component;
					component.sync___set_value_canMove(true, true);
					component.startOfRound = false;
					if ((Object)(object)ClientInstance.Instance != (Object)null)
					{
						PlayerManager component2 = ((Component)ClientInstance.Instance).GetComponent<PlayerManager>();
						if ((Object)(object)component2 != (Object)null)
						{
							component2.player = component;
						}
					}
					foreach (ClientInstance value in ClientInstance.playerInstances.Values)
					{
						if ((Object)(object)value != (Object)null && ((NetworkBehaviour)value).IsOwner)
						{
							PlayerManager component3 = ((Component)value).GetComponent<PlayerManager>();
							if ((Object)(object)component3 != (Object)null)
							{
								component3.player = component;
							}
							break;
						}
					}
				}
				GameObject val = GameObject.Find("Main Camera");
				if ((Object)(object)val != (Object)null)
				{
					Camera component4 = val.GetComponent<Camera>();
					if ((Object)(object)component4 != (Object)null)
					{
						((Behaviour)component4).enabled = false;
					}
					AudioListener component5 = val.GetComponent<AudioListener>();
					if ((Object)(object)component5 != (Object)null)
					{
						((Behaviour)component5).enabled = false;
					}
					KillCam component6 = val.GetComponent<KillCam>();
					if ((Object)(object)component6 != (Object)null)
					{
						component6.isDead = false;
						component6.ragdollCam = false;
						component6.enemy = null;
						component6.ragdoll = null;
					}
				}
				if ((Object)(object)component != (Object)null && (Object)(object)component.playerCamera != (Object)null)
				{
					((Behaviour)component.playerCamera).enabled = true;
					((Component)component.playerCamera).gameObject.SetActive(true);
					AudioListener component7 = ((Component)component.playerCamera).GetComponent<AudioListener>();
					if ((Object)(object)component7 != (Object)null)
					{
						((Behaviour)component7).enabled = true;
					}
				}
				__instance.HideHUD(false);
				HUDTween componentInChildren = ((Component)__instance).GetComponentInChildren<HUDTween>(true);
				if (componentInChildren != null)
				{
					componentInChildren.MoveUp();
				}
				PauseManager.BetweenRounds = false;
				if ((Object)(object)PauseManager.Instance != (Object)null)
				{
					PauseManager.Instance.startRound = false;
					PauseManager.Instance.pause = false;
					PauseManager.Instance.otherPauseBools = false;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)("[GunGamePlus] PlayerSetupOnStartClientPostfix error: " + ex.Message));
				}
			}
		}

		private static IEnumerator EmptyCoroutine()
		{
			yield break;
		}

		public static bool SetPlayerMovePrefix(PlayerManager __instance, bool state)
		{
			if (!GunGameConfig.Enabled.Value || GunGameManager.IsMatchOver)
			{
				return true;
			}
			PauseManager.BetweenRounds = false;
			if (!state)
			{
				try
				{
					if ((Object)(object)__instance.player != (Object)null)
					{
						__instance.player.sync___set_value_canMove(true, true);
						__instance.player.startOfRound = false;
					}
					if ((Object)(object)PauseManager.Instance != (Object)null)
					{
						PauseManager.Instance.startRound = false;
						PauseManager.Instance.pause = false;
						PauseManager.Instance.otherPauseBools = false;
					}
				}
				catch
				{
				}
				return false;
			}
			return true;
		}

		public static bool RightHandFixPrefix(PlayerPickup __instance)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (__instance.sync___get_value_hasObjectInHand() && (Object)(object)__instance.sync___get_value_objInHand() == (Object)null)
			{
				__instance.sync___set_value_hasObjectInHand(false, true);
				return false;
			}
			GameObject val = __instance.sync___get_value_objInHand();
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (val.layer == 7 || val.layer == 9)
			{
				MethodInfo setObjectInHandObserverLogic = GunGameWeaponManager.SetObjectInHandObserverLogic;
				if (setObjectInHandObserverLogic != null)
				{
					try
					{
						setObjectInHandObserverLogic.Invoke(__instance, new object[5]
						{
							val,
							val.transform.position,
							val.transform.rotation,
							((Component)__instance).gameObject,
							true
						});
					}
					catch (Exception arg)
					{
						ManualLogSource logSource = GunGamePlugin.LogSource;
						if (logSource != null)
						{
							logSource.LogError((object)$"[GunGamePlus] RightHandFixPrefix error: {arg}");
						}
					}
				}
				return false;
			}
			return true;
		}

		public static bool LeftHandFixPrefix(PlayerPickup __instance)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if (__instance.sync___get_value_hasObjectInLeftHand() && (Object)(object)__instance.sync___get_value_objInLeftHand() == (Object)null)
			{
				__instance.sync___set_value_hasObjectInLeftHand(false, true);
				return false;
			}
			GameObject val = __instance.sync___get_value_objInLeftHand();
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (val.layer == 7 || val.layer == 9)
			{
				MethodInfo setObjectInHandObserverLogic = GunGameWeaponManager.SetObjectInHandObserverLogic;
				if (setObjectInHandObserverLogic != null)
				{
					try
					{
						setObjectInHandObserverLogic.Invoke(__instance, new object[5]
						{
							val,
							val.transform.position,
							val.transform.rotation,
							((Component)__instance).gameObject,
							false
						});
					}
					catch (Exception arg)
					{
						ManualLogSource logSource = GunGamePlugin.LogSource;
						if (logSource != null)
						{
							logSource.LogError((object)$"[GunGamePlus] LeftHandFixPrefix error: {arg}");
						}
					}
				}
				return false;
			}
			return true;
		}

		public static bool HandsReconstructPrefix(PlayerPickup __instance)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			try
			{
				GameObject val = __instance.sync___get_value_objInLeftHand();
				GameObject val2 = __instance.sync___get_value_objInHand();
				if ((Object)(object)val == (Object)null || (Object)(object)val2 != (Object)null)
				{
					return true;
				}
				object? obj = GunGameWeaponManager.RightIdlePosition?.GetValue(__instance);
				Transform rightIKTarget = (Transform)((obj is Transform) ? obj : null);
				ItemBehaviour component = val.GetComponent<ItemBehaviour>();
				__instance.SetRightIKTarget(rightIKTarget);
				__instance.SetLeftIKTarget(((Object)(object)component != (Object)null) ? component.gripLeft : null);
				object obj2 = GunGameWeaponManager.RigBuilder?.GetValue(__instance);
				obj2?.GetType().GetMethod("Build", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(obj2, null);
				return false;
			}
			catch
			{
				return true;
			}
		}

		public static void SetObjectInHandObserverPostfix(PlayerPickup __instance, GameObject obj)
		{
			if (!((Object)(object)obj == (Object)null))
			{
				ItemBehaviour component = obj.GetComponent<ItemBehaviour>();
				if ((Object)(object)component != (Object)null)
				{
					component.dispenserStart = false;
				}
			}
		}

		public static bool RightHandDropPrefix(PlayerPickup __instance)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			GameObject val = __instance.sync___get_value_objInHand();
			if (__instance.sync___get_value_hasObjectInHand() && ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent<ItemBehaviour>() == (Object)null))
			{
				__instance.sync___set_value_hasObjectInHand(false, true);
				__instance.sync___set_value_objInHand((GameObject)null, true);
				return false;
			}
			PlayerHealth componentInParent = ((Component)__instance).GetComponentInParent<PlayerHealth>();
			if ((Object)(object)componentInParent != (Object)null && componentInParent.sync___get_value_isKilled())
			{
				return false;
			}
			string weaponName = (((Object)(object)val != (Object)null) ? WeaponPool.CleanWeaponName(((Object)val).name) : string.Empty);
			bool flag = WeaponPool.IsPlaceable(weaponName);
			bool flag2 = WeaponPool.IsThrowable(weaponName);
			if (!flag && !flag2)
			{
				int playerIdFromObject = GunGameManager.GetPlayerIdFromObject(((Component)__instance).gameObject);
				if (playerIdFromObject >= 0 && GunGameWeaponManager.IsDropProtected(playerIdFromObject))
				{
					return false;
				}
			}
			return true;
		}

		public static bool RightHandPickupPrefix()
		{
			return !GunGameConfig.Enabled.Value;
		}

		public static bool LeftHandPickupPrefix()
		{
			return !GunGameConfig.Enabled.Value;
		}

		public static bool SwitchWeaponsPrefix()
		{
			return !GunGameConfig.Enabled.Value;
		}

		public static bool HandleDropObjectServer(PlayerPickup __instance, GameObject obj, bool rightHand)
		{
			if (!GunGameConfig.Enabled.Value)
			{
				return true;
			}
			if ((Object)(object)InstanceFinder.NetworkManager == (Object)null || !InstanceFinder.NetworkManager.IsServer)
			{
				return true;
			}
			try
			{
				if ((Object)(object)__instance != (Object)null)
				{
					int playerIdFromObject = GunGameManager.GetPlayerIdFromObject(((Component)__instance).gameObject);
					if (playerIdFromObject >= 0)
					{
						string weaponName = (((Object)(object)obj != (Object)null) ? WeaponPool.CleanWeaponName(((Object)obj).name) : string.Empty);
						bool flag = WeaponPool.IsPlaceable(weaponName);
						bool flag2 = WeaponPool.IsThrowable(weaponName);
						if ((Object)(object)obj != (Object)null && (flag || flag2))
						{
							obj.transform.SetParent((Transform)null);
						}
						MonoBehaviour val = (MonoBehaviour)(((object)GameManager.Instance) ?? ((object)GunGamePlugin.Instance));
						if ((Object)(object)val != (Object)null)
						{
							val.StartCoroutine(DeferredDropHandling(__instance, obj, rightHand, playerIdFromObject, flag, flag2));
						}
						if (flag2 || flag)
						{
							return true;
						}
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] HandleDropObjectServer error: {arg}");
				}
			}
			return false;
		}

		private static IEnumerator DeferredDropHandling(PlayerPickup pickup, GameObject obj, bool rightHand, int playerId, bool isPlaceable, bool isThrowable)
		{
			yield return null;
			try
			{
				if ((Object)(object)pickup != (Object)null)
				{
					if (rightHand)
					{
						pickup.sync___set_value_hasObjectInHand(false, true);
						pickup.sync___set_value_objInHand((GameObject)null, true);
					}
					else
					{
						pickup.sync___set_value_hasObjectInLeftHand(false, true);
						pickup.sync___set_value_objInLeftHand((GameObject)null, true);
					}
				}
			}
			catch
			{
			}
			if (!isPlaceable && !isThrowable && (Object)(object)obj != (Object)null)
			{
				GunGameWeaponManager.DespawnOrDestroy(obj);
			}
			if (!(isPlaceable || isThrowable))
			{
				yield break;
			}
			yield return (object)new WaitForSeconds(1.2f);
			if (playerId < 0 || GunGameManager.IsMatchOver)
			{
				yield break;
			}
			PlayerPickup val = GunGamePlugin.FindPickupForPlayer(playerId);
			if ((Object)(object)val != (Object)null)
			{
				bool num = rightHand && !val.sync___get_value_hasObjectInHand();
				bool flag = !rightHand && !val.sync___get_value_hasObjectInLeftHand();
				if (num || flag)
				{
					int currentTierIndex = GunGameManager.GetCurrentTierIndex(playerId);
					GunGameWeaponManager.GiveWeaponTierToPlayer(playerId, currentTierIndex);
				}
			}
		}

		public static bool HandleDropObjectObserver(PlayerPickup __instance, GameObject obj, bool rightHand)
		{
			if (!GunGameConfig.Enabled.Value)
			{
				return true;
			}
			if ((Object)(object)obj == (Object)null)
			{
				return false;
			}
			string weaponName = WeaponPool.CleanWeaponName(((Object)obj).name);
			bool flag = WeaponPool.IsPlaceable(weaponName);
			if (WeaponPool.IsThrowable(weaponName) || flag)
			{
				return true;
			}
			return false;
		}

		public static void HUDTweenUpdatePostfix(HUDTween __instance)
		{
			if (GunGameConfig.Enabled.Value && !((Object)(object)__instance == (Object)null))
			{
				__instance.MoveUp();
			}
		}

		public static bool FirstPersonControllerOnTriggerEnterPrefix(FirstPersonController __instance, Collider col)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null || (Object)(object)col == (Object)null)
			{
				return true;
			}
			if (((Component)col).CompareTag("Teleport"))
			{
				Teleporter component = ((Component)col).GetComponent<Teleporter>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.teleportPoint != (Object)null)
				{
					Transform teleportPoint = component.teleportPoint;
					__instance.Teleport(teleportPoint.position, component.anglesDifference, true, teleportPoint, component.propulsionPower, component.propulsionDecel, component.dontTranslateRotation);
					return false;
				}
			}
			else if (((Component)col).CompareTag("Killz"))
			{
				Settings instance = Settings.Instance;
				if (instance != null)
				{
					instance.IncreaseSuicidesAmount();
				}
				PlayerHealth component2 = ((Component)__instance).GetComponent<PlayerHealth>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.fellVoid = true;
				}
				__instance.DespawnObject(((Component)__instance).gameObject);
				return false;
			}
			return true;
		}

		public static void FirstPersonControllerUpdatePostfix(FirstPersonController __instance)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			try
			{
				_fiRoundHasStarted?.SetValue(__instance, true);
				PauseManager.BetweenRounds = false;
				if (((NetworkBehaviour)__instance).IsOwner)
				{
					if (!__instance.sync___get_value_canMove())
					{
						__instance.sync___set_value_canMove(true, true);
					}
					__instance.startOfRound = false;
					if ((Object)(object)PauseManager.Instance != (Object)null)
					{
						PauseManager.Instance.startRound = false;
						PauseManager.Instance.pause = false;
						PauseManager.Instance.otherPauseBools = false;
					}
				}
			}
			catch
			{
			}
		}

		public static bool DamageZoneOnEnablePrefix(DamageZone __instance)
		{
			return true;
		}

		public static void SetKillerServerPostfix(PlayerHealth __instance, Transform tempKiller)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null || (Object)(object)tempKiller == (Object)null)
			{
				return;
			}
			try
			{
				int playerIdFromObject = GunGameManager.GetPlayerIdFromObject(((Component)__instance).gameObject);
				int playerIdFromObject2 = GunGameManager.GetPlayerIdFromObject(((Component)tempKiller).gameObject);
				if (playerIdFromObject >= 0 && playerIdFromObject2 >= 0)
				{
					GunGameManager.RecordAttacker(playerIdFromObject, playerIdFromObject2);
				}
			}
			catch
			{
			}
		}

		public static void RemoveHealthServerPostfix(PlayerHealth __instance, float damage)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null || damage <= 0f)
			{
				return;
			}
			try
			{
				int playerIdFromObject = GunGameManager.GetPlayerIdFromObject(((Component)__instance).gameObject);
				if (playerIdFromObject < 0)
				{
					return;
				}
				if ((Object)(object)__instance.killer != (Object)null)
				{
					int playerIdFromObject2 = GunGameManager.GetPlayerIdFromObject(((Component)__instance.killer).gameObject);
					if (playerIdFromObject2 >= 0)
					{
						GunGameManager.RecordAttacker(playerIdFromObject, playerIdFromObject2);
					}
				}
				if (__instance.sync___get_value_health() <= 0f)
				{
					GunGameManager.HandlePlayerDeath(playerIdFromObject);
				}
			}
			catch
			{
			}
		}

		public static void ExplodeServerPostfix(PlayerHealth __instance)
		{
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			try
			{
				int playerIdFromObject = GunGameManager.GetPlayerIdFromObject(((Component)__instance).gameObject);
				if (playerIdFromObject < 0)
				{
					return;
				}
				if ((Object)(object)__instance.killer != (Object)null)
				{
					int playerIdFromObject2 = GunGameManager.GetPlayerIdFromObject(((Component)__instance.killer).gameObject);
					if (playerIdFromObject2 >= 0)
					{
						GunGameManager.RecordAttacker(playerIdFromObject, playerIdFromObject2);
					}
				}
				GunGameManager.HandlePlayerDeath(playerIdFromObject);
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch]
	public static class SpawnerPatches
	{
		private static readonly FieldInfo _fiAudio = typeof(ItemBehaviour).GetField("audio", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo _fiWeaponScript = typeof(ItemBehaviour).GetField("weaponScript", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo _fiInitialLocalPos = typeof(ItemBehaviour).GetField("initialLocalPosition", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo _fiHoveredRenderer = typeof(ItemBehaviour).GetField("hoveredObjectRenderer", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo _fiHoveredMat = typeof(ItemBehaviour).GetField("hoveredObjectMat", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo _fiCol = typeof(ItemBehaviour).GetField("col", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo _fiAimStrafePivot = typeof(ItemBehaviour).GetField("aimStrafePivot", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo _fiMaxPivot = typeof(ItemBehaviour).GetField("maxPivot", BindingFlags.Instance | BindingFlags.NonPublic);

		[HarmonyPatch(typeof(Spawner), "Update")]
		[HarmonyPrefix]
		public static bool SpawnerUpdatePrefix()
		{
			return !GunGameConfig.Enabled.Value;
		}

		[HarmonyPatch(typeof(ItemBehaviour), "Start")]
		[HarmonyPrefix]
		public static bool ItemBehaviourStartPrefix(ItemBehaviour __instance)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			if (!GunGameConfig.Enabled.Value || (Object)(object)__instance == (Object)null)
			{
				return true;
			}
			try
			{
				__instance.dispenserStart = true;
				_fiWeaponScript?.SetValue(__instance, ((Component)__instance).GetComponent<Weapon>());
				((Component)__instance).transform.localScale = new Vector3(2f, 2f, 2f);
				_fiAudio?.SetValue(__instance, ((Component)__instance).GetComponent<AudioSource>());
				_fiInitialLocalPos?.SetValue(__instance, ((Component)__instance).transform.localPosition);
				_fiCol?.SetValue(__instance, ((Component)__instance).GetComponent<Collider>());
				if (_fiMaxPivot != null)
				{
					try
					{
						float num = (float)_fiMaxPivot.GetValue(__instance);
						_fiMaxPivot.SetValue(__instance, 0f - Mathf.Abs(num));
					}
					catch
					{
					}
				}
				MeshRenderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<MeshRenderer>(true);
				_fiHoveredRenderer?.SetValue(__instance, componentsInChildren);
				if (_fiHoveredMat?.GetValue(__instance) is List<Material> list)
				{
					list.Clear();
					if (componentsInChildren != null)
					{
						MeshRenderer[] array = componentsInChildren;
						foreach (MeshRenderer val in array)
						{
							if (!((Object)(object)val != (Object)null) || ((Renderer)val).materials == null)
							{
								continue;
							}
							Material[] materials = ((Renderer)val).materials;
							foreach (Material val2 in materials)
							{
								if ((Object)(object)val2 != (Object)null)
								{
									list.Add(val2);
								}
							}
						}
					}
				}
				Grip[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren<Grip>(true);
				if (componentsInChildren2 != null && componentsInChildren2.Length != 0)
				{
					if (componentsInChildren2.Length != 0 && (Object)(object)componentsInChildren2[0] != (Object)null)
					{
						__instance.gripRight = ((Component)componentsInChildren2[0]).transform;
					}
					if (componentsInChildren2.Length > 1 && (Object)(object)componentsInChildren2[1] != (Object)null)
					{
						__instance.gripLeft = ((Component)componentsInChildren2[1]).transform;
					}
					else if (componentsInChildren2.Length != 0 && (Object)(object)componentsInChildren2[0] != (Object)null)
					{
						__instance.gripLeft = ((Component)componentsInChildren2[0]).transform;
					}
				}
				AimStrafePivot componentInChildren = ((Component)__instance).GetComponentInChildren<AimStrafePivot>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					_fiAimStrafePivot?.SetValue(__instance, ((Component)componentInChildren).transform);
				}
				Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null)
				{
					component.isKinematic = true;
					component.useGravity = false;
					component.velocity = Vector3.zero;
					component.angularVelocity = Vector3.zero;
				}
				return false;
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] ItemBehaviourStartPrefix error: {arg}");
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(ItemBehaviour), "StickOnGround")]
		[HarmonyPrefix]
		public static bool ItemBehaviourStickOnGroundPrefix(ItemBehaviour __instance)
		{
			if ((Object)(object)__instance.cam == (Object)null)
			{
				return false;
			}
			return true;
		}
	}
}
namespace GunGamePlus.Core
{
	public static class GunGameManager
	{
		private static readonly Dictionary<int, int> PlayerKills;

		private static readonly Dictionary<int, float> LastKillTime;

		private static readonly Dictionary<int, (int attackerId, float time)> RecentAttackers;

		private static readonly Dictionary<int, float> LastDeathHandledTime;

		private static bool HasAnnouncedRoundOne;

		private static MethodInfo _miRoundWon;

		private static MethodInfo _miMatchLogsSendToAll;

		private static FieldInfo _fiSpawnedObject;

		public static bool IsMatchOver { get; set; }

		public static bool IsWinSequenceActive { get; private set; }

		static GunGameManager()
		{
			IsMatchOver = false;
			IsWinSequenceActive = false;
			PlayerKills = new Dictionary<int, int>();
			LastKillTime = new Dictionary<int, float>();
			RecentAttackers = new Dictionary<int, (int, float)>();
			LastDeathHandledTime = new Dictionary<int, float>();
			HasAnnouncedRoundOne = false;
			CacheReflection();
		}

		private static void CacheReflection()
		{
			try
			{
				_miRoundWon = typeof(GameManager).GetMethod("RoundWon", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_miMatchLogsSendToAll = typeof(MatchLogs).GetMethod("RpcSendChatLineToAllObservers", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_fiSpawnedObject = typeof(PlayerManager).GetField("SpawnedObject", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] Reflection cache error: {arg}");
				}
			}
		}

		public static void ResetMatchState()
		{
			PlayerKills.Clear();
			LastKillTime.Clear();
			RecentAttackers.Clear();
			LastDeathHandledTime.Clear();
			HasAnnouncedRoundOne = false;
			IsMatchOver = false;
			IsWinSequenceActive = false;
			PauseManager.BetweenRounds = false;
			GunGameWeaponManager.ClearAll();
			GunGameRespawnManager.ResetState();
			ManualLogSource logSource = GunGamePlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogInfo((object)"[GunGamePlus] Match state reset.");
			}
		}

		public static void AnnounceRoundOne()
		{
			if (!IsMatchOver && !HasAnnouncedRoundOne)
			{
				HasAnnouncedRoundOne = true;
				int value = GunGameConfig.KillsToWin.Value;
				string categoryNameForTier = GunGameConfig.GetCategoryNameForTier(0);
				string tierColorHex = GunGameConfig.GetTierColorHex(0, value);
				string primaryWeaponName = GunGameConfig.GetPrimaryWeaponName(0);
				BroadcastChatMessage("<b><color=#FFD700>[Gun Game]</color></b> - <b><color=" + tierColorHex + ">" + categoryNameForTier + "</color></b> (<b><color=white>" + primaryWeaponName + "</color></b>)");
			}
		}

		public static void RecordAttacker(int victimId, int attackerId)
		{
			if (victimId >= 0 && attackerId >= 0 && victimId != attackerId)
			{
				RecentAttackers[victimId] = (attackerId, Time.time);
			}
		}

		public static int GetPlayerKillCount(int playerId)
		{
			if (!PlayerKills.TryGetValue(playerId, out var value))
			{
				return 0;
			}
			return value;
		}

		public static int GetCurrentTierIndex(int playerId)
		{
			int playerKillCount = GetPlayerKillCount(playerId);
			int activeTierCount = GunGameConfig.GetActiveTierCount();
			if (activeTierCount <= 0)
			{
				return 0;
			}
			return Mathf.Clamp(playerKillCount, 0, activeTierCount - 1);
		}

		public static void HandlePlayerDeath(int victimId)
		{
			if (!GunGameConfig.Enabled.Value || IsMatchOver)
			{
				return;
			}
			NetworkManager networkManager = InstanceFinder.NetworkManager;
			bool flag = (Object)(object)networkManager != (Object)null && networkManager.IsServer;
			if (flag)
			{
				try
				{
					PlayerPickup val = GunGamePlugin.FindPickupForPlayer(victimId);
					if ((Object)(object)val != (Object)null)
					{
						GunGameWeaponManager.DespawnHeldWeapons(val);
					}
					GunGameWeaponManager.ClearPlacedTrapsForPlayer(victimId);
				}
				catch
				{
				}
				GunGameRespawnManager.ScheduleRespawn(victimId);
			}
			try
			{
				if (GameManager.Instance?.alivePlayers != null && !GameManager.Instance.alivePlayers.Contains(victimId))
				{
					GameManager.Instance.alivePlayers.Add(victimId);
				}
			}
			catch
			{
			}
			if (!flag)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (LastDeathHandledTime.TryGetValue(victimId, out var value) && unscaledTime - value < 0.3f)
			{
				return;
			}
			LastDeathHandledTime[victimId] = unscaledTime;
			int num = FindKillerPlayerId(victimId);
			int value2 = GunGameConfig.KillsToWin.Value;
			if (num >= 0 && num != victimId)
			{
				if (LastKillTime.TryGetValue(num, out var value3) && unscaledTime - value3 < 0.2f)
				{
					return;
				}
				LastKillTime[num] = unscaledTime;
				int playerKillCount = GetPlayerKillCount(num);
				int num2 = playerKillCount + 1;
				PlayerKills[num] = num2;
				string playerName = GetPlayerName(num);
				string playerName2 = GetPlayerName(victimId);
				string primaryWeaponName = GunGameConfig.GetPrimaryWeaponName(playerKillCount);
				int currentTierIndex = GetCurrentTierIndex(num);
				int num3 = currentTierIndex + 1;
				string categoryNameForTier = GunGameConfig.GetCategoryNameForTier(currentTierIndex);
				string tierColorHex = GunGameConfig.GetTierColorHex(currentTierIndex, value2);
				string primaryWeaponName2 = GunGameConfig.GetPrimaryWeaponName(currentTierIndex);
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)$"[GunGamePlus] Kill: {playerName} killed {playerName2} with {primaryWeaponName} ({num2}/{value2}) - Reached: {categoryNameForTier} ({primaryWeaponName2}) [{num3}/{value2}]");
				}
				if (num2 >= value2)
				{
					BroadcastChatMessage("<b><color=#FFD700>[Gun Game]</color></b> <b>" + playerName + "</b> <color=#FF4444>killed</color> <b>" + playerName2 + "</b> with <b><color=white>" + primaryWeaponName + "</color></b> — <b><color=#00FF66>WINS THE MATCH!</color></b>");
					IsMatchOver = true;
					IsWinSequenceActive = true;
					MonoBehaviour val2 = (MonoBehaviour)(((object)GunGamePlugin.Instance) ?? ((object)GameManager.Instance));
					if ((Object)(object)val2 != (Object)null)
					{
						val2.StartCoroutine(WinSequence(num));
					}
				}
				else
				{
					BroadcastChatMessage($"<b><color=#FFD700>[Gun Game]</color></b> <b>{playerName}</b> has reached: <b><color={tierColorHex}>{categoryNameForTier}</color></b> (<b><color=white>{primaryWeaponName2}</color></b>) <color=#00FFFF>[{num3}/{value2}]</color>");
					GunGameWeaponManager.GiveWeaponTierToPlayer(num, currentTierIndex);
				}
			}
			else
			{
				string playerName3 = GetPlayerName(victimId);
				if (GunGameConfig.SuicidePenalty.Value == SuicidePenaltyMode.LoseTier)
				{
					int playerKillCount2 = GetPlayerKillCount(victimId);
					int value4 = Mathf.Max(0, playerKillCount2 - 1);
					PlayerKills[victimId] = value4;
					int currentTierIndex2 = GetCurrentTierIndex(victimId);
					int num4 = currentTierIndex2 + 1;
					string categoryNameForTier2 = GunGameConfig.GetCategoryNameForTier(currentTierIndex2);
					string tierColorHex2 = GunGameConfig.GetTierColorHex(currentTierIndex2, value2);
					string primaryWeaponName3 = GunGameConfig.GetPrimaryWeaponName(currentTierIndex2);
					BroadcastChatMessage($"<b><color=#FFD700>[Gun Game]</color></b> <b>{playerName3}</b> demoted to: <b><color={tierColorHex2}>{categoryNameForTier2}</color></b> (<b><color=white>{primaryWeaponName3}</color></b>) <color=#00FFFF>[{num4}/{value2}]</color>");
				}
				else
				{
					BroadcastChatMessage("<b><color=#FFD700>[Gun Game]</color></b> <b>" + playerName3 + "</b> <color=#888888>killed themselves</color>");
				}
			}
		}

		public static void SimulateLocalKill(int playerId)
		{
			if (playerId < 0 || IsMatchOver)
			{
				return;
			}
			int value = GunGameConfig.KillsToWin.Value;
			int num = GetPlayerKillCount(playerId) + 1;
			PlayerKills[playerId] = num;
			string playerName = GetPlayerName(playerId);
			int currentTierIndex = GetCurrentTierIndex(playerId);
			int num2 = currentTierIndex + 1;
			string categoryNameForTier = GunGameConfig.GetCategoryNameForTier(currentTierIndex);
			string tierColorHex = GunGameConfig.GetTierColorHex(currentTierIndex, value);
			string primaryWeaponName = GunGameConfig.GetPrimaryWeaponName(currentTierIndex);
			if (num >= value)
			{
				BroadcastChatMessage("<b><color=#FFD700>[Gun Game (Test)]</color></b> <b>" + playerName + "</b> — <b><color=#00FF66>WINS THE MATCH!</color></b>");
				IsMatchOver = true;
				IsWinSequenceActive = true;
				if ((Object)(object)GameManager.Instance != (Object)null)
				{
					((MonoBehaviour)GameManager.Instance).StartCoroutine(WinSequence(playerId));
				}
			}
			else
			{
				BroadcastChatMessage($"<b><color=#FFD700>[Gun Game (Test)]</color></b> <b>{playerName}</b> has reached: <b><color={tierColorHex}>{categoryNameForTier}</color></b> (<b><color=white>{primaryWeaponName}</color></b>) <color=#00FFFF>[{num2}/{value}]</color>");
				GunGameWeaponManager.GiveWeaponTierToPlayer(playerId, currentTierIndex);
			}
		}

		public static void SimulateLocalDemote(int playerId)
		{
			if (playerId >= 0 && !IsMatchOver)
			{
				int value = GunGameConfig.KillsToWin.Value;
				int playerKillCount = GetPlayerKillCount(playerId);
				int value2 = Mathf.Max(0, playerKillCount - 1);
				PlayerKills[playerId] = value2;
				string playerName = GetPlayerName(playerId);
				int currentTierIndex = GetCurrentTierIndex(playerId);
				int num = currentTierIndex + 1;
				string categoryNameForTier = GunGameConfig.GetCategoryNameForTier(currentTierIndex);
				string tierColorHex = GunGameConfig.GetTierColorHex(currentTierIndex, value);
				string primaryWeaponName = GunGameConfig.GetPrimaryWeaponName(currentTierIndex);
				BroadcastChatMessage($"<b><color=#FFD700>[Gun Game (Test)]</color></b> <b>{playerName}</b> demoted to: <b><color={tierColorHex}>{categoryNameForTier}</color></b> (<b><color=white>{primaryWeaponName}</color></b>) <color=#00FFFF>[{num}/{value}]</color>");
				GunGameWeaponManager.GiveWeaponTierToPlayer(playerId, currentTierIndex);
			}
		}

		private static IEnumerator WinSequence(int winnerId)
		{
			ManualLogSource logSource = GunGamePlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogInfo((object)$"[GunGamePlus] Starting win sequence for player {winnerId}");
			}
			yield return (object)new WaitForSeconds(1.5f);
			int playerTeamId = GetPlayerTeamId(winnerId);
			bool endRoundCalled = false;
			try
			{
				if ((Object)(object)ScoreManager.Instance != (Object)null)
				{
					ScoreManager.Instance.AddRoundScore(playerTeamId, 1);
				}
				if (_miRoundWon != null && (Object)(object)GameManager.Instance != (Object)null)
				{
					_miRoundWon.Invoke(GameManager.Instance, new object[1] { playerTeamId });
				}
				if ((Object)(object)RoundManager.Instance != (Object)null)
				{
					RoundManager.Instance.CmdEndRound(playerTeamId);
					endRoundCalled = true;
				}
			}
			catch (Exception arg)
			{
				ManualLogSource logSource2 = GunGamePlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)$"[GunGamePlus] WinSequence round end error: {arg}");
				}
			}
			yield return (object)new WaitForSeconds(4f);
			if (endRoundCalled)
			{
				try
				{
					if ((Object)(object)SceneMotor.Instance != (Object)null)
					{
						SceneMotor.Instance.ChangeNetworkScene();
					}
				}
				catch (Exception arg2)
				{
					ManualLogSource logSource3 = GunGamePlugin.LogSource;
					if (logSource3 != null)
					{
						logSource3.LogError((object)$"[GunGamePlus] ChangeNetworkScene error: {arg2}");
					}
				}
			}
			ResetMatchState();
		}

		public static void BroadcastChatMessage(string text)
		{
			try
			{
				if ((Object)(object)MatchLogs.Instance != (Object)null && _miMatchLogsSendToAll != null)
				{
					_miMatchLogsSendToAll.Invoke(MatchLogs.Instance, new object[1] { text });
				}
			}
			catch
			{
			}
		}

		public static string GetPlayerName(int playerId)
		{
			try
			{
				if (ClientInstance.playerInstances.TryGetValue(playerId, out var value) && (Object)(object)value != (Object)null)
				{
					return value.PlayerNameTag;
				}
			}
			catch
			{
			}
			return $"Player {playerId}";
		}

		public static int GetPlayerTeamId(int playerId)
		{
			if ((Object)(object)ScoreManager.Instance != (Object)null)
			{
				try
				{
					return ScoreManager.Instance.GetTeamId(playerId);
				}
				catch
				{
				}
			}
			return playerId;
		}

		public static int FindKillerPlayerId(int victimId)
		{
			try
			{
				PlayerHealth val = GunGamePlugin.FindPlayerHealth(victimId);
				if ((Object)(object)val != (Object)null && (Object)(object)val.killer != (Object)null)
				{
					int playerIdFromObject = GetPlayerIdFromObject(((Component)val.killer).gameObject);
					if (playerIdFromObject >= 0 && playerIdFromObject != victimId)
					{
						return playerIdFromObject;
					}
				}
			}
			catch
			{
			}
			try
			{
				PlayerPickup val2 = GunGamePlugin.FindPickupForPlayer(victimId);
				if ((Object)(object)val2 != (Object)null)
				{
					PlayerHealth componentInParent = ((Component)val2).GetComponentInParent<PlayerHealth>();
					if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.killer != (Object)null)
					{
						int playerIdFromObject2 = GetPlayerIdFromObject(((Component)componentInParent.killer).gameObject);
						if (playerIdFromObject2 >= 0 && playerIdFromObject2 != victimId)
						{
							return playerIdFromObject2;
						}
					}
				}
			}
			catch
			{
			}
			if (RecentAttackers.TryGetValue(victimId, out (int, float) value) && value.Item1 >= 0 && value.Item1 != victimId && Time.time - value.Item2 < 15f)
			{
				return value.Item1;
			}
			if (ClientInstance.playerInstances.Count == 2)
			{
				foreach (KeyValuePair<int, ClientInstance> playerInstance in ClientInstance.playerInstances)
				{
					if (playerInstance.Key != victimId)
					{
						return playerInstance.Key;
					}
				}
			}
			return -1;
		}

		public static int GetPlayerIdFromObject(GameObject obj)
		{
			if ((Object)(object)obj == (Object)null)
			{
				return -1;
			}
			try
			{
				PlayerValues val = obj.GetComponentInParent<PlayerValues>(true) ?? obj.GetComponentInChildren<PlayerValues>(true);
				if ((Object)(object)val != (Object)null && (Object)(object)val.sync___get_value_playerClient() != (Object)null)
				{
					return val.sync___get_value_playerClient().PlayerId;
				}
				ClientInstance val2 = obj.GetComponentInParent<ClientInstance>(true) ?? obj.GetComponentInChildren<ClientInstance>(true);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2.PlayerId;
				}
				FirstPersonController val3 = obj.GetComponentInParent<FirstPersonController>(true) ?? obj.GetComponentInChildren<FirstPersonController>(true);
				if ((Object)(object)val3 != (Object)null)
				{
					PlayerValues component = ((Component)val3).GetComponent<PlayerValues>();
					if ((Object)(object)component != (Object)null && (Object)(object)component.sync___get_value_playerClient() != (Object)null)
					{
						return component.sync___get_value_playerClient().PlayerId;
					}
				}
				foreach (KeyValuePair<int, ClientInstance> playerInstance in ClientInstance.playerInstances)
				{
					if ((Object)(object)playerInstance.Value == (Object)null)
					{
						continue;
					}
					PlayerManager component2 = ((Component)playerInstance.Value).GetComponent<PlayerManager>();
					if (!((Object)(object)component2 != (Object)null))
					{
						continue;
					}
					if ((Object)(object)component2.player != (Object)null && ((Object)(object)((Component)component2.player).gameObject == (Object)(object)obj || obj.transform.IsChildOf(((Component)component2.player).transform)))
					{
						return playerInstance.Key;
					}
					if (_fiSpawnedObject != null)
					{
						object? value = _fiSpawnedObject.GetValue(component2);
						GameObject val4 = (GameObject)((value is GameObject) ? value : null);
						if ((Object)(object)val4 != (Object)null && ((Object)(object)val4 == (Object)(object)obj || obj.transform.IsChildOf(val4.transform)))
						{
							return playerInstance.Key;
						}
					}
				}
			}
			catch
			{
			}
			return -1;
		}
	}
	public static class GunGameRespawnManager
	{
		private static readonly Dictionary<int, float> RespawnsInProgress;

		private static readonly Dictionary<int, int> RespawnSequence;

		private static float _lastServerCheckTime;

		private static MethodInfo _miRpcLogicCmdRespawn;

		private static MethodInfo _miSpawnPlayer4;

		private static MethodInfo _miPopulateSpawnPoints;

		private static MethodInfo _miSetActiveSpawnPoints;

		private static MethodInfo _miReturnSpawnPoint;

		private static FieldInfo _fiSpawnedObject;

		public static float SceneLoadedTime { get; set; }

		static GunGameRespawnManager()
		{
			RespawnsInProgress = new Dictionary<int, float>();
			RespawnSequence = new Dictionary<int, int>();
			_lastServerCheckTime = 0f;
			SceneLoadedTime = 0f;
			CacheReflection();
		}

		private static void CacheReflection()
		{
			try
			{
				_miRpcLogicCmdRespawn = typeof(PlayerManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.StartsWith("RpcLogic___CmdRespawn"));
				_miSpawnPlayer4 = typeof(PlayerManager).GetMethod("SpawnPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[4]
				{
					typeof(int),
					typeof(int),
					typeof(Vector3),
					typeof(Quaternion)
				}, null);
				_miPopulateSpawnPoints = typeof(PlayerManager).GetMethod("PopulateSpawnPoints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_miSetActiveSpawnPoints = typeof(PlayerManager).GetMethod("SetActiveSpawnPoints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_miReturnSpawnPoint = typeof(PlayerManager).GetMethod("ReturnSpawnPoint", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_fiSpawnedObject = typeof(PlayerManager).GetField("SpawnedObject", BindingFlags.Instance | BindingFlags.NonPublic);
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)("[GunGamePlus] RespawnManager reflection: CmdRespawnLogic=" + ((_miRpcLogicCmdRespawn != null) ? _miRpcLogicCmdRespawn.Name : "NULL")));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource logSource2 = GunGamePlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)$"[GunGamePlus] RespawnManager reflection error: {arg}");
				}
			}
		}

		public static void ResetState()
		{
			SceneLoadedTime = Time.unscaledTime;
			RespawnsInProgress.Clear();
			RespawnSequence.Clear();
			_lastServerCheckTime = Time.unscaledTime;
		}

		public static bool IsRespawnInProgress(int playerId)
		{
			if (RespawnsInProgress.TryGetValue(playerId, out var value))
			{
				if (Time.unscaledTime - value < 3f)
				{
					return true;
				}
				RespawnsInProgress.Remove(playerId);
			}
			return false;
		}

		public static void ScheduleRespawn(int playerId)
		{
			if (GunGameManager.IsMatchOver)
			{
				return;
			}
			NetworkManager networkManager = InstanceFinder.NetworkManager;
			if (!((Object)(object)networkManager == (Object)null) && networkManager.IsServer && !IsRespawnInProgress(playerId))
			{
				RespawnsInProgress[playerId] = Time.unscaledTime;
				if (!RespawnSequence.ContainsKey(playerId))
				{
					RespawnSequence[playerId] = 0;
				}
				int seq = ++RespawnSequence[playerId];
				float delay = Mathf.Max(0.25f, GunGameConfig.RespawnDelay.Value) + (float)playerId * 0.12f;
				MonoBehaviour val = (MonoBehaviour)(((object)GunGamePlugin.Instance) ?? ((object)GameManager.Instance));
				if ((Object)(object)val != (Object)null)
				{
					val.StartCoroutine(RespawnCoroutine(playerId, delay, seq));
				}
				else
				{
					RespawnsInProgress.Remove(playerId);
				}
			}
		}

		public static void ServerCheckAllPlayersAlive()
		{
			if (GunGameManager.IsMatchOver)
			{
				return;
			}
			NetworkManager networkManager = InstanceFinder.NetworkManager;
			if ((Object)(object)networkManager == (Object)null || !networkManager.IsServer || ((Object)(object)PauseManager.Instance != (Object)null && (PauseManager.Instance.inMainMenu || PauseManager.Instance.inVictoryMenu)) || Time.unscaledTime - SceneLoadedTime < 3f || Time.time - _lastServerCheckTime < 0.5f)
			{
				return;
			}
			_lastServerCheckTime = Time.time;
			try
			{
				foreach (KeyValuePair<int, ClientInstance> playerInstance in ClientInstance.playerInstances)
				{
					int key = playerInstance.Key;
					ClientInstance value = playerInstance.Value;
					if (!((Object)(object)value == (Object)null) && !IsRespawnInProgress(key) && !IsPlayerAliveAndValid(((Component)value).GetComponent<PlayerManager>(), key))
					{
						ScheduleRespawn(key);
					}
				}
			}
			catch
			{
			}
		}

		public static (Vector3 position, Quaternion rotation) GetDistinctSpawnPoint(PlayerManager pm, int playerId)
		{
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: 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)
			//IL_0317: 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_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				SpawnPoint[] array = typeof(PlayerManager).GetField("CurrentSpawnPoints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(pm) as SpawnPoint[];
				if (array == null || array.Length == 0)
				{
					array = Object.FindObjectsOfType<SpawnPoint>();
				}
				if (array != null && array.Length != 0)
				{
					SpawnPoint[] array2 = array.Where((SpawnPoint sp) => (Object)(object)sp != (Object)null && ((Component)sp).gameObject.activeInHierarchy).ToArray();
					if (array2.Length == 0)
					{
						array2 = array.Where((SpawnPoint sp) => (Object)(object)sp != (Object)null).ToArray();
					}
					if (array2.Length != 0)
					{
						List<Vector3> list = new List<Vector3>();
						foreach (KeyValuePair<int, ClientInstance> playerInstance in ClientInstance.playerInstances)
						{
							if (playerInstance.Key == playerId || !((Object)(object)playerInstance.Value != (Object)null))
							{
								continue;
							}
							PlayerManager component = ((Component)playerInstance.Value).GetComponent<PlayerManager>();
							GameObject val = (((Object)(object)component?.player != (Object)null) ? ((Component)component.player).gameObject : null);
							if ((Object)(object)val == (Object)null && _fiSpawnedObject != null && (Object)(object)component != (Object)null)
							{
								object? value = _fiSpawnedObject.GetValue(component);
								val = (GameObject)((value is GameObject) ? value : null);
							}
							if ((Object)(object)val != (Object)null && val.activeInHierarchy)
							{
								PlayerHealth component2 = val.GetComponent<PlayerHealth>();
								if ((Object)(object)component2 != (Object)null && !component2.sync___get_value_isKilled() && component2.sync___get_value_health() > 0f)
								{
									list.Add(val.transform.position);
								}
							}
						}
						SpawnPoint val2 = null;
						float num = -1f;
						SpawnPoint[] array3 = array2;
						foreach (SpawnPoint val3 in array3)
						{
							float num3 = float.MaxValue;
							if (list.Count == 0)
							{
								num3 = Random.Range(5f, 20f);
							}
							else
							{
								foreach (Vector3 item in list)
								{
									float num4 = Vector3.Distance(((Component)val3).transform.position, item);
									if (num4 < num3)
									{
										num3 = num4;
									}
								}
							}
							if (num3 > num)
							{
								num = num3;
								val2 = val3;
							}
						}
						if ((Object)(object)val2 == (Object)null)
						{
							int num5 = Mathf.Abs(playerId) % array2.Length;
							val2 = array2[num5];
						}
						if ((Object)(object)val2 != (Object)null)
						{
							Vector3 val4 = ((Component)val2).transform.position + Vector3.up * 0.15f;
							if (num < 2.5f && num >= 0f)
							{
								Vector2 insideUnitCircle = Random.insideUnitCircle;
								Vector2 val5 = ((Vector2)(ref insideUnitCircle)).normalized * Random.Range(0.8f, 1.5f);
								val4 += new Vector3(val5.x, 0f, val5.y);
							}
							return (position: val4, rotation: Quaternion.Euler(0f, ((Component)val2).transform.eulerAngles.y, 0f));
						}
					}
				}
				if ((Object)(object)pm != (Object)null)
				{
					return (position: ((Component)pm).transform.position + Vector3.up * 0.15f, rotation: Quaternion.identity);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)("[GunGamePlus] GetDistinctSpawnPoint error: " + ex.Message));
				}
			}
			return (position: Vector3.zero, rotation: Quaternion.identity);
		}

		private static IEnumerator RespawnCoroutine(int playerId, float delay, int seq)
		{
			try
			{
				yield return (object)new WaitForSeconds(delay);
				if (GunGameManager.IsMatchOver || (RespawnSequence.TryGetValue(playerId, out var value) && value != seq))
				{
					yield break;
				}
				NetworkManager nm = InstanceFinder.NetworkManager;
				if ((Object)(object)nm == (Object)null || !nm.IsServer)
				{
					yield break;
				}
				PlayerManager targetPm = FindPlayerManager(playerId);
				if (IsPlayerAliveAndValid(targetPm, playerId))
				{
					ManualLogSource logSource = GunGamePlugin.LogSource;
					if (logSource != null)
					{
						logSource.LogInfo((object)$"[GunGamePlus] Player {playerId} is already alive and valid; skipping duplicate respawn.");
					}
					int currentTierIndex = GunGameManager.GetCurrentTierIndex(playerId);
					GunGameWeaponManager.GiveWeaponTierToPlayer(playerId, currentTierIndex);
					UnfreezePlayerControls(playerId);
					yield break;
				}
				bool spawned = false;
				GameObject dyingObject = (((Object)(object)targetPm?.player != (Object)null) ? ((Component)targetPm.player).gameObject : null);
				for (int attempt = 1; attempt <= 4; attempt++)
				{
					if (GunGameManager.IsMatchOver)
					{
						break;
					}
					targetPm = FindPlayerManager(playerId);
					if ((Object)(object)targetPm == (Object)null)
					{
						ManualLogSource logSource2 = GunGamePlugin.LogSource;
						if (logSource2 != null)
						{
							logSource2.LogWarning((object)$"[GunGamePlus] PlayerManager not found for player {playerId} (attempt {attempt})");
						}
						yield return (object)new WaitForSeconds(0.25f);
						continue;
					}
					if (IsPlayerAliveAndValid(targetPm, playerId))
					{
						spawned = true;
						break;
					}
					try
					{
						if ((Object)(object)dyingObject != (Object)null)
						{
							NetworkObject component = dyingObject.GetComponent<NetworkObject>();
							if ((Object)(object)component != (Object)null && component.IsSpawned)
							{
								nm.ServerManager.Despawn(component, (DespawnType?)null);
							}
							else
							{
								Object.Destroy((Object)(object)dyingObject);
							}
							dyingObject = null;
						}
						object? obj = _fiSpawnedObject?.GetValue(targetPm);
						GameObject val = (GameObject)((obj is GameObject) ? obj : null);
						if ((Object)(object)val != (Object)null)
						{
							NetworkObject component2 = val.GetComponent<NetworkObject>();
							if ((Object)(object)component2 != (Object)null && component2.IsSpawned)
							{
								nm.ServerManager.Despawn(component2, (DespawnType?)null);
							}
							else
							{
								Object.Destroy((Object)(object)val);
							}
							_fiSpawnedObject?.SetValue(targetPm, null);
						}
					}
					catch
					{
					}
					try
					{
						_miPopulateSpawnPoints?.Invoke(targetPm, null);
						_miSetActiveSpawnPoints?.Invoke(targetPm, null);
					}
					catch
					{
					}
					(Vector3 position, Quaternion rotation) distinctSpawnPoint = GetDistinctSpawnPoint(targetPm, playerId);
					Vector3 item = distinctSpawnPoint.position;
					Quaternion item2 = distinctSpawnPoint.rotation;
					int num = (((Object)(object)CosmeticsManager.Instance != (Object)null) ? CosmeticsManager.Instance.currentsuitIndex : 0);
					int num2 = (((Object)(object)CosmeticsManager.Instance != (Object)null) ? CosmeticsManager.Instance.currentcigIndex : 0);
					if (_miSpawnPlayer4 != null)
					{
						try
						{
							_miSpawnPlayer4.Invoke(targetPm, new object[4] { num, num2, item, item2 });
							ManualLogSource logSource3 = GunGamePlugin.LogSource;
							if (logSource3 != null)
							{
								logSource3.LogInfo((object)$"[GunGamePlus] Direct SpawnPlayer(4) invoked for player {playerId} at {item} (attempt {attempt})");
							}
						}
						catch (Exception ex)
						{
							ManualLogSource logSource4 = GunGamePlugin.LogSource;
							if (logSource4 != null)
							{
								logSource4.LogWarning((object)("[GunGamePlus] Direct SpawnPlayer error: " + ex.Message));
							}
						}
					}
					else if (_miRpcLogicCmdRespawn != null)
					{
						try
						{
							_miRpcLogicCmdRespawn.Invoke(targetPm, null);
							ManualLogSource logSource5 = GunGamePlugin.LogSource;
							if (logSource5 != null)
							{
								logSource5.LogInfo((object)$"[GunGamePlus] Invoked native CmdRespawn logic for player {playerId} (attempt {attempt})");
							}
						}
						catch (Exception ex2)
						{
							ManualLogSource logSource6 = GunGamePlugin.LogSource;
							if (logSource6 != null)
							{
								logSource6.LogWarning((object)("[GunGamePlus] RpcLogicCmdRespawn invocation error: " + ex2.Message));
							}
						}
					}
					float deadline = Time.time + 1.2f;
					while (Time.time < deadline && !GunGameManager.IsMatchOver)
					{
						targetPm = FindPlayerManager(playerId);
						if (IsPlayerAliveAndValid(targetPm, playerId))
						{
							spawned = true;
							break;
						}
						yield return (object)new WaitForSeconds(0.1f);
					}
					if (spawned)
					{
						break;
					}
					yield return (object)new WaitForSeconds(0.2f);
				}
				if (spawned && (Object)(object)targetPm != (Object)null)
				{
					ManualLogSource logSource7 = GunGamePlugin.LogSource;
					if (logSource7 != null)
					{
						logSource7.LogInfo((object)$"[GunGamePlus] Player {playerId} successfully respawned!");
					}
					if (GameManager.Instance?.alivePlayers != null && !GameManager.Instance.alivePlayers.Contains(playerId))
					{
						GameManager.Instance.alivePlayers.Add(playerId);
					}
					try
					{
						targetPm.SetPlayerMove(true);
					}
					catch
					{
					}
					UnfreezePlayerControls(playerId);
					int currentTierIndex2 = GunGameManager.GetCurrentTierIndex(playerId);
					GunGameWeaponManager.GiveWeaponTierToPlayer(playerId, currentTierIndex2);
				}
				else
				{
					ManualLogSource logSource8 = GunGamePlugin.LogSource;
					if (logSource8 != null)
					{
						logSource8.LogError((object)$"[GunGamePlus] Failed to respawn player {playerId} after attempts.");
					}
				}
			}
			finally
			{
				RespawnsInProgress.Remove(playerId);
			}
		}

		public static bool IsPlayerAliveAndValid(PlayerManager pm, int playerId)
		{
			if ((Object)(object)pm == (Object)null)
			{
				pm = FindPlayerManager(playerId);
				if ((Object)(object)pm == (Object)null)
				{
					return false;
				}
			}
			GameObject val = (((Object)(object)pm.player != (Object)null) ? ((Component)pm.player).gameObject : null);
			if ((Object)(object)val == (Object)null && _fiSpawnedObject != null)
			{
				try
				{
					object? value = _fiSpawnedObject.GetValue(pm);
					val = (GameObject)((value is GameObject) ? value : null);
				}
				catch
				{
				}
			}
			if ((Object)(object)val == (Object)null || !val.activeInHierarchy)
			{
				return false;
			}
			PlayerHealth component = val.GetComponent<PlayerHealth>();
			if ((Object)(object)component == (Object)null || component.sync___get_value_isKilled() || component.sync___get_value_health() <= 0f)
			{
				return false;
			}
			NetworkObject component2 = val.GetComponent<NetworkObject>();
			if ((Object)(object)component2 == (Object)null || !component2.IsSpawned)
			{
				return false;
			}
			return true;
		}

		public static PlayerManager FindPlayerManager(int playerId)
		{
			if (ClientInstance.playerInstances.TryGetValue(playerId, out var value) && (Object)(object)value != (Object)null)
			{
				PlayerManager component = ((Component)value).GetComponent<PlayerManager>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			try
			{
				PlayerManager[] array = Object.FindObjectsOfType<PlayerManager>();
				foreach (PlayerManager val in array)
				{
					ClientInstance component2 = ((Component)val).GetComponent<ClientInstance>();
					if ((Object)(object)component2 != (Object)null && component2.PlayerId == playerId)
					{
						return val;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		public static void UnfreezePlayerControls(int playerId)
		{
			try
			{
				PlayerManager val = FindPlayerManager(playerId);
				if ((Object)(object)val != (Object)null && (Object)(object)val.player != (Object)null)
				{
					val.player.sync___set_value_canMove(true, true);
					val.player.startOfRound = false;
				}
				PauseManager.BetweenRounds = false;
				if ((Object)(object)PauseManager.Instance != (Object)null)
				{
					PauseManager.Instance.startRound = false;
					PauseManager.Instance.pause = false;
					PauseManager.Instance.otherPauseBools = false;
				}
			}
			catch
			{
			}
		}
	}
	public static class GunGameWeaponManager
	{
		private static readonly Dictionary<int, int> PendingWeaponTier;

		private static readonly Dictionary<int, int> GiveSequence;

		private static readonly Dictionary<int, float> GivingInProgress;

		private static readonly Dictionary<int, float> DropProtectionUntil;

		private static MethodInfo _miSetObjectInHandRpcLogic;

		private static MethodInfo _miSetObjectInHandObserver;

		private static MethodInfo _miSetObjectInHandObserverLogic;

		private static FieldInfo _fiRightIdlePosition;

		private static FieldInfo _fiRigBuilder;

		public static MethodInfo SetObjectInHandObserverLogic => _miSetObjectInHandObserverLogic;

		public static FieldInfo RightIdlePosition => _fiRightIdlePosition;

		public static FieldInfo RigBuilder => _fiRigBuilder;

		static GunGameWeaponManager()
		{
			PendingWeaponTier = new Dictionary<int, int>();
			GiveSequence = new Dictionary<int, int>();
			GivingInProgress = new Dictionary<int, float>();
			DropProtectionUntil = new Dictionary<int, float>();
			CacheReflection();
		}

		private static void CacheReflection()
		{
			try
			{
				_miSetObjectInHandRpcLogic = typeof(PlayerPickup).GetMethod("RpcLogic___SetObjectInHandServer_46969756", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_miSetObjectInHandObserver = typeof(PlayerPickup).GetMethod("SetObjectInHandObserver", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_miSetObjectInHandObserverLogic = typeof(PlayerPickup).GetMethod("RpcLogic___SetObjectInHandObserver_46969756", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_fiRightIdlePosition = typeof(PlayerPickup).GetField("RightIdlePosition", BindingFlags.Instance | BindingFlags.NonPublic);
				_fiRigBuilder = typeof(PlayerPickup).GetField("RigBuilder", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			catch (Exception arg)
			{
				ManualLogSource logSource = GunGamePlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)$"[GunGamePlus] WeaponManager reflection error: {arg}");
				}
			}
		}

		public static void ClearAll()
		{
			PendingWeaponTier.Clear();
			GiveSequence.Clear();
			GivingInProgress.Clear();
			DropProtectionUntil.Clear();
		}

		public static