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(); foreach (PropHuntUI propHuntUI in array) { if ((Object)(object)propHuntUI != (Object)null) { propHuntUI.HideCurrentRoundUi(); } } } public static void ShowAllCurrentRoundUi() { PropHuntUI[] array = Resources.FindObjectsOfTypeAll(); 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(); } } 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: " + text + ""; 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)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)((Sprite s) => ((Object)s).name == "UI_Tutorial_Objective_0")); gabaritoFont = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)((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.renderMode = (RenderMode)0; canvas.sortingOrder = 9999; CanvasScaler val2 = val.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.matchWidthOrHeight = 0.5f; val.AddComponent(); } 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(); ((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(); 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(); val2.sprite = panelSprite; val2.type = (Type)1; val2.pixelsPerUnitMultiplier = 1f; ((Graphic)val2).color = Color.white; Mask val3 = val.AddComponent(); val3.showMaskGraphic = false; GameObject val4 = new GameObject("Panel_Background"); val4.transform.SetParent((Transform)(object)rootPanel, false); LayoutElement val5 = val4.AddComponent(); val5.ignoreLayout = true; Image val6 = val4.AddComponent(); 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(); ((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(); 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(); 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(); ((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(); ((Graphic)val2).color = new Color(0f, 0f, 0f, 0.35f); ((Graphic)val2).raycastTarget = false; RectTransform component = val.GetComponent(); component.sizeDelta = new Vector2(0f, height); LayoutElement val3 = val.AddComponent(); 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(); ((Graphic)val2).color = new Color(0f, 0f, 0f, 0.35f); ((Graphic)val2).raycastTarget = false; LayoutElement val3 = val.AddComponent(); 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(); val2.ignoreLayout = true; Image val3 = val.AddComponent(); val3.sprite = panelSprite; val3.type = (Type)1; val3.pixelsPerUnitMultiplier = 1f; ((Graphic)val3).color = Color.white; ((Graphic)val3).raycastTarget = false; Mask val4 = val.AddComponent(); 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(); ((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(); 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(); val2.sizeDelta = new Vector2(0f, height); LayoutElement val3 = val.AddComponent(); 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(); ((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(); if ((Object)(object)val == (Object)null) { val = obj.AddComponent(); } 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(); 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((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.Instance.countdownRemainingTime = ConfigurationHandler.Instance.RoundTimerLengthInSeconds; if (SingletonNetworkBehaviour.Instance.matchEndCountdownRoutine != null) { ((MonoBehaviour)SingletonNetworkBehaviour.Instance).StopCoroutine(SingletonNetworkBehaviour.Instance.matchEndCountdownRoutine); } SingletonNetworkBehaviour.Instance.matchEndCountdownRoutine = ((MonoBehaviour)SingletonNetworkBehaviour.Instance).StartCoroutine(SingletonNetworkBehaviour.Instance.CountDownToMatchEndRoutine()); } } internal static class Events { public static event Action 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.write = Write; Reader.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 MeshesByName { get; } public GameObject? PropHuntUIPrefab { get; } public LoadedPropHuntBundle(AssetBundle? bundle, Dictionary 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(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(StringComparer.OrdinalIgnoreCase)); return cachedBundle; } LogBundleContents(val); Dictionary meshesByName = LoadMeshes(val); cachedBundle = new LoadedPropHuntBundle(val, meshesByName); return cachedBundle; } public static Dictionary 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 LoadMeshes(AssetBundle bundle) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) Mesh[] source = bundle.LoadAllAssets(); Dictionary result = source.Where((Mesh m) => (Object)(object)m != (Object)null).GroupBy((Mesh m) => ((Object)m).name, StringComparer.OrdinalIgnoreCase).ToDictionary, string, Mesh>((IGrouping g) => g.Key, (IGrouping 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.Instance).gameObject.AddComponent(); ((Component)GameManager.LocalPlayerInfo).gameObject.AddComponent(); ((Component)SingletonBehaviour.Instance).gameObject.AddComponent(); 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(); } private void OnRemotePlayerRegistered(PlayerInfo player) { Plugin.Log.LogInfo((object)("[" + Name + "] OnRemotePlayerRegistered for player " + ((Object)player).name)); ((Component)player).gameObject.AddComponent(); } 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.Instance)) { Plugin.Log.LogInfo((object)"[PropHunt] Ending this hole"); StopAutoNextHole.END_GAME = isEndGame; if ((int)SingletonNetworkBehaviour.Instance.matchState != 6) { MatchState matchState = SingletonNetworkBehaviour.Instance.matchState; SingletonNetworkBehaviour.Instance.matchState = (MatchState)6; SingletonNetworkBehaviour.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(); 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(); } private void RespawnHunter() { if (GameManager.LocalPlayerAsSpectator.isSpectating) { NotifyHunterDeathChanged(isDead: false); SingletonNetworkBehaviour.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.Instance.SetPlayerSpectator(playerInfo.AsGolfer, flag); } else if (!flag && playerInfo.AsSpectator.isSpectating) { NotifyHunterDeathChanged(isDead: false); SingletonNetworkBehaviour.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, 0); } } private void OnDestroy() { if (ConfigurationHandler.Instance != null) { ConfigurationHandler.Instance.ConfigChanged -= OnConfigurationChanged; } } } public class PropManager : MonoBehaviour { [CompilerGenerated] private sealed class d__35 : IEnumerator, 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.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 d__36 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerInfo victim; public PropManager <>4__this; private PropHuntPlayer 5__1; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__36(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 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; 5__1 = ((Component)victim).gameObject.GetComponent(); 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 _originalPropRoster = new HashSet(); private readonly HashSet _propsThatHaveBeenTagged = new HashSet(); private readonly HashSet _huntersThatHaveDied = new HashSet(); 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 item in TeamManager.Instance.SavedTeamIdByGuid) { if (item.Value == PropHuntGamemode.HUNTER_TEAM) { num++; } } return num; } public HashSet GetRemainingProps() { HashSet hashSet = new HashSet(); 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 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((Action)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(d__35))] private IEnumerator ConvertPropToHunterAfterDelay(PlayerInfo victim, PlayerTeam victimTeam, TeamManager teamManager) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__35(0) { <>4__this = this, victim = victim, victimTeam = victimTeam, teamManager = teamManager }; } [IteratorStateMachine(typeof(d__36))] private IEnumerator RestorePropPlayersBody(PlayerInfo victim) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__36(0) { <>4__this = this, victim = victim }; } } internal class RaycastListener : MonoBehaviour { private const bool VerboseCloneLogging = true; private const int MaxLoggedMeshesPerClone = 20; private Dictionary 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(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 dictionary = BuildCloneTransformHierarchy(original, val); MeshFilter[] componentsInChildren = original.GetComponentsInChildren(true); HashSet 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(); 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(((Component)value).gameObject); RemoveExistingComponent(((Component)value).gameObject); MeshFilter val5 = ((Component)value).gameObject.AddComponent(); MeshRenderer val6 = ((Component)value).gameObject.AddComponent(); 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 == (Object)null || (Object)(object)hitObject == (Object)(object)selectedObject) { return selectedObject; } if (!IsSameOrChildOf(hitObject.transform, selectedObject.transform)) { return selectedObject; } Transform val = FindNamedAncestor(hitObject.transform, "Combo", selectedObject.transform); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } if (!LooksLikeSceneCollection(selectedObject)) { return selectedObject; } Transform val2 = FindDirectChildUnder(selectedObject.transform, hitObject.transform); return (GameObject)(((Object)(object)val2 != (Object)null) ? ((object)((Component)val2).gameObject) : ((object)selectedObject)); } private GameObject FindBestSceneObjectByName(string objectName, Vector3? hitPoint, GameObject preferredRoot = null) { //IL_010d: 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) string objectName2 = objectName; GameObject preferredRoot2 = preferredRoot; if (string.IsNullOrWhiteSpace(objectName2)) { return null; } List list = (from obj in (from obj in Resources.FindObjectsOfTypeAll() where (Object)(object)obj != (Object)null select obj).Where(delegate(GameObject obj) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) Scene scene = obj.scene; return ((Scene)(ref scene)).IsValid(); }) where ((Object)obj).name.Equals(objectName2, StringComparison.Ordinal) select obj).ToList(); if (list.Count == 0) { return null; } if ((Object)(object)preferredRoot2 != (Object)null) { List list2 = list.Where((GameObject obj) => IsSameOrChildOf(obj.transform, preferredRoot2.transform)).ToList(); if (list2.Count > 0) { list = list2; } } if (hitPoint.HasValue) { Vector3 point = hitPoint.Value; return (from obj in list orderby DistanceToObjectBoundsSqr(obj, point), GetPath(obj.transform).Length select obj).FirstOrDefault(); } return (from obj in list orderby obj.activeInHierarchy descending, GetPath(obj.transform).Length select obj).FirstOrDefault(); } private float DistanceToObjectBoundsSqr(GameObject obj, Vector3 point) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_00df: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_0087: 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) if ((Object)(object)obj == (Object)null) { return float.MaxValue; } Vector3 val; if (TryGetRenderableBounds(obj, out var bounds)) { val = ((Bounds)(ref bounds)).ClosestPoint(point) - point; return ((Vector3)(ref val)).sqrMagnitude; } Collider[] componentsInChildren = obj.GetComponentsInChildren(true); bool flag = false; Bounds val2 = default(Bounds); Collider[] array = componentsInChildren; foreach (Collider val3 in array) { if (!((Object)(object)val3 == (Object)null)) { if (!flag) { val2 = val3.bounds; flag = true; } else { ((Bounds)(ref val2)).Encapsulate(val3.bounds); } } } if (flag) { val = ((Bounds)(ref val2)).ClosestPoint(point) - point; return ((Vector3)(ref val)).sqrMagnitude; } val = obj.transform.position - point; return ((Vector3)(ref val)).sqrMagnitude; } private bool LooksLikeSceneCollection(GameObject obj) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if ((Object)(object)obj == (Object)null) { return false; } if (((Object)obj).name.Contains("Combo", StringComparison.OrdinalIgnoreCase)) { return false; } if ((Object)(object)obj.GetComponent() != (Object)null || (Object)(object)obj.GetComponent() != (Object)null || (Object)(object)obj.GetComponent() != (Object)null || (Object)(object)obj.GetComponent() != (Object)null) { return false; } int num = 0; foreach (Transform item in obj.transform) { Transform val = item; if (((Component)val).GetComponentsInChildren(true).Length != 0) { num++; } if (num > 4) { return true; } } return false; } private Transform FindDirectChildUnder(Transform ancestor, Transform descendant) { if ((Object)(object)ancestor == (Object)null || (Object)(object)descendant == (Object)null) { return null; } Transform val = descendant; Transform val2 = null; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)ancestor) { val2 = val; val = val.parent; } return ((Object)(object)val == (Object)(object)ancestor) ? val2 : null; } private Transform FindNamedAncestor(Transform start, string namePart, Transform stopAt) { Transform val = start; while ((Object)(object)val != (Object)null) { if (((Object)val).name.Contains(namePart, StringComparison.OrdinalIgnoreCase)) { return val; } if ((Object)(object)val == (Object)(object)stopAt) { break; } val = val.parent; } return null; } private bool IsSameOrChildOf(Transform possibleChild, Transform possibleParent) { Transform val = possibleChild; while ((Object)(object)val != (Object)null) { if ((Object)(object)val == (Object)(object)possibleParent) { return true; } val = val.parent; } return false; } private GameObject GetEventGameObject(object args, string propertyName) { object eventValue = GetEventValue(args, propertyName); GameObject val = (GameObject)((eventValue is GameObject) ? eventValue : null); if (val != null) { return val; } Transform val2 = (Transform)((eventValue is Transform) ? eventValue : null); if (val2 != null) { return ((Component)val2).gameObject; } return null; } private string GetEventString(object args, string propertyName) { return GetEventValue(args, propertyName) as string; } private Vector3? GetEventVector3(object args, string propertyName) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (GetEventValue(args, propertyName) is Vector3 value) { return value; } return null; } private object GetEventValue(object args, string propertyName) { if (args == null || string.IsNullOrWhiteSpace(propertyName)) { return null; } Type type = args.GetType(); PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(args, null); } FieldInfo field = type.GetField(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return (field != null) ? field.GetValue(args) : null; } private HashSet GetHighestDetailMeshRenderers(GameObject original) { //IL_0039: 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_0042: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(original.GetComponentsInChildren(true)); LODGroup[] componentsInChildren = original.GetComponentsInChildren(true); foreach (LODGroup val in componentsInChildren) { LOD[] lODs = val.GetLODs(); LOD[] array = lODs; foreach (LOD val2 in array) { Renderer[] renderers = val2.renderers; foreach (Renderer val3 in renderers) { MeshRenderer val4 = (MeshRenderer)(object)((val3 is MeshRenderer) ? val3 : null); if (val4 != null) { hashSet.Remove(val4); } } } if (lODs.Length == 0) { continue; } Renderer[] renderers2 = lODs[0].renderers; foreach (Renderer val5 in renderers2) { MeshRenderer val6 = (MeshRenderer)(object)((val5 is MeshRenderer) ? val5 : null); if (val6 != null) { hashSet.Add(val6); } } } return hashSet; } private Dictionary BuildCloneTransformHierarchy(GameObject original, GameObject cloneRoot) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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) Dictionary dictionary = new Dictionary(); dictionary[original.transform] = cloneRoot.transform; Transform[] componentsInChildren = original.GetComponentsInChildren(true); foreach (Transform item in componentsInChildren.OrderBy((Transform t) => GetPath(t).Length)) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)original.transform)) { Transform parent = item.parent; if (!((Object)(object)parent == (Object)null) && dictionary.TryGetValue(parent, out var value) && !((Object)(object)value == (Object)null)) { GameObject val = new GameObject(((Object)((Component)item).gameObject).name); val.isStatic = false; val.layer = ((Component)item).gameObject.layer; val.tag = ((Component)item).gameObject.tag; val.transform.SetParent(value, false); val.transform.localPosition = item.localPosition; val.transform.localRotation = item.localRotation; val.transform.localScale = item.localScale; dictionary[item] = val.transform; } } } return dictionary; } private void RemoveExistingComponent(GameObject obj) where T : Component { if (!((Object)(object)obj == (Object)null)) { T component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } } private Mesh FindReplacementMeshForStaticMesh(GameObject original, MeshFilter sourceMeshFilter) { if (BundledMeshesByName == null || BundledMeshesByName.Count == 0) { return null; } string text = CleanName(((Object)original).name); string text2 = CleanName(((Object)((Component)sourceMeshFilter).gameObject).name); string effectiveMeshObjectName = GetEffectiveMeshObjectName(sourceMeshFilter); List list = BuildStrictStaticMeshCandidates(text, effectiveMeshObjectName, text2); Plugin.Log.LogInfo((object)("[PropClone] Strict static mesh candidates:\n original='" + ((Object)original).name + "' cleanOriginal='" + text + "'\n child='" + ((Object)((Component)sourceMeshFilter).gameObject).name + "' cleanChild='" + text2 + "' effectiveChild='" + effectiveMeshObjectName + "'\n candidates=[" + string.Join(", ", list) + "]")); foreach (string item in list) { Mesh val = FindBundledMeshExact(item); if ((Object)(object)val != (Object)null) { Plugin.Log.LogInfo((object)("[PropClone] Exact bundled mesh match: '" + item + "' -> '" + ((Object)val).name + "'")); return val; } } foreach (string item2 in list) { Mesh val2 = FindBundledMeshNormalized(item2); if ((Object)(object)val2 != (Object)null) { Plugin.Log.LogInfo((object)("[PropClone] Normalized bundled mesh match: '" + item2 + "' -> '" + ((Object)val2).name + "'")); return val2; } } Plugin.Log.LogWarning((object)("[PropClone] Could not find strict bundled replacement mesh.\n original='" + ((Object)original).name + "' cleanOriginal='" + text + "'\n child='" + ((Object)((Component)sourceMeshFilter).gameObject).name + "' cleanChild='" + text2 + "' effectiveChild='" + effectiveMeshObjectName + "'\n tried=[" + string.Join(", ", list) + "]")); LogLikelyBundledMeshes(text, effectiveMeshObjectName); return null; } private string GetEffectiveMeshObjectName(MeshFilter sourceMeshFilter) { if ((Object)(object)sourceMeshFilter == (Object)null) { return string.Empty; } Transform transform = ((Component)sourceMeshFilter).transform; if (IsBoulderName(((Object)transform).name) && (Object)(object)transform.parent != (Object)null && ((Object)transform.parent).name.Equals("Meshes", StringComparison.OrdinalIgnoreCase) && (Object)(object)transform.parent.parent != (Object)null && IsBoulderName(((Object)transform.parent.parent).name)) { return CleanName(((Object)transform.parent.parent).name); } Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { if (IsBoulderName(((Object)parent).name)) { return CleanName(((Object)parent).name); } parent = parent.parent; } return CleanName(((Object)((Component)sourceMeshFilter).gameObject).name); } private bool IsBoulderName(string name) { if (string.IsNullOrWhiteSpace(name)) { return false; } return CleanName(name).StartsWith("Boulder", StringComparison.OrdinalIgnoreCase); } private bool ShouldUseNamedBoulderMesh(MeshFilter sourceMeshFilter) { if ((Object)(object)sourceMeshFilter == (Object)null) { return false; } return IsBoulderName(GetEffectiveMeshObjectName(sourceMeshFilter)); } private List BuildStrictStaticMeshCandidates(string originalName, string childName, string fallbackChildName = null) { List list = new List(); string text = RemoveInstanceSuffix(CleanName(originalName)); string text2 = RemoveInstanceSuffix(CleanName(childName)); string text3 = RemoveInstanceSuffix(CleanName(fallbackChildName)); bool preferUnpadded = IsBoulderName(text2); AddHighDetailNameFamily(list, text2, preferUnpadded); AddHighDetailNameFamily(list, RemoveLodSuffix(text2), preferUnpadded); if (!string.IsNullOrWhiteSpace(text3) && !text3.Equals(text2, StringComparison.OrdinalIgnoreCase)) { AddHighDetailNameFamily(list, text3, IsBoulderName(text3)); AddHighDetailNameFamily(list, RemoveLodSuffix(text3), IsBoulderName(text3)); } if (!text2.Equals(text, StringComparison.OrdinalIgnoreCase)) { AddHighDetailNameFamily(list, text, IsBoulderName(text)); AddHighDetailNameFamily(list, RemoveLodSuffix(text), IsBoulderName(text)); } return list; } private void AddHighDetailNameFamily(List candidates, string baseName, bool preferUnpadded = false) { if (!string.IsNullOrWhiteSpace(baseName)) { baseName = baseName.Trim(); string text = RemoveLodSuffix(baseName); string text2 = UnpadTrailingNumber(text.Replace(" ", "_")); if (preferUnpadded && !text2.Equals(text, StringComparison.OrdinalIgnoreCase)) { AddCandidate(candidates, text2 + "_LOD0"); AddCandidate(candidates, text2 + "_LOD0_0"); AddCandidate(candidates, text2 + "_LOD0_1"); AddCandidate(candidates, text2); } AddCandidate(candidates, text + "_LOD0"); AddCandidate(candidates, text + "_LOD0_0"); AddCandidate(candidates, text + "_LOD0_1"); AddCandidate(candidates, baseName); AddCandidate(candidates, text); string text3 = PadTrailingNumber(text.Replace(" ", "_")); if (!text3.Equals(text, StringComparison.OrdinalIgnoreCase)) { AddCandidate(candidates, text3 + "_LOD0"); AddCandidate(candidates, text3 + "_LOD0_0"); AddCandidate(candidates, text3 + "_LOD0_1"); AddCandidate(candidates, text3); } if (!preferUnpadded && !text2.Equals(text, StringComparison.OrdinalIgnoreCase)) { AddCandidate(candidates, text2 + "_LOD0"); AddCandidate(candidates, text2 + "_LOD0_0"); AddCandidate(candidates, text2 + "_LOD0_1"); AddCandidate(candidates, text2); } } } private string PadTrailingNumber(string name) { if (string.IsNullOrWhiteSpace(name)) { return name; } int num = Math.Max(name.LastIndexOf('_'), name.LastIndexOf(' ')); if (num < 0 || num >= name.Length - 1) { return name; } string text = name.Substring(0, num + 1); string s = name.Substring(num + 1); if (!int.TryParse(s, out var result)) { return name; } return text + result.ToString("00"); } private string UnpadTrailingNumber(string name) { if (string.IsNullOrWhiteSpace(name)) { return name; } int num = Math.Max(name.LastIndexOf('_'), name.LastIndexOf(' ')); if (num < 0 || num >= name.Length - 1) { return name; } string text = name.Substring(0, num + 1); string s = name.Substring(num + 1); if (!int.TryParse(s, out var result)) { return name; } return text + result; } private Mesh FindBundledMeshExact(string candidate) { if (string.IsNullOrWhiteSpace(candidate)) { return null; } if (BundledMeshesByName.TryGetValue(candidate, out Mesh value) && IsUsableReplacementMesh(value)) { return value; } return null; } private Mesh FindBundledMeshNormalized(string candidate) { string candidate2 = candidate; if (string.IsNullOrWhiteSpace(candidate2)) { return null; } string normalizedCandidate = NormalizeMeshName(candidate2); return ((IEnumerable)(from m in BundledMeshesByName.Values.Where(IsUsableReplacementMesh) orderby ScoreMeshCandidate(((Object)m).name, candidate2) descending, SafeVertexCount(m) descending select m)).FirstOrDefault((Func)((Mesh m) => NormalizeMeshName(((Object)m).name) == normalizedCandidate)); } private Mesh FindBestFuzzyBundledMesh(string originalName, string childName) { string normalizedOriginal = NormalizeMeshName(originalName); string normalizedChild = NormalizeMeshName(childName); string normalizedChildNoLod = NormalizeMeshName(RemoveLodSuffix(childName)); string normalizedOriginalNoLod = NormalizeMeshName(RemoveLodSuffix(originalName)); return (from mesh in BundledMeshesByName.Values.Where(IsUsableReplacementMesh) select new { Mesh = mesh, Score = ScoreFuzzyMeshMatch(((Object)mesh).name, normalizedOriginal, normalizedOriginalNoLod, normalizedChild, normalizedChildNoLod) } into x where x.Score > 0 orderby x.Score descending, SafeVertexCount(x.Mesh) descending select x.Mesh).FirstOrDefault(); } private int ScoreFuzzyMeshMatch(string meshName, string normalizedOriginal, string normalizedOriginalNoLod, string normalizedChild, string normalizedChildNoLod) { string text = NormalizeMeshName(meshName); string text2 = NormalizeMeshName(RemoveLodSuffix(meshName)); int num = 0; if (text == normalizedChild) { num += 10000; } if (text == normalizedOriginal) { num += 9000; } if (text == normalizedChildNoLod) { num += 8000; } if (text == normalizedOriginalNoLod) { num += 7000; } if (text2 == normalizedChildNoLod) { num += 6000; } if (text2 == normalizedOriginalNoLod) { num += 5000; } if (!string.IsNullOrWhiteSpace(normalizedChildNoLod) && (text.Contains(normalizedChildNoLod) || normalizedChildNoLod.Contains(text))) { num += 3000; } if (!string.IsNullOrWhiteSpace(normalizedOriginalNoLod) && (text.Contains(normalizedOriginalNoLod) || normalizedOriginalNoLod.Contains(text))) { num += 2000; } if (meshName.Contains("_LOD0", StringComparison.OrdinalIgnoreCase)) { num += 300; } if (meshName.Contains("_LOD1", StringComparison.OrdinalIgnoreCase)) { num += 250; } if (meshName.Contains("_LOD2", StringComparison.OrdinalIgnoreCase)) { num += 100; } if (LooksLikeColliderMesh(meshName)) { num -= 100000; } if (meshName.Contains("bounds", StringComparison.OrdinalIgnoreCase)) { num -= 100000; } if (meshName.Contains("Spline", StringComparison.OrdinalIgnoreCase)) { num -= 50000; } return num; } private int ScoreMeshCandidate(string meshName, string candidate) { return ScoreFuzzyMeshMatch(meshName, NormalizeMeshName(candidate), NormalizeMeshName(RemoveLodSuffix(candidate)), NormalizeMeshName(candidate), NormalizeMeshName(RemoveLodSuffix(candidate))); } private Material[] MatchMaterialsToMesh(Mesh mesh, Material[] sourceMaterials) { if (sourceMaterials == null || sourceMaterials.Length == 0) { return sourceMaterials; } if ((Object)(object)mesh == (Object)null || mesh.subMeshCount <= 0) { return sourceMaterials; } Material[] array = sourceMaterials.Where((Material m) => (Object)(object)m != (Object)null).ToArray(); if (array.Length == 0) { return sourceMaterials; } Material[] array2 = (Material[])(object)new Material[mesh.subMeshCount]; for (int i = 0; i < array2.Length; i++) { array2[i] = array[Mathf.Min(i, array.Length - 1)]; } return array2; } private bool IsUsableReplacementMesh(Mesh mesh) { if ((Object)(object)mesh == (Object)null) { return false; } if (IsBadStaticSceneMesh(mesh)) { return false; } if (LooksLikeColliderMesh(((Object)mesh).name)) { return false; } if (((Object)mesh).name.Contains("bounds", StringComparison.OrdinalIgnoreCase)) { return false; } if (((Object)mesh).name.Contains("Spline", StringComparison.OrdinalIgnoreCase)) { return false; } if (SafeVertexCount(mesh) <= 0) { return false; } return true; } private bool IsBadStaticSceneMesh(Mesh mesh) { if ((Object)(object)mesh == (Object)null) { return false; } string name = ((Object)mesh).name; return name.Contains("Combined Mesh", StringComparison.OrdinalIgnoreCase) || name.Contains("root: scene", StringComparison.OrdinalIgnoreCase); } private bool LooksLikeColliderMesh(string meshName) { if (string.IsNullOrWhiteSpace(meshName)) { return false; } return meshName.Contains("collider", StringComparison.OrdinalIgnoreCase) || meshName.Contains("collision", StringComparison.OrdinalIgnoreCase) || meshName.EndsWith("_col", StringComparison.OrdinalIgnoreCase); } private string RemoveLodSuffix(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } int num = name.IndexOf("_LOD", StringComparison.OrdinalIgnoreCase); if (num >= 0) { return name.Substring(0, num); } return name; } private string RemoveInstanceSuffix(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } name = CleanName(name); int num = name.IndexOf(" (", StringComparison.Ordinal); if (num >= 0) { name = name.Substring(0, num); } return name.Trim(); } private string NormalizeMeshName(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } name = CleanName(name); if (name.EndsWith(".asset", StringComparison.OrdinalIgnoreCase)) { name = name.Substring(0, name.Length - ".asset".Length); } int num = name.LastIndexOf('_'); if (num >= 0 && num < name.Length - 1) { string s = name.Substring(num + 1); if (int.TryParse(s, out var _)) { name = name.Substring(0, num); } } return name.Replace(" ", "", StringComparison.OrdinalIgnoreCase).Replace("-", "", StringComparison.OrdinalIgnoreCase).Replace("_", "", StringComparison.OrdinalIgnoreCase) .Replace(".", "", StringComparison.OrdinalIgnoreCase) .Trim() .ToLowerInvariant(); } private void AddCandidate(List candidates, string value) { string value2 = value; if (!string.IsNullOrWhiteSpace(value2)) { value2 = value2.Trim(); if (!candidates.Any((string c) => c.Equals(value2, StringComparison.OrdinalIgnoreCase))) { candidates.Add(value2); } } } private void LogLikelyBundledMeshes(string cleanOriginalName, string childName) { string cleanOriginalName2 = cleanOriginalName; string childName2 = childName; if (BundledMeshesByName != null && BundledMeshesByName.Count != 0) { var source = (from mesh in BundledMeshesByName.Values.Where(IsUsableReplacementMesh) select new { Mesh = mesh, Score = ScoreFuzzyMeshMatch(((Object)mesh).name, NormalizeMeshName(cleanOriginalName2), NormalizeMeshName(RemoveLodSuffix(cleanOriginalName2)), NormalizeMeshName(childName2), NormalizeMeshName(RemoveLodSuffix(childName2))) } into x where x.Score > 0 orderby x.Score descending, SafeVertexCount(x.Mesh) descending select x).Take(75); Plugin.Log.LogInfo((object)("[PropClone] Likely bundled mesh candidates:\n" + string.Join("\n", source.Select(x => { //IL_007a: 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) //IL_0082: 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_00a3: Unknown result type (might be due to invalid IL or missing references) object[] obj = new object[7] { x.Score, ((Object)x.Mesh).name, SafeIsReadable(x.Mesh), SafeVertexCount(x.Mesh), x.Mesh.subMeshCount, null, null }; RaycastListener raycastListener = this; Bounds bounds = x.Mesh.bounds; obj[5] = raycastListener.Fmt(((Bounds)(ref bounds)).center); RaycastListener raycastListener2 = this; bounds = x.Mesh.bounds; obj[6] = raycastListener2.Fmt(((Bounds)(ref bounds)).size); return string.Format(" score={0}, mesh='{1}', readable={2}, verts={3}, subMeshes={4}, bounds.center={5}, bounds.size={6}", obj); })))); } } private Vector3 DivideVector3(Vector3 a, Vector3 b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007b: 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) return new Vector3(Mathf.Approximately(b.x, 0f) ? a.x : (a.x / b.x), Mathf.Approximately(b.y, 0f) ? a.y : (a.y / b.y), Mathf.Approximately(b.z, 0f) ? a.z : (a.z / b.z)); } private void CopyParticleSystems(GameObject original, GameObject root) { //IL_0094: 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_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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: 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_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)original == (Object)null || (Object)(object)root == (Object)null) { return; } ParticleSystem[] componentsInChildren = original.GetComponentsInChildren(true); Plugin.Log.LogInfo((object)$"[PropClone] Found {componentsInChildren.Length} ParticleSystem(s) under '{((Object)original).name}'"); int num = 0; ParticleSystem[] array = componentsInChildren; foreach (ParticleSystem val in array) { GameObject val2 = Object.Instantiate(((Component)val).gameObject); ((Object)val2).name = ((Object)((Component)val).gameObject).name; val2.isStatic = false; Vector3 val3 = original.transform.InverseTransformPoint(((Component)val).transform.position); Quaternion localRotation = Quaternion.Inverse(original.transform.rotation) * ((Component)val).transform.rotation; Vector3 val4 = DivideVector3(((Component)val).transform.lossyScale, original.transform.lossyScale); val2.transform.SetParent(root.transform, false); val2.transform.localPosition = val3; val2.transform.localRotation = localRotation; val2.transform.localScale = val4; Transform[] componentsInChildren2 = val2.GetComponentsInChildren(true); foreach (Transform val5 in componentsInChildren2) { ((Component)val5).gameObject.isStatic = false; } ParticleSystem component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { component.Clear(true); component.Play(true); } if (num < 20) { num++; Plugin.Log.LogInfo((object)($"[PropClone:Particle {num}] " + "sourcePath='" + GetPath(((Component)val).transform) + "'\n sourceWorldPos=" + Fmt(((Component)val).transform.position) + ", sourceLossyScale=" + Fmt(((Component)val).transform.lossyScale) + "\n calculatedLocalPos=" + Fmt(val3) + ", calculatedLocalScale=" + Fmt(val4) + "\n cloneWorldPosBeforeFinalMove=" + Fmt(val2.transform.position))); } } } private void CopyObjectAsChild(GameObject originalObject, GameObject targetParent) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown if ((Object)(object)originalObject == (Object)null || (Object)(object)targetParent == (Object)null) { return; } Plugin.Log.LogInfo((object)("[PropClone] CopyObjectAsChild original='" + ((Object)originalObject).name + "' targetParent='" + ((Object)targetParent).name + "'")); LogObjectSummary("[PropClone] Before disguise original", originalObject); LogObjectSummary("[PropClone] Before disguise targetParent", targetParent); PlayerInfo val = targetParent.GetComponent(); if ((Object)(object)val == (Object)null) { val = targetParent.GetComponentInParent(); } bool flag = true; if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).isLocalPlayer) { flag = false; } GameObject val2 = CreateMovableVisualClone(originalObject, flag); if ((Object)(object)val2 == (Object)null) { return; } ((Object)val2).name = ((Object)originalObject).name + "_Disguise"; MatchCloneVisualSizeToOriginal(originalObject, val2); LogObjectSummary("[PropClone] Disguise clone before parent", val2); foreach (Transform item in targetParent.transform) { Transform val3 = item; GameObject gameObject = ((Component)val3).gameObject; if (((Object)gameObject).name.ToLower().Contains("disguise")) { Object.Destroy((Object)(object)gameObject); break; } } val2.transform.SetParent(targetParent.transform, false); EnsureVisible(val2); LogObjectSummary("[PropClone] Disguise clone after parent", val2); LogFirstRenderers("[PropClone] Disguise renderers after parent", val2); Plugin.Log.LogInfo((object)("[PropClone] Created disguise from '" + ((Object)originalObject).name + "' on '" + ((Object)targetParent).name + "'. isLocalPlayer=" + (((Object)(object)val != (Object)null) ? ((NetworkBehaviour)val).isLocalPlayer.ToString() : "unknown") + ", " + $"copiedColliders={flag}")); PropHuntPlayer component = targetParent.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.SetCurrentDisguise(val2); } } private void CopyObjectAsDecoy(GameObject originalObject, Transform playerTransform) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)originalObject == (Object)null || (Object)(object)playerTransform == (Object)null) { return; } Plugin.Log.LogInfo((object)("[PropClone] CopyObjectAtPositionAndFlatRotation original='" + ((Object)originalObject).name + "' player='" + ((Object)playerTransform).name + "'")); LogObjectSummary("[PropClone] Before decoy original", originalObject); ManualLogSource log = Plugin.Log; string[] obj = new string[6] { "[PropClone] Player target pos=", Fmt(playerTransform.position), ", rot=", null, null, null }; Quaternion rotation = playerTransform.rotation; obj[3] = Fmt(((Quaternion)(ref rotation)).eulerAngles); obj[4] = ", lossyScale="; obj[5] = Fmt(playerTransform.lossyScale); log.LogInfo((object)string.Concat(obj)); GameObject val = CreateMovableVisualClone(originalObject); if (!((Object)(object)val == (Object)null)) { ((Object)val).name = ((Object)originalObject).name + "_Decoy"; MatchCloneVisualSizeToOriginal(originalObject, val); LogObjectSummary("[PropClone] Decoy clone before final move", val); LogFirstRenderers("[PropClone] Decoy renderers before final move", val); val.transform.SetPositionAndRotation(playerTransform.position, Quaternion.Euler(0f, playerTransform.eulerAngles.y, 0f)); EnsureVisible(val); LogObjectSummary("[PropClone] Decoy clone after final move", val); LogFirstRenderers("[PropClone] Decoy renderers after final move", val); Plugin.Log.LogInfo((object)$"[PropClone] Created decoy from '{((Object)originalObject).name}' at '{playerTransform.position}'"); PropHuntPlayer component = ((Component)playerTransform).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.IncrementDecoyCount(); } } } private void EnsureVisible(GameObject obj) { if (!((Object)(object)obj == (Object)null)) { obj.SetActive(true); obj.isStatic = false; Transform[] componentsInChildren = obj.GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { ((Component)val).gameObject.SetActive(true); ((Component)val).gameObject.isStatic = false; } Renderer[] componentsInChildren2 = obj.GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren2) { val2.enabled = true; val2.allowOcclusionWhenDynamic = false; } LODGroup[] componentsInChildren3 = obj.GetComponentsInChildren(true); foreach (LODGroup val3 in componentsInChildren3) { val3.enabled = true; } } } private string CleanName(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } name = name.Replace("(Clone)", "").Trim(); int num = name.IndexOf(" (", StringComparison.Ordinal); if (num >= 0) { name = name.Substring(0, num); } return name.Trim(); } private void LogObjectSummary(string label, GameObject obj) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { Plugin.Log.LogInfo((object)(label + ": null")); return; } MeshFilter[] componentsInChildren = obj.GetComponentsInChildren(true); Renderer[] componentsInChildren2 = obj.GetComponentsInChildren(true); LODGroup[] componentsInChildren3 = obj.GetComponentsInChildren(true); Collider[] componentsInChildren4 = obj.GetComponentsInChildren(true); ParticleSystem[] componentsInChildren5 = obj.GetComponentsInChildren(true); ManualLogSource log = Plugin.Log; string[] obj2 = new string[19] { label, ": path='", GetPath(obj.transform), "'\n", $" activeSelf={obj.activeSelf}, activeInHierarchy={obj.activeInHierarchy}, isStatic={obj.isStatic}\n", " pos=", Fmt(obj.transform.position), ", localPos=", Fmt(obj.transform.localPosition), "\n rot=", null, null, null, null, null, null, null, null, null }; Quaternion val = obj.transform.rotation; obj2[10] = Fmt(((Quaternion)(ref val)).eulerAngles); obj2[11] = ", localRot="; val = obj.transform.localRotation; obj2[12] = Fmt(((Quaternion)(ref val)).eulerAngles); obj2[13] = "\n lossyScale="; obj2[14] = Fmt(obj.transform.lossyScale); obj2[15] = ", localScale="; obj2[16] = Fmt(obj.transform.localScale); obj2[17] = "\n"; obj2[18] = $" children={obj.transform.childCount}, meshFilters={componentsInChildren.Length}, renderers={componentsInChildren2.Length}, lodGroups={componentsInChildren3.Length}, colliders={componentsInChildren4.Length}, particles={componentsInChildren5.Length}"; log.LogInfo((object)string.Concat(obj2)); } private void LogFirstRenderers(string label, GameObject obj) { //IL_0104: 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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)obj == (Object)null)) { Renderer[] componentsInChildren = obj.GetComponentsInChildren(true); Plugin.Log.LogInfo((object)$"{label}: rendererCount={componentsInChildren.Length}"); int num = Mathf.Min(componentsInChildren.Length, 20); for (int i = 0; i < num; i++) { Renderer val = componentsInChildren[i]; MeshFilter component = ((Component)val).GetComponent(); Mesh val2 = (((Object)(object)component != (Object)null) ? component.sharedMesh : null); ManualLogSource log = Plugin.Log; string[] obj2 = new string[16] { $"{label} [{i + 1}/{componentsInChildren.Length}] path='{GetPath(((Component)val).transform)}'\n", $" enabled={val.enabled}, activeInHierarchy={((Component)val).gameObject.activeInHierarchy}, isStatic={((Component)val).gameObject.isStatic}\n", " rendererWorldPos=", Fmt(((Component)val).transform.position), ", rendererLocalPos=", Fmt(((Component)val).transform.localPosition), "\n bounds.center=", null, null, null, null, null, null, null, null, null }; Bounds bounds = val.bounds; obj2[7] = Fmt(((Bounds)(ref bounds)).center); obj2[8] = ", bounds.size="; bounds = val.bounds; obj2[9] = Fmt(((Bounds)(ref bounds)).size); obj2[10] = "\n mesh='"; obj2[11] = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "null"); obj2[12] = "', readable="; obj2[13] = (((Object)(object)val2 != (Object)null) ? SafeIsReadable(val2).ToString() : "n/a"); obj2[14] = ", vertexCount="; obj2[15] = (((Object)(object)val2 != (Object)null) ? SafeVertexCount(val2).ToString() : "n/a"); log.LogInfo((object)string.Concat(obj2)); } if (componentsInChildren.Length > num) { Plugin.Log.LogInfo((object)$"{label}: truncated renderer log {num}/{componentsInChildren.Length}"); } } } private void CopyColliders(GameObject original, GameObject root, Dictionary sourceToCloneTransform = null) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)original == (Object)null || (Object)(object)root == (Object)null) { return; } Collider[] componentsInChildren = original.GetComponentsInChildren(true); Plugin.Log.LogInfo((object)$"[PropClone] Found {componentsInChildren.Length} Collider(s) under '{((Object)original).name}'"); int num = 0; int num2 = 0; int num3 = 0; Collider[] array = componentsInChildren; foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { num2++; continue; } GameObject val2 = null; Vector3 val3; Quaternion localRotation; Vector3 val4; if (sourceToCloneTransform != null && sourceToCloneTransform.TryGetValue(((Component)val).transform, out Transform value) && (Object)(object)value != (Object)null) { val2 = ((Component)value).gameObject; val3 = value.localPosition; localRotation = value.localRotation; val4 = value.localScale; } else { val2 = new GameObject(((Object)((Component)val).gameObject).name + "_Collider"); val2.isStatic = false; val3 = original.transform.InverseTransformPoint(((Component)val).transform.position); localRotation = Quaternion.Inverse(original.transform.rotation) * ((Component)val).transform.rotation; val4 = DivideVector3(((Component)val).transform.lossyScale, original.transform.lossyScale); val2.transform.SetParent(root.transform, false); val2.transform.localPosition = val3; val2.transform.localRotation = localRotation; val2.transform.localScale = val4; } Collider val5 = CopySingleCollider(val, val2); if ((Object)(object)val5 == (Object)null) { Object.Destroy((Object)(object)val2); num2++; continue; } val5.enabled = val.enabled; val5.isTrigger = val.isTrigger; val5.sharedMaterial = val.sharedMaterial; num++; if (num3 < 20) { num3++; ManualLogSource log = Plugin.Log; string[] obj = new string[19] { $"[PropClone:Collider {num3}] ", "sourcePath='", GetPath(((Component)val).transform), "'\n", $" colliderType='{((object)val).GetType().Name}', enabled={val.enabled}, isTrigger={val.isTrigger}\n", " sourceWorldPos=", Fmt(((Component)val).transform.position), ", sourceWorldRot=", null, null, null, null, null, null, null, null, null, null, null }; Quaternion rotation = ((Component)val).transform.rotation; obj[8] = Fmt(((Quaternion)(ref rotation)).eulerAngles); obj[9] = ", sourceLossyScale="; obj[10] = Fmt(((Component)val).transform.lossyScale); obj[11] = "\n calculatedLocalPos="; obj[12] = Fmt(val3); obj[13] = ", calculatedLocalRot="; obj[14] = Fmt(((Quaternion)(ref localRotation)).eulerAngles); obj[15] = ", calculatedLocalScale="; obj[16] = Fmt(val4); obj[17] = "\n cloneWorldPosBeforeFinalMove="; obj[18] = Fmt(val2.transform.position); log.LogInfo((object)string.Concat(obj)); } } Plugin.Log.LogInfo((object)$"[PropClone] Collider copy complete for '{((Object)original).name}'. copied={num}, skipped={num2}"); } private Collider CopySingleCollider(Collider sourceCollider, GameObject targetObject) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) BoxCollider val = (BoxCollider)(object)((sourceCollider is BoxCollider) ? sourceCollider : null); if (val == null) { SphereCollider val2 = (SphereCollider)(object)((sourceCollider is SphereCollider) ? sourceCollider : null); if (val2 == null) { CapsuleCollider val3 = (CapsuleCollider)(object)((sourceCollider is CapsuleCollider) ? sourceCollider : null); if (val3 == null) { MeshCollider val4 = (MeshCollider)(object)((sourceCollider is MeshCollider) ? sourceCollider : null); if (val4 == null) { TerrainCollider val5 = (TerrainCollider)(object)((sourceCollider is TerrainCollider) ? sourceCollider : null); if (val5 == null) { WheelCollider val6 = (WheelCollider)(object)((sourceCollider is WheelCollider) ? sourceCollider : null); if (val6 != null) { WheelCollider val7 = targetObject.AddComponent(); val7.center = val6.center; val7.radius = val6.radius; val7.suspensionDistance = val6.suspensionDistance; val7.forceAppPointDistance = val6.forceAppPointDistance; val7.mass = val6.mass; val7.wheelDampingRate = val6.wheelDampingRate; val7.suspensionSpring = val6.suspensionSpring; val7.forwardFriction = val6.forwardFriction; val7.sidewaysFriction = val6.sidewaysFriction; return (Collider)(object)val7; } Plugin.Log.LogWarning((object)("[PropClone] Unsupported collider type '" + ((object)sourceCollider).GetType().Name + "' at '" + GetPath(((Component)sourceCollider).transform) + "'")); return null; } TerrainCollider val8 = targetObject.AddComponent(); val8.terrainData = val5.terrainData; return (Collider)(object)val8; } MeshCollider val9 = targetObject.AddComponent(); val9.sharedMesh = GetSafeColliderMesh(val4); val9.convex = val4.convex; val9.cookingOptions = val4.cookingOptions; return (Collider)(object)val9; } CapsuleCollider val10 = targetObject.AddComponent(); val10.center = val3.center; val10.radius = val3.radius; val10.height = val3.height; val10.direction = val3.direction; return (Collider)(object)val10; } SphereCollider val11 = targetObject.AddComponent(); val11.center = val2.center; val11.radius = val2.radius; return (Collider)(object)val11; } BoxCollider val12 = targetObject.AddComponent(); val12.center = val.center; val12.size = val.size; return (Collider)(object)val12; } private Mesh GetSafeColliderMesh(MeshCollider source) { if ((Object)(object)source == (Object)null) { return null; } Mesh sharedMesh = source.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { return null; } if (!IsBadStaticSceneMesh(sharedMesh)) { return sharedMesh; } MeshFilter component = ((Component)source).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) { return component.sharedMesh; } return sharedMesh; } private string GetPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return "null"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private string Fmt(Vector3 value) { //IL_0006: 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_001c: Unknown result type (might be due to invalid IL or missing references) return $"({value.x:F3}, {value.y:F3}, {value.z:F3})"; } private bool SafeIsReadable(Mesh mesh) { if ((Object)(object)mesh == (Object)null) { return false; } try { return mesh.isReadable; } catch { return false; } } private int SafeVertexCount(Mesh mesh) { if ((Object)(object)mesh == (Object)null) { return -1; } try { return mesh.vertexCount; } catch { return -1; } } } } namespace PropHunt.Patches { public class CustomTimerPatches { [HarmonyPatch(typeof(TeeOffCountdown), "Hide")] [HarmonyPostfix] public static void Hide_Postfix(TeeOffCountdown __instance) { if (!MatchSetupRules.GetValueAsBool((Rule)2) && ConfigurationHandler.Instance.IsRoundTimerActivated) { CustomRoundTimer customRoundTimer = ((Component)SingletonBehaviour.Instance).gameObject.AddComponent(); } } } public class HittablePatches { [HarmonyPatch(typeof(Hittable), "HitWithItem")] [HarmonyPostfix] public static void HitWithItem_Postfix(Hittable __instance, ItemType itemType, ItemUseId itemUseId, Vector3 hitLocalPosition, Vector3 direction, Vector3 localOrigin, float distance, PlayerInventory itemUser, bool isReflected, bool isInSpecialState, bool canHitWithNoUser) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)"HitWithItem_Postfix"); HandleHunterShot(__instance, itemType, itemUser, isReflected); } [HarmonyPostfix] [HarmonyPatch(typeof(Hittable), "UserCode_CmdHitWithItem__ItemType__ItemUseId__Vector3__Vector3__Vector3__Single__PlayerInventory__Boolean__Boolean__Boolean__NetworkConnectionToClient")] private static void UserCode_CmdHitWithItem_Postfix(Hittable __instance, ItemType itemType, ItemUseId itemUseId, Vector3 hitLocalPosition, Vector3 direction, Vector3 localOrigin, float distance, PlayerInventory itemUser, bool isReflected, bool isInSpecialState, bool canHitWithNoUser, NetworkConnectionToClient sender) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)"UserCode_CmdHitWithItem_Postfix"); if (NetworkServer.active) { HandleHunterShot(__instance, itemType, itemUser, isReflected); } } private static void HandleHunterShot(Hittable hittable, ItemType itemType, PlayerInventory itemUser, bool isReflected) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Invalid comparison between Unknown and I4 if ((Object)(object)hittable == (Object)null || (Object)(object)itemUser == (Object)null || (Object)(object)itemUser.PlayerInfo == (Object)null) { return; } PlayerInfo playerInfo = itemUser.PlayerInfo; if (TeamManager.Instance.EnsurePlayerTeam(playerInfo).teamId == PropHuntGamemode.HUNTER_TEAM && !isReflected && ((int)itemType == 2 || (int)itemType == 3 || (int)itemType == 7 || (int)itemType == 10)) { PlayerInfo val = ((Component)hittable).gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)hittable).gameObject.GetComponentInParent(); } if (!((Object)(object)val == (Object)null)) { Plugin.Log.LogInfo((object)("[PropHunt] Server saw hunter shot. target='" + ((Object)val).name + "', attacker='" + ((Object)playerInfo).name + "'")); Events.InvokeOnShotByHunter(val, playerInfo); } } } } public class HoleProgressBarUIPatches { [HarmonyPatch(typeof(HoleProgressBarUi), "Awake")] [HarmonyPrefix] public static bool Awake_Prefix(HoleProgressBarUi __instance) { ((Component)((Component)__instance).transform).gameObject.SetActive(false); return false; } [HarmonyPatch(typeof(HoleProgressBarUi), "Start")] [HarmonyPrefix] public static bool Start_Prefix(HoleProgressBarUi __instance) { ((Component)((Component)__instance).transform).gameObject.SetActive(false); return false; } } public class InfoFeedPatches { [HarmonyPatch(typeof(InfoFeed), "ShowKnockoutMessage")] [HarmonyPrefix] public static bool StartOrCancelMatch_Prefix(PlayerInfo responsiblePlayer, PlayerInfo knockedOutPlayer, KnockoutType knockoutType) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Invalid comparison between Unknown and I4 if ((Object)(object)responsiblePlayer == (Object)null || (Object)(object)knockedOutPlayer == (Object)null) { return true; } PlayerTeam val = TeamManager.Instance.EnsurePlayerTeam(responsiblePlayer); PlayerTeam val2 = TeamManager.Instance.EnsurePlayerTeam(knockedOutPlayer); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return true; } if (val.teamId == PropHuntGamemode.HUNTER_TEAM && val2.teamId == PropHuntGamemode.PROP_TEAM) { return (int)knockoutType > 0; } return true; } [HarmonyPatch(typeof(InfoFeed), "ColorizePlayerName")] [HarmonyPrefix] public static bool ColorizePlayerName_Prefix(string playerName, Color playerColor, ref string __result) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (TryGetTeamColorForPlayerName(playerName, out var color)) { __result = "" + playerName + ""; return false; } __result = "" + playerName + ""; return false; } private static bool TryGetTeamColorForPlayerName(string playerName, out Color color) { //IL_0002: 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_00c8: Unknown result type (might be due to invalid IL or missing references) color = default(Color); if (string.IsNullOrEmpty(playerName)) { return false; } if ((Object)(object)TeamManager.Instance == (Object)null) { return false; } foreach (PlayerTeam player in TeamManager.Instance.Players) { if ((Object)(object)player == (Object)null) { continue; } ulong guid = player.playerInfo.PlayerId.Guid; if (CourseManager.GetPlayerName(guid) != playerName) { continue; } PlayerTeam val = TeamManager.Instance.EnsurePlayerTeam(player.playerInfo); if ((Object)(object)val == (Object)null) { return false; } color = TeamManager.Instance.Teams[val.teamId].Color; return true; } return false; } } public class NameTagUiPatches { [HarmonyPatch(typeof(NameTagUi), "LateUpdate")] [HarmonyPostfix] public static void LateUpdate_Postfix(NameTagUi __instance) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)SingletonNetworkBehaviour.Instance != (Object)null && SingletonNetworkBehaviour.Instance.currentHoleCourseIndex == -1) { ((Graphic)__instance.tag).color = Color.white; } if (!((Behaviour)__instance.tag).enabled) { ((Behaviour)__instance.tag).enabled = true; } if ((Object)(object)TeamManager.Instance == (Object)null || (GameModeUtilities.CurrentGamemodeId != null && !GameModeUtilities.Modes[GameModeUtilities.CurrentGamemodeId].IsTeamBased) || TeamManager.Instance.SavedTeamIdByGuid == null || TeamManager.Instance.SavedTeamIdByGuid.Count == 0 || TeamManager.Instance.Teams == null || TeamManager.Instance.Teams.Count == 0) { return; } PlayerInfo playerInfo = __instance.playerInfo; if (!((Object)(object)playerInfo == (Object)null) && !((NetworkBehaviour)playerInfo).isLocalPlayer) { int num = TeamManager.Instance.SavedTeamIdByGuid[playerInfo.PlayerId.guid]; if (TeamManager.Instance.LocalPlayerTeam.teamId == PropHuntGamemode.HUNTER_TEAM && num == PropHuntGamemode.PROP_TEAM) { ((Behaviour)__instance.tag).enabled = false; } } } } public class PlayerGolferPatches { [HarmonyPatch(typeof(PlayerGolfer), "InformScored")] [HarmonyPrefix] public static void InformScored_Prefix(PlayerGolfer __instance) { } } public class PlayerInventoryPatches { [HarmonyPatch(typeof(PlayerInventory), "DecrementUseFromSlotAt")] [HarmonyPrefix] public static bool DecrementUseFromSlotAt_Prefix(PlayerInventory __instance, int index) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (TeamManager.Instance.LocalPlayerTeam.teamId != PropHuntGamemode.HUNTER_TEAM) { return true; } InventorySlot effectiveSlot = __instance.GetEffectiveSlot(index); if (((object)(ItemType)(ref effectiveSlot.itemType)).Equals((object)(ItemType)2)) { return false; } return true; } } public class ScoreboardPatches { [HarmonyPatch(typeof(Scoreboard), "Show")] [HarmonyPostfix] public static void Show_Postfix(Scoreboard __instance) { PropHuntUI.HideAllCurrentRoundUi(); } [HarmonyPatch(typeof(Scoreboard), "Hide")] [HarmonyPostfix] public static void Hide_Postfix(Scoreboard __instance) { PropHuntUI.ShowAllCurrentRoundUi(); } [HarmonyPatch(typeof(Scoreboard), "OnCourseManagerForceDisplayScoreboardChanged")] [HarmonyPostfix] public static void OnCourseManagerForceDisplayScoreboardChanged_Postfix(Scoreboard __instance) { if (__instance.isVisible) { PropHuntUI.HideAllCurrentRoundUi(); } } } public class TeeOffCountdownPatches { private static int _lastHoleIndex = -1; [HarmonyPatch(typeof(TeeOffCountdown), "ApplyVisibility")] [HarmonyPrefix] public static void Show_Prefix(TeeOffCountdown __instance) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if (!NetworkServer.active || (int)CourseManager.MatchState != 2) { return; } Plugin.Log.LogInfo((object)"Shark spawn server"); if (!((Object)(object)TeamManager.Instance == (Object)null) && !((Object)(object)SingletonNetworkBehaviour.Instance == (Object)null) && SingletonNetworkBehaviour.Instance.allCheckpoints != null && SingletonNetworkBehaviour.Instance.allCheckpoints.Count != 0 && GolfHoleManager.HasMaxReferenceDistance) { var list = (from x in SingletonNetworkBehaviour.Instance.allCheckpoints.Where((Checkpoint checkpoint) => (Object)(object)checkpoint != (Object)null).Select(delegate(Checkpoint checkpoint) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)checkpoint).transform.position; Vector3 val5 = position - ((Component)GolfHoleManager.MainHole).transform.position; float progress = 1f - BMath.Clamp01(((Vector3)(ref val5)).magnitude / GolfHoleManager.MaxReferenceDistance); return new { Checkpoint = checkpoint, Progress = progress }; }) orderby x.Progress descending select x).ToList(); int val = Math.Max(1, (int)Math.Floor((float)list.Count / 2f)); TeamData val2 = TeamManager.Instance.Teams[PropHuntGamemode.HUNTER_TEAM]; HashSet members = val2.Members; List list2 = (from shark in members where (Object)(object)shark != (Object)null && (Object)(object)shark.playerInfo != (Object)null orderby shark.playerInfo.PlayerId.guid select shark).ToList(); Random random = new Random(); for (int num = list2.Count - 1; num > 0; num--) { int num2 = random.Next(num + 1); List list3 = list2; int index = num; int index2 = num2; PlayerTeam value = list2[num2]; PlayerTeam value2 = list2[num]; list3[index] = value; list2[index2] = value2; } int val3 = Math.Min(val, list2.Count); val3 = Math.Max(1, val3); for (int i = 0; i < list2.Count; i++) { PlayerTeam val4 = list2[i]; int num3 = i % val3; Checkpoint checkpoint2 = list[num3].Checkpoint; CheckpointManager.TryActivate(checkpoint2, val4.playerInfo); Plugin.Log.LogInfo((object)$"Shark spawn server assigned {val4.playerInfo.PlayerId.guid} to checkpoint {num3}"); } Plugin.Log.LogInfo((object)"Shark spawn server done"); } } [HarmonyPatch(typeof(TeeOffCountdown), "ApplyVisibility")] [HarmonyPostfix] public static void Show_Postfix(TeeOffCountdown __instance) { if ((Object)(object)PropManager.Instance != (Object)null) { PropManager.Instance.SetInitialPropRoster(); } if (NetworkClient.active) { int currentHoleCourseIndex = CourseManager.CurrentHoleCourseIndex; if (currentHoleCourseIndex != _lastHoleIndex && !((Object)(object)TeamManager.Instance == (Object)null) && !((Object)(object)TeamManager.Instance.LocalPlayerTeam == (Object)null) && !((Object)(object)GameManager.LocalPlayerInfo == (Object)null) && TeamManager.Instance.LocalPlayerTeam.teamId == PropHuntGamemode.HUNTER_TEAM) { GameManager.LocalPlayerInfo.Movement.TryBeginRespawn(false, (RespawnTarget)0); _lastHoleIndex = currentHoleCourseIndex; Plugin.Log.LogInfo((object)"Shark spawn client respawned local shark"); } } } } public class VFXManagerPatches { [HarmonyPatch(typeof(VfxManager), "PlayDuelingPistolHitForAllClients")] [HarmonyPrefix] public static void PlayDuelingPistolHitForAllClients_Prefix(PlayerInventory shootingPlayer, GunShotHitVfxData hitData) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shootingPlayer == (Object)null) { return; } PlayerInfo playerInfo = shootingPlayer.PlayerInfo; string text = (((Object)(object)playerInfo != (Object)null) ? playerInfo.PlayerId.guid.ToString() : "unknown"); Vector3 hitPoint = ((GunShotHitVfxData)(ref hitData)).GetHitPoint(); Hittable val = FindClosestHittableToPoint(hitPoint, 0.35f); if ((Object)(object)val != (Object)null) { Plugin.Log.LogInfo((object)("Dueling pistol hit hittable. Shooter=" + text + ", Hittable=" + ((Object)val).name + ", Object=" + ((Object)((Component)val).gameObject).name + ", Layer=" + LayerMask.LayerToName(((Component)val).gameObject.layer) + ", " + $"Point={hitPoint}")); return; } Collider val2 = FindClosestColliderToPoint(hitPoint, 0.35f); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogInfo((object)($"Dueling pistol hit non-hittable at {hitPoint}, but no nearby collider was found. " + "Shooter=" + text)); return; } GameObject gameObject = ((Component)val2).gameObject; Plugin.Log.LogInfo((object)("Dueling pistol hit non-hittable. Shooter=" + text + ", Object=" + ((Object)gameObject).name + ", Layer=" + LayerMask.LayerToName(gameObject.layer) + ", Collider=" + ((object)val2).GetType().Name + ", " + $"Point={hitPoint}")); if (LayerMask.LayerToName(gameObject.layer).ToLower().Equals("environment") || LayerMask.LayerToName(gameObject.layer).ToLower().Equals("foliage")) { PropHuntPlayer component = ((Component)playerInfo).GetComponent(); component.ApplyIncorrectShotHealthPenalty(); } } private static Collider FindClosestColliderToPoint(Vector3 point, float radius) { //IL_0001: 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) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(point, radius, -1, (QueryTriggerInteraction)1); Collider result = null; float num = float.MaxValue; Collider[] array2 = array; foreach (Collider val in array2) { if (!((Object)(object)val == (Object)null)) { float num2 = Vector3.Distance(val.ClosestPoint(point), point); if (!(num2 >= num)) { num = num2; result = val; } } } return result; } private static Hittable FindClosestHittableToPoint(Vector3 point, float radius) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(point, radius, -1, (QueryTriggerInteraction)1); Hittable result = null; float num = float.MaxValue; Collider[] array2 = array; foreach (Collider val in array2) { if ((Object)(object)val == (Object)null) { continue; } Hittable componentInParent = ((Component)val).GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null)) { float num2 = Vector3.Distance(val.ClosestPoint(point), point); if (!(num2 >= num)) { num = num2; result = componentInParent; } } } return result; } } } namespace PropHunt.Configuration { public class ConfigurationHandler { private ConfigFile _config; private BepInExConfigSync _bepInExConfigSync; private ConfigEntry ConfigRoundTimerActivated; private ConfigEntry ConfigRoundTimerLengthInSeconds; private ConfigEntry ConfigPropHeatUpdateIntervalInSeconds; private ConfigEntry ConfigPropHeatActivationPercent; private ConfigEntry ConfigHunterBlackoutDurationInSeconds; private ConfigEntry ConfigIncorrectShotHealthPenalty; private ConfigEntry ConfigMaxNumberOfDecoysCanPlace; private ConfigEntry ConfigMaxNumberOfDisguisesTaken; public static ConfigurationHandler Instance { get; private set; } public bool IsRoundTimerActivated => ConfigRoundTimerActivated.Value; public int RoundTimerLengthInSeconds => ConfigRoundTimerLengthInSeconds.Value; public int PropHeatUpdateIntervalInSeconds => ConfigPropHeatUpdateIntervalInSeconds.Value; public int PropHeatActivationPercent => ConfigPropHeatActivationPercent.Value; public int HunterBlackoutDurationInSeconds => ConfigHunterBlackoutDurationInSeconds.Value; public int IncorrectShotHealthPenalty => ConfigIncorrectShotHealthPenalty.Value; public int MaxNumberOfDecoysCanPlace => ConfigMaxNumberOfDecoysCanPlace.Value; public int MaxNumberOfDisguisesTaken => ConfigMaxNumberOfDisguisesTaken.Value; public event Action ConfigChanged; public ConfigurationHandler(ConfigFile configFile) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown Instance = this; _config = configFile; Plugin.Log.LogInfo((object)$"ConfigurationHandler initialising {configFile}"); BindCustomTimerConfigurations(); BindHunterHintConfigurations(); BindHunterHealthConfigurations(); BindPropConfigurations(); _bepInExConfigSync = new BepInExConfigSync(_config, "com.github.glarmer.PropHunt:PropHunt"); _bepInExConfigSync.SyncedValueChanged += delegate { this.ConfigChanged?.Invoke(); }; Plugin.Log.LogInfo((object)"ConfigurationHandler initialised"); } private void BindCustomTimerConfigurations() { ConfigRoundTimerActivated = Bind("Round Timer", "RoundTimerEnabled", defaultValue: true, "Whether or not the round timer is activated", delegate { this.ConfigChanged?.Invoke(); }); ConfigRoundTimerLengthInSeconds = Bind("Round Timer", "RoundTimerLength", 820, "The length in seconds of the round timer", delegate { this.ConfigChanged?.Invoke(); }, (int v) => Math.Clamp(v, 120, 3600)); ConfigHunterBlackoutDurationInSeconds = Bind("Round Timer", "HunterBlackoutDuration", 30, "How long, in seconds, hunters have a black screen and disabled minimap render after spawning", delegate { this.ConfigChanged?.Invoke(); }, (int v) => Math.Clamp(v, 0, ConfigRoundTimerLengthInSeconds.Value)); } private void BindHunterHintConfigurations() { ConfigPropHeatUpdateIntervalInSeconds = Bind("Minimap Hunter Hints", "PropHeatUpdateInterval", 5, "How often, in seconds, the hunter minimap prop heat direction updates", delegate { this.ConfigChanged?.Invoke(); }, (int v) => Math.Clamp(v, 1, 300)); ConfigPropHeatActivationPercent = Bind("Minimap Hunter Hints", "PropHeatActivationPercent", 75, "How far through the round timer, as a percentage, before hunter minimap prop heat appears", delegate { this.ConfigChanged?.Invoke(); }, (int v) => Math.Clamp(v, 0, 100)); } private void BindHunterHealthConfigurations() { ConfigIncorrectShotHealthPenalty = Bind("Hunter Health", "IncorrectShotHealthPenalty", 10, "How much health a hunter loses when shooting something other than a player", delegate { this.ConfigChanged?.Invoke(); }, (int v) => Math.Clamp(v, 0, 100)); } private void BindPropConfigurations() { ConfigMaxNumberOfDecoysCanPlace = Bind("Prop Configuration", "MaxNumberOfDecoysCanPlace", 3, "Maximum number of decoys each prop can place", delegate { this.ConfigChanged?.Invoke(); }, (int v) => Math.Clamp(v, 0, 1000)); ConfigMaxNumberOfDisguisesTaken = Bind("Prop Configuration", "MaxNumberOfDisguisesTaken", 3, "Maximum number of disguises each prop can take", delegate { this.ConfigChanged?.Invoke(); }, (int v) => Math.Clamp(v, 0, 1000)); } public void SyncConfiguration() { if (NetworkServer.active) { _bepInExConfigSync.PushHostConfigToScope(); } else if (NetworkClient.active) { _bepInExConfigSync.RequestFromHost(); } } private ConfigEntry Bind(string section, string key, T defaultValue, string description, Action onChanged = null, Func clamp = null) { Func clamp2 = clamp; Action onChanged2 = onChanged; ConfigEntry entry = _config.Bind(section, key, defaultValue, description); if (clamp2 != null) { entry.Value = clamp2(entry.Value); } Plugin.Log.LogInfo((object)$"{key} set to: {entry.Value}"); if (onChanged2 != null) { entry.SettingChanged += delegate { if (clamp2 != null) { T val = clamp2(entry.Value); if (!object.Equals(entry.Value, val)) { entry.Value = val; return; } } onChanged2(); }; } return entry; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ConstantExpectedAttribute : Attribute { public object? Min { get; set; } public object? Max { get; set; } } [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ExperimentalAttribute : Attribute { public string DiagnosticId { get; } public string? UrlFormat { get; set; } public ExperimentalAttribute(string diagnosticId) { DiagnosticId = diagnosticId; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SetsRequiredMembersAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class StringSyntaxAttribute : Attribute { public const string CompositeFormat = "CompositeFormat"; public const string DateOnlyFormat = "DateOnlyFormat"; public const string DateTimeFormat = "DateTimeFormat"; public const string EnumFormat = "EnumFormat"; public const string GuidFormat = "GuidFormat"; public const string Json = "Json"; public const string NumericFormat = "NumericFormat"; public const string Regex = "Regex"; public const string TimeOnlyFormat = "TimeOnlyFormat"; public const string TimeSpanFormat = "TimeSpanFormat"; public const string Uri = "Uri"; public const string Xml = "Xml"; public string Syntax { get; } public object?[] Arguments { get; } public StringSyntaxAttribute(string syntax) { Syntax = syntax; Arguments = new object[0]; } public StringSyntaxAttribute(string syntax, params object?[] arguments) { Syntax = syntax; Arguments = arguments; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class UnscopedRefAttribute : Attribute { } } namespace System.Runtime.Versioning { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiresPreviewFeaturesAttribute : Attribute { public string? Message { get; } public string? Url { get; set; } public RequiresPreviewFeaturesAttribute() { } public RequiresPreviewFeaturesAttribute(string? message) { Message = message; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CollectionBuilderAttribute : Attribute { public Type BuilderType { get; } public string MethodName { get; } public CollectionBuilderAttribute(Type builderType, string methodName) { BuilderType = builderType; MethodName = methodName; } } [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class CompilerFeatureRequiredAttribute : Attribute { public const string RefStructs = "RefStructs"; public const string RequiredMembers = "RequiredMembers"; public string FeatureName { get; } public bool IsOptional { get; set; } public CompilerFeatureRequiredAttribute(string featureName) { FeatureName = featureName; } } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute { public string[] Arguments { get; } public InterpolatedStringHandlerArgumentAttribute(string argument) { Arguments = new string[1] { argument }; } public InterpolatedStringHandlerArgumentAttribute(params string[] arguments) { Arguments = arguments; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class InterpolatedStringHandlerAttribute : Attribute { } [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] internal static class IsExternalInit { } [AttributeUsage(AttributeTargets.Method, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class ModuleInitializerAttribute : Attribute { } [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class OverloadResolutionPriorityAttribute : Attribute { public int Priority { get; } public OverloadResolutionPriorityAttribute(int priority) { Priority = priority; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)] [ExcludeFromCodeCoverage] internal sealed class ParamCollectionAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class RequiredMemberAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] [EditorBrowsable(EditorBrowsableState.Never)] [ExcludeFromCodeCoverage] internal sealed class RequiresLocationAttribute : Attribute { } [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)] [ExcludeFromCodeCoverage] internal sealed class SkipLocalsInitAttribute : Attribute { } }