Decompiled source of StraftatDeathmatch v1.4.2

StraftatDeathmatch.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Object;
using FishNet.Managing.Scened;
using FishNet.Object;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MyceliumNetworking;
using Steamworks;
using StraftatDeathmatch.Reloading;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("StraftatDeathmatch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.2.0")]
[assembly: AssemblyInformationalVersion("1.4.2")]
[assembly: AssemblyProduct("StraftatDeathmatch")]
[assembly: AssemblyTitle("StraftatDeathmatch")]
[assembly: AssemblyVersion("1.4.2.0")]
[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 StraftatDeathmatch
{
	internal static class BountyManager
	{
		private static readonly BountyRules Ledger = new BountyRules();

		private static readonly Dictionary<int, BountyRules.Drop> Remote = new Dictionary<int, BountyRules.Drop>();

		private static readonly Dictionary<int, GameObject> Visuals = new Dictionary<int, GameObject>();

		private static Mesh _head;

		private static Material _gold;

		private static Material _glow;

		private static float _nextTick;

		private static bool _assetWarning;

		private static Camera _camera;

		private static CommandBuffer _overlay;

		private static Material _reveal;

		private static Material _haloMaterial;

		private static Mesh _halo;

		private static Vector3 Position(BountyRules.Drop drop)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(drop.X, drop.Y, drop.Z);
		}

		public static void Spawn(Vector3 deathPosition)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (PlayerLookup.IsServer && !((Object)(object)DeathmatchPlugin.Instance == (Object)null))
			{
				((MonoBehaviour)DeathmatchPlugin.Instance).StartCoroutine(Place(deathPosition, ScoreKeeper.RoundEpoch));
			}
		}

		private static IEnumerator Place(Vector3 death, int epoch)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Vector3? position = null;
			IEnumerator search = BountyPlacement.Search(death, delegate(Vector3 found)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				position = found;
			});
			while (search.MoveNext())
			{
				yield return null;
				if (epoch != ScoreKeeper.RoundEpoch || ScoreKeeper.MatchOver)
				{
					yield break;
				}
			}
			if (!position.HasValue)
			{
				ManualLogSource log = DeathmatchPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"[Bounty] No safe floor found near the defeated ace; drop skipped.");
				}
			}
			else
			{
				Ledger.Spawn(position.Value.x, position.Value.y, position.Value.z, Time.time);
				ScoreKeeper.MarkDirty();
			}
		}

		public static void Tick()
		{
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			if (ScoreKeeper.ModeActiveLocally() && !ScoreKeeper.MatchOver)
			{
				bool num;
				if (!PlayerLookup.IsServer)
				{
					if (!ScoreKeeper.SyncedActive || !ScoreKeeper.SyncedShutdownEnabled)
					{
						goto IL_0049;
					}
					num = Time.unscaledTime - ScoreKeeper.LastSyncTime < 6f;
				}
				else
				{
					num = DeathmatchPlugin.ShutdownEnabled.Value;
				}
				if (num)
				{
					if (PlayerLookup.IsServer && Time.time >= _nextTick)
					{
						_nextTick = Time.time + 0.05f;
						BountyPlacement.Prepare();
						if (Ledger.Expire(Time.time))
						{
							ScoreKeeper.MarkDirty();
						}
						foreach (BountyRules.Drop item in new List<BountyRules.Drop>(Ledger.Drops.Values))
						{
							int num2 = -1;
							float num3 = 1.5625f;
							foreach (int key in ClientInstance.playerInstances.Keys)
							{
								if (PlayerLookup.TryGetLivingBody(key, out var body))
								{
									Vector3 val = body.transform.position + Vector3.up;
									Vector3 val2 = val - Position(item);
									float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
									if (!(sqrMagnitude > num3) && WorldSight.Clear(val, Position(item)))
									{
										num2 = key;
										num3 = sqrMagnitude;
									}
								}
							}
							if (num2 >= 0 && Ledger.TryClaim(item.Id, alive: true, num3, clearPath: true, Time.time))
							{
								ScoreKeeper.AwardBounty(num2);
								if (ScoreKeeper.MatchOver)
								{
									break;
								}
							}
						}
					}
					if (ScoreKeeper.MatchOver)
					{
						Reset();
						return;
					}
					Dictionary<int, BountyRules.Drop> dictionary = (PlayerLookup.IsServer ? Ledger.Drops : Remote);
					foreach (int item2 in new List<int>(Visuals.Keys))
					{
						if (!dictionary.ContainsKey(item2))
						{
							Object.Destroy((Object)(object)Visuals[item2]);
							Visuals.Remove(item2);
						}
					}
					foreach (BountyRules.Drop value2 in dictionary.Values)
					{
						if (!Visuals.TryGetValue(value2.Id, out var value) || (Object)(object)value == (Object)null)
						{
							value = (Visuals[value2.Id] = CreateVisual());
						}
						value.SetActive(BountyRules.IsVisible(value2.ExpiresAt - Time.time));
						Animate(value, Position(value2), Time.time);
					}
					DrawThroughWalls();
					return;
				}
			}
			goto IL_0049;
			IL_0049:
			if (Ledger.Drops.Count > 0 || Remote.Count > 0 || Visuals.Count > 0)
			{
				Reset();
				ScoreKeeper.MarkDirty();
			}
		}

		private static void DrawThroughWalls()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			Camera val = CombatVisuals.LocalCamera();
			if ((Object)(object)_camera != (Object)(object)val)
			{
				ReleaseOverlay();
				_camera = val;
				if ((Object)(object)_camera != (Object)null)
				{
					_overlay = new CommandBuffer
					{
						name = "Deathmatch bounty reveal"
					};
					_camera.AddCommandBuffer((CameraEvent)20, _overlay);
				}
			}
			if (_overlay == null)
			{
				return;
			}
			_overlay.Clear();
			if ((Object)(object)_reveal == (Object)null)
			{
				_reveal = CombatVisuals.CreateRevealMaterial();
				((Object)_reveal).name = "Deathmatch Gold Reveal";
				_reveal.SetColor("_Color", new Color(1f, 0.72f, 0.06f, 0.85f));
			}
			if ((Object)(object)_halo == (Object)null)
			{
				_halo = CreateHaloMesh();
			}
			if ((Object)(object)_haloMaterial == (Object)null)
			{
				_haloMaterial = CombatVisuals.CreateRevealMaterial();
				((Object)_haloMaterial).name = "Deathmatch Distant Bounty Halo";
				_haloMaterial.SetColor("_Color", Color.white);
			}
			foreach (GameObject value in Visuals.Values)
			{
				if ((Object)(object)value != (Object)null && value.activeInHierarchy)
				{
					Vector3 position = value.transform.position;
					float num = HaloRadius(Vector3.Distance(((Component)_camera).transform.position, position));
					_overlay.DrawMesh(_halo, Matrix4x4.TRS(position, ((Component)_camera).transform.rotation, Vector3.one * num), _haloMaterial);
					CombatVisuals.DrawReveal(_overlay, (IEnumerable<Renderer>)(object)new MeshRenderer[1] { value.GetComponentInChildren<MeshRenderer>() }, _reveal);
				}
			}
		}

		internal static float HaloRadius(float distance)
		{
			return 1.2f * (0.55f + Mathf.Max(0f, distance) * 0.022f);
		}

		private static Mesh CreateHaloMesh()
		{
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			float[] array = new float[5] { 0f, 0.48f, 0.62f, 0.76f, 1f };
			float[] array2 = new float[5] { 0f, 0.04f, 0.32f, 0.09f, 0f };
			Vector3[] array3 = (Vector3[])(object)new Vector3[array.Length * 64];
			Color[] array4 = (Color[])(object)new Color[array3.Length];
			int[] array5 = new int[(array.Length - 1) * 64 * 6];
			for (int i = 0; i < array.Length; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = (float)j * (float)Math.PI * 2f / 64f;
					int num2 = i * 64 + j;
					array3[num2] = new Vector3(Mathf.Cos(num), Mathf.Sin(num), 0f) * array[i];
					array4[num2] = new Color(1f, 0.73f, 0.12f, array2[i]);
					if (i != array.Length - 1)
					{
						int num3 = i * 64 + (j + 1) % 64;
						int num4 = num2 * 6;
						array5[num4] = num2;
						array5[num4 + 1] = num3;
						array5[num4 + 2] = num2 + 64;
						array5[num4 + 3] = num3;
						array5[num4 + 4] = num3 + 64;
						array5[num4 + 5] = num2 + 64;
					}
				}
			}
			Mesh val = new Mesh
			{
				name = "Deathmatch Soft Gold Ring",
				vertices = array3,
				colors = array4,
				triangles = array5
			};
			val.RecalculateBounds();
			return val;
		}

		private static void ReleaseOverlay()
		{
			if (_overlay != null)
			{
				if ((Object)(object)_camera != (Object)null)
				{
					_camera.RemoveCommandBuffer((CameraEvent)20, _overlay);
				}
				_overlay.Release();
				_overlay = null;
			}
			_camera = null;
		}

		internal static GameObject CreateVisual()
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: 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_02f9: 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_0352: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_head == (Object)null)
			{
				Mesh[] array = Resources.FindObjectsOfTypeAll<Mesh>();
				foreach (Mesh val in array)
				{
					if (((Object)val).name == "SM_Aboubi_Head00")
					{
						_head = val;
						break;
					}
				}
			}
			if ((Object)(object)_gold == (Object)null)
			{
				_gold = new Material(Shader.Find("Standard"))
				{
					name = "Deathmatch Bounty Gold",
					color = new Color(1f, 0.65f, 0.06f)
				};
				_gold.SetFloat("_Metallic", 0.65f);
				_gold.SetFloat("_Glossiness", 0.7f);
				_gold.EnableKeyword("_EMISSION");
				_gold.SetColor("_EmissionColor", new Color(0.65f, 0.28f, 0.015f));
				_glow = new Material(Shader.Find("Sprites/Default"))
				{
					name = "Deathmatch Bounty Halo",
					color = new Color(1f, 0.7f, 0.08f)
				};
			}
			GameObject val2 = new GameObject("Deathmatch Ace Bounty");
			if ((Object)(object)_head != (Object)null)
			{
				GameObject val3 = new GameObject("Golden Aboubi Head");
				val3.transform.SetParent(val2.transform, false);
				val3.AddComponent<MeshFilter>().sharedMesh = _head;
				((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterial = _gold;
				Transform transform = val3.transform;
				Bounds bounds = _head.bounds;
				transform.localPosition = -((Bounds)(ref bounds)).center * 1.6f;
				val3.transform.localScale = Vector3.one * 1.6f;
			}
			else
			{
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
				obj.transform.SetParent(val2.transform, false);
				Object.Destroy((Object)(object)obj.GetComponent<Collider>());
				obj.GetComponent<Renderer>().sharedMaterial = _gold;
				obj.transform.localScale = Vector3.one * 0.6f;
				if (!_assetWarning)
				{
					_assetWarning = true;
					ManualLogSource log = DeathmatchPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[Bounty] Aboubi head mesh unavailable; using a gold token fallback.");
					}
				}
			}
			GameObject val4 = new GameObject("Bounty Halo");
			val4.transform.SetParent(val2.transform, false);
			LineRenderer val5 = val4.AddComponent<LineRenderer>();
			((Renderer)val5).sharedMaterial = _glow;
			val5.useWorldSpace = false;
			val5.loop = true;
			val5.widthMultiplier = 0.025f;
			val5.positionCount = 40;
			for (int j = 0; j < 40; j++)
			{
				float num = (float)j * (float)Math.PI * 2f / 40f;
				val5.SetPosition(j, new Vector3(Mathf.Cos(num) * 0.45f, -0.3f, Mathf.Sin(num) * 0.45f));
			}
			GameObject val6 = new GameObject("Bounty Point Label");
			val6.transform.SetParent(val2.transform, false);
			val6.transform.localPosition = Vector3.up * 0.57f;
			TextMeshPro obj2 = val6.AddComponent<TextMeshPro>();
			((TMP_Text)obj2).text = "+1";
			((TMP_Text)obj2).fontSize = 4f;
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((Graphic)obj2).color = new Color(1f, 0.85f, 0.2f);
			((TMP_Text)obj2).rectTransform.sizeDelta = new Vector2(1f, 0.4f);
			return val2;
		}

		internal static void Animate(GameObject visual, Vector3 position, float time)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			visual.transform.position = position + Vector3.up * (Mathf.Sin(time * 2.6f) * 0.13f);
			visual.transform.rotation = Quaternion.Euler(0f, time * 65f, 0f);
			Transform val = visual.transform.Find("Bounty Point Label");
			Camera val2 = CombatVisuals.LocalCamera();
			if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
			{
				val.rotation = ((Component)val2).transform.rotation;
			}
		}

		public static string Serialize()
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (BountyRules.Drop value in Ledger.Drops.Values)
			{
				float num = value.ExpiresAt - Time.time;
				if (!(num <= 0f))
				{
					if (stringBuilder.Length > 0)
					{
						stringBuilder.Append(';');
					}
					stringBuilder.Append(value.Id).Append(':').Append(value.X.ToString("R", CultureInfo.InvariantCulture))
						.Append(':')
						.Append(value.Y.ToString("R", CultureInfo.InvariantCulture))
						.Append(':')
						.Append(value.Z.ToString("R", CultureInfo.InvariantCulture))
						.Append(':')
						.Append(num.ToString("R", CultureInfo.InvariantCulture));
				}
			}
			return stringBuilder.ToString();
		}

		public static void ApplySynced(string data)
		{
			Remote.Clear();
			if (string.IsNullOrEmpty(data))
			{
				return;
			}
			string[] array = data.Split(new char[1] { ';' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length == 5 && int.TryParse(array2[0], out var result) && Parse(array2[1], out var result2) && Parse(array2[2], out var result3) && Parse(array2[3], out var result4) && Parse(array2[4], out var result5) && !(result5 <= 0f))
				{
					Remote[result] = new BountyRules.Drop
					{
						Id = result,
						X = result2,
						Y = result3,
						Z = result4,
						ExpiresAt = Time.time + Mathf.Min(30f, result5)
					};
				}
			}
		}

		private static bool Parse(string value, out float result)
		{
			if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out result) && !float.IsNaN(result))
			{
				return !float.IsInfinity(result);
			}
			return false;
		}

		public static void Reset()
		{
			Ledger.Clear();
			Remote.Clear();
			ReleaseOverlay();
			if ((Object)(object)_reveal != (Object)null)
			{
				Object.Destroy((Object)(object)_reveal);
			}
			_reveal = null;
			if ((Object)(object)_haloMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_haloMaterial);
			}
			if ((Object)(object)_halo != (Object)null)
			{
				Object.Destroy((Object)(object)_halo);
			}
			_haloMaterial = null;
			_halo = null;
			foreach (GameObject value in Visuals.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			Visuals.Clear();
			_nextTick = 0f;
			if ((Object)(object)_gold != (Object)null)
			{
				Object.Destroy((Object)(object)_gold);
			}
			if ((Object)(object)_glow != (Object)null)
			{
				Object.Destroy((Object)(object)_glow);
			}
			_gold = null;
			_glow = null;
			_head = null;
		}
	}
	internal static class BountyPlacement
	{
		private struct Footprint
		{
			public float MinX;

			public float MaxX;

			public float MinZ;

			public float MaxZ;

			public float CenterX;

			public float CenterZ;
		}

		private const double SliceMs = 1.5;

		private const double BudgetMs = 250.0;

		private static readonly RaycastHit[] ColumnHits = (RaycastHit[])(object)new RaycastHit[64];

		private static readonly RaycastHit[] SupportHits = (RaycastHit[])(object)new RaycastHit[16];

		private static readonly Collider[] Nearby = (Collider[])(object)new Collider[64];

		private static readonly Dictionary<int, bool> WorldColliders = new Dictionary<int, bool>();

		private static readonly List<Footprint> Footprints = new List<Footprint>();

		private static readonly List<Vector3> Spawns = new List<Vector3>();

		private static int _scene = int.MinValue;

		private static float _top;

		private static float _bottom;

		private static bool World(Collider collider)
		{
			if ((Object)(object)collider == (Object)null || collider.isTrigger)
			{
				return false;
			}
			int instanceID = ((Object)collider).GetInstanceID();
			if (!WorldColliders.TryGetValue(instanceID, out var value))
			{
				value = (WorldColliders[instanceID] = (Object)(object)((Component)collider).GetComponentInParent<PlayerHealth>() == (Object)null && (Object)(object)((Component)collider).GetComponentInParent<ItemBehaviour>() == (Object)null && (Object)(object)((Component)collider).GetComponentInParent<DamageZone>() == (Object)null);
			}
			return value;
		}

		public static void Prepare()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			int handle = ((Scene)(ref activeScene)).handle;
			if (handle == _scene)
			{
				return;
			}
			_scene = handle;
			WorldColliders.Clear();
			Footprints.Clear();
			Spawns.Clear();
			_top = float.MinValue;
			_bottom = float.MaxValue;
			Collider[] array = Object.FindObjectsOfType<Collider>();
			foreach (Collider val in array)
			{
				if (val.enabled && World(val))
				{
					Bounds bounds = val.bounds;
					_top = Mathf.Max(_top, ((Bounds)(ref bounds)).max.y);
					_bottom = Mathf.Min(_bottom, ((Bounds)(ref bounds)).min.y);
					if (!(((Bounds)(ref bounds)).size.x < 1.1f) && !(((Bounds)(ref bounds)).size.z < 1.1f))
					{
						Footprints.Add(new Footprint
						{
							MinX = ((Bounds)(ref bounds)).min.x + 0.6f,
							MaxX = ((Bounds)(ref bounds)).max.x - 0.6f,
							MinZ = ((Bounds)(ref bounds)).min.z + 0.6f,
							MaxZ = ((Bounds)(ref bounds)).max.z - 0.6f,
							CenterX = ((Bounds)(ref bounds)).center.x,
							CenterZ = ((Bounds)(ref bounds)).center.z
						});
					}
				}
			}
			SpawnPoint[] array2 = Object.FindObjectsOfType<SpawnPoint>(true);
			foreach (SpawnPoint val2 in array2)
			{
				Spawns.Add(((Component)val2).transform.position);
			}
			if (_top < _bottom)
			{
				_top = (_bottom = 0f);
			}
		}

		private static RaycastHit[] Down(Vector3 origin, float distance, RaycastHit[] buffer, out int count)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			count = Physics.RaycastNonAlloc(origin, Vector3.down, buffer, distance, -5, (QueryTriggerInteraction)1);
			if (count < buffer.Length)
			{
				return buffer;
			}
			RaycastHit[] array = Physics.RaycastAll(origin, Vector3.down, distance, -5, (QueryTriggerInteraction)1);
			count = array.Length;
			return array;
		}

		private static bool Floor(Vector3 origin, float distance, out RaycastHit floor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			floor = default(RaycastHit);
			float num = float.MaxValue;
			int count;
			RaycastHit[] array = Down(origin, distance, SupportHits, out count);
			for (int i = 0; i < count; i++)
			{
				if (World(((RaycastHit)(ref array[i])).collider) && !(((RaycastHit)(ref array[i])).distance >= num))
				{
					floor = array[i];
					num = ((RaycastHit)(ref array[i])).distance;
				}
			}
			if (num < float.MaxValue)
			{
				return ((RaycastHit)(ref floor)).normal.y >= 0.92f;
			}
			return false;
		}

		internal static bool SafeFloor(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.OverlapCapsuleNonAlloc(point + Vector3.up * 0.48f, point + Vector3.up * 1.45f, 0.4f, Nearby, -5, (QueryTriggerInteraction)1);
			if (num == Nearby.Length)
			{
				return false;
			}
			for (int i = 0; i < num; i++)
			{
				if (World(Nearby[i]))
				{
					return false;
				}
			}
			for (int j = 0; j < 8; j++)
			{
				float num2 = (float)j * (float)Math.PI / 4f;
				Vector3 val = new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * 0.55f;
				if (!Floor(point + val + Vector3.up * 0.3f, 0.6f, out var floor) || Mathf.Abs(((RaycastHit)(ref floor)).point.y - point.y) > 0.2f)
				{
					return false;
				}
			}
			num = Physics.OverlapSphereNonAlloc(point + Vector3.up * 0.8f, 0.6f, Nearby, -1, (QueryTriggerInteraction)2);
			if (num == Nearby.Length)
			{
				return false;
			}
			for (int k = 0; k < num; k++)
			{
				if ((Object)(object)((Component)Nearby[k]).GetComponentInParent<DamageZone>() != (Object)null)
				{
					return false;
				}
			}
			return true;
		}

		public static IEnumerator Search(Vector3 death, Action<Vector3> found)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (Floor(death + Vector3.up * 0.5f, 6f, out var floor) && SafeFloor(((RaycastHit)(ref floor)).point))
			{
				found(((RaycastHit)(ref floor)).point + Vector3.up);
				yield break;
			}
			Stopwatch clock = Stopwatch.StartNew();
			double spent = 0.0;
			Prepare();
			Vector3 anchor = new Vector3(death.x, Mathf.Clamp(death.y, _bottom, _top), death.z);
			ColumnOrder columns = new ColumnOrder(anchor.x, anchor.z);
			columns.Add(anchor.x, anchor.z);
			for (float num = 1f; num <= 64f; num *= 2f)
			{
				for (int i = 0; i < 24; i++)
				{
					float num2 = (float)i * (float)Math.PI / 12f;
					columns.Add(anchor.x + Mathf.Cos(num2) * num, anchor.z + Mathf.Sin(num2) * num);
				}
			}
			foreach (Vector3 spawn in Spawns)
			{
				columns.Add(spawn.x, spawn.z);
			}
			foreach (Footprint footprint in Footprints)
			{
				columns.Add(Mathf.Clamp(anchor.x, footprint.MinX, footprint.MaxX), Mathf.Clamp(anchor.z, footprint.MinZ, footprint.MaxZ));
				columns.Add(footprint.CenterX, footprint.CenterZ);
			}
			float top = _top + 2f;
			float bottom = _bottom - 2f;
			float best = float.MaxValue;
			Vector3 bestPoint = Vector3.zero;
			List<KeyValuePair<float, Vector3>> floors = new List<KeyValuePair<float, Vector3>>();
			float x;
			float z;
			while (columns.Next(best, out x, out z))
			{
				int count;
				RaycastHit[] array = Down(new Vector3(x, top, z), top - bottom, ColumnHits, out count);
				floors.Clear();
				for (int j = 0; j < count; j++)
				{
					Vector3 val = ((RaycastHit)(ref array[j])).point - anchor;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < best && ((RaycastHit)(ref array[j])).normal.y >= 0.92f && World(((RaycastHit)(ref array[j])).collider))
					{
						floors.Add(new KeyValuePair<float, Vector3>(sqrMagnitude, ((RaycastHit)(ref array[j])).point));
					}
				}
				floors.Sort((KeyValuePair<float, Vector3> a, KeyValuePair<float, Vector3> b) => a.Key.CompareTo(b.Key));
				foreach (KeyValuePair<float, Vector3> item in floors)
				{
					if (SafeFloor(item.Value))
					{
						best = item.Key;
						bestPoint = item.Value;
						break;
					}
				}
				if (!(clock.Elapsed.TotalMilliseconds < 1.5))
				{
					spent += clock.Elapsed.TotalMilliseconds;
					if (spent >= 250.0)
					{
						break;
					}
					yield return null;
					clock.Restart();
				}
			}
			if (best < float.MaxValue)
			{
				found(bestPoint + Vector3.up);
			}
		}
	}
	internal sealed class ColumnOrder
	{
		private struct Column
		{
			public float X;

			public float Z;

			public float Bound;
		}

		private readonly float _x;

		private readonly float _z;

		private readonly List<Column> _columns = new List<Column>();

		private readonly HashSet<long> _cells = new HashSet<long>();

		private bool _sorted;

		private int _next;

		public int Count => _columns.Count;

		public ColumnOrder(float anchorX, float anchorZ)
		{
			_x = anchorX;
			_z = anchorZ;
		}

		public void Add(float x, float z)
		{
			if (!float.IsNaN(x) && !float.IsNaN(z) && !float.IsInfinity(x) && !float.IsInfinity(z))
			{
				long item = ((long)Math.Round(x * 4f) << 32) ^ (uint)(int)Math.Round(z * 4f);
				if (_cells.Add(item))
				{
					float num = x - _x;
					float num2 = z - _z;
					_columns.Add(new Column
					{
						X = x,
						Z = z,
						Bound = num * num + num2 * num2
					});
				}
			}
		}

		public bool Next(float best, out float x, out float z)
		{
			if (!_sorted)
			{
				_columns.Sort((Column a, Column b) => a.Bound.CompareTo(b.Bound));
				_sorted = true;
			}
			x = (z = 0f);
			if (_next >= _columns.Count || _columns[_next].Bound >= best)
			{
				return false;
			}
			x = _columns[_next].X;
			z = _columns[_next].Z;
			_next++;
			return true;
		}
	}
	internal sealed class BountyRules
	{
		internal sealed class Drop
		{
			public int Id;

			public float X;

			public float Y;

			public float Z;

			public float ExpiresAt;
		}

		public const float PickupRadius = 1.25f;

		public const float Lifetime = 30f;

		public const float BlinkDuration = 5f;

		public readonly Dictionary<int, Drop> Drops = new Dictionary<int, Drop>();

		private int _nextId;

		public Drop Spawn(float x, float y, float z, float now = 0f)
		{
			Drop drop = new Drop
			{
				Id = ++_nextId,
				X = x,
				Y = y,
				Z = z,
				ExpiresAt = now + 30f
			};
			Drops.Add(drop.Id, drop);
			return drop;
		}

		public bool TryClaim(int id, bool alive, float distanceSquared, bool clearPath, float now = 0f)
		{
			if (!Drops.TryGetValue(id, out var value) || now >= value.ExpiresAt || !alive || !clearPath || float.IsNaN(distanceSquared) || distanceSquared < 0f || distanceSquared > 1.5625f)
			{
				return false;
			}
			return Drops.Remove(id);
		}

		public bool Expire(float now)
		{
			bool result = false;
			foreach (Drop item in new List<Drop>(Drops.Values))
			{
				if (now >= item.ExpiresAt)
				{
					Drops.Remove(item.Id);
					result = true;
				}
			}
			return result;
		}

		public static bool IsVisible(float remaining)
		{
			if (remaining > 0f)
			{
				if (!(remaining > 5f))
				{
					return (int)((5f - remaining) * 6f) % 2 == 0;
				}
				return true;
			}
			return false;
		}

		public void Clear()
		{
			Drops.Clear();
		}
	}
	internal sealed class CombatRules
	{
		internal struct Result
		{
			public bool Credited;

			public bool Revenge;

			public bool Shutdown;

			public bool NemesisCreated;

			public bool BecameAce;

			public bool KillerIsAce;

			public int Bonus
			{
				get
				{
					if (!Revenge || Shutdown)
					{
						return 0;
					}
					return 1;
				}
			}
		}

		public readonly Dictionary<int, int> Scores = new Dictionary<int, int>();

		public readonly Dictionary<int, int> Kills = new Dictionary<int, int>();

		public readonly Dictionary<int, int> Deaths = new Dictionary<int, int>();

		public readonly Dictionary<int, int> Streaks = new Dictionary<int, int>();

		private readonly Dictionary<long, int> _unanswered = new Dictionary<long, int>();

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

		public static int Get(Dictionary<int, int> data, int id)
		{
			if (!data.TryGetValue(id, out var value))
			{
				return 0;
			}
			return value;
		}

		private static long Pair(int killer, int victim)
		{
			return (long)(((ulong)(uint)killer << 32) | (uint)victim);
		}

		public bool IsNemesis(int seeker, int target)
		{
			if (_unanswered.TryGetValue(Pair(target, seeker), out var value))
			{
				return value >= 3;
			}
			return false;
		}

		public IEnumerable<KeyValuePair<int, int>> Rivalries()
		{
			foreach (KeyValuePair<long, int> item in _unanswered)
			{
				if (item.Value >= 3)
				{
					yield return new KeyValuePair<int, int>((int)item.Key, (int)(item.Key >> 32));
				}
			}
		}

		public void AwardBounty(int player)
		{
			Scores[player] = Get(Scores, player) + 1;
		}

		public Result RecordDeath(int victim, int killer, bool revengeEnabled, bool shutdownEnabled, bool killerAlive, ICollection<int> players, bool victimWasAce)
		{
			Result result = default(Result);
			bool flag = IsAce(killer, players, shutdownEnabled);
			Deaths[victim] = Get(Deaths, victim) + 1;
			Streaks[victim] = 0;
			if (killer < 0 || killer == victim)
			{
				return result;
			}
			result.Credited = true;
			long key = Pair(victim, killer);
			long key2 = Pair(killer, victim);
			int value;
			int num = (_unanswered.TryGetValue(key, out value) ? value : 0);
			int value2;
			int num2 = (_unanswered.TryGetValue(key2, out value2) ? value2 : 0);
			result.Revenge = revengeEnabled && num >= 3;
			result.Shutdown = victimWasAce;
			_unanswered.Remove(key);
			_unanswered[key2] = Math.Min(3, num2 + 1);
			result.NemesisCreated = revengeEnabled && num2 == 2;
			Kills[killer] = Get(Kills, killer) + 1;
			Scores[killer] = Get(Scores, killer) + 1 + result.Bonus;
			if (killerAlive)
			{
				int value3 = Get(Streaks, killer) + 1;
				Streaks[killer] = value3;
			}
			result.KillerIsAce = IsAce(killer, players, shutdownEnabled);
			result.BecameAce = !flag && result.KillerIsAce;
			return result;
		}

		public bool IsUnderdog(int id, ICollection<int> players)
		{
			if (players.Count < 2 || !players.Contains(id))
			{
				return false;
			}
			int num = int.MinValue;
			foreach (int player in players)
			{
				int val = Get(Scores, player);
				num = Math.Max(num, val);
			}
			return (long)num - (long)Get(Scores, id) >= 5;
		}

		public bool IsScoreAce(int id, ICollection<int> players)
		{
			if (players.Count < 2 || !players.Contains(id))
			{
				return false;
			}
			int num = int.MinValue;
			foreach (int player in players)
			{
				if (player != id)
				{
					num = Math.Max(num, Get(Scores, player));
				}
			}
			return (long)Get(Scores, id) - (long)num >= 5;
		}

		public bool IsAce(int id, ICollection<int> players, bool enabled)
		{
			if (enabled && players.Contains(id))
			{
				if (Get(Streaks, id) < 3)
				{
					return IsScoreAce(id, players);
				}
				return true;
			}
			return false;
		}

		public IEnumerable<KeyValuePair<int, string>> RefreshAces(ICollection<int> players, bool enabled)
		{
			List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
			_aces.RemoveWhere((int id) => !players.Contains(id));
			foreach (int player in players)
			{
				bool flag = IsAce(player, players, enabled);
				if (flag && _aces.Add(player))
				{
					list.Add(new KeyValuePair<int, string>(player, (Get(Streaks, player) >= 3) ? "ace" : "ace_score"));
				}
				else if (!flag && _aces.Remove(player))
				{
					list.Add(new KeyValuePair<int, string>(player, "ace_lost"));
				}
			}
			return list;
		}

		public void RemovePlayer(int id)
		{
			_aces.Remove(id);
			Scores.Remove(id);
			Kills.Remove(id);
			Deaths.Remove(id);
			Streaks.Remove(id);
			foreach (long item in new List<long>(_unanswered.Keys))
			{
				if ((int)(item >> 32) == id || (int)item == id)
				{
					_unanswered.Remove(item);
				}
			}
		}

		public void Clear()
		{
			_aces.Clear();
			Scores.Clear();
			Kills.Clear();
			Deaths.Clear();
			Streaks.Clear();
			_unanswered.Clear();
		}
	}
	internal sealed class UnderdogHealthState
	{
		public const float BonusInternalHp = 1f;

		private float _remaining = 1f;

		private float _last;

		private bool _observed;

		private bool _applied;

		public float HealOnKill(float health, bool eligible)
		{
			float restored;
			return HealOnKill(health, eligible, out restored);
		}

		public float HealOnKill(float health, bool eligible, out float restored)
		{
			health = Update(health, eligible);
			float num = health;
			if (health > 0f)
			{
				health = Math.Max(health, Math.Min(4f, health + 1f));
			}
			restored = health - num;
			_last = health;
			return health;
		}

		public float Update(float health, bool eligible)
		{
			if (_observed && _applied)
			{
				_remaining = Math.Max(0f, _remaining - Math.Max(0f, _last - health));
			}
			_observed = true;
			if (health <= 0f)
			{
				_remaining = 0f;
				_applied = false;
				_last = health;
				return health;
			}
			if (eligible != _applied)
			{
				health += (eligible ? _remaining : (0f - Math.Min(_remaining, health)));
				_applied = eligible;
			}
			_last = health;
			return health;
		}
	}
	internal static class CombatVisuals
	{
		private sealed class OutlineState
		{
			public Renderer Renderer;

			public MaterialPropertyBlock Original;
		}

		private static readonly Dictionary<Renderer, OutlineState> Outlined = new Dictionary<Renderer, OutlineState>();

		private static readonly FieldInfo BodyMeshes = AccessTools.Field(typeof(PlayerSetup), "gameObjectsToDisableForMe");

		private static Camera _camera;

		private static CommandBuffer _buffer;

		private static Material _reveal;

		private static Material _visibleMask;

		private static Material _clearMask;

		public static Camera LocalCamera()
		{
			GameObject val = PlayerLookup.FindBody(PlayerLookup.LocalPlayerId);
			FirstPersonController val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<FirstPersonController>() : null);
			if (!((Object)(object)val2 != (Object)null) || !((Object)(object)val2.playerCamera != (Object)null))
			{
				return Camera.main;
			}
			return val2.playerCamera;
		}

		internal static List<Renderer> BodyRenderers(GameObject body)
		{
			List<Renderer> list = new List<Renderer>();
			PlayerSetup component = body.GetComponent<PlayerSetup>();
			GameObject[] array = (((Object)(object)component != (Object)null) ? (BodyMeshes?.GetValue(component) as GameObject[]) : null);
			if (array != null)
			{
				GameObject[] array2 = array;
				foreach (GameObject val in array2)
				{
					if (!((Object)(object)val != (Object)null))
					{
						continue;
					}
					Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer item in componentsInChildren)
					{
						if (!list.Contains(item))
						{
							list.Add(item);
						}
					}
				}
			}
			return list;
		}

		internal static Material CreateRevealMaterial()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			Material val = new Material(Shader.Find("Hidden/Internal-Colored"))
			{
				name = "Deathmatch Nemesis Reveal",
				hideFlags = (HideFlags)61
			};
			val.SetInt("_SrcBlend", 5);
			val.SetInt("_DstBlend", 10);
			val.SetInt("_Cull", 0);
			val.SetInt("_ZWrite", 0);
			val.SetInt("_ZTest", 8);
			return val;
		}

		internal static void SetPulse(Material material, float time)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.05f + 0.1f * (0.5f + 0.5f * Mathf.Sin(time * (float)Math.PI * 2f * 1.1f));
			material.SetColor("_Color", new Color(1f, 0f, 0f, num));
		}

		private static Material CreateNemesisMask(string name, CompareFunction comparison, StencilOp operation, bool color, CompareFunction depth)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected I4, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected I4, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected I4, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			Material val = new Material(Shader.Find("UI/Default"))
			{
				name = name,
				hideFlags = (HideFlags)61
			};
			val.SetInt("unity_GUIZTestMode", (int)depth);
			val.SetInt("_Stencil", 128);
			val.SetInt("_StencilReadMask", 128);
			val.SetInt("_StencilWriteMask", 128);
			val.SetInt("_StencilComp", (int)comparison);
			val.SetInt("_StencilOp", (int)operation);
			val.SetInt("_ColorMask", color ? 15 : 0);
			val.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
			return val;
		}

		internal static void DrawNemesisReveal(CommandBuffer buffer, IEnumerable<Renderer> renderers, float time)
		{
			if ((Object)(object)_clearMask == (Object)null)
			{
				_clearMask = CreateNemesisMask("Deathmatch Nemesis Mask Clear", (CompareFunction)8, (StencilOp)1, color: false, (CompareFunction)8);
			}
			if ((Object)(object)_visibleMask == (Object)null)
			{
				_visibleMask = CreateNemesisMask("Deathmatch Visible Nemesis Mask", (CompareFunction)8, (StencilOp)2, color: false, (CompareFunction)4);
			}
			if ((Object)(object)_reveal == (Object)null)
			{
				_reveal = CreateNemesisMask("Deathmatch Occluded Nemesis", (CompareFunction)6, (StencilOp)2, color: true, (CompareFunction)8);
			}
			SetPulse(_reveal, time);
			DrawReveal(buffer, renderers, _clearMask);
			DrawReveal(buffer, renderers, _visibleMask);
			DrawReveal(buffer, renderers, _reveal);
			DrawReveal(buffer, renderers, _clearMask);
		}

		internal static void DrawReveal(CommandBuffer buffer, IEnumerable<Renderer> renderers, Material material)
		{
			foreach (Renderer renderer in renderers)
			{
				if ((Object)(object)renderer == (Object)null || !renderer.enabled || !((Component)renderer).gameObject.activeInHierarchy)
				{
					continue;
				}
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
				int num2;
				if (val == null || !((Object)(object)val.sharedMesh != (Object)null))
				{
					MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
					int? obj;
					if (component == null)
					{
						obj = null;
					}
					else
					{
						Mesh sharedMesh = component.sharedMesh;
						obj = ((sharedMesh != null) ? new int?(sharedMesh.subMeshCount) : ((int?)null));
					}
					int? num = obj;
					num2 = num.GetValueOrDefault();
				}
				else
				{
					num2 = val.sharedMesh.subMeshCount;
				}
				int num3 = num2;
				for (int i = 0; i < num3; i++)
				{
					buffer.DrawRenderer(renderer, material, i, 0);
				}
			}
		}

		internal static void SetAceOutline(Renderer renderer)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			Material[] sharedMaterials = renderer.sharedMaterials;
			foreach (Material val in sharedMaterials)
			{
				if ((Object)(object)val != (Object)null && val.HasProperty("_ASEOutlineWidth"))
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				if (!Outlined.TryGetValue(renderer, out var value))
				{
					value = new OutlineState
					{
						Renderer = renderer,
						Original = new MaterialPropertyBlock()
					};
					renderer.GetPropertyBlock(value.Original);
					Outlined.Add(renderer, value);
				}
				MaterialPropertyBlock val2 = new MaterialPropertyBlock();
				renderer.GetPropertyBlock(val2);
				val2.SetFloat("_ASEOutlineWidth", ((Object)renderer).name.Contains("Head") ? 0.025f : 0.045f);
				val2.SetColor("_ASEOutlineColor", Color.red);
				renderer.SetPropertyBlock(val2);
			}
		}

		internal static bool AceVisible(Camera camera, IEnumerable<Renderer> renderers)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)camera == (Object)null)
			{
				return false;
			}
			Vector3 position = ((Component)camera).transform.position;
			foreach (Renderer renderer in renderers)
			{
				if (!((Object)(object)renderer == (Object)null) && renderer.enabled && ((Component)renderer).gameObject.activeInHierarchy)
				{
					Bounds bounds = renderer.bounds;
					Vector3 val = Vector3.up * ((Bounds)(ref bounds)).extents.y * 0.75f;
					if (WorldSight.Clear(position, ((Bounds)(ref bounds)).center) || WorldSight.Clear(position, ((Bounds)(ref bounds)).center + val) || WorldSight.Clear(position, ((Bounds)(ref bounds)).center - val))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static void Tick()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			int localPlayerId = PlayerLookup.LocalPlayerId;
			if (!ScoreKeeper.ModeActiveLocally() || ScoreKeeper.MatchOver || (!PlayerLookup.IsServer && (!ScoreKeeper.SyncedActive || !(Time.unscaledTime - ScoreKeeper.LastSyncTime < 6f))) || !PlayerLookup.TryGetLivingBody(localPlayerId, out var body) || (!((Object)(object)PauseManager.Instance == (Object)null) && (PauseManager.Instance.inMainMenu || PauseManager.Instance.inVictoryMenu)))
			{
				Reset();
				return;
			}
			Camera val = LocalCamera();
			if ((Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled)
			{
				Reset();
				return;
			}
			if ((Object)(object)_camera != (Object)(object)val)
			{
				ReleaseBuffer();
				_camera = val;
				_buffer = new CommandBuffer
				{
					name = "Deathmatch private nemesis reveal"
				};
				_camera.AddCommandBuffer((CameraEvent)11, _buffer);
			}
			_buffer.Clear();
			HashSet<Renderer> hashSet = new HashSet<Renderer>();
			foreach (int key in ClientInstance.playerInstances.Keys)
			{
				if (key == localPlayerId || !PlayerLookup.TryGetLivingBody(key, out body))
				{
					continue;
				}
				bool flag = ScoreKeeper.IsAce(key);
				bool flag2 = ScoreKeeper.IsNemesis(localPlayerId, key);
				if (!flag && !flag2)
				{
					continue;
				}
				List<Renderer> list = BodyRenderers(PlayerLookup.FindBody(key));
				if (flag && AceVisible(val, list))
				{
					foreach (Renderer item in list)
					{
						if ((Object)(object)item != (Object)null)
						{
							SetAceOutline(item);
							hashSet.Add(item);
						}
					}
				}
				if (flag2)
				{
					DrawNemesisReveal(_buffer, list, Time.unscaledTime);
				}
			}
			foreach (Renderer item2 in new List<Renderer>(Outlined.Keys))
			{
				if ((Object)(object)item2 == (Object)null || !hashSet.Contains(item2))
				{
					if ((Object)(object)item2 != (Object)null)
					{
						item2.SetPropertyBlock(Outlined[item2].Original);
					}
					Outlined.Remove(item2);
				}
			}
		}

		private static void ReleaseBuffer()
		{
			if (_buffer != null)
			{
				if ((Object)(object)_camera != (Object)null)
				{
					_camera.RemoveCommandBuffer((CameraEvent)11, _buffer);
				}
				_buffer.Release();
				_buffer = null;
			}
			_camera = null;
		}

		public static void Reset()
		{
			foreach (OutlineState value in Outlined.Values)
			{
				if ((Object)(object)value.Renderer != (Object)null)
				{
					value.Renderer.SetPropertyBlock(value.Original);
				}
			}
			Outlined.Clear();
			ReleaseBuffer();
			if ((Object)(object)_reveal != (Object)null)
			{
				Object.Destroy((Object)(object)_reveal);
			}
			if ((Object)(object)_visibleMask != (Object)null)
			{
				Object.Destroy((Object)(object)_visibleMask);
			}
			if ((Object)(object)_clearMask != (Object)null)
			{
				Object.Destroy((Object)(object)_clearMask);
			}
			_reveal = null;
			_visibleMask = null;
			_clearMask = null;
		}
	}
	public class DeathmatchHud : MonoBehaviour
	{
		private const float RefreshInterval = 0.25f;

		private GameObject _panel;

		private TextMeshProUGUI _text;

		private float _nextRefreshTime;

		private void Awake()
		{
			//IL_0038: 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_0052: Expected O, but got Unknown
			//IL_007f: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			Canvas obj = ((Component)this).gameObject.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 1000;
			CanvasScaler obj2 = ((Component)this).gameObject.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			_panel = new GameObject("DeathmatchPanel");
			_panel.transform.SetParent(((Component)this).transform, false);
			RectTransform obj3 = _panel.AddComponent<RectTransform>();
			obj3.anchorMin = new Vector2(1f, 1f);
			obj3.anchorMax = new Vector2(1f, 1f);
			obj3.pivot = new Vector2(1f, 1f);
			obj3.anchoredPosition = new Vector2(-18f, -440f);
			((Graphic)_panel.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.45f);
			VerticalLayoutGroup obj4 = _panel.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj4).padding = new RectOffset(12, 12, 8, 8);
			((LayoutGroup)obj4).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandHeight = false;
			ContentSizeFitter obj5 = _panel.AddComponent<ContentSizeFitter>();
			obj5.horizontalFit = (FitMode)2;
			obj5.verticalFit = (FitMode)2;
			GameObject val = new GameObject("DeathmatchText");
			val.transform.SetParent(_panel.transform, false);
			val.AddComponent<RectTransform>();
			_text = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)_text).fontSize = 22f;
			((TMP_Text)_text).richText = true;
			((TMP_Text)_text).enableWordWrapping = false;
			((TMP_Text)_text).alignment = (TextAlignmentOptions)257;
			((Graphic)_text).raycastTarget = false;
			((Graphic)_panel.GetComponent<Image>()).raycastTarget = false;
			_panel.SetActive(false);
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextRefreshTime))
			{
				_nextRefreshTime = Time.unscaledTime + 0.25f;
				bool flag = DeathmatchPlugin.ShowScoreboard.Value && ScoreKeeper.ModeActiveLocally() && (Object)(object)PauseManager.Instance != (Object)null && !PauseManager.Instance.inMainMenu && !PauseManager.Instance.inVictoryMenu && ClientInstance.playerInstances.Count > 0;
				if (_panel.activeSelf != flag)
				{
					_panel.SetActive(flag);
				}
				if (flag)
				{
					ChineseFont.Attach((TMP_Text)(object)_text);
					((TMP_Text)_text).text = BuildText();
				}
			}
		}

		private static string BuildText()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<b><color=#FF4040>").Append(Localization.Text("DEATHMATCH", "死亡竞赛", "TODOS CONTRA TODOS")).Append("</color></b>  <color=#AAAAAA>")
				.Append(Localization.Text("Target: ", "目标:", "Meta: "))
				.Append(ScoreKeeper.EffectiveKillsToWin)
				.Append(Localization.Text(" pts", " 分", " pts"))
				.Append("</color>");
			int secondsLeft = ScoreKeeper.SecondsLeft;
			if (secondsLeft >= 0)
			{
				stringBuilder.Append("  <color=#AAAAAA>-  ").Append(secondsLeft / 60).Append(':')
					.Append((secondsLeft % 60).ToString("00"))
					.Append("</color>");
			}
			int localPlayerId = PlayerLookup.LocalPlayerId;
			List<ScoreKeeper.Row> rows = ScoreKeeper.GetRows();
			stringBuilder.Append("\n<color=#AAAAAA>").Append(Localization.Text("Player    Pts / K / D", "玩家    积分 / 击杀 / 死亡", "Jugador    Pts / Bajas / Muertes")).Append("</color>");
			for (int i = 0; i < rows.Count; i++)
			{
				ScoreKeeper.Row row = rows[i];
				string value = Localization.SafeName(row.PlayerId);
				stringBuilder.Append('\n');
				string value2 = ((row.PlayerId == localPlayerId) ? "#FFD24A" : "#DDDDDD");
				stringBuilder.Append("<color=").Append(value2).Append('>');
				int num;
				if (row.Score > 0)
				{
					num = ((row.Score == rows[0].Score) ? 1 : 0);
					if (num != 0)
					{
						stringBuilder.Append("<b>");
					}
				}
				else
				{
					num = 0;
				}
				stringBuilder.Append(value).Append("  ").Append(row.Score)
					.Append(" <color=#888888>/ ")
					.Append(row.Kills)
					.Append(" / ")
					.Append(row.Deaths)
					.Append("</color>");
				if (num != 0)
				{
					stringBuilder.Append("</b>");
				}
				stringBuilder.Append("</color>");
				if (ScoreKeeper.IsAce(row.PlayerId))
				{
					stringBuilder.Append(Localization.Text(" <color=#FFAD40>[ACE]</color>", " <color=#FFAD40>[高手]</color>", " <color=#FFAD40>[AS]</color>"));
				}
				if (ScoreKeeper.IsUnderdog(row.PlayerId))
				{
					stringBuilder.Append(Localization.Text(" <color=#72E6AE>[+25 HP / +20% speed]</color>", " <color=#72E6AE>[+25血 / +20%移速]</color>", " <color=#72E6AE>[+25 vida / +20% vel.]</color>"));
				}
			}
			if (ScoreKeeper.MatchOver)
			{
				stringBuilder.Append("\n<color=#AAAAAA>").Append(Localization.Text("Round over", "本局结束", "Ronda terminada")).Append("</color>");
			}
			return stringBuilder.ToString();
		}
	}
	internal static class DeathmatchPatches
	{
		private static Harmony _harmony;

		private static FieldInfo _fiRoundHasStarted;

		private static readonly FieldInfo DrawHandle = AccessTools.Field(typeof(GameManager), "waitForDrawCoroutine");

		public static bool DeathHooked { get; private set; }

		private static bool Active => ScoreKeeper.ModeActiveLocally();

		public static void Apply()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			if (_harmony != null)
			{
				return;
			}
			_harmony = new Harmony("com.clst.straftatdeathmatch.patches");
			_fiRoundHasStarted = AccessTools.Field(typeof(FirstPersonController), "roundHasStarted");
			UnderdogBonus.Apply(_harmony);
			SuppressionGuard.Apply(_harmony);
			KillCredit.Apply(_harmony);
			Type[] args = new Type[4]
			{
				typeof(int),
				typeof(int),
				typeof(Vector3),
				typeof(Quaternion)
			};
			Type[] args2 = new Type[2]
			{
				typeof(int),
				typeof(int)
			};
			try
			{
				NativeDeathHook.Apply(_harmony, typeof(DeathmatchPatches), "GameManager_PlayerDied_Prefix", "GameManager_PlayerDiedGeneration_Prefix");
				DeathHooked = true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = DeathmatchPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("[Patch] no supported death notification; Deathmatch stays off: " + ex.GetType().Name + " - " + ex.Message));
				}
			}
			Prefix(typeof(GameManager), "WaitForDraw", "GameManager_WaitForDraw_Prefix");
			Prefix(typeof(RoundManager), "CmdEndRound", "RoundManager_CmdEndRound_Prefix");
			Postfix(typeof(GameManager), "RpcLogic___SetStartTime_431000436", "GameManager_SetStartTime_Postfix");
			Prefix(typeof(PlayerManager), "ReturnSpawnPoint", "PlayerManager_ReturnSpawnPoint_Prefix");
			Prefix(typeof(PlayerManager), "SpawnPlayer", "PlayerManager_SpawnPlayer2_Prefix", args2);
			Postfix(typeof(PlayerManager), "SpawnPlayer", "PlayerManager_SpawnPlayer4_Postfix", args);
			Postfix(typeof(PlayerManager), "WaitForRoundStart", "PlayerManager_WaitForRoundStart_Postfix");
			Prefix(typeof(PlayerManager), "IncrementReadyPlayers", "PlayerManager_Ready_Prefix");
			Prefix(typeof(PauseManager), "StartRoundDelay", "PauseManager_StartRoundDelay_Prefix");
			Prefix(typeof(KillCam), "Update", "KillCam_Update_Prefix");
			Prefix(typeof(Weapon), "FriendlyFireCheck", "Weapon_FriendlyFireCheck_Prefix");
			Postfix(typeof(PlayerHealth), "RpcLogic___ExplodeForAll_576886416", "PlayerHealth_ExplodeForAll_Postfix");
			Postfix(typeof(PlayerHealth), "RpcLogic___DespawnObject_2166136261", "PlayerHealth_DespawnObject_Postfix");
			Postfix(typeof(PlayerValues), "sync___set_value_playerClient", "PlayerValues_SetPlayerClient_Postfix");
			Prefix(typeof(PlayerPickup), "RightHandDrop", "PlayerPickup_RightHandDrop_Prefix");
			Prefix(typeof(PlayerPickup), "LeftHandDrop", "PlayerPickup_LeftHandDrop_Prefix");
			Prefix(typeof(PlayerPickup), "RpcLogic___DropObjectServer_2127535046", "PlayerPickup_DropObjectServer_Prefix");
			Prefix(typeof(PlayerPickup), "RpcLogic___DropObjectObserver_2127535046", "PlayerPickup_DropObjectObserver_Prefix");
			Postfix(typeof(PlayerPickup), "OnStartClient", "PlayerPickup_OnStartClient_Postfix");
			Prefix(typeof(PlayerSetup), "OnDisable", "PlayerSetup_OnDisable_Prefix");
			Postfix(typeof(PlayerSetup), "OnStartClient", "PlayerSetup_OnStartClient_Postfix");
			Prefix(typeof(PlayerHealth), "OnDisable", "PlayerHealth_OnDisable_Prefix");
			Prefix(typeof(ProximityMine), "KillShockWave", "ProximityMine_KillShockWave_Prefix");
			Prefix(typeof(Claymore), "KillShockWave", "Claymore_KillShockWave_Prefix");
			Prefix(typeof(DamageZone), "OnEnable", "DamageZone_OnEnable_Prefix");
			Prefix(typeof(FirstPersonController), "OnTriggerStay", "FirstPersonController_OnTriggerStay_Prefix");
		}

		private static void Prefix(Type type, string method, string patch, Type[] args = null)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = ((args == null) ? AccessTools.Method(type, method, (Type[])null, (Type[])null) : AccessTools.Method(type, method, args, (Type[])null));
				if (methodInfo == null)
				{
					ManualLogSource log = DeathmatchPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Patch] " + type.Name + "." + method + " not found"));
					}
				}
				else
				{
					_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(DeathmatchPatches), patch, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = DeathmatchPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Patch] " + type.Name + "." + method + ": " + ex.GetType().Name + " - " + ex.Message));
				}
			}
		}

		private static void Postfix(Type type, string method, string patch, Type[] args = null)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = ((args == null) ? AccessTools.Method(type, method, (Type[])null, (Type[])null) : AccessTools.Method(type, method, args, (Type[])null));
				if (methodInfo == null)
				{
					ManualLogSource log = DeathmatchPlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Patch] " + type.Name + "." + method + " not found"));
					}
				}
				else
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(DeathmatchPatches), patch, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = DeathmatchPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Patch] " + type.Name + "." + method + ": " + ex.GetType().Name + " - " + ex.Message));
				}
			}
		}

		public static bool GameManager_PlayerDied_Prefix(int playerId)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || !PlayerLookup.IsServer)
			{
				return true;
			}
			if (ScoreKeeper.MatchOver)
			{
				return false;
			}
			try
			{
				if ((Object)(object)GameManager.Instance != (Object)null)
				{
					GameManager.Instance.alivePlayers.Add(playerId);
				}
				GameObject val = PlayerLookup.FindBody(playerId);
				PlayerHealth health = (((Object)(object)val != (Object)null) ? val.GetComponent<PlayerHealth>() : null);
				if (!ScoreKeeper.TryBeginDeath(playerId, health))
				{
					return false;
				}
				bool victimWasAce = ScoreKeeper.IsAce(playerId);
				Vector3 deathPosition = (((Object)(object)val != (Object)null) ? val.transform.position : Vector3.zero);
				RespawnController.OnServerDeath(playerId);
				MonoBehaviour val2 = (MonoBehaviour)(object)(((Object)(object)GameManager.Instance != (Object)null) ? ((DeathmatchPlugin)(object)GameManager.Instance) : DeathmatchPlugin.Instance);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.StartCoroutine(ResolveKill(playerId, health, deathPosition, ScoreKeeper.RoundEpoch, victimWasAce));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = DeathmatchPlugin.Log;
				if (log != null)
				{
					log.LogError((object)("[Death] handling player " + playerId + ": " + ex));
				}
				try
				{
					RespawnController.Schedule(playerId);
				}
				catch
				{
				}
			}
			return false;
		}

		private static bool GameManager_PlayerDiedGeneration_Prefix(GameManager __instance, int playerId, uint spawnGeneration)
		{
			if (!Active || !PlayerLookup.IsServer)
			{
				return true;
			}
			if (!NativeDeathHook.IsCurrent(__instance, spawnGeneration))
			{
				return false;
			}
			return GameManager_PlayerDied_Prefix(playerId);
		}

		private static IEnumerator ResolveKill(int victimId, PlayerHealth health, Vector3 deathPosition, int roundEpoch, bool victimWasAce)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			yield return (object)new WaitForSeconds(0.1f);
			if (!ScoreKeeper.MatchOver && ScoreKeeper.RoundEpoch == roundEpoch && Active)
			{
				int killerId = -1;
				try
				{
					killerId = KillCredit.Resolve(health);
				}
				catch
				{
				}
				ScoreKeeper.OnServerKill(victimId, killerId, deathPosition, victimWasAce);
			}
		}

		public static bool GameManager_WaitForDraw_Prefix(GameManager __instance, ref IEnumerator __result)
		{
			if (!Active || !PlayerLookup.IsServer)
			{
				return true;
			}
			__result = ReleaseDrawHandle(__instance);
			return false;
		}

		private static IEnumerator ReleaseDrawHandle(GameManager manager)
		{
			yield return null;
			if ((Object)(object)manager != (Object)null)
			{
				DrawHandle?.SetValue(manager, null);
			}
		}

		public static bool RoundManager_CmdEndRound_Prefix()
		{
			if (Active && PlayerLookup.IsServer && !ScoreKeeper.MatchOver)
			{
				return false;
			}
			return true;
		}

		public static void GameManager_SetStartTime_Postfix(float serverTimeTillStart)
		{
			ScoreKeeper.OnStartTimeIssued(serverTimeTillStart);
		}

		public static bool PlayerManager_ReturnSpawnPoint_Prefix(PlayerManager __instance, ref Transform __result)
		{
			if (!Active || !PlayerLookup.IsServer)
			{
				return true;
			}
			try
			{
				ClientInstance component = ((Component)__instance).GetComponent<ClientInstance>();
				if (SpawnSelector.TryPick(((Object)(object)component != (Object)null) ? component.PlayerId : (-1), out var point, out var _, out var _))
				{
					__result = ((Component)point).transform;
					return false;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = DeathmatchPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Spawn] ReturnSpawnPoint: " + ex.GetType().Name));
				}
			}
			return true;
		}

		public static bool PlayerManager_SpawnPlayer2_Prefix(PlayerManager __instance, int __0, int __1)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || !PlayerLookup.IsServer)
			{
				return true;
			}
			try
			{
				ClientInstance component = ((Component)__instance).GetComponent<ClientInstance>();
				int forPlayerId = (((Object)(object)component != (Object)null) ? component.PlayerId : (-1));
				if (SpawnSelector.TryPick(forPlayerId, out var point, out var position, out var rotation) && RespawnController.InvokeSpawnPlayer(__instance, __0, __1, position, rotation))
				{
					ManualLogSource log = DeathmatchPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[Spawn] player=" + forPlayerId + " take-start spawn at '" + ((Object)point).name + "'"));
					}
					return false;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = DeathmatchPlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Spawn] SpawnPlayer: " + ex.GetType().Name + " - " + ex.Message));
				}
			}
			return true;
		}

		public static void PlayerManager_SpawnPlayer4_Postfix(PlayerManager __instance, int __0, int __1)
		{
			if (!Active || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			try
			{
				ClientInstance component = ((Component)__instance).GetComponent<ClientInstance>();
				if (!((Object)(object)component == (Object)null) && component.PlayerId >= 0 && PlayerLookup.IsServer)
				{
					RespawnController.RememberCosmetics(component.PlayerId, __0, __1);
					RespawnController.OnServerSpawned(component.PlayerId);
					if ((Object)(object)GameManager.Instance != (Object)null)
					{
						GameManager.Instance.alivePlayers.Add(component.PlayerId);
					}
					ScoreKeeper.MarkDirty();
				}
			}
			catch
			{
			}
		}

		public static void PlayerManager_WaitForRoundStart_Postfix(PlayerManager __instance, ref IEnumerator __result)
		{
			if (__result != null)
			{
				if (Active && RoundStartGuard.UseQuickStart(__instance))
				{
					__result = QuickStart(__instance);
				}
				else if (!((NetworkBehaviour)__instance).IsServer)
				{
					__result = AwaitStartTime(__instance, __result);
				}
			}
		}

		private static IEnumerator AwaitStartTime(PlayerManager pm, IEnumerator vanilla)
		{
			LateJoinWatch watch = new LateJoinWatch(ScoreKeeper.StartTimesIssued);
			while (true)
			{
				if (watch.Late(ScoreKeeper.StartTimesIssued, ScoreKeeper.HostReportsLive))
				{
					ManualLogSource log = DeathmatchPlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)"[Spawn] joined a live match; skipping the round-start wait");
					}
					IEnumerator quick = QuickStart(pm);
					while (quick.MoveNext())
					{
						yield return quick.Current;
					}
					break;
				}
				if (!vanilla.MoveNext())
				{
					break;
				}
				yield return vanilla.Current;
			}
		}

		private static bool PlayerManager_Ready_Prefix(PlayerManager __instance)
		{
			if (!Active || !((NetworkBehaviour)__instance).IsServer || !((NetworkBehaviour)__instance).IsOwner || (Object)(object)GameManager.Instance == (Object)null)
			{
				return true;
			}
			__instance.RpcLogic___IncrementReadyPlayers_328543758(((NetworkBehaviour)__instance).Owner);
			return false;
		}

		private static void PauseManager_StartRoundDelay_Prefix(PauseManager __instance)
		{
			if (Active && !__instance.inMainMenu && !__instance.inVictoryMenu)
			{
				AccessTools.Method(typeof(PauseManager), "StoppingMapCoroutine", (Type[])null, (Type[])null)?.Invoke(__instance, null);
				AccessTools.Field(typeof(PauseManager), "canShow")?.SetValue(__instance, true);
				__instance.startRound = true;
			}
		}

		private static IEnumerator QuickStart(PlayerManager pm)
		{
			FirstPersonController body = (((Object)(object)pm != (Object)null) ? pm.player : null);
			int epoch = ScoreKeeper.RoundEpoch;
			yield return null;
			if ((Object)(object)pm == (Object)null || (Object)(object)body == (Object)null || (Object)(object)pm.player != (Object)(object)body || epoch != ScoreKeeper.RoundEpoch)
			{
				yield break;
			}
			try
			{
				pm.SetPlayerMove(true);
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)PauseManager.Instance != (Object)null)
				{
					PauseManager.Instance.startRound = false;
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)pm.player != (Object)null)
				{
					pm.player.startOfRound = false;
					if (_fiRoundHasStarted != null)
					{
						_fiRoundHasStarted.SetValue(pm.player, true);
					}
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)pm.player != (Object)null && (Object)(object)pm.player.setupScript != (Object)null)
				{
					pm.player.setupScript.EnableTaserEffectServer();
				}
			}
			catch
			{
			}
			float end = Time.time + 3f;
			while (Time.time < end)
			{
				if ((Object)(object)pm == (Object)null || (Object)(object)body == (Object)null || (Object)(object)pm.player != (Object)(object)body || epoch != ScoreKeeper.RoundEpoch)
				{
					yield break;
				}
				try
				{
					if ((Object)(object)pm.player != (Object)null && !pm.player.sync___get_value_canMove())
					{
						pm.SetPlayerMove(true);
					}
					if ((Object)(object)PauseManager.Instance != (Object)null && PauseManager.Instance.startRound)
					{
						PauseManager.Instance.startRound = false;
					}
				}
				catch
				{
				}
				yield return (object)new WaitForSeconds(0.25f);
			}
			if ((Object)(object)pm != (Object)null)
			{
				pm.waitForRoundStartCoroutine = null;
			}
		}

		public static bool KillCam_Update_Prefix()
		{
			if (Active)
			{
				return !ScoreKeeper.IsMidMatchLocally();
			}
			return true;
		}

		private static bool Weapon_FriendlyFireCheck_Prefix(ref bool __result)
		{
			if (!Active)
			{
				return true;
			}
			__result = false;
			return false;
		}

		public static void PlayerHealth_ExplodeForAll_Postfix(PlayerHealth __instance)
		{
			if (Active && !((Object)(object)__instance == (Object)null))
			{
				RespawnController.TrackRagdoll(__instance);
			}
		}

		public static void PlayerHealth_DespawnObject_Postfix(PlayerHealth __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).IsOwner)
				{
					ScoreKeeper.LocalDiedThisMap = true;
				}
			}
			catch
			{
			}
		}

		public static void PlayerValues_SetPlayerClient_Postfix(PlayerValues __instance, ClientInstance __0)
		{
			if (!Active || (Object)(object)__0 == (Object)null)
			{
				return;
			}
			PlayerLookup.RegisterBody(__instance);
			try
			{
				if (__0.PlayerId >= 0)
				{
					RespawnController.DestroyRagdoll(__0.PlayerId);
				}
			}
			catch
			{
			}
		}

		private static bool IsDead(PlayerPickup pickup)
		{
			PlayerHealth val = (((Object)(object)pickup != (Object)null) ? ((Component)pickup).GetComponentInParent<PlayerHealth>() : null);
			if ((Object)(object)val != (Object)null)
			{
				if (!(val.sync___get_value_health() <= 0f))
				{
					return val.sync___get_value_isKilled();
				}
				return true;
			}
			return false;
		}

		public static bool PlayerPickup_RightHandDrop_Prefix(PlayerPickup __instance)
		{
			try
			{
				if (Active)
				{
					LoadoutKeeper.OnHandDropping(__instance);
				}
			}
			catch
			{
			}
			if (!Active || !ScoreKeeper.CleanupItemsEffective)
			{
				return true;
			}
			try
			{
				if (__instance.sync___get_value_hasObjectInHand())
				{
					GameObject val = __instance.sync___get_value_objInHand();
					if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent<ItemBehaviour>() == (Object)null)
					{
						RespawnController.ClearHand(__instance, rightHand: true);
						return false;
					}
				}
				if (IsDead(__instance))
				{
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		public static bool PlayerPickup_LeftHandDrop_Prefix(PlayerPickup __instance)
		{
			try
			{
				if (Active)
				{
					LoadoutKeeper.OnHandDropping(__instance);
				}
			}
			catch
			{
			}
			if (!Active || !ScoreKeeper.CleanupItemsEffective)
			{
				return true;
			}
			try
			{
				if (__instance.sync___get_value_hasObjectInLeftHand())
				{
					GameObject val = __instance.sync___get_value_objInLeftHand();
					if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent<ItemBehaviour>() == (Object)null)
					{
						RespawnController.ClearHand(__instance, rightHand: false);
						return false;
					}
				}
				if (IsDead(__instance))
				{
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		public static bool PlayerPickup_DropObjectServer_Prefix(PlayerPickup __instance, GameObject obj, bool rightHand)
		{
			if (!Active || !PlayerLookup.IsServer || !ScoreKeeper.CleanupItemsEffective)
			{
				return true;
			}
			try
			{
				if ((Object)(object)obj == (Object)null)
				{
					RespawnController.ClearHand(__instance, rightHand);
					return false;
				}
				NetworkObject component = obj.GetComponent<NetworkObject>();
				if ((Object)(object)component != (Object)null && !component.IsSpawned)
				{
					RespawnController.ClearHand(__instance, rightHand);
					return false;
				}
				if (IsDead(__instance))
				{
					RespawnController.ClearHand(__instance, rightHand);
					RespawnController.DespawnOrDestroy(obj);
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		public static bool PlayerPickup_DropObjectObserver_Prefix(GameObject obj)
		{
			if (!Active)
			{
				return true;
			}
			return (Object)(object)obj != (Object)null;
		}

		public static void PlayerPickup_OnStartClient_Postfix(PlayerPickup __instance)
		{
			if (!Active || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			try
			{
				LoadoutKeeper.OnPickupStarted(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource log = DeathmatchPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Loadout] OnStartClient: " + ex.GetType().Name + " - " + ex.Message));
				}
			}
		}

		public static bool PlayerSetup_OnDisable_Prefix(PlayerSetup __instance)
		{
			if (Active)
			{
				return LocalBodyCleanupGuard.Allow((NetworkBehaviour)(object)__instance);
			}
			return true;
		}

		private static bool PlayerHealth_OnDisable_Prefix(PlayerHealth __instance)
		{
			if (Active)
			{
				return LocalBodyCleanupGuard.Allow((NetworkBehaviour)(object)__instance);
			}
			return true;
		}

		private static void PlayerSetup_OnStartClient_Postfix(PlayerSetup __instance)
		{
			if (Active)
			{
				PlayerLookup.RegisterBody(((Component)__instance).GetComponent<PlayerValues>());
				LocalBodyCleanupGuard.Record(__instance);
				if (!((NetworkBehaviour)__instance).IsOwner && (Object)(object)DeathmatchPlugin.Instance != (Object)null)
				{
					((MonoBehaviour)DeathmatchPlugin.Instance).StartCoroutine(RemoteHitboxes.AfterClientSetup(__instance));
				}
			}
		}

		public static bool ProximityMine_KillShockWave_Prefix(ProximityMine __instance)
		{
			GameObject val = (((Object)(object)__instance != (Object)null) ? __instance.sync___get_value__rootObject() : null);
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)val.GetComponent<FirstPersonController>() != (Object)null;
			}
			return false;
		}

		public static bool Claymore_KillShockWave_Prefix(Claymore __instance)
		{
			GameObject val = (((Object)(object)__instance != (Object)null) ? __instance.sync___get_value__rootObject() : null);
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)val.GetComponent<FirstPersonController>() != (Object)null;
			}
			return false;
		}

		public static bool DamageZone_OnEnable_Prefix(DamageZone __instance)
		{
			if (!Active || !ScoreKeeper.RemoveDamageZonesEffective)
			{
				return true;
			}
			try
			{
				Collider[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].enabled = false;
				}
				if ((Object)(object)__instance.toDestroy != (Object)null)
				{
					Object.Destroy((Object)(object)__instance.toDestroy);
				}
				Object.Destroy((Object)(object)((Component)__instance).gameObject);
			}
			catch
			{
			}
			return false;
		}

		public static bool FirstPersonController_OnTriggerStay_Prefix(Collider col)
		{
			if (Active && ScoreKeeper.RemoveDamageZonesEffective && (Object)(object)col != (Object)null && ((Component)col).CompareTag("DamageZone"))
			{
				return false;
			}
			return true;
		}
	}
	[BepInPlugin("com.clst.straftatdeathmatch", "Straftat Deathmatch", "1.4.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class DeathmatchPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.clst.straftatdeathmatch";

		public const string PluginName = "Straftat Deathmatch";

		public const string PluginVersion = "1.4.2";

		public const uint ModId = 20260905u;

		internal static ManualLogSource Log;

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<int> KillsToWin;

		public static ConfigEntry<int> TimeLimitMinutes;

		public static ConfigEntry<float> RespawnDelay;

		public static ConfigEntry<float> MinEnemyDistance;

		public static ConfigEntry<bool> AvoidLineOfSight;

		public static ConfigEntry<float> SpawnJitter;

		public static ConfigEntry<bool> CleanupItemsOnDeath;

		public static ConfigEntry<bool> CleanupMinesOnDeath;

		public static ConfigEntry<bool> RemoveDamageZones;

		public static ConfigEntry<bool> RestoreLoadoutOnRespawn;

		public static ConfigEntry<string> DefaultWeapon;

		public static ConfigEntry<string> LoadoutExcludedClasses;

		public static ConfigEntry<string> LoadoutExcludedWeapons;

		public static ConfigEntry<bool> ShowScoreboard;

		public static ConfigEntry<bool> KillFeedInChat;

		public static ConfigEntry<bool> RevengeEnabled;

		public static ConfigEntry<bool> ShutdownEnabled;

		public static ConfigEntry<bool> UnderdogEnabled;

		public static ConfigEntry<bool> KillHealing;

		public static ConfigEntry<float> LastHitCredit;

		public static ConfigEntry<bool> ReloadRebalance;

		public static ConfigEntry<string> Language;

		public static ConfigEntry<bool> AllowKillSelf;

		public static ConfigEntry<KeyboardShortcut> KillSelfShortcut;

		private bool _fishNetHooked;

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

		public static DeathmatchPlugin Instance { get; private set; }

		internal static bool HostEnabled
		{
			get
			{
				if (Enabled.Value)
				{
					return DeathmatchPatches.DeathHooked;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Expected O, but got Unknown
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Expected O, but got Unknown
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_0559: Unknown result type (might be due to invalid IL or missing references)
			//IL_055e: Unknown result type (might be due to invalid IL or missing references)
			//IL_057b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0580: Unknown result type (might be due to invalid IL or missing references)
			//IL_059d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Deathmatch mode. Only the host's setting matters for gameplay.");
			KillsToWin = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Kills To Win", 20, new ConfigDescription("Points needed to win, including revenge bonuses and collected ace bounties.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			TimeLimitMinutes = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Time Limit Minutes", 0, new ConfigDescription("Round time limit in minutes. 0 disables it. The highest score wins; a tied lead goes to overtime.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>()));
			RespawnDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Respawn Delay", 2f, new ConfigDescription("Seconds before a dead player respawns.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f), Array.Empty<object>()));
			MinEnemyDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "Min Enemy Spawn Distance", 12f, new ConfigDescription("Spawn points closer than this to a living enemy are avoided when any other point exists.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			AvoidLineOfSight = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "Avoid Enemy Line Of Sight", true, "Prefer cover that blocks sight in both directions. When cover is unavailable, prefer less exposed positions and face away from visible enemies.");
			SpawnJitter = ((BaseUnityPlugin)this).Config.Bind<float>("Spawning", "Spawn Jitter", 0.5f, new ConfigDescription("Random offset in meters applied around the chosen spawn point. 0 spawns exactly on the point.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			CleanupItemsOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Cleanup", "Cleanup Items On Death", true, "Remove whatever a player was holding when they die instead of dropping it on the ground.");
			CleanupMinesOnDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Cleanup", "Cleanup Mines On Death", true, "Remove mines and claymores placed by a player when they die.");
			RemoveDamageZones = ((BaseUnityPlugin)this).Config.Bind<bool>("Cleanup", "Remove Damage Zones", false, "Disable map damage zones for continuous play.");
			RestoreLoadoutOnRespawn = ((BaseUnityPlugin)this).Config.Bind<bool>("Loadout", "Restore Loadout On Respawn", true, "Respawn holding the weapons you had when you were killed. Pick a weapon up once, then swap at map spawners when you want something else.");
			DefaultWeapon = ((BaseUnityPlugin)this).Config.Bind<string>("Loadout", "Default Weapon", "Gun", "Prefab name of the weapon given to a player who died empty-handed (Gun is the pistol; other examples: Glock, Revolver, AK-K, Shotgun). Empty gives nothing.");
			LoadoutExcludedClasses = ((BaseUnityPlugin)this).Config.Bind<string>("Loadout", "Excluded Weapon Classes", "DualLauncher", "Comma-separated Weapon component classes that are never restored. DualLauncher covers grenades and all launchers.");
			LoadoutExcludedWeapons = ((BaseUnityPlugin)this).Config.Bind<string>("Loadout", "Excluded Weapons", "", "Comma-separated weapon prefab names that are never restored.");
			ShowScoreboard = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Show Scoreboard", true, "Show points, kills, deaths, aces and catch-up assistance on the scoreboard.");
			KillFeedInChat = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Kill Feed In Chat", false, "Post the current score to chat after every kill. Disabling this does not hide revenge or ace announcements.");
			RevengeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "Revenge Reward", true, "Three unanswered kills create a nemesis, shown only to the revenge seeker as a dim red pulse on body parts hidden behind cover. Revenge earns +1 point, except against an ace: that kill only drops one contested bounty. Other opponents do not break the chain.");
			ShutdownEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "Ace Shutdown", true, "Three kills in one life, or a sole lead of at least 5 points over second place, make an ace. Aces have a red outline blocked by walls and no kill healing, including the promotion kill. Being killed by another player drops one +1 golden head based on pre-kill status. Both conditions must end to lose ace status. Heads have wall reveal, a distance-scaled gold halo and safe placement; blink at 25 seconds and expire at 30.");
			KillHealing = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "Heal On Kill", true, "Non-aces restore 25 HP per kill, up to 100, with a private pale-green edge flash. Aces never heal from kills, including the promotion kill. Spent catch-up HP is not refilled. Bounty pickups do not heal.");
			LastHitCredit = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Last Hit Credit Seconds", 8f, new ConfigDescription("Falls, damage zones and self-kills with no killer count as a kill for the last player who hit or pushed the victim within this many seconds. 0 disables.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			UnderdogEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "Underdog Bonus", true, "Anyone at least 5 points behind the leader receives +25 HP and +20% movement speed, shown on the scoreboard. Score changes never refill spent bonus HP. Can coexist with ace status.");
			ReloadRebalance = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "Reload Rebalance", false, "Optional host rule, off by default; changes apply on the next map. Adds infinite reserve, manual reload and no dual wielding for 32 weapon presets. Bayshore, Elephant and Blank State keep vanilla ammo, reloads and visuals. Webley/G11 aimed bursts require at least 3 magazine rounds. Standalone Reload Balance is suppressed for this session without changing its files or config. All peers need 1.4.2.");
			Language = ((BaseUnityPlugin)this).Config.Bind<string>("Localization", "Language", "en", new ConfigDescription("Local display language: en (English, default), zh-CN (Simplified Chinese), es (Spanish), or Auto (system language). Menu names, descriptions and HUD change immediately; new announcements use the selected language.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "en", "zh-CN", "es", "Auto" }), Array.Empty<object>()));
			AllowKillSelf = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Allow Kill Self", false, "Host rule for testing: every player may press the Kill Self Shortcut (F6 by default) to die and respawn. Off by default, so normal matches cannot use it.");
			KillSelfShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Debug", "Kill Self Shortcut", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Kills your own player for respawn testing when the host turns on Allow Kill Self.");
			ScoreKeeper.Init();
			RespawnController.Init();
			LoadoutKeeper.Init();
			try
			{
				DeathmatchPatches.Apply();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Patching failed: " + ex));
			}
			ReloadBalance.Init();
			ModMenuLocalization.Apply();
			((BaseUnityPlugin)this).Config.SettingChanged += delegate
			{
				ScoreKeeper.MarkDirty();
			};
			try
			{
				MyceliumNetwork.RegisterNetworkObject((object)this, 20260905u, 0);
			}
			catch (Exception ex2)
			{
				Log.LogError((object)("Mycelium registration failed: " + ex2.GetType().Name + " - " + ex2.Message));
			}
			try
			{
				MyceliumNetwork.PlayerEntered += OnMyceliumPlayerEntered;
			}
			catch
			{
			}
			try
			{
				MyceliumNetwork.LobbyEntered += ScoreKeeper.ForgetHost;
				MyceliumNetwork.LobbyCreated += ScoreKeeper.ForgetHost;
				MyceliumNetwork.LobbyLeft += ScoreKeeper.ForgetHost;
			}
			catch
			{
			}
			SceneManager.sceneLoaded += OnSceneLoaded;
			GameObject val = new GameObject("DeathmatchHud");
			val.transform.SetParent(((Component)this).transform, false);
			val.AddComponent<DeathmatchHud>();
			GameObject val2 = new GameObject("Deathmatch Heal Flash");
			val2.transform.SetParent(((Component)this).transform, false);
			val2.AddComponent<KillHealFlash>();
			GameObject val3 = new GameObject("Deathmatch Reward Feedback");
			val3.transform.SetParent(((Component)this).transform, false);
			val3.AddComponent<RewardFeedback>();
			Log.LogInfo((object)"Straftat Deathmatch 1.4.2 loaded.");
		}

		private void OnDestroy()
		{
			CombatVisuals.Reset();
			BountyManager.Reset();
			UnderdogBonus.Reset();
			try
			{
				MyceliumNetwork.DeregisterNetworkObject((object)this, 20260905u, 0);
			}
			catch
			{
			}
			try
			{
				MyceliumNetwork.PlayerEntered -= OnMyceliumPlayerEntered;
			}
			catch
			{
			}
			try
			{
				MyceliumNetwork.LobbyEntered -= ScoreKeeper.ForgetHost;
				MyceliumNetwork.LobbyCreated -= ScoreKeeper.ForgetHost;
				MyceliumNetwork.LobbyLeft -= ScoreKeeper.ForgetHost;
			}
			catch
			{
			}
			SceneManager.sceneLoaded -= OnSceneLoaded;
			if (_fishNetHooked && (Object)(object)InstanceFinder.SceneManager != (Object)null)
			{
				InstanceFinder.SceneManager.OnLoadEnd -= OnFishNetSceneLoaded;
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ResetForScene(scene);
		}

		private void OnFishNetSceneLoaded(SceneLoadEndEventArgs args)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ResetForScene(SceneManager.GetActiveScene());
		}

		private void ResetForScene(Scene scene)
		{
			if (((Scene)(ref scene)).IsValid() && !(((Scene)(ref scene)).name == "EmptyScene") && _resetScenes.Add(((Scene)(ref scene)).handle))
			{
				FullReset();
			}
		}

		private void OnMyceliumPlayerEntered(CSteamID id)
		{
			ScoreKeeper.MarkDirty();
		}

		internal static void FullReset()
		{
			RewardFeedback.Clear();
			KillHealFlash.Clear();
			KillCredit.Reset();
			CombatVisuals.Reset();
			BountyManager.Reset();
			UnderdogBonus.Reset();
			ScoreKeeper.Reset();
			RespawnController.Reset();
			LoadoutKeeper.Reset();
			LoadoutSpawner.Reset();
			SpawnSelector.Reset();
			PlayerLookup.Reset();
			RoundStartGuard.Reset();
			RespawnController.CleanupWorldEffects();
		}

		private void Update()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			SceneManager sceneManager = InstanceFinder.SceneManager;
			if (!_fishNetHooked && (Object)(object)sceneManager != (Object)null)
			{
				sceneManager.OnLoadEnd += OnFishNetSceneLoaded;
				_fishNetHooked = true;
			}
			else if (_fishNetHooked && (Object)(object)sceneManager == (Object)null)
			{
				_fishNetHooked = false;
				FullReset();
			}
			KeyboardShortcut value = KillSelfShortcut.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && ScoreKeeper.ModeActiveLocally())
			{
				RequestKillSelf();
			}
			LoadoutKeeper.ClientTick();
			UnderdogBonus.Tick();
			BountyManager.Tick();
			if ((Object)(object)GameManager.Instance == (Object)null || !PlayerLookup.IsServer)
			{
				return;
			}
			ScoreKeeper.ServerTick();
			if (!HostEnabled)
			{
				return;
			}
			RespawnController.ServerTick();
			LoadoutSpawner.ServerTick();
			HashSet<int> alivePlayers = GameManager.Instance.alivePlayers;
			foreach (KeyValuePair<int, ClientInstance> playerInstance in ClientInstance.playerInstances)
			{
				if (!alivePlayers.Contains(playerInstance.Key))
				{
					alivePlayers.Add(playerInstance.Key);
				}
			}
		}

		private void LateUpdate()
		{
			CombatVisuals.Tick();
		}

		internal void BroadcastState()
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (MyceliumNetwork.InLobby)
				{
					object[] obj = new object[17]
					{
						HostEnabled,
						ScoreKeeper.MatchLive,
						KillsToWin.Value,
						ScoreKeeper.SecondsLeft,
						CleanupItemsOnDeath.Value,
						RemoveDamageZones.Value,
						ScoreKeeper.Serialize(),
						RestoreLoadoutOnRespawn.Value,
						DefaultWeapon.Value ?? "",
						LoadoutExcludedClasses.Value ?? "",
						LoadoutExcludedWeapons.Value ?? "",
						ScoreKeeper.MatchOver,
						ShutdownEnabled.Value,
						ReloadBalance.Active,
						ScoreKeeper.SerializeRivalries(),
						BountyManager.Serialize(),
						null
					};
					Scene activeScene = SceneManager.GetActiveScene();
					obj[16] = ((Scene)(ref activeScene)).name;
					MyceliumNetwork.RPC(20260905u, "SyncDeathmatchStateV6", (Relia