Decompiled source of PropHunt v0.2.2

com.github.glarmer.prophunt.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Gamemode_Lib;
using Gamemode_Lib.ConfigSync;
using Gamemode_Lib.Events;
using Gamemode_Lib.Patches.Features;
using Gamemode_Lib.Teams;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using PropHunt;
using PropHunt.Configuration;
using PropHunt.Patches;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("GameAssembly")]
[assembly: IgnoresAccessChecksTo("SharedAssembly")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.glarmer.prophunt")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+3e6fbe44ee04c4023aa26dab097769c228f67ddc")]
[assembly: AssemblyProduct("com.github.glarmer.prophunt")]
[assembly: AssemblyTitle("PropHunt")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class PropHuntUI : MonoBehaviour
{
	private Canvas canvas;

	private RectTransform rootPanel;

	private TMP_FontAsset gabaritoFont;

	private Sprite panelSprite;

	private Material panelBackgroundStencilMaterial;

	private Material panelOuterBackgroundMaterial;

	private Camera minimapCamera;

	private RenderTexture minimapTexture;

	private RawImage minimapImage;

	private RawImage propHeatImage;

	private Image hunterBlackoutImage;

	private RectTransform propHeatRect;

	private Texture2D propHeatTexture;

	private TMP_Text teamNameText;

	private TMP_Text leftInfoText;

	private TMP_Text rightInfoText;

	private TMP_Text hunterBlackoutTimerText;

	private Transform player;

	private PropHuntPlayer localPropHuntPlayer;

	private Vector2 cachedPropHeatDirection = Vector2.up;

	private bool hasPropHeatDirection;

	private float nextPropHeatUpdateTime;

	private float propHeatInitializationTime;

	private float propHeatActivationTime;

	private float hunterBlackoutStartTime;

	private int hunterBlackoutHoleIndex = -1;

	private bool wasHunter;

	private const float PropHeatSize = 108f;

	private const float HunterBlackoutFadeDuration = 1.5f;

	private const int PanelBackgroundStencil = 16;

	private const float PanelOuterBackgroundOutset = 2f;

	private const float PanelOuterBackgroundBottomOutset = 3f;

	public static void HideAllCurrentRoundUi()
	{
		PropHuntUI[] array = Resources.FindObjectsOfTypeAll<PropHuntUI>();
		foreach (PropHuntUI propHuntUI in array)
		{
			if ((Object)(object)propHuntUI != (Object)null)
			{
				propHuntUI.HideCurrentRoundUi();
			}
		}
	}

	public static void ShowAllCurrentRoundUi()
	{
		PropHuntUI[] array = Resources.FindObjectsOfTypeAll<PropHuntUI>();
		foreach (PropHuntUI propHuntUI in array)
		{
			if ((Object)(object)propHuntUI != (Object)null)
			{
				propHuntUI.ShowCurrentRoundUi();
			}
		}
	}

	private void HideCurrentRoundUi()
	{
		if (((Behaviour)this).enabled)
		{
			if ((Object)(object)canvas != (Object)null)
			{
				((Component)canvas).gameObject.SetActive(false);
			}
			if ((Object)(object)minimapCamera != (Object)null)
			{
				((Component)minimapCamera).gameObject.SetActive(false);
			}
			((Behaviour)this).enabled = false;
		}
	}

	private void ShowCurrentRoundUi()
	{
		if (!((Behaviour)this).enabled)
		{
			if ((Object)(object)canvas != (Object)null)
			{
				((Component)canvas).gameObject.SetActive(true);
			}
			if ((Object)(object)minimapCamera != (Object)null)
			{
				((Component)minimapCamera).gameObject.SetActive(true);
			}
			((Behaviour)this).enabled = true;
		}
	}

	private void Awake()
	{
		if (Object.op_Implicit((Object)(object)GameManager.LocalPlayerInfo))
		{
			localPropHuntPlayer = ((Component)GameManager.LocalPlayerInfo).gameObject.GetComponent<PropHuntPlayer>();
		}
	}

	private void Start()
	{
		FindGameAssets();
		FindPlayer();
		CreateCanvas();
		CreateHunterBlackoutOverlay();
		CreatePanel();
		CreateRows();
		CreateMinimapCamera();
		propHeatInitializationTime = Time.time;
		RefreshPropHeatActivationTime();
		if (ConfigurationHandler.Instance != null)
		{
			ConfigurationHandler.Instance.ConfigChanged += OnConfigurationChanged;
		}
	}

	private void Update()
	{
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)TeamManager.Instance))
		{
			string text = "";
			bool flag = TeamManager.Instance.LocalPlayerTeam.teamId == PropHuntGamemode.HUNTER_TEAM;
			text = (flag ? "Hunter" : "Prop");
			string text2 = "FFFFFF";
			text2 = ColorUtility.ToHtmlStringRGB(flag ? TeamManager.Instance.Teams[PropHuntGamemode.HUNTER_TEAM].Color : TeamManager.Instance.Teams[PropHuntGamemode.PROP_TEAM].Color);
			teamNameText.text = "Team: <color=#" + text2 + ">" + text + "</color>";
			if (flag)
			{
				leftInfoText.text = $"Health: {localPropHuntPlayer.hunterHealth}";
				rightInfoText.text = $"Hunters: {PropManager.Instance.GetNumberOfHunters()}";
			}
			else
			{
				leftInfoText.text = $"Disguises: {localPropHuntPlayer.maxNumberOfDisguisesTaken - localPropHuntPlayer.numberOfDisguisesTaken}/{localPropHuntPlayer.maxNumberOfDisguisesTaken}";
				rightInfoText.text = $"Decoys: {localPropHuntPlayer.maxNumberOfDecoysCanPlace - localPropHuntPlayer.numberOfDecoysPlaced}/{localPropHuntPlayer.maxNumberOfDecoysCanPlace}";
			}
			UpdateHunterBlackout(flag);
			UpdatePropHeatIndicator(flag);
		}
	}

	private void LateUpdate()
	{
		UpdateMinimapCamera();
	}

	private void FindGameAssets()
	{
		panelSprite = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name == "UI_Tutorial_Objective_0"));
		gabaritoFont = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name == "Gabarito-SemiBold SDF"));
		if ((Object)(object)panelSprite == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Could not find sprite: UI_Tutorial_Objective_0");
		}
		if ((Object)(object)gabaritoFont == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Could not find font: Gabarito-SemiBold SDF");
		}
		CreatePanelBackgroundMaterials();
	}

	private void FindPlayer()
	{
		GameObject gameObject = ((Component)GameManager.LocalPlayerInfo).gameObject;
		if ((Object)(object)gameObject != (Object)null)
		{
			player = gameObject.transform;
		}
		else if (Object.op_Implicit((Object)(object)Camera.main))
		{
			player = ((Component)Camera.main).transform;
		}
		else
		{
			Plugin.Log.LogInfo((object)"Could not find player");
		}
	}

	private void CreateCanvas()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("PropHunt_Mod_Canvas");
		val.transform.SetParent(((Component)this).transform, false);
		canvas = val.AddComponent<Canvas>();
		canvas.renderMode = (RenderMode)0;
		canvas.sortingOrder = 9999;
		CanvasScaler val2 = val.AddComponent<CanvasScaler>();
		val2.uiScaleMode = (ScaleMode)1;
		val2.referenceResolution = new Vector2(1920f, 1080f);
		val2.matchWidthOrHeight = 0.5f;
		val.AddComponent<GraphicRaycaster>();
	}

	private void CreateHunterBlackoutOverlay()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0036: 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_0067: 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_007f: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Hunter_Blackout_Overlay");
		val.transform.SetParent(((Component)canvas).transform, false);
		hunterBlackoutImage = val.AddComponent<Image>();
		((Graphic)hunterBlackoutImage).color = Color.black;
		((Graphic)hunterBlackoutImage).raycastTarget = false;
		RectTransform rectTransform = ((Graphic)hunterBlackoutImage).rectTransform;
		rectTransform.anchorMin = Vector2.zero;
		rectTransform.anchorMax = Vector2.one;
		rectTransform.offsetMin = Vector2.zero;
		rectTransform.offsetMax = Vector2.zero;
		val.SetActive(false);
	}

	private void CreatePanel()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0040: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: 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_0105: Expected O, but got Unknown
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Expected O, but got Unknown
		GameObject val = new GameObject("PropHunt_UI_Panel");
		val.transform.SetParent(((Component)canvas).transform, false);
		rootPanel = val.AddComponent<RectTransform>();
		rootPanel.anchorMin = new Vector2(1f, 1f);
		rootPanel.anchorMax = new Vector2(1f, 1f);
		rootPanel.pivot = new Vector2(1f, 1f);
		rootPanel.anchoredPosition = new Vector2(-25f, -25f);
		rootPanel.sizeDelta = new Vector2(320f, 400f);
		Image val2 = val.AddComponent<Image>();
		val2.sprite = panelSprite;
		val2.type = (Type)1;
		val2.pixelsPerUnitMultiplier = 1f;
		((Graphic)val2).color = Color.white;
		Mask val3 = val.AddComponent<Mask>();
		val3.showMaskGraphic = false;
		GameObject val4 = new GameObject("Panel_Background");
		val4.transform.SetParent((Transform)(object)rootPanel, false);
		LayoutElement val5 = val4.AddComponent<LayoutElement>();
		val5.ignoreLayout = true;
		Image val6 = val4.AddComponent<Image>();
		val6.sprite = panelSprite;
		val6.type = (Type)1;
		val6.fillMethod = (FillMethod)4;
		val6.fillAmount = 1f;
		val6.pixelsPerUnitMultiplier = 1f;
		((Graphic)val6).color = Color.white;
		((Graphic)val6).raycastTarget = false;
		RectTransform rectTransform = ((Graphic)val6).rectTransform;
		rectTransform.anchorMin = Vector2.zero;
		rectTransform.anchorMax = Vector2.one;
		rectTransform.offsetMin = Vector2.zero;
		rectTransform.offsetMax = Vector2.zero;
		val4.transform.SetAsFirstSibling();
		CreatePanelBackgroundStencilWriter();
		CreateOuterPanelBackground();
		VerticalLayoutGroup val7 = val.AddComponent<VerticalLayoutGroup>();
		((LayoutGroup)val7).padding = new RectOffset(4, 4, 4, 0);
		((HorizontalOrVerticalLayoutGroup)val7).spacing = 0f;
		((LayoutGroup)val7).childAlignment = (TextAnchor)1;
		((HorizontalOrVerticalLayoutGroup)val7).childControlWidth = true;
		((HorizontalOrVerticalLayoutGroup)val7).childControlHeight = true;
		((HorizontalOrVerticalLayoutGroup)val7).childForceExpandWidth = true;
		((HorizontalOrVerticalLayoutGroup)val7).childForceExpandHeight = false;
	}

	private void CreatePanelBackgroundStencilWriter()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Panel_Background_Stencil_Writer");
		val.transform.SetParent(((Component)canvas).transform, false);
		Image val2 = val.AddComponent<Image>();
		val2.sprite = panelSprite;
		val2.type = (Type)1;
		val2.fillMethod = (FillMethod)4;
		val2.fillAmount = 1f;
		val2.pixelsPerUnitMultiplier = 1f;
		((Graphic)val2).color = Color.white;
		((Graphic)val2).raycastTarget = false;
		((Graphic)val2).material = panelBackgroundStencilMaterial;
		RectTransform rectTransform = ((Graphic)val2).rectTransform;
		CopyRootPanelLayout(rectTransform);
		val.transform.SetSiblingIndex(((Transform)rootPanel).GetSiblingIndex());
		((Transform)rootPanel).SetAsLastSibling();
	}

	private void CreateOuterPanelBackground()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Panel_Background_Outer");
		val.transform.SetParent(((Component)canvas).transform, false);
		Image val2 = val.AddComponent<Image>();
		val2.sprite = panelSprite;
		val2.type = (Type)1;
		val2.fillMethod = (FillMethod)4;
		val2.fillAmount = 1f;
		val2.pixelsPerUnitMultiplier = 1f;
		((Graphic)val2).color = Color.white;
		((Graphic)val2).raycastTarget = false;
		((Graphic)val2).material = panelOuterBackgroundMaterial;
		RectTransform rectTransform = ((Graphic)val2).rectTransform;
		CopyRootPanelLayout(rectTransform);
		rectTransform.anchoredPosition = rootPanel.anchoredPosition + Vector2.one * 2f;
		rectTransform.sizeDelta = rootPanel.sizeDelta + new Vector2(4f, 5f);
		val.transform.SetSiblingIndex(((Transform)rootPanel).GetSiblingIndex());
		((Transform)rootPanel).SetAsLastSibling();
	}

	private void CopyRootPanelLayout(RectTransform target)
	{
		//IL_0008: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		target.anchorMin = rootPanel.anchorMin;
		target.anchorMax = rootPanel.anchorMax;
		target.pivot = rootPanel.pivot;
		target.anchoredPosition = rootPanel.anchoredPosition;
		target.sizeDelta = rootPanel.sizeDelta;
	}

	private void CreatePanelBackgroundMaterials()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		//IL_0056: 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_006c: Expected O, but got Unknown
		Shader val = Shader.Find("UI/Default");
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Could not find shader: UI/Default");
			return;
		}
		panelBackgroundStencilMaterial = new Material(val)
		{
			name = "PropHunt_Panel_Background_Stencil"
		};
		ConfigureStencilMaterial(panelBackgroundStencilMaterial, (CompareFunction)8, (StencilOp)2, 16, (ColorWriteMask)0);
		panelOuterBackgroundMaterial = new Material(val)
		{
			name = "PropHunt_Panel_Outer_Background"
		};
		ConfigureStencilMaterial(panelOuterBackgroundMaterial, (CompareFunction)6, (StencilOp)0, 16, (ColorWriteMask)15);
	}

	private void ConfigureStencilMaterial(Material material, CompareFunction stencilComparison, StencilOp stencilOperation, int stencilReference, ColorWriteMask colorWriteMask)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Expected I4, but got Unknown
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Expected I4, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected I4, but got Unknown
		material.SetInt("_StencilComp", (int)stencilComparison);
		material.SetInt("_Stencil", stencilReference);
		material.SetInt("_StencilOp", (int)stencilOperation);
		material.SetInt("_StencilWriteMask", 16);
		material.SetInt("_StencilReadMask", 16);
		material.SetInt("_ColorMask", (int)colorWriteMask);
		material.SetInt("_UseUIAlphaClip", 1);
		material.EnableKeyword("UNITY_UI_ALPHACLIP");
	}

	private void CreateRows()
	{
		GameObject val = CreateRow("Row_TeamName", (Transform)(object)rootPanel, 36f);
		teamNameText = CreateText(val.transform, "TEAM PROPS", 26, (TextAlignmentOptions)514);
		CreateRowDivider((Transform)(object)rootPanel);
		GameObject val2 = CreateRow("Row_Info", (Transform)(object)rootPanel, 36f);
		HorizontalLayoutGroup val3 = val2.AddComponent<HorizontalLayoutGroup>();
		((HorizontalOrVerticalLayoutGroup)val3).spacing = 0f;
		((LayoutGroup)val3).childAlignment = (TextAnchor)4;
		((HorizontalOrVerticalLayoutGroup)val3).childControlWidth = true;
		((HorizontalOrVerticalLayoutGroup)val3).childControlHeight = true;
		((HorizontalOrVerticalLayoutGroup)val3).childForceExpandWidth = false;
		((HorizontalOrVerticalLayoutGroup)val3).childForceExpandHeight = true;
		leftInfoText = CreateText(val2.transform, "Props: 0", 22, (TextAlignmentOptions)514);
		AddFlexibleLayout(((Component)leftInfoText).gameObject, 1);
		CreateColumnDivider(val2.transform, 3f);
		rightInfoText = CreateText(val2.transform, "Hunters: 0", 22, (TextAlignmentOptions)514);
		AddFlexibleLayout(((Component)rightInfoText).gameObject, 1);
		CreateRowDivider((Transform)(object)rootPanel);
		float height = 310f;
		GameObject val4 = CreateRow("Row_Minimap_Spacer", (Transform)(object)rootPanel, height);
		CreateBottomMinimapOverlay(height);
	}

	private GameObject CreateRowDivider(Transform parent, float height = 4f)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Row_Divider");
		val.transform.SetParent(parent, false);
		Image val2 = val.AddComponent<Image>();
		((Graphic)val2).color = new Color(0f, 0f, 0f, 0.35f);
		((Graphic)val2).raycastTarget = false;
		RectTransform component = val.GetComponent<RectTransform>();
		component.sizeDelta = new Vector2(0f, height);
		LayoutElement val3 = val.AddComponent<LayoutElement>();
		val3.preferredHeight = height;
		val3.minHeight = height;
		val3.minWidth = 4f;
		val3.flexibleWidth = 1f;
		return val;
	}

	private GameObject CreateColumnDivider(Transform parent, float width)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Column_Divider");
		val.transform.SetParent(parent, false);
		Image val2 = val.AddComponent<Image>();
		((Graphic)val2).color = new Color(0f, 0f, 0f, 0.35f);
		((Graphic)val2).raycastTarget = false;
		LayoutElement val3 = val.AddComponent<LayoutElement>();
		val3.preferredWidth = width;
		val3.minWidth = width;
		val3.flexibleWidth = 0f;
		val3.flexibleHeight = 1f;
		return val;
	}

	private void CreateBottomMinimapOverlay(float height)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0057: 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_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Expected O, but got Unknown
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: 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)
		GameObject val = new GameObject("Minimap_Panel_Shape_Mask");
		val.transform.SetParent((Transform)(object)rootPanel, false);
		LayoutElement val2 = val.AddComponent<LayoutElement>();
		val2.ignoreLayout = true;
		Image val3 = val.AddComponent<Image>();
		val3.sprite = panelSprite;
		val3.type = (Type)1;
		val3.pixelsPerUnitMultiplier = 1f;
		((Graphic)val3).color = Color.white;
		((Graphic)val3).raycastTarget = false;
		Mask val4 = val.AddComponent<Mask>();
		val4.showMaskGraphic = false;
		RectTransform rectTransform = ((Graphic)val3).rectTransform;
		rectTransform.anchorMin = Vector2.zero;
		rectTransform.anchorMax = Vector2.one;
		rectTransform.pivot = new Vector2(0.5f, 0.5f);
		rectTransform.offsetMin = Vector2.zero;
		rectTransform.offsetMax = Vector2.zero;
		GameObject val5 = new GameObject("Minimap_Image");
		val5.transform.SetParent(val.transform, false);
		minimapImage = val5.AddComponent<RawImage>();
		((Graphic)minimapImage).color = Color.white;
		((Graphic)minimapImage).raycastTarget = false;
		RectTransform rectTransform2 = ((Graphic)minimapImage).rectTransform;
		rectTransform2.anchorMin = new Vector2(0f, 0f);
		rectTransform2.anchorMax = new Vector2(1f, 0f);
		rectTransform2.pivot = new Vector2(0.5f, 0f);
		rectTransform2.anchoredPosition = Vector2.zero;
		float num = 4f;
		float num2 = 3f;
		rectTransform2.sizeDelta = new Vector2(0f, height);
		rectTransform2.offsetMin = new Vector2(num, num2);
		rectTransform2.offsetMax = new Vector2(0f - num, height + num2);
		CreatePropHeatIndicator(val5.transform);
		CreateHunterBlackoutTimer(val.transform, height);
		val.transform.SetSiblingIndex(1);
	}

	private void CreateHunterBlackoutTimer(Transform parent, float height)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: 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_008c: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		hunterBlackoutTimerText = CreateText(parent, "", 72, (TextAlignmentOptions)514);
		((Graphic)hunterBlackoutTimerText).color = Color.black;
		((Component)hunterBlackoutTimerText).gameObject.SetActive(false);
		RectTransform rectTransform = hunterBlackoutTimerText.rectTransform;
		rectTransform.anchorMin = new Vector2(0f, 0f);
		rectTransform.anchorMax = new Vector2(1f, 0f);
		rectTransform.pivot = new Vector2(0.5f, 0f);
		rectTransform.anchoredPosition = Vector2.zero;
		rectTransform.sizeDelta = new Vector2(0f, height);
		rectTransform.offsetMin = new Vector2(4f, 3f);
		rectTransform.offsetMax = new Vector2(-4f, height + 3f);
		hunterBlackoutTimerText.transform.SetAsLastSibling();
	}

	private void CreatePropHeatIndicator(Transform parent)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Prop_Heat_Indicator");
		val.transform.SetParent(parent, false);
		propHeatImage = val.AddComponent<RawImage>();
		propHeatImage.texture = (Texture)(object)CreatePropHeatTexture(96);
		((Graphic)propHeatImage).color = new Color(1f, 0.04f, 0f, 0f);
		((Graphic)propHeatImage).raycastTarget = false;
		propHeatRect = ((Graphic)propHeatImage).rectTransform;
		propHeatRect.anchorMin = new Vector2(0.5f, 0.5f);
		propHeatRect.anchorMax = new Vector2(0.5f, 0.5f);
		propHeatRect.pivot = new Vector2(0.5f, 0.5f);
		propHeatRect.sizeDelta = new Vector2(108f, 108f);
		propHeatRect.anchoredPosition = Vector2.zero;
		val.SetActive(false);
		val.transform.SetAsLastSibling();
	}

	private Texture2D CreatePropHeatTexture(int size)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		propHeatTexture = new Texture2D(size, size, (TextureFormat)4, false);
		((Object)propHeatTexture).name = "PropHunt_Prop_Heat_Texture";
		((Texture)propHeatTexture).wrapMode = (TextureWrapMode)1;
		float num = (float)(size - 1) * 0.5f;
		for (int i = 0; i < size; i++)
		{
			for (int j = 0; j < size; j++)
			{
				float num2 = ((float)j - num) / num;
				float num3 = ((float)i - num) / num;
				float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
				float num5 = Mathf.Clamp01(1f - num4);
				num5 *= num5;
				propHeatTexture.SetPixel(j, i, new Color(1f, 0.02f, 0f, num5));
			}
		}
		propHeatTexture.Apply();
		return propHeatTexture;
	}

	private GameObject CreateRow(string name, Transform parent, float height)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.sizeDelta = new Vector2(0f, height);
		LayoutElement val3 = val.AddComponent<LayoutElement>();
		val3.preferredHeight = height;
		val3.minHeight = height;
		val3.flexibleWidth = 1f;
		return val;
	}

	private TMP_Text CreateText(Transform parent, string value, int fontSize, TextAlignmentOptions alignment)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: 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_0088: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("TMP_Text");
		val.transform.SetParent(parent, false);
		TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val2).text = value;
		((TMP_Text)val2).fontSize = fontSize;
		((TMP_Text)val2).alignment = alignment;
		((Graphic)val2).color = Color.black;
		((TMP_Text)val2).enableWordWrapping = false;
		((TMP_Text)val2).overflowMode = (TextOverflowModes)1;
		if ((Object)(object)gabaritoFont != (Object)null)
		{
			((TMP_Text)val2).font = gabaritoFont;
		}
		RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
		rectTransform.anchorMin = Vector2.zero;
		rectTransform.anchorMax = Vector2.one;
		rectTransform.offsetMin = Vector2.zero;
		rectTransform.offsetMax = Vector2.zero;
		return (TMP_Text)(object)val2;
	}

	private void AddFlexibleLayout(GameObject obj, int flexibleWidth)
	{
		LayoutElement val = obj.GetComponent<LayoutElement>();
		if ((Object)(object)val == (Object)null)
		{
			val = obj.AddComponent<LayoutElement>();
		}
		val.flexibleWidth = flexibleWidth;
	}

	private void CreateMinimapCamera()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0049: 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_008d: Expected O, but got Unknown
		GameObject val = new GameObject("PropHunt_Minimap_Camera");
		minimapCamera = val.AddComponent<Camera>();
		minimapCamera.orthographic = true;
		minimapCamera.orthographicSize = 35f;
		minimapCamera.clearFlags = (CameraClearFlags)2;
		minimapCamera.backgroundColor = Color.black;
		minimapCamera.nearClipPlane = 0.1f;
		minimapCamera.farClipPlane = 500f;
		minimapTexture = new RenderTexture(512, 512, 16);
		((Object)minimapTexture).name = "PropHunt_Minimap_RenderTexture";
		minimapTexture.Create();
		minimapCamera.targetTexture = minimapTexture;
		minimapImage.texture = (Texture)(object)minimapTexture;
	}

	private void UpdateMinimapCamera()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player == (Object)null) && !((Object)(object)minimapCamera == (Object)null))
		{
			Vector3 position = player.position;
			((Component)minimapCamera).transform.position = new Vector3(position.x, position.y + 80f, position.z);
			((Component)minimapCamera).transform.rotation = Quaternion.Euler(90f, 0f, 0f);
		}
	}

	private void UpdatePropHeatIndicator(bool isHunter)
	{
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)propHeatImage == (Object)null || (Object)(object)propHeatRect == (Object)null)
		{
			return;
		}
		if (!isHunter || IsHunterBlackoutVisible() || (Object)(object)PropManager.Instance == (Object)null || (Object)(object)player == (Object)null || Time.time < propHeatActivationTime)
		{
			((Component)propHeatImage).gameObject.SetActive(false);
			hasPropHeatDirection = false;
			nextPropHeatUpdateTime = 0f;
			return;
		}
		if (Time.time >= nextPropHeatUpdateTime)
		{
			bool flag = (hasPropHeatDirection = TryRefreshPropHeatDirection());
			nextPropHeatUpdateTime = Time.time + (flag ? GetPropHeatUpdateInterval() : 0.25f);
		}
		((Component)propHeatImage).gameObject.SetActive(hasPropHeatDirection);
		if (hasPropHeatDirection)
		{
			float num = 0.78f + Mathf.Sin(Time.time * 4f) * 0.22f;
			((Graphic)propHeatImage).color = new Color(1f, 0.04f, 0f, 0.48f * num);
		}
	}

	private bool TryRefreshPropHeatDirection()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_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)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: 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_013a: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00b4: 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_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: 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_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		Rect rect = ((Graphic)minimapImage).rectTransform.rect;
		if (((Rect)(ref rect)).width < 1f || ((Rect)(ref rect)).height < 1f)
		{
			return false;
		}
		Vector3 val = Vector3.zero;
		Vector3 val2 = Vector3.zero;
		float num = float.PositiveInfinity;
		int num2 = 0;
		foreach (PlayerInfo remainingProp in PropManager.Instance.GetRemainingProps())
		{
			if (!((Object)(object)remainingProp == (Object)null) && !((Object)(object)((Component)remainingProp).transform == (Object)null))
			{
				Vector3 position = ((Component)remainingProp).transform.position;
				Vector3 val3 = position - player.position;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					val2 = val3;
				}
				val += position;
				num2++;
			}
		}
		if (num2 == 0)
		{
			return false;
		}
		Vector3 val4 = val / (float)num2;
		Vector3 val5 = val4 - player.position;
		Vector2 val6 = default(Vector2);
		((Vector2)(ref val6))..ctor(val5.x, val5.z);
		if (((Vector2)(ref val6)).sqrMagnitude < 0.01f)
		{
			((Vector2)(ref val6))..ctor(val2.x, val2.z);
		}
		if (((Vector2)(ref val6)).sqrMagnitude < 0.01f)
		{
			val6 = cachedPropHeatDirection;
		}
		cachedPropHeatDirection = ((Vector2)(ref val6)).normalized;
		propHeatRect.anchoredPosition = GetMinimapEdgePosition(cachedPropHeatDirection, rect);
		return true;
	}

	private Vector2 GetMinimapEdgePosition(Vector2 direction, Rect minimapRect)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(0f, ((Rect)(ref minimapRect)).width * 0.5f - 54f);
		float num2 = Mathf.Max(0f, ((Rect)(ref minimapRect)).height * 0.5f - 54f);
		float num3 = ((Mathf.Abs(direction.x) > 0.001f) ? (num / Mathf.Abs(direction.x)) : float.PositiveInfinity);
		float num4 = ((Mathf.Abs(direction.y) > 0.001f) ? (num2 / Mathf.Abs(direction.y)) : float.PositiveInfinity);
		float num5 = Mathf.Min(num3, num4);
		return direction * num5;
	}

	private float GetPropHeatActivationDelay()
	{
		ConfigurationHandler instance = ConfigurationHandler.Instance;
		if (instance == null)
		{
			return 0f;
		}
		return (float)instance.RoundTimerLengthInSeconds * ((float)instance.PropHeatActivationPercent / 100f);
	}

	private float GetPropHeatUpdateInterval()
	{
		ConfigurationHandler instance = ConfigurationHandler.Instance;
		if (instance == null)
		{
			return 5f;
		}
		return Mathf.Max(1f, (float)instance.PropHeatUpdateIntervalInSeconds);
	}

	private void UpdateHunterBlackout(bool isHunter)
	{
		if ((Object)(object)hunterBlackoutImage == (Object)null)
		{
			return;
		}
		int hunterBlackoutDuration = GetHunterBlackoutDuration();
		int currentHoleCourseIndex = CourseManager.CurrentHoleCourseIndex;
		if (isHunter && (!wasHunter || hunterBlackoutHoleIndex != currentHoleCourseIndex))
		{
			hunterBlackoutStartTime = Time.time;
			hunterBlackoutHoleIndex = currentHoleCourseIndex;
		}
		wasHunter = isHunter;
		if (!isHunter || hunterBlackoutDuration <= 0 || hunterBlackoutHoleIndex != currentHoleCourseIndex)
		{
			SetHunterBlackoutAlpha(0f);
			return;
		}
		float num = Time.time - hunterBlackoutStartTime;
		float hunterBlackoutAlpha = 0f;
		if (num < (float)hunterBlackoutDuration)
		{
			hunterBlackoutAlpha = 1f;
		}
		else if (num < (float)hunterBlackoutDuration + 1.5f)
		{
			hunterBlackoutAlpha = 1f - (num - (float)hunterBlackoutDuration) / 1.5f;
		}
		SetHunterBlackoutAlpha(hunterBlackoutAlpha);
	}

	private bool IsHunterBlackoutVisible()
	{
		return (Object)(object)hunterBlackoutImage != (Object)null && ((Component)hunterBlackoutImage).gameObject.activeSelf;
	}

	private void SetHunterBlackoutAlpha(float alpha)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		bool flag = alpha > 0.001f;
		((Component)hunterBlackoutImage).gameObject.SetActive(flag);
		((Graphic)hunterBlackoutImage).color = new Color(0f, 0f, 0f, Mathf.Clamp01(alpha));
		if (flag)
		{
			((Component)hunterBlackoutImage).transform.SetAsFirstSibling();
		}
		if ((Object)(object)minimapImage != (Object)null)
		{
			((Behaviour)minimapImage).enabled = !flag;
		}
		if ((Object)(object)hunterBlackoutTimerText != (Object)null)
		{
			((Component)hunterBlackoutTimerText).gameObject.SetActive(flag);
			if (flag)
			{
				hunterBlackoutTimerText.text = Mathf.CeilToInt(GetHunterBlackoutRemainingTime()).ToString();
			}
		}
	}

	private float GetHunterBlackoutRemainingTime()
	{
		return Mathf.Max(0f, (float)GetHunterBlackoutDuration() - (Time.time - hunterBlackoutStartTime));
	}

	private int GetHunterBlackoutDuration()
	{
		ConfigurationHandler instance = ConfigurationHandler.Instance;
		if (instance == null)
		{
			return 30;
		}
		return Mathf.Max(0, instance.HunterBlackoutDurationInSeconds);
	}

	private void RefreshPropHeatActivationTime()
	{
		propHeatActivationTime = propHeatInitializationTime + GetPropHeatActivationDelay();
	}

	private void OnConfigurationChanged()
	{
		RefreshPropHeatActivationTime();
	}

	public void SetTeamName(string teamName)
	{
		if ((Object)(object)teamNameText != (Object)null)
		{
			teamNameText.text = teamName;
		}
	}

	public void SetInfoText(string left, string right)
	{
		if ((Object)(object)leftInfoText != (Object)null)
		{
			leftInfoText.text = left;
		}
		if ((Object)(object)rightInfoText != (Object)null)
		{
			rightInfoText.text = right;
		}
	}

	private void OnDestroy()
	{
		if ((Object)(object)minimapTexture != (Object)null)
		{
			minimapTexture.Release();
			Object.Destroy((Object)(object)minimapTexture);
		}
		if ((Object)(object)minimapCamera != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)minimapCamera).gameObject);
		}
		if ((Object)(object)propHeatTexture != (Object)null)
		{
			Object.Destroy((Object)(object)propHeatTexture);
		}
		if ((Object)(object)panelBackgroundStencilMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)panelBackgroundStencilMaterial);
		}
		if ((Object)(object)panelOuterBackgroundMaterial != (Object)null)
		{
			Object.Destroy((Object)(object)panelOuterBackgroundMaterial);
		}
		if (ConfigurationHandler.Instance != null)
		{
			ConfigurationHandler.Instance.ConfigChanged -= OnConfigurationChanged;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace SharksAndMinnows.Patches
{
	public class ItemSpawnerPatches
	{
		[HarmonyPatch(typeof(ItemSpawner), "OnTriggerEnter")]
		[HarmonyPrefix]
		public static bool OnTriggerEnter_Prefix(ItemSpawner __instance, Collider other)
		{
			PlayerTeam val = default(PlayerTeam);
			ComponentExtensions.TryGetComponentInParent<PlayerTeam>((Component)(object)other, ref val, true);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			return true;
		}
	}
}
namespace PropHunt
{
	public class CustomRoundTimer : MonoBehaviour
	{
		public void Awake()
		{
			StartTimer();
		}

		private void StartTimer()
		{
			SingletonNetworkBehaviour<CourseManager>.Instance.countdownRemainingTime = ConfigurationHandler.Instance.RoundTimerLengthInSeconds;
			if (SingletonNetworkBehaviour<CourseManager>.Instance.matchEndCountdownRoutine != null)
			{
				((MonoBehaviour)SingletonNetworkBehaviour<CourseManager>.Instance).StopCoroutine(SingletonNetworkBehaviour<CourseManager>.Instance.matchEndCountdownRoutine);
			}
			SingletonNetworkBehaviour<CourseManager>.Instance.matchEndCountdownRoutine = ((MonoBehaviour)SingletonNetworkBehaviour<CourseManager>.Instance).StartCoroutine(SingletonNetworkBehaviour<CourseManager>.Instance.CountDownToMatchEndRoutine());
		}
	}
	internal static class Events
	{
		public static event Action<PlayerInfo, PlayerInfo> OnShotByHunter;

		public static void InvokeOnShotByHunter(PlayerInfo victim, PlayerInfo hitter)
		{
			Events.OnShotByHunter?.Invoke(victim, hitter);
		}
	}
	internal struct HunterDeathStateMessage : NetworkMessage
	{
		public ulong HunterGuid;

		public bool IsDead;
	}
	internal static class HunterDeathStateMessageSerializer
	{
		private static bool registered;

		public static void Register()
		{
			if (!registered)
			{
				Writer<HunterDeathStateMessage>.write = Write;
				Reader<HunterDeathStateMessage>.read = Read;
				registered = true;
			}
		}

		private static void Write(NetworkWriter writer, HunterDeathStateMessage message)
		{
			NetworkWriterExtensions.WriteULong(writer, message.HunterGuid);
			NetworkWriterExtensions.WriteBool(writer, message.IsDead);
		}

		private static HunterDeathStateMessage Read(NetworkReader reader)
		{
			HunterDeathStateMessage result = default(HunterDeathStateMessage);
			result.HunterGuid = NetworkReaderExtensions.ReadULong(reader);
			result.IsDead = NetworkReaderExtensions.ReadBool(reader);
			return result;
		}
	}
	public class MeshBundleLoader
	{
		public sealed class LoadedPropHuntBundle
		{
			public AssetBundle? Bundle { get; }

			public Dictionary<string, Mesh> MeshesByName { get; }

			public GameObject? PropHuntUIPrefab { get; }

			public LoadedPropHuntBundle(AssetBundle? bundle, Dictionary<string, Mesh> meshesByName)
			{
				Bundle = bundle;
				MeshesByName = meshesByName;
			}
		}

		private const string BundleFileName = "prophunt_export";

		private static LoadedPropHuntBundle? cachedBundle;

		public static LoadedPropHuntBundle LoadBundle()
		{
			if (cachedBundle != null)
			{
				Plugin.Log.LogInfo((object)"[PropClone] Using cached PropHunt asset bundle.");
				return cachedBundle;
			}
			string text = FindBundlePath();
			if (string.IsNullOrEmpty(text))
			{
				Plugin.Log.LogWarning((object)("[PropClone] Bundle not found. Expected 'prophunt_export' in either '" + Path.Combine(Paths.PluginPath, "PropHunt") + "' or '" + Paths.PluginPath + "'"));
				cachedBundle = new LoadedPropHuntBundle(null, new Dictionary<string, Mesh>(StringComparer.OrdinalIgnoreCase));
				return cachedBundle;
			}
			AssetBundle val = AssetBundle.LoadFromFile(text);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)("[PropClone] Failed to load bundle from '" + text + "'"));
				cachedBundle = new LoadedPropHuntBundle(null, new Dictionary<string, Mesh>(StringComparer.OrdinalIgnoreCase));
				return cachedBundle;
			}
			LogBundleContents(val);
			Dictionary<string, Mesh> meshesByName = LoadMeshes(val);
			cachedBundle = new LoadedPropHuntBundle(val, meshesByName);
			return cachedBundle;
		}

		public static Dictionary<string, Mesh> LoadMeshBundle()
		{
			return LoadBundle().MeshesByName;
		}

		public static GameObject? LoadPropHuntUIPrefab()
		{
			return LoadBundle().PropHuntUIPrefab;
		}

		public static void UnloadCachedBundle(bool unloadAllLoadedObjects = false)
		{
			if ((Object)(object)cachedBundle?.Bundle != (Object)null)
			{
				cachedBundle.Bundle.Unload(unloadAllLoadedObjects);
				Plugin.Log.LogInfo((object)"[PropClone] Unloaded cached PropHunt asset bundle.");
			}
			cachedBundle = null;
		}

		private static string? FindBundlePath()
		{
			string location = typeof(Plugin).Assembly.Location;
			string text = Path.GetDirectoryName(location) ?? "";
			string text2 = Path.Join(text.AsSpan(), "prophunt_export".AsSpan());
			if (File.Exists(text2))
			{
				return text2;
			}
			text2 = Path.Combine(Paths.PluginPath, "prophunt_export");
			if (File.Exists(text2))
			{
				return text2;
			}
			return null;
		}

		private static Dictionary<string, Mesh> LoadMeshes(AssetBundle bundle)
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			Mesh[] source = bundle.LoadAllAssets<Mesh>();
			Dictionary<string, Mesh> result = source.Where((Mesh m) => (Object)(object)m != (Object)null).GroupBy<Mesh, string>((Mesh m) => ((Object)m).name, StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, Mesh>, string, Mesh>((IGrouping<string, Mesh> g) => g.Key, (IGrouping<string, Mesh> g) => g.First(), StringComparer.OrdinalIgnoreCase);
			foreach (Mesh item in (from m in source
				where (Object)(object)m != (Object)null
				orderby ((Object)m).name
				select m).Take(200))
			{
				Plugin.Log.LogInfo((object)("[PropClone] Bundled mesh: '" + ((Object)item).name + "', " + $"subMeshes={item.subMeshCount}, bounds={item.bounds}"));
			}
			return result;
		}

		private static void LogBundleContents(AssetBundle bundle)
		{
			string[] allAssetNames = bundle.GetAllAssetNames();
			Plugin.Log.LogInfo((object)$"[PropClone] Bundle contains {allAssetNames.Length} asset(s):");
			foreach (string item in allAssetNames.OrderBy((string a) => a).Take(300))
			{
				Plugin.Log.LogInfo((object)("[PropClone] Bundle asset: " + item));
			}
			if (allAssetNames.Length > 300)
			{
				Plugin.Log.LogInfo((object)$"[PropClone] Bundle asset log truncated. Remaining: {allAssetNames.Length - 300}");
			}
		}
	}
	[BepInPlugin("com.github.glarmer.prophunt", "PropHunt", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static ConfigurationHandler ConfigurationHandler;

		private PropHuntGamemode gamemode;

		public const string Id = "com.github.glarmer.prophunt";

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "PropHunt";

		public static string Version => "0.1.0";

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigurationHandler = new ConfigurationHandler(((BaseUnityPlugin)this).Config);
			gamemode = new PropHuntGamemode();
			GameModeUtilities.RegisterGameMode((IGamemode)(object)gamemode);
			Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
		}
	}
	public class PropHuntGamemode : IGamemode
	{
		public static int HUNTER_TEAM = 0;

		public static int PROP_TEAM = 1;

		private static bool _cached = false;

		private static float _defaultMoveSpeed;

		private static float _walkMoveSpeed;

		private static float _wadingSpeed;

		private static float _speedBoostFactor;

		private static float _diveHorizontalSpeed;

		private static float _diveUpwardsSpeed;

		private static float _diveGetUpDuration;

		private static float _jumpUpwardsSpeed;

		private static float _swingChargingSpeed;

		private static float _swingAimingSpeed;

		public Harmony GamemodeHarmony { get; init; }

		public string Name { get; } = "PropHunt";


		public string ModId { get; } = "com.github.glarmer.prophunt";


		public int MinPlayers { get; } = 2;


		public int MaxPlayers { get; } = 200;


		public bool IsTeamBased { get; } = true;


		public bool IsNormalStartProcedure { get; } = true;


		public int TeamCount { get; } = 2;


		public string Description { get; } = "Can the Props disguise themselves long enough to evade the Hunters? Only time will tell!";


		public bool IsTaggingEnabled { get; } = true;


		public PropHuntGamemode()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			GamemodeHarmony = new Harmony(((IGamemode)this).GameModeId);
		}

		public void OnGameStart()
		{
			Plugin.Log.LogInfo((object)("[" + Name + "] OnGameStart"));
			StopAutoNextHole.END_GAME = false;
			GamemodeHarmony.PatchAll(typeof(HoleProgressBarUIPatches));
			GamemodeHarmony.PatchAll(typeof(StopCountdownToMatchEnd));
			GamemodeHarmony.PatchAll(typeof(StopAutoNextHole));
			GamemodeHarmony.PatchAll(typeof(HideAheadOfBallMessage));
			GamemodeHarmony.PatchAll(typeof(PlayerGolferPatches));
			GamemodeHarmony.PatchAll(typeof(InfoFeedPatches));
			GamemodeHarmony.PatchAll(typeof(TeeOffCountdownPatches));
			GamemodeHarmony.PatchAll(typeof(PlayerInventoryPatches));
			GamemodeHarmony.PatchAll(typeof(DisableLevelBounds));
			GamemodeHarmony.PatchAll(typeof(CustomTimerPatches));
			GamemodeHarmony.PatchAll(typeof(NameTagUiPatches));
			GamemodeHarmony.PatchAll(typeof(HittablePatches));
			GamemodeHarmony.PatchAll(typeof(VFXManagerPatches));
			GamemodeHarmony.PatchAll(typeof(ScoreboardPatches));
			ConfigurationHandler.Instance.SyncConfiguration();
			GameObject val = GameObject.Find("Hole progress bar");
			if ((Object)(object)val != (Object)null)
			{
				val.SetActive(false);
			}
			((Component)SingletonBehaviour<GameManager>.Instance).gameObject.AddComponent<RaycastListener>();
			((Component)GameManager.LocalPlayerInfo).gameObject.AddComponent<PropHuntPlayer>();
			((Component)SingletonBehaviour<GameManager>.Instance).gameObject.AddComponent<PropManager>();
			PlayerEvents.OnLocalPlayerLoaded += OnLocalPlayerRegistered;
			PlayerEvents.OnRemotePlayerLoaded += OnRemotePlayerRegistered;
			MatchEvents.OnTeeOffFinished += OnTeeOffFinished;
			if (NetworkServer.active)
			{
				PropManager.RegisterNetworkHandlers();
				GrantAllHuntersInfiniteGuns();
			}
		}

		private void OnTeeOffFinished()
		{
			if (NetworkServer.active)
			{
				GrantAllHuntersInfiniteGuns();
			}
		}

		private void GrantAllHuntersInfiniteGuns()
		{
			foreach (PlayerInfo remotePlayer in GameManager.RemotePlayers)
			{
				GrantHunterInfiniteGun(remotePlayer);
			}
			GrantHunterInfiniteGun(GameManager.LocalPlayerInfo);
		}

		private void OnLocalPlayerRegistered()
		{
			PlayerInfo localPlayerInfo = GameManager.LocalPlayerInfo;
			Plugin.Log.LogInfo((object)("[" + Name + "] OnLocalPlayerRegistered for player " + ((Object)localPlayerInfo).name));
			((Component)GameManager.LocalPlayerInfo).gameObject.AddComponent<PropHuntPlayer>();
		}

		private void OnRemotePlayerRegistered(PlayerInfo player)
		{
			Plugin.Log.LogInfo((object)("[" + Name + "] OnRemotePlayerRegistered  for player " + ((Object)player).name));
			((Component)player).gameObject.AddComponent<PropHuntPlayer>();
		}

		public static void GrantHunterInfiniteGun(PlayerInfo player)
		{
			if (NetworkServer.active && TeamManager.Instance.EnsurePlayerTeam(player).teamId == HUNTER_TEAM)
			{
				PlayerInventory inventory = player.Inventory;
				inventory.ServerTryAddItem((ItemType)2, 1);
				CourseManager.InformPlayerPickedUpItem(inventory.PlayerInfo);
			}
		}

		public void OnGameEnd()
		{
			Plugin.Log.LogInfo((object)("[" + Name + "] OnGameEnd"));
			if (Object.op_Implicit((Object)(object)PropManager.Instance))
			{
				Object.Destroy((Object)(object)PropManager.Instance);
			}
			if (Object.op_Implicit((Object)(object)RaycastListener.Instance))
			{
				Object.Destroy((Object)(object)RaycastListener.Instance);
			}
			PlayerEvents.OnLocalPlayerLoaded -= OnLocalPlayerRegistered;
			PlayerEvents.OnRemotePlayerLoaded -= OnRemotePlayerRegistered;
			MatchEvents.OnTeeOffFinished -= OnTeeOffFinished;
			GamemodeHarmony.UnpatchSelf();
		}

		public bool CanStart(int playerCount)
		{
			return true;
		}

		public static void EndCurrentHole(bool isEndGame)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && Object.op_Implicit((Object)(object)SingletonNetworkBehaviour<CourseManager>.Instance))
			{
				Plugin.Log.LogInfo((object)"[PropHunt] Ending this hole");
				StopAutoNextHole.END_GAME = isEndGame;
				if ((int)SingletonNetworkBehaviour<CourseManager>.Instance.matchState != 6)
				{
					MatchState matchState = SingletonNetworkBehaviour<CourseManager>.Instance.matchState;
					SingletonNetworkBehaviour<CourseManager>.Instance.matchState = (MatchState)6;
					SingletonNetworkBehaviour<CourseManager>.Instance.OnMatchStateChanged(matchState, (MatchState)6);
					Plugin.Log.LogInfo((object)"[PropHunt] Ending this hole");
				}
			}
		}

		void IGamemode.set_GamemodeHarmony(Harmony value)
		{
			GamemodeHarmony = value;
		}
	}
	public class PropHuntPlayer : MonoBehaviour
	{
		private Camera? _camera;

		private GameObject _currentDisguise;

		private bool isDisguised = false;

		private bool hasTriggeredHunterZeroHealth;

		private bool hasNotifiedHunterDeath;

		public PlayerInfo playerInfo;

		public PlayerTeam playerTeam;

		private GameObject bones;

		private GameObject geometry;

		private const int MaxHunterHealth = 100;

		public int numberOfDecoysPlaced { get; private set; } = 0;


		public int maxNumberOfDecoysCanPlace { get; private set; } = 3;


		public int numberOfDisguisesTaken { get; private set; } = 0;


		public int maxNumberOfDisguisesTaken { get; private set; } = 3;


		public int hunterHealth { get; private set; } = 100;


		private void Start()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			RespawnHunter();
			playerInfo = ((Component)((Component)this).transform).GetComponent<PlayerInfo>();
			playerTeam = TeamManager.Instance.EnsurePlayerTeam(playerInfo);
			if (((NetworkBehaviour)playerInfo).isLocalPlayer)
			{
				_camera = Camera.main;
			}
			ApplyPropConfiguration();
			if (ConfigurationHandler.Instance != null)
			{
				ConfigurationHandler.Instance.ConfigChanged += OnConfigurationChanged;
			}
			foreach (Transform item in ((Component)this).transform)
			{
				Transform val = item;
				if (((Object)val).name == "Bones")
				{
					bones = ((Component)val).gameObject;
				}
				if (((Object)val).name == "Geometry")
				{
					geometry = ((Component)val).gameObject;
				}
				if (Object.op_Implicit((Object)(object)bones) && Object.op_Implicit((Object)(object)geometry))
				{
					break;
				}
			}
			((Component)this).gameObject.AddComponent<PropHuntUI>();
		}

		private void RespawnHunter()
		{
			if (GameManager.LocalPlayerAsSpectator.isSpectating)
			{
				NotifyHunterDeathChanged(isDead: false);
				SingletonNetworkBehaviour<MatchSetupMenu>.Instance.SetPlayerSpectator(GameManager.LocalPlayerAsGolfer, false);
			}
		}

		private void Update()
		{
			CommonUpdate();
			LocalCommonUpdate();
			if (playerTeam.teamId == PropHuntGamemode.HUNTER_TEAM)
			{
				HunterUpdate();
				LocalHunterUpdate();
			}
			else if (playerTeam.teamId == PropHuntGamemode.PROP_TEAM)
			{
				PropUpdate();
				LocalPropUpdate();
			}
		}

		public void SetBodyVisible(bool visible)
		{
			bones.SetActive(visible);
			geometry.SetActive(visible);
			if (visible)
			{
				Object.Destroy((Object)(object)_currentDisguise);
			}
		}

		private void UpdatePlayerTeam()
		{
			playerTeam = TeamManager.Instance.EnsurePlayerTeam(playerInfo);
			if (playerTeam.teamId == PropHuntGamemode.PROP_TEAM && isDisguised)
			{
				SetBodyVisible(visible: false);
			}
			if (playerTeam.teamId == PropHuntGamemode.HUNTER_TEAM)
			{
				SetBodyVisible(visible: true);
			}
		}

		private void LocalPropUpdate()
		{
			if (!((NetworkBehaviour)playerInfo).isLocalPlayer)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)_camera))
			{
				Plugin.Log.LogError((object)"[PropHunt] Cannot locate local main camera!");
			}
			else if (Keyboard.current != null)
			{
				bool flag = false;
				bool flag2 = false;
				if (Gamepad.current != null)
				{
					flag2 = ((ButtonControl)Keyboard.current.fKey).wasPressedThisFrame || Gamepad.current.leftStickButton.wasPressedThisFrame;
					flag = ((ButtonControl)Keyboard.current.eKey).wasPressedThisFrame || Gamepad.current.rightStickButton.wasPressedThisFrame;
				}
				else
				{
					flag2 = ((ButtonControl)Keyboard.current.fKey).wasPressedThisFrame;
					flag = ((ButtonControl)Keyboard.current.eKey).wasPressedThisFrame;
				}
				if (flag2)
				{
					PlaceDecoy();
				}
				if (flag)
				{
					DisguiseSelf();
				}
			}
		}

		private void LocalHunterUpdate()
		{
			if (((NetworkBehaviour)playerInfo).isLocalPlayer)
			{
				bool flag = hunterHealth <= 0;
				if (flag && !playerInfo.AsSpectator.isSpectating)
				{
					hunterHealth = 0;
					NotifyHunterDeathChanged(isDead: true);
					SingletonNetworkBehaviour<MatchSetupMenu>.Instance.SetPlayerSpectator(playerInfo.AsGolfer, flag);
				}
				else if (!flag && playerInfo.AsSpectator.isSpectating)
				{
					NotifyHunterDeathChanged(isDead: false);
					SingletonNetworkBehaviour<MatchSetupMenu>.Instance.SetPlayerSpectator(playerInfo.AsGolfer, flag);
				}
			}
		}

		private void LocalCommonUpdate()
		{
			if (((NetworkBehaviour)playerInfo).isLocalPlayer)
			{
			}
		}

		private void PropUpdate()
		{
		}

		private void HunterUpdate()
		{
		}

		private void CommonUpdate()
		{
		}

		private void ApplyPropConfiguration()
		{
			ConfigurationHandler instance = ConfigurationHandler.Instance;
			if (instance != null)
			{
				maxNumberOfDecoysCanPlace = instance.MaxNumberOfDecoysCanPlace;
				maxNumberOfDisguisesTaken = instance.MaxNumberOfDisguisesTaken;
			}
		}

		private void OnConfigurationChanged()
		{
			ApplyPropConfiguration();
		}

		private void DisguiseSelf()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (numberOfDisguisesTaken < maxNumberOfDisguisesTaken)
			{
				RaycastUtility.RequestRaycastOnHost("disguise", GameManager.LocalPlayerId.guid, ((Component)_camera).transform.position, ((Component)_camera).transform.forward, 100f, default(LayerMask));
			}
		}

		private void PlaceDecoy()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (numberOfDecoysPlaced < maxNumberOfDecoysCanPlace)
			{
				RaycastUtility.RequestRaycastOnHost("decoy", GameManager.LocalPlayerId.guid, ((Component)_camera).transform.position, ((Component)_camera).transform.forward, 100f, default(LayerMask));
			}
		}

		internal void SetCurrentDisguise(GameObject disguise)
		{
			isDisguised = true;
			SetBodyVisible(visible: false);
			_currentDisguise = disguise;
			Plugin.Log.LogInfo((object)("Set " + ((Object)playerInfo).name + "'s disguise to " + ((Object)_currentDisguise).name));
			numberOfDisguisesTaken++;
		}

		public void IncrementDecoyCount()
		{
			numberOfDecoysPlaced++;
		}

		public void ApplyIncorrectShotHealthPenalty()
		{
			int damage = ((ConfigurationHandler.Instance != null) ? ConfigurationHandler.Instance.IncorrectShotHealthPenalty : 10);
			DamageHunter(damage);
		}

		public void DamageHunter(int damage)
		{
			if (damage <= 0)
			{
				return;
			}
			if ((Object)(object)TeamManager.Instance != (Object)null)
			{
				playerTeam = TeamManager.Instance.EnsurePlayerTeam(playerInfo);
			}
			if (!((Object)(object)playerTeam == (Object)null) && playerTeam.teamId == PropHuntGamemode.HUNTER_TEAM && hunterHealth > 0)
			{
				hunterHealth = Mathf.Max(0, hunterHealth - damage);
				ManualLogSource log = Plugin.Log;
				PlayerInfo obj = playerInfo;
				log.LogInfo((object)$"[PropHuntPlayer] Hunter health changed. player={((obj != null) ? ((Object)obj).name : null)} health={hunterHealth}");
				if (hunterHealth == 0 && !hasTriggeredHunterZeroHealth)
				{
					hasTriggeredHunterZeroHealth = true;
					OnHunterHealthDepleted();
				}
			}
		}

		public void ResetHunterHealth()
		{
			hunterHealth = 100;
			hasTriggeredHunterZeroHealth = false;
			NotifyHunterDeathChanged(isDead: false);
		}

		public void OnHunterHealthDepleted()
		{
			ManualLogSource log = Plugin.Log;
			PlayerInfo obj = playerInfo;
			log.LogInfo((object)("[PropHuntPlayer] Hunter health depleted. player=" + ((obj != null) ? ((Object)obj).name : null)));
			NotifyHunterDeathChanged(isDead: true);
		}

		private void NotifyHunterDeathChanged(bool isDead)
		{
			ulong guid = playerInfo.PlayerId.guid;
			if (NetworkServer.active)
			{
				hasNotifiedHunterDeath = isDead;
				PropManager.Instance?.SetHunterDied(guid, isDead);
			}
			else if (((NetworkBehaviour)playerInfo).isLocalPlayer && NetworkClient.active && hasNotifiedHunterDeath != isDead)
			{
				hasNotifiedHunterDeath = isDead;
				HunterDeathStateMessageSerializer.Register();
				HunterDeathStateMessage hunterDeathStateMessage = default(HunterDeathStateMessage);
				hunterDeathStateMessage.HunterGuid = guid;
				hunterDeathStateMessage.IsDead = isDead;
				NetworkClient.Send<HunterDeathStateMessage>(hunterDeathStateMessage, 0);
			}
		}

		private void OnDestroy()
		{
			if (ConfigurationHandler.Instance != null)
			{
				ConfigurationHandler.Instance.ConfigChanged -= OnConfigurationChanged;
			}
		}
	}
	public class PropManager : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <ConvertPropToHunterAfterDelay>d__35 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PlayerInfo victim;

			public PlayerTeam victimTeam;

			public TeamManager teamManager;

			public PropManager <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.25f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)victim == (Object)null || (Object)(object)victimTeam == (Object)null || (Object)(object)teamManager == (Object)null)
					{
						return false;
					}
					teamManager.SetTeam(victimTeam, PropHuntGamemode.HUNTER_TEAM, true);
					<>4__this.AddPropTagged(victim.PlayerId.guid);
					victim.Movement.TryBeginRespawn(false, (RespawnTarget)0);
					Plugin.Log.LogInfo((object)$"[PropManager] Conversion complete. victimGuid={victim.PlayerId.guid} tagged={<>4__this._propsThatHaveBeenTagged.Count}/{<>4__this._originalPropRoster.Count} deadHunters={<>4__this._huntersThatHaveDied.Count}/{<>4__this.GetNumberOfHunters()}");
					PropHuntGamemode.GrantHunterInfiniteGun(victim);
					return false;
				}
			}

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

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

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

			private object <>2__current;

			public PlayerInfo victim;

			public PropManager <>4__this;

			private PropHuntPlayer <victimProp>5__1;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.3f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<victimProp>5__1 = ((Component)victim).gameObject.GetComponent<PropHuntPlayer>();
					<victimProp>5__1.SetBodyVisible(visible: true);
					return false;
				}
			}

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

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

		private readonly HashSet<ulong> _originalPropRoster = new HashSet<ulong>();

		private readonly HashSet<ulong> _propsThatHaveBeenTagged = new HashSet<ulong>();

		private readonly HashSet<ulong> _huntersThatHaveDied = new HashSet<ulong>();

		private bool _hasEndedHole;

		public static PropManager Instance;

		public void Awake()
		{
			Plugin.Log.LogInfo((object)"[PropManager] Awake() called");
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				Object.DontDestroyOnLoad((Object)(object)Instance);
				Plugin.Log.LogInfo((object)"[PropManager] Instance set + DontDestroyOnLoad");
				SceneEvents.OnNextHole += OnNextHole;
				SceneEvents.OnReturnToLobby += OnReturnToLobby;
				Events.OnShotByHunter += OnPlayerShot;
				if ((Object)(object)TeamManager.Instance != (Object)null)
				{
					TeamManager.Instance.AllPlayersOnOneTeam += OnAllPlayersOnOneTeam;
					Plugin.Log.LogInfo((object)"[PropManager] Subscribed: TeamManager.AllPlayersOnOneTeam");
				}
				else
				{
					Plugin.Log.LogInfo((object)"[PropManager] TeamManager.Instance was null in Awake(); AllPlayersOnOneTeam not subscribed (yet?)");
				}
			}
			else
			{
				Plugin.Log.LogInfo((object)"[PropManager] Duplicate instance detected; destroying the old component");
				Object.Destroy((Object)(object)Instance);
				Instance = this;
			}
		}

		public int GetNumberOfOriginalProps()
		{
			return _originalPropRoster.Count;
		}

		public int GetNumberOfCapturedProps()
		{
			return _propsThatHaveBeenTagged.Count;
		}

		public int GetNumberOfRemainingProps()
		{
			return GetNumberOfOriginalProps() - GetNumberOfCapturedProps();
		}

		public int GetNumberOfHunters()
		{
			if ((Object)(object)TeamManager.Instance == (Object)null)
			{
				return 0;
			}
			int num = 0;
			foreach (KeyValuePair<ulong, int> item in TeamManager.Instance.SavedTeamIdByGuid)
			{
				if (item.Value == PropHuntGamemode.HUNTER_TEAM)
				{
					num++;
				}
			}
			return num;
		}

		public HashSet<PlayerInfo> GetRemainingProps()
		{
			HashSet<PlayerInfo> hashSet = new HashSet<PlayerInfo>();
			PlayerInfo item = default(PlayerInfo);
			foreach (ulong item2 in _originalPropRoster)
			{
				if (!_propsThatHaveBeenTagged.Contains(item2))
				{
					GameManager.TryFindPlayerByGuid(item2, ref item);
					hashSet.Add(item);
				}
			}
			return hashSet;
		}

		public bool HasPropBeenCaptured(ulong prop)
		{
			return _propsThatHaveBeenTagged.Contains(prop);
		}

		public int GetNumberOfDeadHunters()
		{
			return _huntersThatHaveDied.Count;
		}

		public int GetNumberOfLivingHunters()
		{
			return Mathf.Max(0, GetNumberOfHunters() - GetNumberOfDeadHunters());
		}

		public bool HasHunterDied(ulong hunter)
		{
			return _huntersThatHaveDied.Contains(hunter);
		}

		public void Start()
		{
			Plugin.Log.LogInfo((object)"[PropManager] Start() called; initializing prop roster");
			SetInitialPropRoster();
			Plugin.Log.LogInfo((object)$"[PropManager] Initial roster loaded. originalPropRoster={_originalPropRoster.Count}");
		}

		public void OnDestroy()
		{
			Plugin.Log.LogInfo((object)"[PropManager] OnDestroy() called; unsubscribing events");
			SceneEvents.OnNextHole -= OnNextHole;
			SceneEvents.OnReturnToLobby -= OnReturnToLobby;
			Events.OnShotByHunter -= OnPlayerShot;
			if ((Object)(object)TeamManager.Instance != (Object)null)
			{
				TeamManager.Instance.AllPlayersOnOneTeam -= OnAllPlayersOnOneTeam;
				Plugin.Log.LogInfo((object)"[PropManager] Unsubscribed: TeamManager.AllPlayersOnOneTeam");
			}
			else
			{
				Plugin.Log.LogInfo((object)"[PropManager] TeamManager.Instance was null in OnDestroy(); skipping AllPlayersOnOneTeam unsubscribe");
			}
			Plugin.Log.LogInfo((object)"[PropManager] Unsubscribed: PlayerTag.PlayerTagged");
		}

		private void OnAllPlayersOnOneTeam(TeamData teamData)
		{
			Plugin.Log.LogInfo((object)$"[PropManager] OnAllPlayersOnOneTeam(teamId={teamData?.ID}) called");
			if (teamData != null && teamData.ID == PropHuntGamemode.HUNTER_TEAM)
			{
				Plugin.Log.LogInfo((object)$"[PropManager] AllPlayersOnOneTeam -> Hunters. originalPropRoster={_originalPropRoster.Count} tagged={_propsThatHaveBeenTagged.Count} deadHunters={_huntersThatHaveDied.Count}. Ending game");
				EndHole(isEndGame: true);
			}
		}

		private void OnNextHole(Scene scenePrev, Scene sceneNew)
		{
			_hasEndedHole = false;
			ClearHuntersThatHaveDied();
		}

		public void Update()
		{
			if (_originalPropRoster.Count == 0)
			{
				SetInitialPropRoster();
			}
			TryEndHole();
		}

		private void TryEndHole()
		{
			if (_hasEndedHole)
			{
				return;
			}
			if (_originalPropRoster.Count > 0 && _propsThatHaveBeenTagged.Count >= _originalPropRoster.Count)
			{
				Plugin.Log.LogInfo((object)$"[PropManager] All props caught. originalPropRoster={_originalPropRoster.Count} tagged={_propsThatHaveBeenTagged.Count}. Ending hole");
				EndHole(isEndGame: true);
				return;
			}
			int numberOfHunters = GetNumberOfHunters();
			if (numberOfHunters > 0 && _huntersThatHaveDied.Count >= numberOfHunters)
			{
				Plugin.Log.LogInfo((object)$"[PropManager] All hunters died. hunters={numberOfHunters} deadHunters={_huntersThatHaveDied.Count}. Ending hole");
				EndHole(isEndGame: true);
			}
		}

		private void EndHole(bool isEndGame)
		{
			_hasEndedHole = true;
			PropHuntUI.HideAllCurrentRoundUi();
			PropHuntGamemode.EndCurrentHole(isEndGame);
		}

		public void SetInitialPropRoster()
		{
			if ((Object)(object)TeamManager.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"[PropManager] TeamManager.Instance is null; cannot build initial roster");
				return;
			}
			int num = 0;
			int num2 = 0;
			foreach (KeyValuePair<ulong, int> item in TeamManager.Instance.SavedTeamIdByGuid)
			{
				num++;
				if (item.Value == PropHuntGamemode.PROP_TEAM)
				{
					_originalPropRoster.Add(item.Key);
					num2++;
					Plugin.Log.LogInfo((object)$"[PropManager] Added initial prop guid={item.Key}");
				}
			}
		}

		private void OnReturnToLobby(Scene scene, Scene scene1)
		{
			Plugin.Log.LogInfo((object)"[PropManager] OnReturnToLobby() called");
			ClearAllProps();
		}

		private void ClearAllProps()
		{
			_propsThatHaveBeenTagged.Clear();
			_huntersThatHaveDied.Clear();
			_originalPropRoster.Clear();
			_hasEndedHole = false;
		}

		public void ClearHuntersThatHaveDied()
		{
			Plugin.Log.LogInfo((object)$"[PropManager] ClearHuntersThatHaveDied() clearing {_huntersThatHaveDied.Count} dead hunters (tagged={_propsThatHaveBeenTagged.Count} roster={_originalPropRoster.Count})");
			_huntersThatHaveDied.Clear();
		}

		public void ClearPropsThatHaveBeenTagged()
		{
			Plugin.Log.LogInfo((object)$"[PropManager] ClearPropsThatHaveBeenTagged() clearing {_propsThatHaveBeenTagged.Count} tagged props (deadHunters={_huntersThatHaveDied.Count} roster={_originalPropRoster.Count})");
			_propsThatHaveBeenTagged.Clear();
		}

		public void ClearOriginalPropRoster()
		{
			_originalPropRoster.Clear();
			Plugin.Log.LogInfo((object)"[PropManager] ClearOriginalPropRoster() cleared roster");
		}

		public void AddPropTagged(ulong prop)
		{
			bool flag = _propsThatHaveBeenTagged.Add(prop);
			Plugin.Log.LogInfo((object)$"[PropManager] AddPropTagged(guid={prop}) added={flag} tagged={_propsThatHaveBeenTagged.Count} deadHunters={_huntersThatHaveDied.Count} roster={_originalPropRoster.Count}");
			TryEndHole();
		}

		public void AddHunterDied(ulong hunter)
		{
			bool flag = _huntersThatHaveDied.Add(hunter);
			Plugin.Log.LogInfo((object)$"[PropManager] AddHunterDied(guid={hunter}) added={flag} deadHunters={_huntersThatHaveDied.Count} hunters={GetNumberOfHunters()} tagged={_propsThatHaveBeenTagged.Count} roster={_originalPropRoster.Count}");
			TryEndHole();
		}

		public void RemoveHunterDied(ulong hunter)
		{
			bool flag = _huntersThatHaveDied.Remove(hunter);
			Plugin.Log.LogInfo((object)$"[PropManager] RemoveHunterDied(guid={hunter}) removed={flag} deadHunters={_huntersThatHaveDied.Count} hunters={GetNumberOfHunters()}");
		}

		public void SetHunterDied(ulong hunter, bool isDead)
		{
			if (isDead)
			{
				AddHunterDied(hunter);
			}
			else
			{
				RemoveHunterDied(hunter);
			}
		}

		public static void RegisterNetworkHandlers()
		{
			HunterDeathStateMessageSerializer.Register();
			NetworkServer.RegisterHandler<HunterDeathStateMessage>((Action<NetworkConnectionToClient, HunterDeathStateMessage>)OnHunterDeathStateMessage, true);
		}

		private static void OnHunterDeathStateMessage(NetworkConnectionToClient sender, HunterDeathStateMessage message)
		{
			if (NetworkServer.active && !((Object)(object)Instance == (Object)null))
			{
				if ((Object)(object)TeamManager.Instance == (Object)null || !TeamManager.Instance.SavedTeamIdByGuid.TryGetValue(message.HunterGuid, out var value) || value != PropHuntGamemode.HUNTER_TEAM)
				{
					Plugin.Log.LogInfo((object)$"[PropManager] Ignoring hunter death update for non-hunter guid={message.HunterGuid}");
					return;
				}
				Plugin.Log.LogInfo((object)$"[PropManager] Server received hunter death update. guid={message.HunterGuid} isDead={message.IsDead}");
				Instance.SetHunterDied(message.HunterGuid, message.IsDead);
			}
		}

		private void OnPlayerShot(PlayerInfo victim, PlayerInfo hitter)
		{
			if ((Object)(object)victim == (Object)null || (Object)(object)hitter == (Object)null)
			{
				return;
			}
			Plugin.Log.LogInfo((object)$"[PropManager] OnPlayerTagged(victim={victim.PlayerId.guid}, hitter={hitter.PlayerId.guid}, serverActive={NetworkServer.active})");
			TeamManager instance = TeamManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"[PropManager] TeamManager.Instance is null; aborting tag handling");
				return;
			}
			PlayerTeam val = instance.EnsurePlayerTeam(victim);
			PlayerTeam val2 = instance.EnsurePlayerTeam(hitter);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogInfo((object)$"[PropManager] EnsurePlayerTeam failed. victimTeamNull={(Object)(object)val == (Object)null} hitterTeamNull={(Object)(object)val2 == (Object)null}");
				return;
			}
			if (val2.teamId != PropHuntGamemode.HUNTER_TEAM || val.teamId != PropHuntGamemode.PROP_TEAM)
			{
				Plugin.Log.LogInfo((object)$"[PropManager] Tag ignored. hitterTeam={val2.teamId}, victimTeam={val.teamId}");
				return;
			}
			if (((NetworkBehaviour)victim).isLocalPlayer)
			{
				Plugin.Log.LogInfo((object)$"[PropManager] Victim is local player; applying hunter movement. victimGuid={victim.PlayerId.guid}");
			}
			((MonoBehaviour)this).StartCoroutine(RestorePropPlayersBody(victim));
			if (NetworkServer.active)
			{
				Plugin.Log.LogInfo((object)$"[PropManager] Valid tag: prop->hunter conversion. victimGuid={victim.PlayerId.guid} hitterGuid={hitter.PlayerId.guid}");
				((MonoBehaviour)this).StartCoroutine(ConvertPropToHunterAfterDelay(victim, val, instance));
			}
		}

		[IteratorStateMachine(typeof(<ConvertPropToHunterAfterDelay>d__35))]
		private IEnumerator ConvertPropToHunterAfterDelay(PlayerInfo victim, PlayerTeam victimTeam, TeamManager teamManager)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ConvertPropToHunterAfterDelay>d__35(0)
			{
				<>4__this = this,
				victim = victim,
				victimTeam = victimTeam,
				teamManager = teamManager
			};
		}

		[IteratorStateMachine(typeof(<RestorePropPlayersBody>d__36))]
		private IEnumerator RestorePropPlayersBody(PlayerInfo victim)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <RestorePropPlayersBody>d__36(0)
			{
				<>4__this = this,
				victim = victim
			};
		}
	}
	internal class RaycastListener : MonoBehaviour
	{
		private const bool VerboseCloneLogging = true;

		private const int MaxLoggedMeshesPerClone = 20;

		private Dictionary<string, Mesh> BundledMeshesByName { get; set; }

		public static RaycastListener? Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				Object.DontDestroyOnLoad((Object)(object)this);
			}
			else
			{
				Object.Destroy((Object)(object)this);
			}
			BundledMeshesByName = MeshBundleLoader.LoadMeshBundle();
			RaycastUtility.RaycastResultReceived += DoOnRaycastComplete;
		}

		private void OnDestroy()
		{
			Instance = null;
			RaycastUtility.RaycastResultReceived -= DoOnRaycastComplete;
		}

		private void DoOnRaycastComplete(RaycastResultReceivedEventArgs args)
		{
			//IL_0010: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log.LogInfo((object)("[PropClone] Raycast complete. " + $"purpose='{args.Purpose}', root='{args.ClosestValidRootObjectName}', requester='{args.RequestingClientGuid}'"));
			if (!PlayerInfo.playerInfoPerPlayerGuid.TryGetValue(args.RequestingClientGuid, out var value))
			{
				Plugin.Log.LogWarning((object)$"[PropClone] No PlayerInfo for requester guid '{args.RequestingClientGuid}'");
				return;
			}
			GameObject val = ResolveSelectedObject(args);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("[PropClone] Could not find selected object '" + args.ClosestValidRootObjectName + "'"));
				return;
			}
			LogObjectSummary("[PropClone] Selected object", val);
			LogObjectSummary("[PropClone] Player object", ((Component)value).gameObject);
			string text = args.Purpose.ToLowerInvariant();
			if (text.Contains("decoy"))
			{
				CopyObjectAsDecoy(val, ((Component)value).transform);
			}
			else if (text.Contains("disguise"))
			{
				CopyObjectAsChild(val, ((Component)value).gameObject);
			}
		}

		private void MatchCloneVisualSizeToOriginal(GameObject original, GameObject clone)
		{
			//IL_0091: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: 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_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)original == (Object)null || (Object)(object)clone == (Object)null)
			{
				return;
			}
			if (!TryGetRenderableBounds(original, out var bounds))
			{
				Plugin.Log.LogWarning((object)("[PropClone] Could not get original render bounds for '" + ((Object)original).name + "'"));
				return;
			}
			if (!TryGetRenderableBounds(clone, out var bounds2))
			{
				Plugin.Log.LogWarning((object)("[PropClone] Could not get clone render bounds for '" + ((Object)clone).name + "'"));
				return;
			}
			Vector3 size = ((Bounds)(ref bounds)).size;
			Vector3 size2 = ((Bounds)(ref bounds2)).size;
			if (size2.x <= 0f || size2.y <= 0f || size2.z <= 0f)
			{
				Plugin.Log.LogWarning((object)("[PropClone] Clone bounds invalid for size match. clone='" + ((Object)clone).name + "', cloneSize=" + Fmt(size2)));
				return;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(size.x / size2.x, size.y / size2.y, size.z / size2.z);
			float num = val.y;
			if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0f)
			{
				num = Mathf.Max(val.x, val.z);
			}
			if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0f)
			{
				Plugin.Log.LogWarning((object)("[PropClone] Invalid size multiplier for '" + ((Object)clone).name + "'. originalSize=" + Fmt(size) + ", cloneSize=" + Fmt(size2) + ", multiplier=" + Fmt(val)));
				return;
			}
			Vector3 localScale = clone.transform.localScale;
			clone.transform.localScale = localScale * num;
			Plugin.Log.LogInfo((object)("[PropClone] Matched clone visual size.\n    original='" + ((Object)original).name + "', clone='" + ((Object)clone).name + "'\n    originalBounds.size=" + Fmt(size) + "\n    cloneBounds.sizeBefore=" + Fmt(size2) + "\n    scaleMultiplier=" + Fmt(val) + "\n" + $"    uniformMultiplier={num:F4}\n" + "    rootScaleBefore=" + Fmt(localScale) + "\n    rootScaleAfter=" + Fmt(clone.transform.localScale)));
		}

		private bool TryGetRenderableBounds(GameObject obj, out Bounds bounds)
		{
			//IL_0002: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			if ((Object)(object)obj == (Object)null)
			{
				return false;
			}
			Renderer[] componentsInChildren = obj.GetComponentsInChildren<Renderer>(true);
			bool flag = false;
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null) && val.enabled && !(val is ParticleSystemRenderer))
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			return flag;
		}

		private GameObject CreateMovableVisualClone(GameObject original, bool copyColliders = true)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0779: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0596: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0610: Unknown result type (might be due to invalid IL or missing references)
			//IL_062a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0644: Unknown result type (might be due to invalid IL or missing references)
			//IL_0649: Unknown result type (might be due to invalid IL or missing references)
			//IL_064d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)original == (Object)null)
			{
				return null;
			}
			Plugin.Log.LogInfo((object)("[PropClone] Creating visual clone for '" + GetPath(original.transform) + "'"));
			LogObjectSummary("[PropClone] Original root", original);
			GameObject val = new GameObject(((Object)original).name + "_VisualClone");
			val.transform.position = Vector3.zero;
			val.transform.rotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			val.isStatic = false;
			val.layer = original.layer;
			val.tag = original.tag;
			Dictionary<Transform, Transform> dictionary = BuildCloneTransformHierarchy(original, val);
			MeshFilter[] componentsInChildren = original.GetComponentsInChildren<MeshFilter>(true);
			HashSet<MeshRenderer> highestDetailMeshRenderers = GetHighestDetailMeshRenderers(original);
			Plugin.Log.LogInfo((object)($"[PropClone] Found {componentsInChildren.Length} MeshFilter(s) under '{((Object)original).name}'. " + $"Copying {highestDetailMeshRenderers.Count} highest-detail MeshRenderer(s)."));
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			MeshFilter[] array = componentsInChildren;
			foreach (MeshFilter val2 in array)
			{
				MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>();
				if ((Object)(object)component == (Object)null)
				{
					num4++;
					Plugin.Log.LogInfo((object)("[PropClone] Skipping MeshFilter without MeshRenderer: '" + GetPath(((Component)val2).transform) + "'"));
					continue;
				}
				Mesh sharedMesh = val2.sharedMesh;
				if ((Object)(object)sharedMesh == (Object)null)
				{
					num4++;
					Plugin.Log.LogInfo((object)("[PropClone] Skipping MeshFilter without sharedMesh: '" + GetPath(((Component)val2).transform) + "'"));
					continue;
				}
				if (!highestDetailMeshRenderers.Contains(component))
				{
					num4++;
					if (num < 20)
					{
						num++;
						Plugin.Log.LogInfo((object)$"[PropClone:Mesh {num}] Skipping lower LOD renderer: '{GetPath(((Component)val2).transform)}'");
					}
					continue;
				}
				if (!dictionary.TryGetValue(((Component)val2).transform, out var value) || (Object)(object)value == (Object)null)
				{
					num4++;
					Plugin.Log.LogWarning((object)("[PropClone] Skipping mesh because the clone transform was not created: '" + GetPath(((Component)val2).transform) + "'"));
					continue;
				}
				Mesh val3 = sharedMesh;
				bool flag = IsBadStaticSceneMesh(sharedMesh);
				bool flag2 = ShouldUseNamedBoulderMesh(val2);
				if (flag || flag2)
				{
					Mesh val4 = FindReplacementMeshForStaticMesh(original, val2);
					if ((Object)(object)val4 == (Object)null)
					{
						if (!flag2 || flag)
						{
							num4++;
							Plugin.Log.LogWarning((object)("[PropClone] Skipping static combined mesh because no replacement was found.\n    original='" + ((Object)original).name + "'\n    sourcePath='" + GetPath(((Component)val2).transform) + "'\n    sourceMesh='" + ((Object)sharedMesh).name + "'"));
							continue;
						}
						Plugin.Log.LogWarning((object)("[PropClone] Could not find named boulder mesh replacement; keeping source mesh.\n    sourcePath='" + GetPath(((Component)val2).transform) + "'\n    effectiveName='" + GetEffectiveMeshObjectName(val2) + "'\n    sourceMesh='" + ((Object)sharedMesh).name + "'"));
					}
					else
					{
						val3 = val4;
						num3++;
						Plugin.Log.LogInfo((object)("[PropClone] Replaced mesh.\n    sourcePath='" + GetPath(((Component)val2).transform) + "'\n" + $"    sourceMesh='{((Object)sharedMesh).name}', staticCombined={flag}, namedBoulder={flag2}\n" + "    replacementMesh='" + ((Object)val3).name + "'"));
					}
				}
				RemoveExistingComponent<MeshFilter>(((Component)value).gameObject);
				RemoveExistingComponent<MeshRenderer>(((Component)value).gameObject);
				MeshFilter val5 = ((Component)value).gameObject.AddComponent<MeshFilter>();
				MeshRenderer val6 = ((Component)value).gameObject.AddComponent<MeshRenderer>();
				val5.sharedMesh = val3;
				((Renderer)val6).sharedMaterials = (Material[])(((Object)(object)val3 == (Object)(object)sharedMesh) ? ((Array)((Renderer)component).sharedMaterials) : ((Array)MatchMaterialsToMesh(val3, ((Renderer)component).sharedMaterials)));
				((Renderer)val6).enabled = ((Renderer)component).enabled;
				((Renderer)val6).shadowCastingMode = ((Renderer)component).shadowCastingMode;
				((Renderer)val6).receiveShadows = ((Renderer)component).receiveShadows;
				((Renderer)val6).lightProbeUsage = ((Renderer)component).lightProbeUsage;
				((Renderer)val6).reflectionProbeUsage = ((Renderer)component).reflectionProbeUsage;
				((Renderer)val6).allowOcclusionWhenDynamic = false;
				num2++;
				if (num < 20)
				{
					num++;
					Bounds bounds = ((Renderer)component).bounds;
					ManualLogSource log = Plugin.Log;
					string[] obj = new string[25]
					{
						$"[PropClone:Mesh {num}] ",
						"sourcePath='",
						GetPath(((Component)val2).transform),
						"'\n",
						$"    sourceMesh='{((Object)sharedMesh).name}', replacementMesh='{((Object)val3).name}', staticCombined={flag}\n",
						$"    meshReadable={SafeIsReadable(val3)}, vertexCount={SafeVertexCount(val3)}, subMeshes={val3.subMeshCount}\n",
						"    sourceLocalPos=",
						Fmt(((Component)val2).transform.localPosition),
						", sourceLocalRot=",
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Quaternion localRotation = ((Component)val2).transform.localRotation;
					obj[9] = Fmt(((Quaternion)(ref localRotation)).eulerAngles);
					obj[10] = ", sourceLocalScale=";
					obj[11] = Fmt(((Component)val2).transform.localScale);
					obj[12] = "\n    sourceBounds.center=";
					obj[13] = Fmt(((Bounds)(ref bounds)).center);
					obj[14] = ", sourceBounds.size=";
					obj[15] = Fmt(((Bounds)(ref bounds)).size);
					obj[16] = "\n    cloneLocalPos=";
					obj[17] = Fmt(value.localPosition);
					obj[18] = ", cloneLocalRot=";
					localRotation = value.localRotation;
					obj[19] = Fmt(((Quaternion)(ref localRotation)).eulerAngles);
					obj[20] = ", cloneLocalScale=";
					obj[21] = Fmt(value.localScale);
					obj[22] = "\n    materials=[";
					obj[23] = string.Join(", ", from m in ((Renderer)val6).sharedMaterials
						where (Object)(object)m != (Object)null
						select ((Object)m).name);
					obj[24] = "]";
					log.LogInfo((object)string.Concat(obj));
				}
			}
			if (componentsInChildren.Length > 20)
			{
				Plugin.Log.LogInfo((object)$"[PropClone] Mesh log truncated. Logged {20}/{componentsInChildren.Length} meshes.");
			}
			Plugin.Log.LogInfo((object)("[PropClone] Clone mesh copy complete for '" + ((Object)original).name + "'. " + $"copied={num2}, replacedStaticMeshes={num3}, skipped={num4}, cloneRootPos={Fmt(val.transform.position)}"));
			CopyParticleSystems(original, val);
			if (copyColliders)
			{
				CopyColliders(original, val, dictionary);
			}
			else
			{
				Plugin.Log.LogInfo((object)("[PropClone] Skipping collider copy for '" + ((Object)original).name + "' because this is the local player's disguise."));
			}
			EnsureVisible(val);
			if (num2 == 0)
			{
				Plugin.Log.LogWarning((object)("[PropClone] Clone for '" + ((Object)original).name + "' has no usable meshes. Destroying empty clone."));
				Object.Destroy((Object)(object)val);
				return null;
			}
			return val;
		}

		private GameObject ResolveSelectedObject(RaycastResultReceivedEventArgs args)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GetEventGameObject(args, "ClosestValidRootObject");
			Vector3? eventVector = GetEventVector3(args, "HitPoint");
			if ((Object)(object)val == (Object)null)
			{
				val = FindBestSceneObjectByName(args.ClosestValidRootObjectName, eventVector);
			}
			string eventString = GetEventString(args, "HitObjectName");
			GameObject val2 = FindBestSceneObjectByName(eventString, eventVector, val);
			GameObject val3 = ChooseCloneSource(val, val2);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)val)
			{
				Plugin.Log.LogInfo((object)("[PropClone] Narrowed clone source from '" + GetPath(((Object)(object)val != (Object)null) ? val.transform : null) + "' to '" + GetPath(val3.transform) + "' using hit object '" + GetPath(((Object)(object)val2 != (Object)null) ? val2.transform : null) + "'"));
			}
			return ((Object)(object)val3 != (Object)null) ? val3 : val;
		}

		private GameObject ChooseCloneSource(GameObject selectedObject, GameObject hitObject)
		{
			if ((Object)(object)selectedObject == (Object)null)
			{
				return hitObject;
			}
			if ((Object)(object)hitObject == (Obj