using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using DooDesch.Transition; using DooDesch.UI; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.Audio; using Il2CppScheduleOne.AvatarFramework; using Il2CppScheduleOne.Building; using Il2CppScheduleOne.Building.Doors; using Il2CppScheduleOne.Combat; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Doors; using Il2CppScheduleOne.Dragging; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.FX; using Il2CppScheduleOne.GameTime; using Il2CppScheduleOne.Interaction; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Map; using Il2CppScheduleOne.Misc; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.PlayerScripts.Health; using Il2CppScheduleOne.Police; using Il2CppScheduleOne.Property; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.Tiles; using Il2CppScheduleOne.Trash; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.Phone; using Il2CppScheduleOne.Vehicles; using Il2CppSteamworks; using Il2CppSystem.Collections.Generic; using Il2CppTMPro; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using PropHunt; using PropHunt.Catch; using PropHunt.Config; using PropHunt.Disguise; using PropHunt.Game; using PropHunt.Music; using PropHunt.Net; using PropHunt.Patches; using PropHunt.Phone; using PropHunt.PlayArea; using PropHunt.Quests; using PropHunt.Taunt; using PropHunt.UI; using PropHunt.UI.Hud; using PropHunt.View; using S1API.AssetBundles; using S1API.Internal.Abstraction; using S1API.PhoneApp; using S1API.Quests; using S1API.Quests.Constants; using S1API.UI; using SideHustle; using SideHustle.Multiplayer; using SteamNetworkLib; using SteamNetworkLib.Exceptions; using SteamNetworkLib.Models; using SteamNetworkLib.Sync; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Core), "PropHunt", "1.1.0", "DooDesch", "https://github.com/DooDesch-Mods/ScheduleOne-PropHunt")] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonOptionalDependencies(new string[] { "SideHustle" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("PropHunt")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+d3b289cb3c93d4a580f26229dac8c050be859ded")] [assembly: AssemblyProduct("PropHunt")] [assembly: AssemblyTitle("PropHunt")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DooDesch.Transition { internal static class Veil { internal static class Ease { public static float In(float t) { t = Mathf.Clamp01(t); return t * t * t; } public static float Out(float t) { t = Mathf.Clamp01(t); float num = 1f - t; return 1f - num * num * num; } public static float InOut(float t) { t = Mathf.Clamp01(t); return t * t * (3f - 2f * t); } } internal static bool EyelidsAvailable { get { try { return Singleton.InstanceExists; } catch { return false; } } } internal static bool BlackAvailable { get { try { return Singleton.InstanceExists || Singleton.InstanceExists; } catch { return false; } } } private static EyelidOverlay Eyes() { try { return Singleton.InstanceExists ? Singleton.Instance : null; } catch { return null; } } internal static void SetEyelids(float openness) { EyelidOverlay val = Eyes(); if ((Object)(object)val == (Object)null) { return; } try { val.AutoUpdate = false; val.SetOpen(Mathf.Clamp01(openness)); } catch { } } internal static float CurrentEyelidOpen(float fallback = 1f) { EyelidOverlay val = Eyes(); if ((Object)(object)val == (Object)null) { return fallback; } try { return val.CurrentOpen; } catch { return fallback; } } internal static void ReleaseEyelids() { EyelidOverlay val = Eyes(); if ((Object)(object)val == (Object)null) { return; } try { val.AutoUpdate = true; } catch { } } internal static float EyelidTargetOpen() { try { Player local = Player.Local; if ((Object)(object)local != (Object)null && (Object)(object)local.Energy != (Object)null) { float currentEnergy = local.Energy.CurrentEnergy; return (currentEnergy < 20f) ? Mathf.Lerp(0.625f, 1f, currentEnergy / 20f) : 1f; } } catch { } return 1f; } internal static IEnumerator CloseEyelids(float dur) { float start = CurrentEyelidOpen(); if (dur <= 0f) { SetEyelids(0f); yield break; } for (float t = 0f; t < dur; t += Time.deltaTime) { SetEyelids(Mathf.Lerp(start, 0f, Ease.InOut(t / dur))); yield return null; } SetEyelids(0f); } internal static IEnumerator OpenEyelidsToTarget(float dur) { float target = EyelidTargetOpen(); if (dur <= 0f) { SetEyelids(target); ReleaseEyelids(); yield break; } for (float t = 0f; t < dur; t += Time.deltaTime) { SetEyelids(Mathf.Lerp(0f, target, Ease.Out(t / dur))); yield return null; } SetEyelids(target); ReleaseEyelids(); } internal static IEnumerator FadeEyelids(float target, float dur, bool releaseToGame) { if ((Object)(object)Eyes() == (Object)null) { yield break; } float start = CurrentEyelidOpen(target); if (dur > 0f) { for (float t = 0f; t < dur; t += Time.deltaTime) { SetEyelids(Mathf.Lerp(start, target, Ease.InOut(t / dur))); yield return null; } } SetEyelids(target); if (releaseToGame) { ReleaseEyelids(); } } internal static void BlackOpen(float t) { Black(toBlack: true, t); } internal static void BlackClose(float t) { Black(toBlack: false, t); } private static void Black(bool toBlack, float t) { try { if (Singleton.InstanceExists) { BlackOverlay instance = Singleton.Instance; if (toBlack) { instance.Open(t); } else { instance.Close(t); } } else if (Singleton.InstanceExists) { Singleton.Instance.SetBlackOverlayVisible(toBlack, t); } } catch (Exception ex) { ScreenTransition.Warn?.Invoke("Veil.Black failed: " + ex.Message); } } internal static void SetCanMove(bool canMove) { try { PlayerMovement instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.CanMove = canMove; } } catch { } } internal static void SetCanLook(bool canLook) { try { PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(canLook); } } catch { } } } internal enum VeilMode { Eyelids, Black, EyelidsAndBlack } internal struct TransitionRequest { public VeilMode Mechanism; public float CloseSeconds; public float OpenSeconds; public float HoldSeconds; public bool LockMovement; public bool LockCamera; public Action DuringBlack; public Action OnMidHold; public Action OnDone; public Func WaitUntilReady; public float WaitDeadlineSeconds; public Action WhileWaiting; public Func KeepClosedAfter; public string Key; } internal static class ScreenTransition { public static Action Warn = delegate(string msg) { try { MelonLogger.Warning(msg); } catch { } }; private static readonly HashSet Active = new HashSet(); public static bool IsRunning(string key) { return Active.Contains(Bucket(key)); } public static bool Play(TransitionRequest req) { string text = Bucket(req.Key); if (Active.Contains(text)) { return false; } bool flag = req.Mechanism == VeilMode.Eyelids || req.Mechanism == VeilMode.EyelidsAndBlack; bool flag2 = req.Mechanism == VeilMode.Black || req.Mechanism == VeilMode.EyelidsAndBlack; if ((!flag || !Veil.EyelidsAvailable) && (!flag2 || !Veil.BlackAvailable)) { Safe(req.DuringBlack); Safe(req.OnDone); return true; } Active.Add(text); try { MelonCoroutines.Start(Run(req, text, flag, flag2)); } catch (Exception ex) { Warn?.Invoke("ScreenTransition.Play start failed: " + ex.Message); Active.Remove(text); Safe(req.DuringBlack); Safe(req.OnDone); } return true; } public static void ForceReset(string key = null) { if (key == null) { Active.Clear(); } else { Active.Remove(Bucket(key)); } try { Veil.BlackClose(0f); Veil.SetEyelids(1f); Veil.ReleaseEyelids(); Veil.SetCanMove(canMove: true); Veil.SetCanLook(canLook: true); } catch (Exception ex) { Warn?.Invoke("ScreenTransition.ForceReset failed: " + ex.Message); } } private static IEnumerator Run(TransitionRequest req, string key, bool eye, bool black) { bool lockedMove = false; bool lockedLook = false; try { if (req.LockMovement) { Veil.SetCanMove(canMove: false); lockedMove = true; } if (req.LockCamera) { Veil.SetCanLook(canLook: false); lockedLook = true; } if (black) { Veil.BlackOpen(req.CloseSeconds); } if (eye) { yield return Veil.CloseEyelids(req.CloseSeconds); } else { yield return Wait(req.CloseSeconds); } Safe(req.DuringBlack); yield return null; yield return null; if (req.WaitUntilReady != null) { float deadline = Time.time + Mathf.Max(0f, req.WaitDeadlineSeconds); while (Time.time < deadline && !SafeReady(req.WaitUntilReady)) { Safe(req.WhileWaiting); yield return null; } Safe(req.WhileWaiting); } if (req.HoldSeconds > 0f) { float deadline = req.HoldSeconds * 0.5f; yield return Wait(deadline); Safe(req.OnMidHold); yield return Wait(req.HoldSeconds - deadline); } else { Safe(req.OnMidHold); } if (req.KeepClosedAfter == null || !SafeReady(req.KeepClosedAfter)) { if (black) { Veil.BlackClose(req.OpenSeconds); } if (eye) { yield return Veil.OpenEyelidsToTarget(req.OpenSeconds); } else { yield return Wait(req.OpenSeconds); } } Safe(req.OnDone); } finally { bool flag = req.KeepClosedAfter != null && SafeReady(req.KeepClosedAfter); if (eye) { if (flag) { Veil.SetEyelids(0f); } else { Veil.SetEyelids(Veil.EyelidTargetOpen()); Veil.ReleaseEyelids(); } } if (black && !flag) { Veil.BlackClose(0.25f); } if (lockedMove) { Veil.SetCanMove(canMove: true); } if (lockedLook) { Veil.SetCanLook(canLook: true); } Active.Remove(key); } } private static string Bucket(string key) { if (!string.IsNullOrEmpty(key)) { return key; } return "default"; } private static IEnumerator Wait(float sec) { if (!(sec <= 0f)) { for (float t = 0f; t < sec; t += Time.deltaTime) { yield return null; } } } private static bool SafeReady(Func f) { try { return f(); } catch { return false; } } private static void Safe(Action a) { if (a == null) { return; } try { a(); } catch (Exception ex) { Warn?.Invoke("ScreenTransition callback failed: " + ex.Message); } } } } namespace PropHunt { public sealed class Core : MelonMod { private static LaunchContext _session; private static GamemodeDescriptor _descriptor; private static GameModeController _controller; private static bool _patched; public static Core Instance { get; private set; } public static Instance Log { get; private set; } internal static GameModeController Session => _controller; [Conditional("DEBUG")] public static void LogDebug(string msg) { Instance log = Log; if (log != null) { log.Msg(msg); } } public override void OnInitializeMelon() { Instance = this; Log = ((MelonBase)this).LoggerInstance; PropHuntPreferences.Initialize(); RegisterWithSideHustle(); Log.Msg($"PropHunt initialized. Enabled={PropHuntPreferences.Enabled}"); } private static void RegisterWithSideHustle() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0034: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown try { GamemodeDescriptor val = new GamemodeDescriptor(); val.Id = "doodesch.prophunt"; val.DisplayName = "PropHunt"; val.Description = "Hiders disguise as props; hunters find them before the timer runs out."; val.Author = "DooDesch"; val.Support = (GamemodeSupport)1; val.Surface = (GamemodeSurface)1; val.OnHostMultiplayer = OnHostMultiplayer; val.OnJoinMultiplayer = OnJoinMultiplayer; val.OnExitToHub = OnExitToHub; val.HostSettings = PropHuntSettingsSpec.Build(); val.Presets = RoundPresets.Build(); val.BlockVanillaQuests = true; val.AllowedQuestTitles = new string[1] { "PropHunt" }; val.SkipIntro = true; val.ForceNewGame = true; val.BlockSaveDuringSession = true; val.SuppressNpcCombatReactions = true; val.DisableVanillaPlayerDeath = true; val.DefaultRequiredModsOnly = true; ModPolicy val2 = new ModPolicy(); val2.AllowedMods = new string[3] { "Snitch", "Inkorporated", "Inkubator" }; val.Policy = val2; _descriptor = val; API.Register(_descriptor); Log.Msg("[PropHunt] registered with Side Hustle."); } catch (Exception ex) { Log.Warning("[PropHunt] Side Hustle not available; cannot register as a gamemode: " + ex.Message); } } private static void OnHostMultiplayer(LaunchContext ctx) { _session = ctx; Log.Msg($"[PropHunt] hosting via Side Hustle (lobby {ctx.LobbyId}, {ctx.PlayerCount} player(s))."); try { MultiplayerInfo multiplayer = ctx.Multiplayer; if (multiplayer != null && !string.IsNullOrEmpty(multiplayer.Mode) && multiplayer.Mode.StartsWith("Custom - ") && !string.IsNullOrEmpty(multiplayer.ConfigBlob)) { PropHuntPreferences.SaveCustomPreset(multiplayer.ConfigBlob, multiplayer.Mode.Substring("Custom - ".Length)); if (_descriptor != null) { _descriptor.Presets = RoundPresets.Build(); } } } catch (Exception ex) { Log.Warning("[PropHunt] save custom preset failed: " + ex.Message); } PropHuntNet.Initialize(); _controller?.Dispose(); _controller = new GameModeController(ctx, isHost: true); _controller.StartAsHost(); } private static void OnJoinMultiplayer(LaunchContext ctx) { _session = ctx; Log.Msg($"[PropHunt] joined via Side Hustle (lobby {ctx.LobbyId}, host {ctx.HostName ?? "?"})."); PropHuntNet.Initialize(); _controller?.Dispose(); _controller = new GameModeController(ctx, isHost: false); _controller.StartAsClient(); } private static void OnExitToHub(LaunchContext ctx) { Log.Msg("[PropHunt] session ended; tearing down."); HudController.Teardown(); _controller?.Dispose(); _controller = null; _session = null; } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { if (sceneName == "Main" && !_patched) { _patched = true; bool flag = false; try { using IEnumerator enumerator = ((MelonBase)this).HarmonyInstance.GetPatchedMethods().GetEnumerator(); if (enumerator.MoveNext()) { _ = enumerator.Current; flag = true; } } catch { } try { if (flag) { Log.Msg("[PropHunt] gameplay patches already applied; skipping PatchAll."); } else { ((MelonBase)this).HarmonyInstance.PatchAll(); Log.Msg("[PropHunt] PatchAll completed."); } } catch (Exception ex) { Log.Error("[PropHunt] PatchAll FAILED (later patches skipped): " + ex); } try { int num = 0; foreach (MethodBase patchedMethod in ((MelonBase)this).HarmonyInstance.GetPatchedMethods()) { _ = patchedMethod; num++; } Log.Msg($"[PropHunt] patched method count: {num}"); } catch { } } if (sceneName == "Menu" || sceneName == "Main") { PropHuntNet.Initialize(); } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (sceneName != "Main") { return; } try { if (WeaponCatalog.RefreshFromRegistry() && _descriptor != null) { _descriptor.HostSettings = PropHuntSettingsSpec.Build(); } } catch (Exception ex) { Log.Warning("[PropHunt] weapon catalog refresh failed: " + ex.Message); } } public override void OnSceneWasUnloaded(int buildIndex, string sceneName) { if (sceneName != "Main") { return; } try { HudController.Teardown(); } catch { } if (_controller != null) { Log.Msg("[PropHunt] left the gameplay scene; tearing down the session."); try { _controller.Dispose(); } catch { } _controller = null; _session = null; } } public override void OnUpdate() { PropHuntNet.Tick(); _controller?.Tick(Time.deltaTime); PropHuntPhoneApp.Instance?.Tick(); HudController.Tick(); } public override void OnLateUpdate() { _controller?.LateTick(); } public override void OnGUI() { if (_controller != null) { _controller.DrawGui(); } } } } namespace PropHunt.View { internal static class BodyCam { private static bool _active; private const float PullBack = 3.6f; private const float Lift = 2.1f; private const float StartLerp = 0.5f; private const float StopLerp = 0.4f; internal static bool Active => _active; internal static void Start() { //IL_002d: 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_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_0043: 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_004b: 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) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_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) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) if (_active) { return; } try { PlayerCamera instance = PlayerSingleton.Instance; Player local = Player.Local; if (!((Object)(object)instance == (Object)null) && !((Object)(object)local == (Object)null)) { Vector3 val = BodyPoint(local); Vector3 val2 = -((Component)local).transform.forward; Vector3 val3 = val + val2 * 3.6f + Vector3.up * 2.1f; Vector3 val4 = val - val3; Quaternion val5 = Quaternion.LookRotation(((Vector3)(ref val4)).normalized, Vector3.up); local.SetVisibleToLocalPlayer(true); instance.blockNextStopTransformOverride = false; instance.OverrideTransform(val3, val5, 0.5f, false); _active = true; } } catch (Exception) { } } internal static void Track(PlayerCamera cam) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!_active || (Object)(object)cam == (Object)null) { return; } try { Player local = Player.Local; if (!((Object)(object)local == (Object)null)) { ((Component)cam).transform.LookAt(BodyPoint(local)); local.SetVisibleToLocalPlayer(true); } } catch { } } internal static void Stop() { if (!_active) { return; } _active = false; try { PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.StopTransformOverride(0.4f, true, true); } } catch (Exception) { } try { Player local = Player.Local; if (local != null) { local.SetVisibleToLocalPlayer(false); } } catch { } } private static Vector3 BodyPoint(Player lp) { //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_0049: 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_004f: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)lp.Avatar != (Object)null && (Object)(object)lp.Avatar.CenterPointTransform != (Object)null) { return lp.Avatar.CenterPointTransform.position; } } catch { } return ((Component)lp).transform.position + Vector3.up; } } internal static class EyeBlink { private const string BlinkKey = "PropHunt.Blink"; private static bool _blindHeld; private const float CloseSeconds = 0.5f; private const float OpenSeconds = 0.65f; private const float BlindCloseSeconds = 0.4f; private const float BlindOpenSeconds = 0.45f; internal static bool Running => ScreenTransition.IsRunning("PropHunt.Blink"); internal static void Teleport(Action onShut) { if (onShut != null) { ScreenTransition.Play(new TransitionRequest { Mechanism = VeilMode.Eyelids, CloseSeconds = 0.5f, OpenSeconds = 0.65f, DuringBlack = onShut, KeepClosedAfter = () => _blindHeld, Key = "PropHunt.Blink" }); } } internal static void Blind() { if (_blindHeld) { return; } _blindHeld = true; if (!Veil.EyelidsAvailable) { return; } try { MelonCoroutines.Start(Veil.FadeEyelids(0f, 0.4f, releaseToGame: false)); } catch { } } internal static void Unblind() { if (!_blindHeld) { return; } _blindHeld = false; if (!Veil.EyelidsAvailable) { return; } try { MelonCoroutines.Start(Veil.FadeEyelids(1f, 0.45f, releaseToGame: true)); } catch { Veil.SetEyelids(1f); Veil.ReleaseEyelids(); } } internal static void ResetState() { _blindHeld = false; ScreenTransition.ForceReset("PropHunt.Blink"); } } internal static class SpectatorCam { internal static bool Active; internal static Transform Target; internal static float Distance = 3.5f; internal static float Height = 1f; } internal sealed class SpectatorController { private readonly GameModeController _ctl; private bool _active; private bool _freecam; private int _cycle; private ulong _targetId; private float _nextRefresh; internal bool Active => _active; internal string HudText { get; private set; } internal SpectatorController(GameModeController ctl) { _ctl = ctl; } internal void Tick() { try { bool flag = ShouldSpectate(); if (flag && !_active) { Enter(); } else if (!flag && _active) { Exit(); return; } if (!_active) { HudText = null; return; } if (Input.GetKeyDown((KeyCode)52)) { ToggleMode(); } if (_freecam) { HudText = "FREECAM [4] follow-cam"; return; } if (Time.time >= _nextRefresh) { _nextRefresh = Time.time + 1f; PlayerRegistry.Refresh(); } EnsureTarget(); if (Input.GetKeyDown((KeyCode)323)) { CycleTarget(); } UpdateFollowCam(); } catch (Exception) { } } internal void ForceExit() { if (_active) { Exit(); } } private bool ShouldSpectate() { RoundPhase phase = _ctl.Phase; if (phase != RoundPhase.Hiding && phase != RoundPhase.Hunting) { return false; } PlayerState playerState = LocalState(); if (playerState == null) { return false; } if (playerState.Role == PlayerRole.Spectator) { return true; } if (playerState.Role == PlayerRole.Hider && playerState.Eliminated) { return true; } return false; } private void Enter() { _active = true; _freecam = false; _targetId = 0uL; SetCanMove(can: false); SetCanLook(can: false); PlayerRegistry.Refresh(); EnsureTarget(); SpectatorCam.Active = true; } private void Exit() { _active = false; SpectatorCam.Active = false; SpectatorCam.Target = null; if (_freecam) { SetFreeCam(on: false); _freecam = false; } SetCanLook(can: true); SetCanMove(can: true); HudText = null; } private void ToggleMode() { _freecam = !_freecam; if (_freecam) { SpectatorCam.Active = false; SetFreeCam(on: true); return; } SetFreeCam(on: false); SetCanMove(can: false); SetCanLook(can: false); SpectatorCam.Active = true; } private void EnsureTarget() { if (_targetId == 0L || !IsAliveOther(_targetId)) { List list = AliveOthers(); _targetId = ((list.Count > 0) ? list[0] : 0); _cycle = 0; } } private void CycleTarget() { List list = AliveOthers(); if (list.Count == 0) { _targetId = 0uL; return; } _cycle = (_cycle + 1) % list.Count; _targetId = list[_cycle]; } private List AliveOthers() { List list = new List(); List list2 = new List(); ulong localId = _ctl.LocalId; foreach (KeyValuePair player in _ctl.State.Players) { PlayerState value = player.Value; if (value.SteamId != localId && !value.Eliminated) { if (value.Role == PlayerRole.Hider) { list.Add(value.SteamId); } else if (value.Role == PlayerRole.Hunter) { list2.Add(value.SteamId); } } } list.Sort(); list2.Sort(); list.AddRange(list2); return list; } private bool IsAliveOther(ulong id) { if (id != _ctl.LocalId && _ctl.State.Players.TryGetValue(id, out var value) && !value.Eliminated) { if (value.Role != PlayerRole.Hider) { return value.Role == PlayerRole.Hunter; } return true; } return false; } private void UpdateFollowCam() { Player val = ((_targetId != 0L) ? PlayerRegistry.Get(_targetId) : null); PlayerState playerState = LocalState(); string text = ((playerState != null && playerState.Role == PlayerRole.Spectator) ? "You join next round. " : "Caught! "); if ((Object)(object)val == (Object)null) { SpectatorCam.Target = null; HudText = text + "Spectating - waiting for a player... [4] freecam"; } else { SpectatorCam.Target = ((Component)val).transform; HudText = text + "Spectating " + SafeName(val) + " [click] next [4] freecam"; } } private PlayerState LocalState() { ulong localId = _ctl.LocalId; if (localId == 0L || !_ctl.State.Players.TryGetValue(localId, out var value)) { return null; } return value; } private static void SetCanMove(bool can) { try { PlayerMovement instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.CanMove = can; } } catch { } } private static void SetCanLook(bool can) { try { PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(can); } } catch { } } private static void SetFreeCam(bool on) { try { PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetFreeCam(on, true); } } catch { } } private static string SafeName(Player p) { try { string playerName = p.PlayerName; return string.IsNullOrEmpty(playerName) ? "a player" : playerName; } catch { return "a player"; } } } internal sealed class ThirdPersonController { private readonly GameModeController _ctl; private bool _on; private bool? _appliedArmsVisible; private ViewmodelAvatar _viewmodel; private float _scrollAccum; private float _zoomVel; private bool Allowed { get { if (_ctl.RoundActive && _ctl.LocalRole != PlayerRole.Hunter) { return !_ctl.LocalSpectating; } return false; } } internal bool IsOn { get { if (_on) { return Allowed; } return false; } } internal ThirdPersonController(GameModeController ctl) { _ctl = ctl; } internal void ForceOff() { _on = false; } internal void ForceOn() { _on = true; } internal void Tick() { try { if (!BodyCam.Active) { if (Input.GetKeyDown((KeyCode)118) && Allowed) { _on = !_on; } bool flag = (ThirdPersonView.Active = _on && Allowed); if (flag) { UpdateCameraForProp(); } SetArmsVisible(!flag); SetOwnBodyVisible(flag && _ctl.LocalPropId < 0); } } catch { } } private void UpdateCameraForProp() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) try { float num = ((_ctl.LocalPropId >= 0) ? PropCatalog.SizeOf(_ctl.LocalPropId) : 0f); if (num > 0f) { ThirdPersonView.BaseDistance = Mathf.Clamp(num * 1.7f + 1f, 1.6f, 9f); ThirdPersonView.Height = Mathf.Clamp(num * 0.4f, 0.2f, 2f); } else { ThirdPersonView.BaseDistance = 2.8f; ThirdPersonView.Height = 0.4f; } _scrollAccum += Input.mouseScrollDelta.y; int num2 = 0; while (Mathf.Abs(_scrollAccum) >= 1f && num2++ < 6) { float num3 = Mathf.Sign(_scrollAccum); ThirdPersonView.ZoomMultiplier = Mathf.Clamp(ThirdPersonView.ZoomMultiplier * Mathf.Pow(1.1f, 0f - num3), 0.55f, 2.5f); _scrollAccum -= num3; } float num4 = Mathf.Clamp(ThirdPersonView.BaseDistance * ThirdPersonView.ZoomMultiplier, 0.5f, 16f); ThirdPersonView.Distance = Mathf.SmoothDamp(ThirdPersonView.Distance, num4, ref _zoomVel, 0.12f); } catch { } } private void SetOwnBodyVisible(bool visible) { try { Player local = Player.Local; if ((Object)(object)local == (Object)null) { return; } local.SetVisibleToLocalPlayer(visible); if (!visible) { return; } try { local.SetThirdPersonMeshesVisibility(true); } catch { } } catch { } } private void SetArmsVisible(bool visible) { if (_appliedArmsVisible == visible) { return; } _appliedArmsVisible = visible; try { if ((Object)(object)_viewmodel == (Object)null) { _viewmodel = Object.FindObjectOfType(); } if ((Object)(object)_viewmodel != (Object)null) { _viewmodel.SetVisibility(visible); } } catch { } } internal void Dispose() { _on = false; ThirdPersonView.Active = false; ThirdPersonView.ZoomMultiplier = 1f; _scrollAccum = 0f; SetArmsVisible(visible: true); SetOwnBodyVisible(visible: false); } } internal static class ThirdPersonView { internal static bool Active; internal static float Distance = 2.8f; internal static float Height = 0.4f; internal static float BaseDistance = 2.8f; internal static float ZoomMultiplier = 1f; internal const float ZoomStepPercent = 0.1f; internal const float ZoomMultiplierMin = 0.55f; internal const float ZoomMultiplierMax = 2.5f; internal const float GlobalMinDistance = 0.5f; internal const float GlobalMaxDistance = 16f; } } namespace PropHunt.UI { internal sealed class Onboarding { private readonly GameModeController _ctl; private RoundPhase _lastPhase; private bool _cardActive; private bool _spawnCaptured; private Vector3 _spawnPos; private float _cardShownAt; private bool _helpOpen; private const float CardMaxSeconds = 45f; private const float LeaveRadius = 8f; internal bool CardActive => _cardActive; internal bool HelpOpen => _helpOpen; internal bool ShowControlsHint { get { if (_ctl.RoundActive) { return !_helpOpen; } return false; } } internal bool LocalIsHunter => _ctl.LocalRole == PlayerRole.Hunter; internal string CardTitle { get { if (!LocalIsHunter) { return "YOU ARE A HIDER"; } return "YOU ARE A HUNTER"; } } internal string CardGoal { get { if (!LocalIsHunter) { return "Disguise as a prop and survive until the hunt timer runs out."; } return "Find and shoot the disguised props before the hunt timer runs out."; } } internal string[] CardKeys { get { if (LocalIsHunter) { return new string[2] { "[" + KeyBinds.Name((KeyCode)323) + "] shoot / catch (big props take more hits)", "You are blinded until the hunt begins." }; } return new string[4] { $"[{KeyBinds.Name((KeyCode)101)}] become what you look at [{KeyBinds.Name((KeyCode)50)}] random prop", $"[{KeyBinds.Name((KeyCode)102)}]+mouse rotate [{KeyBinds.Name((KeyCode)306)}] slow-walk", $"[{KeyBinds.Name((KeyCode)113)}] decoy [{KeyBinds.Name((KeyCode)103)}] stun [{KeyBinds.Name((KeyCode)49)}] taunt (hold = wheel)", $"[{KeyBinds.Name((KeyCode)118)}] third-person [{KeyBinds.Name((KeyCode)98)}] prop markers on/off" }; } } internal string CardFooter => "[" + KeyBinds.Name((KeyCode)104) + "] controls anytime - leave the safehouse when you are ready"; internal string ControlsHintText => "[" + KeyBinds.Name((KeyCode)104) + "] Controls"; internal string[] HelpHider => new string[9] { "[" + KeyBinds.Name((KeyCode)101) + "] become looked-at prop", "[" + KeyBinds.Name((KeyCode)50) + "] random prop", "[" + KeyBinds.Name((KeyCode)102) + "]+mouse rotate facing", "[" + KeyBinds.Name((KeyCode)306) + "] slow-walk", "[" + KeyBinds.Name((KeyCode)113) + "] drop decoy", "[" + KeyBinds.Name((KeyCode)103) + "] concussion (stun hunters)", "[" + KeyBinds.Name((KeyCode)49) + "] taunt (hold = wheel)", "[" + KeyBinds.Name((KeyCode)118) + "] third-person view", "[" + KeyBinds.Name((KeyCode)98) + "] toggle becomable-prop markers (off = blend in)" }; internal string[] HelpHunter => new string[3] { "[" + KeyBinds.Name((KeyCode)323) + "] shoot / catch props", "Props have HP - big props take more hits.", "Blinded during the hide phase." }; internal string[] HelpSpectator => new string[2] { "[" + KeyBinds.Name((KeyCode)52) + "] follow-cam <-> freecam", "[" + KeyBinds.Name((KeyCode)323) + "] next player (follow-cam)" }; internal Onboarding(GameModeController ctl) { _ctl = ctl; } internal void Tick() { try { RoundPhase phase = _ctl.Phase; if (phase == RoundPhase.Hiding && _lastPhase != RoundPhase.Hiding) { PlayerRole localRole = _ctl.LocalRole; if (localRole == PlayerRole.Hider || localRole == PlayerRole.Hunter) { _cardActive = true; _spawnCaptured = false; _cardShownAt = Time.time; } } _lastPhase = phase; if (Input.GetKeyDown((KeyCode)104)) { _helpOpen = !_helpOpen; } if (_cardActive) { UpdateCardDismiss(); } } catch { } } private void UpdateCardDismiss() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (Time.time - _cardShownAt > 45f) { _cardActive = false; return; } RoundPhase phase = _ctl.Phase; if (phase != RoundPhase.Hiding && phase != RoundPhase.Hunting) { _cardActive = false; return; } if (phase == RoundPhase.Hunting) { _cardActive = false; return; } Player local = Player.Local; if ((Object)(object)local == (Object)null) { return; } Vector3 position = ((Component)local).transform.position; if (!_spawnCaptured) { _spawnPos = position; _spawnCaptured = true; return; } float num = position.x - _spawnPos.x; float num2 = position.z - _spawnPos.z; if (num * num + num2 * num2 > 64f) { _cardActive = false; } } internal void Reset() { _cardActive = false; _spawnCaptured = false; _helpOpen = false; _lastPhase = RoundPhase.Lobby; } } } namespace PropHunt.UI.Hud { internal static class HudController { private static HudRoot _root; internal static void Tick() { try { GameModeController active = GameModeController.Active; if (active == null || !InGameplayScene()) { if (_root != null) { Teardown(); } return; } if (_root == null) { _root = new HudRoot(); } _root.Apply(active); } catch { } } private static bool InGameplayScene() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name == "Main"; } catch { return true; } } internal static void ShowHitmarker() { try { _root?.ShowHitmarker(); } catch { } } internal static void Teardown() { try { _root?.Destroy(); } catch { } _root = null; } } internal sealed class HudRoot { private readonly GameObject _go; private readonly Transform _host; private readonly GameObject _statusPill; private readonly Text _status; private readonly HpBar _hp; private readonly HpBar _hunterHp; private readonly Text _hint; private readonly Text _transform; private readonly GameObject _abilityPill; private readonly Text _ability; private readonly GameObject _becomePill; private readonly Text _become; private readonly FlashLabel _flash; private readonly Hitmarker _hitmarker; private readonly GameObject _specPill; private readonly Text _spec; private readonly GameObject _oobPill; private readonly Text _oob; private readonly GameObject _safehousePill; private readonly Text _safehouse; private readonly GameObject _downedPill; private readonly Text _downed; private readonly Scoreboard _scoreboard; private readonly GameObject _cardPanel; private readonly Text _cardTitle; private readonly Text _cardBody; private readonly GameObject _helpPanel; private readonly Text _helpBody; private readonly Text _controlsHint; private string _cStatus; private string _cHint; private string _cTransform; private string _cAbility; private string _cBecome; private string _cSpec; private string _cOob; private string _cDowned; private string _cCardTitle; private string _cCardBody; private string _cHelpBody; private string _cControlsHint; private bool _cCardHunter; private bool _aStatus; private bool _aHp; private bool _aHunterHp; private bool _aHint; private bool _aTransform; private bool _aAbility; private bool _aBecome; private bool _aSpec; private bool _aOob; private bool _aSafehouse; private bool _aDowned; private bool _aCard; private bool _aHelp; private bool _aControlsHint; internal HudRoot() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Expected O, but got Unknown //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_051a: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) //IL_0539: Unknown result type (might be due to invalid IL or missing references) //IL_057f: Unknown result type (might be due to invalid IL or missing references) //IL_05c0: Unknown result type (might be due to invalid IL or missing references) //IL_05ca: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Unknown result type (might be due to invalid IL or missing references) //IL_0625: Unknown result type (might be due to invalid IL or missing references) //IL_0677: Unknown result type (might be due to invalid IL or missing references) //IL_0681: Unknown result type (might be due to invalid IL or missing references) //IL_0696: Unknown result type (might be due to invalid IL or missing references) //IL_06dc: Unknown result type (might be due to invalid IL or missing references) //IL_0729: Unknown result type (might be due to invalid IL or missing references) //IL_077a: Unknown result type (might be due to invalid IL or missing references) //IL_0784: Unknown result type (might be due to invalid IL or missing references) //IL_0799: Unknown result type (might be due to invalid IL or missing references) //IL_07de: Unknown result type (might be due to invalid IL or missing references) //IL_082b: Unknown result type (might be due to invalid IL or missing references) //IL_088a: Unknown result type (might be due to invalid IL or missing references) //IL_0894: Unknown result type (might be due to invalid IL or missing references) _go = new GameObject("PropHunt_Hud"); Object.DontDestroyOnLoad((Object)(object)_go); Canvas obj = _go.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 100; GameObject val = UIFactory.Panel("hud_root", _go.transform, Theme.Clear, (Vector2?)null, (Vector2?)null, true); ((Graphic)val.GetComponent()).raycastTarget = false; _host = val.transform; _statusPill = HudWidgets.Pill(_host, "hud_status", Theme.WithAlpha(Theme.BgDeep, 0.74f)); HudWidgets.Outline(_statusPill, Theme.HairlineStrong); HudWidgets.Place(_statusPill, 0.5f, 1f, 0f, -12f, 760f, 36f); _status = HudWidgets.Label(_statusPill.transform, "txt", 16, Theme.TextPrimary, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_status).rectTransform, 12f, 0f, 12f, 0f); _hp = new HpBar(_host); HudWidgets.Place(_hp.Root, 0.5f, 1f, 0f, -56f, 260f, 18f); _hunterHp = new HpBar(_host); HudWidgets.Place(_hunterHp.Root, 0.5f, 1f, 0f, -56f, 260f, 18f); _hint = HudWidgets.Label(_host, "hud_hint", 13, Theme.InfoText, (TextAnchor)4, (FontStyle)0); HudWidgets.Place((Component)(object)_hint, 0.5f, 1f, 0f, -84f, 1100f, 24f); _transform = HudWidgets.Label(_host, "hud_transform", 13, Theme.SuccessText, (TextAnchor)4, (FontStyle)1); HudWidgets.Place((Component)(object)_transform, 0.5f, 1f, 0f, -112f, 800f, 22f); _abilityPill = HudWidgets.Pill(_host, "hud_ability", Theme.WithAlpha(Theme.BgDeep, 0.7f)); HudWidgets.Outline(_abilityPill, Theme.Hairline); HudWidgets.Place(_abilityPill, 0.5f, 1f, 0f, -140f, 440f, 26f); _ability = HudWidgets.Label(_abilityPill.transform, "txt", 13, Theme.InfoText, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_ability).rectTransform, 12f, 0f, 12f, 0f); _becomePill = HudWidgets.Pill(_host, "hud_become", Theme.WithAlpha(Theme.BgDeep, 0.78f)); HudWidgets.Place(_becomePill, 0.5f, 0.5f, 0f, -52f, 380f, 30f); _become = HudWidgets.Label(_becomePill.transform, "txt", 16, Theme.SuccessText, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_become).rectTransform, 10f, 0f, 10f, 0f); _flash = new FlashLabel(_host, 34); HudWidgets.Place(_flash.Root, 0.5f, 0.5f, 0f, 84f, 700f, 48f); _hitmarker = new Hitmarker(_host); _specPill = HudWidgets.Pill(_host, "hud_spec", Theme.WithAlpha(Theme.BgDeep, 0.74f)); HudWidgets.Outline(_specPill, Theme.Hairline); HudWidgets.Place(_specPill, 0.5f, 0f, 0f, 74f, 540f, 34f); _spec = HudWidgets.Label(_specPill.transform, "txt", 13, Theme.InfoText, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_spec).rectTransform, 14f, 0f, 14f, 0f); _oobPill = HudWidgets.Pill(_host, "hud_oob", Theme.WithAlpha(Theme.DangerSubtle, 0.9f)); HudWidgets.Outline(_oobPill, Theme.Danger); HudWidgets.Place(_oobPill, 0.5f, 1f, 0f, -188f, 600f, 44f); _oob = HudWidgets.Label(_oobPill.transform, "txt", 20, Theme.DangerText, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_oob).rectTransform, 12f, 0f, 12f, 0f); _safehousePill = HudWidgets.Pill(_host, "hud_safehouse", Theme.WithAlpha(Theme.SuccessSubtle, 0.9f)); HudWidgets.Outline(_safehousePill, Theme.Success); HudWidgets.Place(_safehousePill, 0.5f, 0.5f, 0f, -110f, 440f, 36f); _safehouse = HudWidgets.Label(_safehousePill.transform, "txt", 16, Theme.SuccessText, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_safehouse).rectTransform, 12f, 0f, 12f, 0f); _downedPill = HudWidgets.Pill(_host, "hud_downed", Theme.WithAlpha(Theme.WarningSubtle, 0.92f)); HudWidgets.Outline(_downedPill, Theme.Warning); HudWidgets.Place(_downedPill, 0.5f, 0.5f, 0f, -150f, 460f, 40f); _downed = HudWidgets.Label(_downedPill.transform, "txt", 16, Theme.WarningText, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_downed).rectTransform, 12f, 0f, 12f, 0f); _scoreboard = new Scoreboard(_host); _cardPanel = HudWidgets.Pill(_host, "hud_card", Theme.WithAlpha(Theme.BgDeep, 0.92f)); HudWidgets.Outline(_cardPanel, Theme.HairlineStrong); HudWidgets.Place(_cardPanel, 0.5f, 0.5f, 0f, 120f, 600f, 220f); _cardTitle = HudWidgets.Label(_cardPanel.transform, "title", 20, Theme.SuccessText, (TextAnchor)1, (FontStyle)1); HudWidgets.Place((Component)(object)_cardTitle, 0.5f, 1f, 0f, -16f, 560f, 30f); _cardBody = HudWidgets.Label(_cardPanel.transform, "body", 13, Theme.TextPrimary, (TextAnchor)1, (FontStyle)0); _cardBody.lineSpacing = 1.25f; HudWidgets.Stretch(((Graphic)_cardBody).rectTransform, 22f, 56f, 22f, 16f); _helpPanel = HudWidgets.Pill(_host, "hud_help", Theme.WithAlpha(Theme.BgDeep, 0.95f)); HudWidgets.Outline(_helpPanel, Theme.HairlineStrong); HudWidgets.Place(_helpPanel, 0.5f, 0.5f, 0f, 0f, 620f, 580f); Text obj2 = HudWidgets.Label(_helpPanel.transform, "title", 20, Theme.TextPrimary, (TextAnchor)1, (FontStyle)1); HudWidgets.Place((Component)(object)obj2, 0.5f, 1f, 0f, -16f, 580f, 28f); obj2.text = "PropHunt - Controls"; _helpBody = HudWidgets.Label(_helpPanel.transform, "body", 13, Theme.TextPrimary, (TextAnchor)0, (FontStyle)0); _helpBody.lineSpacing = 1.3f; _helpBody.supportRichText = true; HudWidgets.Stretch(((Graphic)_helpBody).rectTransform, 28f, 56f, 28f, 16f); _controlsHint = HudWidgets.Label(_host, "hud_controls_hint", 11, Theme.WithAlpha(Theme.TextMuted, 0.9f), (TextAnchor)7, (FontStyle)1); HudWidgets.Place((Component)(object)_controlsHint, 0.5f, 0f, 0f, 22f, 360f, 20f); HideAll(); try { Canvas.ForceUpdateCanvases(); } catch { } } private void HideAll() { Hide(_statusPill, ref _aStatus); Hide(_hp.Root, ref _aHp); Hide(_hunterHp.Root, ref _aHunterHp); Hide(_downedPill, ref _aDowned); Hide(((Component)_hint).gameObject, ref _aHint); Hide(((Component)_transform).gameObject, ref _aTransform); Hide(_abilityPill, ref _aAbility); Hide(_becomePill, ref _aBecome); Hide(_specPill, ref _aSpec); Hide(_oobPill, ref _aOob); Hide(_safehousePill, ref _aSafehouse); Hide(_cardPanel, ref _aCard); Hide(_helpPanel, ref _aHelp); Hide(((Component)_controlsHint).gameObject, ref _aControlsHint); } private static void Hide(GameObject go, ref bool cache) { go.SetActive(false); cache = false; } internal void Apply(GameModeController ctl) { //IL_0743: Unknown result type (might be due to invalid IL or missing references) RoundPhase phase = ctl.Phase; bool flag = phase == RoundPhase.Hiding || phase == RoundPhase.Hunting; bool flag2 = ctl.LocalRole == PlayerRole.Hider && !ctl.LocalSpectating; bool num = flag2 && ctl.LocalPropId >= 0; string text = "PropHunt - " + phase; if (flag) { text += $" {ctl.SecondsLeft}s Hiders left: {ctl.AliveHiderCount} You: {ctl.LocalRole}"; int secondsToWhistle = ctl.SecondsToWhistle; if (secondsToWhistle >= 0) { text += $" whistle in {secondsToWhistle}s"; } } else if (phase == RoundPhase.RoundEnd || phase == RoundPhase.Safehouse) { int secondsUntilNextRound = ctl.SecondsUntilNextRound; text = ((phase == RoundPhase.Safehouse && ctl.State.SafehouseReady) ? (text + ((secondsUntilNextRound > 0) ? $" starting in {secondsUntilNextRound}s" : " starting...")) : ((secondsUntilNextRound > 0) ? (text + $" next round in {secondsUntilNextRound}s") : ((phase != RoundPhase.Safehouse) ? (text + " round over") : (text + " waiting for the host...")))); } SetText(_status, ref _cStatus, text); SetActive(_statusPill, ref _aStatus, val: true); bool flag3 = num && phase == RoundPhase.Hunting; if (flag3) { _hp.Set(Mathf.Max(0, ctl.LocalMaxHits - ctl.LocalHits), Mathf.Max(1, ctl.LocalMaxHits)); } SetActive(_hp.Root, ref _aHp, flag3); bool num2 = ctl.LocalRole == PlayerRole.Hunter && !ctl.LocalSpectating; bool flag4 = ctl.Settings != null && ctl.Settings.FriendlyFire; bool flag5 = num2 && phase == RoundPhase.Hunting && flag4 && !ctl.LocalDowned; if (flag5) { _hunterHp.Set(Mathf.Max(0, ctl.LocalHunterMaxHits - ctl.LocalHunterHits), Mathf.Max(1, ctl.LocalHunterMaxHits)); } SetActive(_hunterHp.Root, ref _aHunterHp, flag5); bool localDowned = ctl.LocalDowned; if (localDowned) { SetText(_downed, ref _cDowned, $"KNOCKED DOWN - {ctl.LocalDownedSecondsLeft}s"); } SetActive(_downedPill, ref _aDowned, localDowned); string value = (ctl.ThirdPersonOn ? ("[" + KeyBinds.Name((KeyCode)118) + "] 1st-person") : ("[" + KeyBinds.Name((KeyCode)118) + "] 3rd-person")); string text2 = null; if (flag2 && flag) { string lookTargetName = ctl.LookTargetName; string value2 = ((lookTargetName != null) ? ("[" + KeyBinds.Name((KeyCode)101) + "] become " + lookTargetName) : "Look at a highlighted object to become it"); string value3 = ((phase == RoundPhase.Hunting) ? "Stay hidden! " : ""); string value4 = ((ctl.LocalPropId >= 0) ? (" [" + KeyBinds.Name((KeyCode)102) + "]+mouse rotate") : ""); string value5 = ((ctl.Settings == null || ctl.Settings.AllowRandomChange) ? (" [" + KeyBinds.Name((KeyCode)50) + "] random") : ""); text2 = $"{value3}{value2}{value5}{value4} {value}"; } else if (phase == RoundPhase.Hiding && ctl.LocalRole == PlayerRole.Hunter) { text2 = "Get ready... (blinded until the hunt begins)"; } else if (phase == RoundPhase.Hunting && ctl.LocalRole == PlayerRole.Hunter) { text2 = "Find the props - [" + KeyBinds.Name((KeyCode)323) + "] to catch (big props take more hits)"; } SetText(_hint, ref _cHint, text2 ?? ""); SetActive(((Component)_hint).gameObject, ref _aHint, text2 != null); if (num && flag && ctl.Settings != null) { RoundSettings settings = ctl.Settings; string text3 = ctl.LocalPropName ?? "a prop"; string text4 = ((settings.MaxPropChanges > 0) ? $"{Mathf.Max(0, settings.MaxPropChanges - ctl.LocalChanges)} CHANGES LEFT" : "UNLIMITED CHANGES"); SetText(_transform, ref _cTransform, "You are now: " + text3 + " - " + text4); SetActive(((Component)_transform).gameObject, ref _aTransform, val: true); string obj = ((settings.MaxDecoys > 0) ? $"[{KeyBinds.Name((KeyCode)113)}] Decoy ({Mathf.Max(0, settings.MaxDecoys - ctl.LocalDecoysUsed)})" : ""); string text5 = ((settings.ConcussCharges > 0) ? $"[{KeyBinds.Name((KeyCode)103)}] Stun ({Mathf.Max(0, settings.ConcussCharges - ctl.LocalConcussUsed)})" : ""); string text6 = (obj + " " + text5).Trim(); SetText(_ability, ref _cAbility, text6); SetActive(_abilityPill, ref _aAbility, text6.Length > 0); } else { SetActive(((Component)_transform).gameObject, ref _aTransform, val: false); SetActive(_abilityPill, ref _aAbility, val: false); } string text7 = ((flag2 && flag) ? ctl.LookTargetName : null); if (text7 != null) { SetText(_become, ref _cBecome, "[" + KeyBinds.Name((KeyCode)101) + "] become " + text7); } SetActive(_becomePill, ref _aBecome, text7 != null); if (ctl.FxActive) { _flash.Trigger(ctl.FxText, ctl.FxColor, Time.unscaledTime); } _flash.Tick(Time.unscaledTime); _hitmarker.Tick(Time.unscaledTime); string spectatorHudText = ctl.SpectatorHudText; bool flag6 = !string.IsNullOrEmpty(spectatorHudText); if (flag6) { SetText(_spec, ref _cSpec, spectatorHudText); } SetActive(_specPill, ref _aSpec, flag6); bool localOutside = ctl.LocalOutside; if (localOutside) { SetText(_oob, ref _cOob, $"RETURN TO THE PLAY AREA! {Mathf.CeilToInt(ctl.OobGrace)}s"); } SetActive(_oobPill, ref _aOob, localOutside); SetActive(_safehousePill, ref _aSafehouse, phase == RoundPhase.Safehouse && ctl.State.SafehouseReady); if (_aSafehouse && _safehouse.text != "Doors opening - get ready!") { _safehouse.text = "Doors opening - get ready!"; } ApplyControls(ctl); _scoreboard.Apply(ctl); } private void ApplyControls(GameModeController ctl) { //IL_00af: 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) Onboarding onboarding = ctl.Onboarding; if (onboarding == null) { SetActive(_cardPanel, ref _aCard, val: false); SetActive(_helpPanel, ref _aHelp, val: false); SetActive(((Component)_controlsHint).gameObject, ref _aControlsHint, val: false); return; } bool flag = onboarding.CardActive && !ctl.TauntWheelOpen && !onboarding.HelpOpen; if (flag) { SetText(_cardTitle, ref _cCardTitle, onboarding.CardTitle); if (_cCardHunter != onboarding.LocalIsHunter) { _cCardHunter = onboarding.LocalIsHunter; ((Graphic)_cardTitle).color = (onboarding.LocalIsHunter ? Theme.DangerText : Theme.SuccessText); } string val = onboarding.CardGoal + "\n\n" + string.Join("\n", onboarding.CardKeys) + "\n\n" + onboarding.CardFooter; SetText(_cardBody, ref _cCardBody, val); } SetActive(_cardPanel, ref _aCard, flag); if (onboarding.HelpOpen) { string val2 = "HIDER\n " + string.Join("\n ", onboarding.HelpHider) + "\n\nHUNTER\n " + string.Join("\n ", onboarding.HelpHunter) + "\n\nSPECTATOR (when caught)\n " + string.Join("\n ", onboarding.HelpSpectator) + "\n\n" + onboarding.ControlsHintText.Replace("Controls", "close"); SetText(_helpBody, ref _cHelpBody, val2); } SetActive(_helpPanel, ref _aHelp, onboarding.HelpOpen); bool showControlsHint = onboarding.ShowControlsHint; if (showControlsHint) { SetText(_controlsHint, ref _cControlsHint, onboarding.ControlsHintText); } SetActive(((Component)_controlsHint).gameObject, ref _aControlsHint, showControlsHint); } private static void SetText(Text t, ref string cache, string val) { if (!(cache == val)) { cache = val; t.text = val; } } private static void SetActive(GameObject go, ref bool cache, bool val) { if (cache != val) { cache = val; go.SetActive(val); } } internal void ShowHitmarker() { try { _hitmarker.Trigger(Time.unscaledTime); } catch { } } internal void Destroy() { if ((Object)(object)_go != (Object)null) { Object.Destroy((Object)(object)_go); } } } internal static class HudWidgets { internal static Text Label(Transform parent, string name, int size, Color color, TextAnchor anchor = (TextAnchor)4, FontStyle style = (FontStyle)0) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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) return HudPrimitives.Label(parent, name, size, color, anchor, style); } internal static GameObject Pill(Transform parent, string name, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return HudPrimitives.Pill(parent, name, color); } internal static void Outline(GameObject go, Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HudPrimitives.Outline(go, color); } internal static void Place(Component c, float ax, float ay, float x, float y, float w, float h) { HudPrimitives.Place(c, ax, ay, x, y, w, h); } internal static void Place(GameObject go, float ax, float ay, float x, float y, float w, float h) { HudPrimitives.Place(go, ax, ay, x, y, w, h); } internal static void Stretch(RectTransform rt, float l, float t, float r, float b) { HudPrimitives.Stretch(rt, l, t, r, b); } } internal sealed class HpBar { private readonly GameObject _root; private readonly Image _fill; private readonly Text _label; private float _lastFill = -1f; private string _lastText; private Color _lastColor; internal GameObject Root => _root; internal HpBar(Transform parent) { //IL_0018: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) _root = HudWidgets.Pill(parent, "hud_hp_track", Theme.WithAlpha(Theme.BgDeep, 0.8f)); HudWidgets.Outline(_root, Theme.HairlineStrong); GameObject val = HudWidgets.Pill(_root.transform, "hud_hp_fill", Theme.Success); _fill = val.GetComponent(); _fill.type = (Type)3; _fill.fillMethod = (FillMethod)0; _fill.fillOrigin = 0; _fill.fillAmount = 1f; HudWidgets.Stretch(((Graphic)_fill).rectTransform, 2f, 2f, 2f, 2f); _label = HudWidgets.Label(_root.transform, "hud_hp_txt", 11, Theme.TextPrimary, (TextAnchor)4, (FontStyle)1); HudWidgets.Stretch(((Graphic)_label).rectTransform, 0f, 0f, 0f, 0f); } internal void Set(int remaining, int max) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_005d: 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_0047: 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_006b: 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) float num = ((max > 0) ? Mathf.Clamp01((float)remaining / (float)max) : 0f); if (!Mathf.Approximately(num, _lastFill)) { _lastFill = num; _fill.fillAmount = num; } Color val = ((num > 0.5f) ? Theme.Success : ((num > 0.25f) ? Theme.Warning : Theme.Danger)); if (val != _lastColor) { _lastColor = val; ((Graphic)_fill).color = val; } string text = $"{remaining} / {max} HP"; if (text != _lastText) { _lastText = text; _label.text = text; } } } internal sealed class Hitmarker { private const float Dur = 0.22f; private readonly GameObject _root; private readonly CanvasGroup _cg; private float _start; internal GameObject Root => _root; internal Hitmarker(Transform parent) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) _root = HudWidgets.Pill(parent, "hud_hitmarker", Theme.Clear); _cg = _root.AddComponent(); _cg.blocksRaycasts = false; _cg.interactable = false; HudWidgets.Place(_root, 0.5f, 0.5f, 0f, 0f, 40f, 40f); MakeTick(-11f, 11f, -45f); MakeTick(11f, 11f, 45f); MakeTick(-11f, -11f, 45f); MakeTick(11f, -11f, -45f); _root.SetActive(false); } private void MakeTick(float x, float y, float rot) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) GameObject obj = HudWidgets.Pill(_root.transform, "tick", Color.white); HudWidgets.Place(obj, 0.5f, 0.5f, x, y, 11f, 3f); ((Transform)obj.GetComponent()).localEulerAngles = new Vector3(0f, 0f, rot); } internal void Trigger(float now) { _start = now; if (!_root.activeSelf) { _root.SetActive(true); } } internal void Tick(float now) { if (_root.activeSelf) { float num = now - _start; if (num >= 0.22f) { _root.SetActive(false); } else { _cg.alpha = Mathf.Clamp01(1f - num / 0.22f); } } } } internal sealed class Scoreboard { private struct Award { public string Title; public string Name; public string Metric; } private const float CardWidth = 720f; private const float Inset = 30f; private const float ContentW = 660f; private const float RowH = 30f; private const float CRank = 0f; private const float WRank = 36f; private const float CName = 44f; private const float WName = 220f; private const float CRole = 270f; private const float WRole = 96f; private const float CCatch = 374f; private const float WCatch = 86f; private const float CSurv = 466f; private const float WSurv = 92f; private const float CScore = 564f; private const float WScore = 76f; private readonly GameObject _card; private readonly GameObject _content; private bool _active; private string _sig; internal Scoreboard(Transform parent) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0070: Unknown result type (might be due to invalid IL or missing references) _card = HudWidgets.Pill(parent, "hud_scoreboard", Theme.WithAlpha(Theme.BgDeep, 0.94f)); HudWidgets.Outline(_card, Theme.HairlineStrong); HudWidgets.Place(_card, 0.5f, 0.5f, 0f, 0f, 720f, 480f); _content = UIFactory.Panel("content", _card.transform, Theme.Clear, (Vector2?)null, (Vector2?)null, false); ((Graphic)_content.GetComponent()).raycastTarget = false; HudWidgets.Stretch(_content.GetComponent(), 30f, 26f, 30f, 26f); _card.SetActive(false); } internal void Apply(GameModeController ctl) { if (ctl.Phase != RoundPhase.RoundEnd) { if (_active) { _active = false; _card.SetActive(false); } return; } GameState state = ctl.State; string text = $"{state.Winner}|{state.RoundNumber}|{state.Players.Count}"; if (!_active) { _active = true; _card.SetActive(true); } if (text != _sig) { _sig = text; Rebuild(state, ctl.LocalId); } } private void Rebuild(GameState st, ulong localId) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: 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_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_039d: 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_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0422: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) UIFactory.ClearChildren(_content.transform); try { PlayerRegistry.Refresh(); } catch { } List list = new List(st.Players.Values); list.Sort((PlayerState a, PlayerState b) => b.SessScore.CompareTo(a.SessScore)); List list2 = BuildAwards(list); float num = 0f; if (st.Winner != 0) { _ = st.Winner; _ = 1; } Color color = ((st.Winner == 0) ? Theme.DangerText : ((st.Winner == 1) ? Theme.SuccessText : Theme.TextPrimary)); Text t = HudWidgets.Label(_content.transform, "headline", 28, color, (TextAnchor)1, (FontStyle)1); FullRow(t, num, 38f); num += 42f; Text val = HudWidgets.Label(_content.transform, "sub", 11, Theme.TextMuted, (TextAnchor)1, (FontStyle)1); val.text = $"ROUND {st.RoundNumber} - {list.Count} PLAYERS"; FullRow(val, num, 16f); num += 26f; if (list2.Count > 0) { float num2 = (660f - 10f * (float)(list2.Count - 1)) / (float)list2.Count; for (int num3 = 0; num3 < list2.Count; num3++) { Award award = list2[num3]; GameObject val2 = HudWidgets.Pill(_content.transform, "award", Theme.WithAlpha(Theme.WarningSubtle, 0.55f)); HudWidgets.Outline(val2, Theme.WithAlpha(Theme.Warning, 0.4f)); TopLeft(val2, (float)num3 * (num2 + 10f), num, num2, 58f); Cell(val2.transform, "t", award.Title.ToUpperInvariant(), Theme.WarningText, 11, (TextAnchor)1, (FontStyle)1, 8f, 6f, num2 - 16f, 14f); Cell(val2.transform, "n", award.Name, Theme.TextPrimary, 14, (TextAnchor)1, (FontStyle)1, 8f, 22f, num2 - 16f, 20f); Cell(val2.transform, "m", award.Metric, Theme.TextMuted, 11, (TextAnchor)1, (FontStyle)0, 8f, 40f, num2 - 16f, 14f); } num += 72f; } TopLeft(HudWidgets.Pill(_content.transform, "lb_head", Theme.WithAlpha(Theme.BgElevated, 0.6f)), 0f, num, 660f, 30f); HeaderCell("Player", 44f, 220f, (TextAnchor)3, num); HeaderCell("Role", 270f, 96f, (TextAnchor)3, num); HeaderCell("Catches", 374f, 86f, (TextAnchor)5, num); HeaderCell("Survived", 466f, 92f, (TextAnchor)5, num); HeaderCell("Score", 564f, 76f, (TextAnchor)5, num); num += 34f; int num4 = 1; foreach (PlayerState item in list) { bool flag = item.SteamId == localId; GameObject go = HudWidgets.Pill(_content.transform, "row", flag ? Theme.AccentSubtle : Theme.WithAlpha(Theme.BgElevated, (num4 % 2 == 0) ? 0.32f : 0.16f)); if (flag) { HudWidgets.Outline(go, Theme.WithAlpha(Theme.AccentBorder, 0.7f)); } TopLeft(go, 0f, num, 660f, 28f); Color color2 = (flag ? Theme.TextPrimary : Theme.TextPrimary); Cell(_content.transform, "rank", num4.ToString(), Theme.TextMuted, 13, (TextAnchor)4, (FontStyle)1, 0f, num, 36f, 30f); Cell(_content.transform, "name", NameOf(item) + (flag ? " (you)" : ""), color2, 13, (TextAnchor)3, (FontStyle)(flag ? 1 : 0), 44f, num, 220f, 30f); RoleChip(item, 270f, num); Cell(_content.transform, "catch", item.CatchesMade.ToString(), Theme.TextMuted, 13, (TextAnchor)5, (FontStyle)0, 374f, num, 86f, 30f); Cell(_content.transform, "surv", item.SurvivedSeconds + "s", Theme.TextMuted, 13, (TextAnchor)5, (FontStyle)0, 466f, num, 92f, 30f); Cell(_content.transform, "score", item.SessScore.ToString(), Theme.TextPrimary, 13, (TextAnchor)5, (FontStyle)1, 564f, num, 76f, 30f); num += 30f; num4++; } float num5 = num + 26f + 26f; _card.GetComponent().sizeDelta = new Vector2(720f, Mathf.Min(num5, (float)Screen.height - 40f)); } private void Cell(Transform parent, string name, string text, Color color, int size, TextAnchor anchor, FontStyle style, float x, float y, float w, float h) { //IL_0004: 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) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Text obj = HudWidgets.Label(parent, name, size, color, anchor, style); obj.text = text; RectTransform rectTransform = ((Graphic)obj).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.anchoredPosition = new Vector2(x, 0f - y); rectTransform.sizeDelta = new Vector2(w, h); } private void HeaderCell(string text, float x, float w, TextAnchor anchor, float y) { //IL_0012: 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) Cell(_content.transform, "h", text, Theme.InfoText, 11, anchor, (FontStyle)1, x, y, w, 30f); } private void RoleChip(PlayerState p, float x, float y) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) string text = RoleShort(p); Color val = RoleColor(p); GameObject obj = HudWidgets.Pill(_content.transform, "rolechip", Theme.WithAlpha(val, 0.18f)); RectTransform component = obj.GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(x, 0f - (y + 4f)); component.sizeDelta = new Vector2(88f, 20f); Text obj2 = HudWidgets.Label(obj.transform, "txt", 11, val, (TextAnchor)4, (FontStyle)1); obj2.text = text; HudWidgets.Stretch(((Graphic)obj2).rectTransform, 4f, 0f, 4f, 0f); } private static void TopLeft(GameObject go, float x, float y, float w, float h) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) RectTransform component = go.GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(x, 0f - y); component.sizeDelta = new Vector2(w, h); } private void FullRow(Text t, float y, float h) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0087: Unknown result type (might be due to invalid IL or missing references) RectTransform rectTransform = ((Graphic)t).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.pivot = new Vector2(0.5f, 1f); rectTransform.offsetMin = new Vector2(0f, 0f); rectTransform.offsetMax = new Vector2(0f, 0f); rectTransform.anchoredPosition = new Vector2(0f, 0f - y); rectTransform.sizeDelta = new Vector2(0f, h); } private static List BuildAwards(List players) { List list = new List(); AddAward(list, players, "Top Hunter", (PlayerState p) => p.CatchesMade, (int v) => $"{v} catches"); AddAward(list, players, "Survivor", (PlayerState p) => (p.Role == PlayerRole.Hider) ? p.SurvivedSeconds : 0, (int v) => $"{v}s alive"); AddAward(list, players, "Trickster", (PlayerState p) => p.DecoyBaits, (int v) => $"{v} decoy baits"); AddAward(list, players, "Shocker", (PlayerState p) => p.StunsLanded, (int v) => $"{v} stuns"); return list; } private static void AddAward(List list, List players, string title, Func sel, Func fmt) { PlayerState playerState = null; int num = 0; foreach (PlayerState player in players) { int num2 = sel(player); if (num2 > num) { num = num2; playerState = player; } } if (playerState != null && num > 0) { list.Add(new Award { Title = title, Name = NameOf(playerState), Metric = fmt(num) }); } } private static string NameOf(PlayerState p) { try { Player val = PlayerRegistry.Get(p.SteamId); if ((Object)(object)val != (Object)null) { string playerName = val.PlayerName; if (!string.IsNullOrEmpty(playerName)) { return playerName; } } } catch { } return "Player " + p.SteamId % 10000; } private static string RoleShort(PlayerState p) { if (p.Role == PlayerRole.Hunter) { return "Hunter"; } if (p.Role == PlayerRole.Hider) { if (!p.Eliminated) { return "Hider"; } return "Caught"; } return "Spectator"; } private static Color RoleColor(PlayerState p) { //IL_0009: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (p.Role == PlayerRole.Hunter) { return Theme.DangerText; } if (p.Role == PlayerRole.Hider) { if (!p.Eliminated) { return Theme.SuccessText; } return Theme.TextMuted; } return Theme.InfoText; } } } namespace PropHunt.Taunt { internal sealed class TauntController { private struct StaggerEntry { public float At; public ulong Id; public string Sound; } private readonly GameModeController _ctl; private long _nextWhistleUnix; private readonly List _staggerQueue = new List(); internal TauntController(GameModeController ctl) { _ctl = ctl; } internal void Tick() { if (!_ctl.IsHost) { return; } float time = Time.time; for (int num = _staggerQueue.Count - 1; num >= 0; num--) { if (!(time < _staggerQueue[num].At)) { StaggerEntry staggerEntry = _staggerQueue[num]; _staggerQueue.RemoveAt(num); if (IsLiveHider(staggerEntry.Id)) { try { SteamNetworkClient client = PropHuntNet.Client; if (client != null) { client.BroadcastMessage((P2PMessage)(object)new TauntMessage { SteamId = staggerEntry.Id, Sound = staggerEntry.Sound, IsWhistle = true }); } } catch { } _ctl.NotifyTaunt(staggerEntry.Id, staggerEntry.Sound, isWhistle: true); } } } if (_ctl.Phase != RoundPhase.Hunting) { _nextWhistleUnix = 0L; _staggerQueue.Clear(); return; } int tauntIntervalSeconds = _ctl.Settings.TauntIntervalSeconds; if (tauntIntervalSeconds <= 0) { return; } long num2 = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); if (_nextWhistleUnix <= 0) { _nextWhistleUnix = num2 + tauntIntervalSeconds; } else { if (num2 < _nextWhistleUnix) { return; } _nextWhistleUnix = num2 + tauntIntervalSeconds; float num3 = Mathf.Max(0f, _ctl.Settings.WhistleStaggerSeconds); float num4 = 0f; int num5 = 0; foreach (PlayerState value in _ctl.State.Players.Values) { if (value.Role == PlayerRole.Hider && !value.Eliminated) { _staggerQueue.Add(new StaggerEntry { At = time + num4, Id = value.SteamId, Sound = TauntSounds.PickDefault() }); num4 += num3; num5++; } } } } private bool IsLiveHider(ulong id) { if (_ctl.State.Players.TryGetValue(id, out var value) && value.Role == PlayerRole.Hider) { return !value.Eliminated; } return false; } } internal static class TauntSounds { private static Dictionary _cache; private static float _cacheBuiltAt = -999f; private static List _defaultPool; private static string _flushName; private const string FlushClip = "foley-toilet-flush-without-tank-refill-238004"; private const float FlushChance = 0.001f; private const float ManualVolumeScale = 0.6f; private const float WhistleVolumeScale = 0.45f; private static string FavPath => Path.Combine(MelonEnvironment.UserDataDirectory, "PropHunt", "taunt_favorites.txt"); private static void BuildCache() { if (_cache != null && Time.time - _cacheBuiltAt < 5f) { return; } _cache = new Dictionary(StringComparer.OrdinalIgnoreCase); try { Il2CppArrayBase val = Resources.FindObjectsOfTypeAll(); if (val != null) { for (int i = 0; i < val.Length; i++) { AudioClip val2 = val[i]; if ((Object)(object)val2 != (Object)null && !string.IsNullOrEmpty(((Object)val2).name) && !_cache.ContainsKey(((Object)val2).name)) { _cache[((Object)val2).name] = val2; } } } } catch (Exception) { } _cacheBuiltAt = Time.time; } private static AudioClip GetClip(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (_cache == null || !_cache.ContainsKey(name)) { BuildCache(); } if (_cache == null || !_cache.TryGetValue(name, out var value)) { return null; } return value; } internal static void Play(string clipName, Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayInternal(clipName, pos, WhistleVolume: false); } internal static void PlayWhistle(string clipName, Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayInternal(clipName, pos, WhistleVolume: true); } private static void PlayInternal(string clipName, Vector3 pos, bool WhistleVolume) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) AudioClip clip = GetClip(clipName); if (!((Object)(object)clip == (Object)null)) { PlayClip(clip, pos, WhistleVolume ? 0.45f : 0.6f); } } internal static void PlayFx(string[] candidates, Vector3 pos, float volumeScale = 0.7f) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) AudioClip val = ResolveAny(candidates); if (!((Object)(object)val == (Object)null)) { PlayClip(val, pos, volumeScale); } } private static AudioClip ResolveAny(string[] names) { if (names == null) { return null; } BuildCache(); if (_cache == null) { return null; } string[] array = names; foreach (string text in array) { if (!string.IsNullOrEmpty(text) && _cache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { return value; } } array = names; foreach (string value2 in array) { if (string.IsNullOrEmpty(value2)) { continue; } foreach (KeyValuePair item in _cache) { if ((Object)(object)item.Value != (Object)null && item.Key.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0) { return item.Value; } } } return null; } private static void PlayClip(AudioClip clip, Vector3 pos, float volumeScale) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)clip == (Object)null) { return; } try { GameObject val = new GameObject("ph_taunt"); val.transform.position = pos; AudioSource val2 = val.AddComponent(); val2.clip = clip; val2.spatialBlend = 1f; val2.rolloffMode = (AudioRolloffMode)0; val2.minDistance = 6f; val2.maxDistance = 140f; val2.dopplerLevel = 0f; float num = 0.7f; try { AudioManager instance = Singleton.Instance; if ((Object)(object)instance != (Object)null) { val2.outputAudioMixerGroup = instance.MainGameMixer; num = instance.GetVolume((EAudioType)2, true); } } catch { } val2.volume = num * volumeScale; val2.Play(); Object.Destroy((Object)(object)val, clip.length + 0.2f); } catch (Exception) { } } private static void BuildDefaults() { BuildCache(); _defaultPool = new List(); _flushName = null; if (_cache == null) { return; } foreach (KeyValuePair item in _cache) { string key = item.Key; if (key.IndexOf("cork pop", StringComparison.OrdinalIgnoreCase) >= 0) { _defaultPool.Add(key); } else if (Regex.IsMatch(key, "^fart\\s*\\d+$", RegexOptions.IgnoreCase)) { _defaultPool.Add(key); } else if (string.Equals(key, "foley-toilet-flush-without-tank-refill-238004", StringComparison.OrdinalIgnoreCase)) { _flushName = key; } } } internal static List DefaultNames() { if (_defaultPool == null) { BuildDefaults(); } return new List(_defaultPool ?? new List()); } internal static List WheelOptions() { List list = ManualFavorites(); if (list.Count <= 0) { return DefaultNames(); } return list; } internal static string PickDefault() { if (_defaultPool == null || _defaultPool.Count == 0) { BuildDefaults(); } if (_flushName != null && Random.value < 0.001f) { return _flushName; } if (_defaultPool != null && _defaultPool.Count > 0) { return _defaultPool[Random.Range(0, _defaultPool.Count)]; } return null; } internal static List ManualFavorites() { List list = new List(); try { if (File.Exists(FavPath)) { string[] array = File.ReadAllLines(FavPath); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0 && !text.StartsWith("#") && !list.Contains(text)) { list.Add(text); } } } } catch (Exception) { } return list; } internal static void AddFavorite(string name) { if (string.IsNullOrEmpty(name)) { return; } try { if (!ManualFavorites().Contains(name)) { Directory.CreateDirectory(Path.GetDirectoryName(FavPath)); File.AppendAllText(FavPath, name + "\n"); } } catch (Exception) { } } } internal sealed class TauntWheel { private readonly GameModeController _ctl; private List _labels = new List(); private List _sounds = new List(); private string _selectedSound; private string _selectedLabel = "Default"; private int _highlight; private bool _open; private float _downAt = -1f; private Vector2 _aim; private const float HoldThreshold = 0.22f; private const float AimSpeed = 9f; private const float MaxAim = 100f; private const float DeadZone = 22f; internal bool MenuOpen => _open; internal TauntWheel(GameModeController ctl) { _ctl = ctl; } internal void Tick() { if ((_ctl.Phase != RoundPhase.Hiding && _ctl.Phase != RoundPhase.Hunting) || _ctl.LocalRole != PlayerRole.Hider) { if (_open) { Close(commit: false); } _downAt = -1f; return; } try { if (Input.GetKeyDown((KeyCode)49)) { _downAt = Time.time; } if (!_open && _downAt >= 0f && Input.GetKey((KeyCode)49) && Time.time - _downAt >= 0.22f) { Open(); } if (_open) { UpdateAim(); } if (Input.GetKeyUp((KeyCode)49)) { if (_open) { Close(commit: true); } else if (_downAt >= 0f) { _ctl.RequestManualTaunt(_selectedSound); } _downAt = -1f; } } catch (Exception) { } } private void Open() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) _labels = new List { "Default" }; _sounds = new List { null }; foreach (string item in TauntSounds.WheelOptions()) { _labels.Add(item); _sounds.Add(item); } _aim = Vector2.zero; _highlight = Mathf.Max(0, _sounds.IndexOf(_selectedSound)); _open = true; SetCanLook(can: false); } private void Close(bool commit) { if (commit && _highlight >= 0 && _highlight < _sounds.Count) { _selectedSound = _sounds[_highlight]; _selectedLabel = _labels[_highlight]; } _open = false; SetCanLook(can: true); } private void UpdateAim() { //IL_0012: 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_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) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) //IL_0055: Unknown result type (might be due to invalid IL or missing references) int count = _labels.Count; if (count == 0) { return; } _aim += new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")) * 9f; _aim = Vector2.ClampMagnitude(_aim, 100f); if (!(((Vector2)(ref _aim)).magnitude < 22f)) { float num = Mathf.Atan2(_aim.x, _aim.y) * 57.29578f; if (num < 0f) { num += 360f; } _highlight = Mathf.Clamp(Mathf.RoundToInt(num / 360f * (float)count) % count, 0, count - 1); } } private static void SetCanLook(bool can) { try { PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(can); } } catch { } } internal void DrawGui() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0297: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) if (_open && _labels.Count != 0) { int count = _labels.Count; float num = (float)Screen.width * 0.5f; float num2 = (float)Screen.height * 0.5f; float num3 = Mathf.Max(180f, (float)count * 24f); GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontStyle = (FontStyle)1, wordWrap = false }; for (int i = 0; i < count; i++) { float num4 = (float)i / (float)count * (float)Math.PI * 2f; float num5 = num + Mathf.Sin(num4) * num3; float num6 = num2 - Mathf.Cos(num4) * num3; bool flag = i == _highlight; float num7 = (flag ? 140f : 116f); float num8 = (flag ? 32f : 26f); Color color = GUI.color; GUI.color = (flag ? new Color(0.2f, 0.85f, 0.4f, 0.96f) : new Color(0.05f, 0.06f, 0.09f, 0.78f)); GUI.Box(new Rect(num5 - num7 / 2f, num6 - num8 / 2f, num7, num8), GUIContent.none); GUI.color = color; val.fontSize = (flag ? 14 : 12); val.normal.textColor = (Color)(flag ? Color.black : new Color(0.82f, 0.88f, 1f)); GUI.Label(new Rect(num5 - num7 / 2f, num6 - num8 / 2f, num7, num8), Short(_labels[i]), val); } GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontStyle = (FontStyle)1, fontSize = 18 }; val2.normal.textColor = new Color(0.3f, 1f, 0.5f); GUI.Label(new Rect(num - 220f, num2 - 14f, 440f, 24f), Short(_labels[_highlight]), val2); GUIStyle val3 = new GUIStyle(val2) { fontSize = 12 }; val3.normal.textColor = new Color(0.6f, 0.85f, 1f); GUI.Label(new Rect(num - 220f, num2 + 12f, 440f, 18f), "move mouse - release [1] to set", val3); } } private static string Short(string s) { if (!string.IsNullOrEmpty(s)) { if (s.Length <= 22) { return s; } return s.Substring(0, 22); } return "?"; } internal void Dispose() { if (_open) { Close(commit: false); } } } } namespace PropHunt.Quests { internal static class GuideQuest { internal const string Title = "PropHunt"; private static PropHuntGuideQuest _quest; private static readonly Dictionary _active = new Dictionary(); private static readonly Dictionary _titles = new Dictionary(); private static readonly List _toRemove = new List(); private static bool _appOpened; internal static void Tick() { GameModeController active = GameModeController.Active; if (active == null || !QuestUiReady()) { return; } Dictionary dictionary = Desired(active); if (_quest == null) { if (dictionary.Count == 0) { return; } try { _quest = QuestManager.CreateQuest((string)null) as PropHuntGuideQuest; } catch (Exception ex) { Core.Log.Warning("[PropHunt] guide quest create failed: " + ex.Message); return; } if (_quest == null) { return; } } _toRemove.Clear(); foreach (KeyValuePair item in _active) { if (!dictionary.ContainsKey(item.Key)) { _toRemove.Add(item.Key); } } foreach (string item2 in _toRemove) { QuestEntry val = _active[item2]; bool flag = Resolve(item2, active); try { string text = ResolveTitle(item2, flag); if (text != null) { val.Title = text; } if (flag) { val.Complete(); } else { val.SetState((QuestState)3); } } catch { } _active.Remove(item2); _titles.Remove(item2); } foreach (KeyValuePair item3 in dictionary) { string value; if (!_active.ContainsKey(item3.Key)) { try { _active[item3.Key] = _quest.AddObjective(item3.Value); _titles[item3.Key] = item3.Value; } catch (Exception ex2) { Core.Log.Warning("[PropHunt] guide quest add failed: " + ex2.Message); } } else if (_titles.TryGetValue(item3.Key, out value) && value != item3.Value) { try { _active[item3.Key].Title = item3.Value; } catch { } _titles[item3.Key] = item3.Value; } } } private static Dictionary Desired(GameModeController ctl) { Dictionary dictionary = new Dictionary(); bool isHost = ctl.IsHost; bool localSpectating = ctl.LocalSpectating; PlayerRole localRole = ctl.LocalRole; if (!_appOpened) { dictionary["open"] = (isHost ? "Open the PropHunt app to run the match." : "Open the PropHunt app to track the match."); } switch (ctl.Phase) { case RoundPhase.Lobby: if (isHost) { dictionary["start_match"] = "Start the match in the PropHunt app."; } else { dictionary["wait_match"] = "Wait for the host to start the match."; } break; case RoundPhase.Safehouse: { int value = ctl.State.RoundNumber + 1; if (isHost) { dictionary["start_round"] = $"Start round {value} in the PropHunt app."; } else { dictionary["wait_round"] = $"Wait for round {value} to begin."; } break; } case RoundPhase.Hiding: if (!localSpectating) { dictionary["prep"] = ((localRole == PlayerRole.Hunter) ? "Get ready - you're blinded until the hunt begins." : "Disguise as a prop and find a hiding spot."); } break; case RoundPhase.Hunting: if (!localSpectating) { switch (localRole) { case PlayerRole.Hunter: dictionary["round_hunt"] = "Find and catch every hidden prop."; break; case PlayerRole.Hider: dictionary["round_hide"] = "Stay hidden and survive until the hunt ends."; break; } } break; } return dictionary; } private static bool Resolve(string key, GameModeController ctl) { if (!(key == "round_hide")) { if (key == "round_hunt") { return ctl.State.Winner == 0; } return true; } return ctl.State.Winner == 1; } private static string ResolveTitle(string key, bool won) { if (!(key == "round_hide")) { if (key == "round_hunt") { if (!won) { return "The hiders survived."; } return "Caught every prop!"; } return null; } if (!won) { return "You were caught."; } return "You survived the round!"; } internal static void OnAppOpened() { _appOpened = true; } internal static void Stop() { try { PropHuntGuideQuest quest = _quest; if (quest != null) { ((Quest)quest).Cancel(); } } catch { } _quest = null; _active.Clear(); _titles.Clear(); _toRemove.Clear(); _appOpened = false; } private static bool QuestUiReady() { try { return (Object)(object)Player.Local != (Object)null && PlayerSingleton.InstanceExists && Singleton.InstanceExists; } catch { return false; } } } public class PropHuntGuideQuest : Quest { private static Sprite _icon; private static bool _iconAbsent; protected override string Title => "PropHunt"; protected override string Description => "Run and follow the prop hunt from the PropHunt app on your phone."; protected override bool AutoBegin => true; protected override Sprite QuestIcon { get { if ((Object)(object)_icon != (Object)null) { return _icon; } if (_iconAbsent) { return null; } _icon = LoadIcon(); if ((Object)(object)_icon == (Object)null) { _iconAbsent = true; } return _icon; } } private static Sprite LoadIcon() { //IL_004f: 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_005c: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PropHunt.Assets.phone_icon.png"); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { filterMode = (FilterMode)1 }; ((Object)val).hideFlags = (HideFlags)32; if (ImageConversion.LoadImage(val, Il2CppStructArray.op_Implicit(array))) { Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); if ((Object)(object)val2 != (Object)null) { ((Object)val2).hideFlags = (HideFlags)32; } return val2; } return null; } catch { return null; } } protected override void OnCreated() { ((Registerable)this).OnCreated(); try { ((Quest)this).AddEntry("PropHunt session", (Vector3?)null); } catch (Exception ex) { Core.Log.Warning("[PropHunt] guide quest OnCreated failed: " + ex.Message); } } internal QuestEntry AddObjective(string title) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) Player local = Player.Local; QuestEntry val = (((Object)(object)local != (Object)null) ? ((Quest)this).AddEntry(title, (Vector3?)((Component)local).transform.position) : ((Quest)this).AddEntry(title, (Vector3?)null)); try { val.Begin(); } catch { } return val; } } } namespace PropHunt.PlayArea { internal static class BorderMesh { internal const int Segments = 96; internal const float Height = 200f; internal const float Depth = 200f; internal static void Build(MeshFilter mf, float radius, float height) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown if (!((Object)(object)mf == (Object)null)) { Vector3[] array = (Vector3[])(object)new Vector3[194]; Vector2[] array2 = (Vector2[])(object)new Vector2[194]; Vector3[] array3 = (Vector3[])(object)new Vector3[194]; Vector3 val = default(Vector3); for (int i = 0; i <= 96; i++) { float num = (float)i / 96f; float num2 = num * (float)Math.PI * 2f; float num3 = Mathf.Cos(num2); float num4 = Mathf.Sin(num2); ((Vector3)(ref val))..ctor(num3, 0f, num4); int num5 = i * 2; int num6 = i * 2 + 1; array[num5] = new Vector3(num3 * radius, -200f, num4 * radius); array2[num5] = new Vector2(num, 0f); array3[num5] = val; array[num6] = new Vector3(num3 * radius, height, num4 * radius); array2[num6] = new Vector2(num, 1f); array3[num6] = val; } int[] array4 = new int[576]; int num7 = 0; for (int j = 0; j < 96; j++) { int num8 = j * 2; int num9 = (j + 1) * 2; int num10 = j * 2 + 1; int num11 = (j + 1) * 2 + 1; array4[num7++] = num8; array4[num7++] = num10; array4[num7++] = num11; array4[num7++] = num8; array4[num7++] = num11; array4[num7++] = num9; } Mesh val2 = mf.sharedMesh; if ((Object)(object)val2 == (Object)null) { val2 = (mf.sharedMesh = new Mesh { name = "ph_border_cylinder" }); } val2.Clear(); val2.vertices = Il2CppStructArray.op_Implicit(array); val2.uv = Il2CppStructArray.op_Implicit(array2); val2.normals = Il2CppStructArray.op_Implicit(array3); val2.triangles = Il2CppStructArray.op_Implicit(array4); val2.RecalculateBounds(); } } } internal static class BorderShader { private const string ResourceName = "PropHunt.Assets.Bundles.propborder"; private static bool _tried; private static Shader _shader; internal static Material TryCreateMaterial(Color wallColor, Color rimColor) { //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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown Shader shader = GetShader(); if ((Object)(object)shader == (Object)null) { return null; } try { Material val = new Material(shader); TrySetColor(val, "_WallColor", wallColor); TrySetColor(val, "_RimColor", rimColor); val.renderQueue = 3010; return val; } catch { return null; } } private static void TrySetColor(Material m, string name, Color c) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { m.SetColor(name, c); } catch { } } private static Shader GetShader() { if (_tried) { return _shader; } _tried = true; try { WrappedAssetBundle assetBundleFromStream = AssetLoader.GetAssetBundleFromStream("PropHunt.Assets.Bundles.propborder", Assembly.GetExecutingAssembly()); if (assetBundleFromStream == null) { Instance log = Core.Log; if (log != null) { log.Warning("[PropHunt] border shader: bundle null - not built yet?"); } return null; } Shader[] array = assetBundleFromStream.LoadAllAssets(); _shader = ((array != null && array.Length != 0) ? array[0] : null); if ((Object)(object)_shader == (Object)null) { _shader = assetBundleFromStream.LoadAsset("Border"); if ((Object)(object)_shader == (Object)null) { _shader = assetBundleFromStream.LoadAsset("PropHunt/Border"); } } if (!((Object)(object)_shader != (Object)null)) { Instance log2 = Core.Log; if (log2 != null) { log2.Warning("[PropHunt] border shader: not found in bundle - wall will be invisible"); } } } catch (Exception ex) { Instance log3 = Core.Log; if (log3 != null) { log3.Warning("[PropHunt] border shader load failed: " + ex.Message); } _shader = null; } return _shader; } } internal sealed class PlayAreaBorder { private readonly GameModeController _ctl; private GameObject _root; private MeshFilter _mf; private MeshRenderer _mr; private Material _mat; private string _builtSig; private const float ProximityFullNear = 5f; private const float ProximityFadeOut = 45f; internal PlayAreaBorder(GameModeController ctl) { _ctl = ctl; } internal void Tick() { try { GameState state = _ctl.State; if (state == null || !(state.AreaRadius > 0f) || (_ctl.Phase != RoundPhase.Hiding && _ctl.Phase != RoundPhase.Hunting && _ctl.Phase != RoundPhase.RoundEnd)) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } return; } string text = $"{state.AreaX:F1}|{state.AreaY:F1}|{state.AreaZ:F1}|{state.AreaRadius:F1}"; if ((Object)(object)_root == (Object)null || _builtSig != text) { Build(state.AreaX, state.AreaY, state.AreaZ, state.AreaRadius, text); } if ((Object)(object)_root != (Object)null) { _root.SetActive(true); } UpdateProximity(state); } catch (Exception) { } } private void UpdateProximity(GameState s) { //IL_0027: 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) if ((Object)(object)_mat == (Object)null) { return; } try { Player local = Player.Local; if (!((Object)(object)local == (Object)null)) { Vector3 position = ((Component)local).transform.position; float num = position.x - s.AreaX; float num2 = position.z - s.AreaZ; float num3 = s.AreaRadius - Mathf.Sqrt(num * num + num2 * num2); float num4 = Mathf.Clamp01(Mathf.InverseLerp(5f, 45f, num3)); _mat.SetFloat("_Proximity", num4); } } catch { } } private void Build(float cx, float cy, float cz, float radius, string sig) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) Destroy(); EnsureMat(); _root = new GameObject("ph_border_wall"); Object.DontDestroyOnLoad((Object)(object)_root); _root.transform.position = new Vector3(cx, cy, cz); _mf = _root.AddComponent(); _mr = _root.AddComponent(); ((Renderer)_mr).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)_mr).receiveShadows = false; if ((Object)(object)_mat != (Object)null) { ((Renderer)_mr).sharedMaterial = _mat; } ((Renderer)_mr).enabled = (Object)(object)_mat != (Object)null; BorderMesh.Build(_mf, radius, 200f); _builtSig = sig; } private void EnsureMat() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_mat != (Object)null) { return; } _mat = BorderShader.TryCreateMaterial(new Color(1f, 0.25f, 0.1f, 0.45f), new Color(1f, 0.55f, 0.2f, 1f)); if ((Object)(object)_mat != (Object)null) { Object.DontDestroyOnLoad((Object)(object)_mat); return; } Instance log = Core.Log; if (log != null) { log.Warning("[PropHunt] border shader bundle missing - play-area wall is invisible until 'propborder' is built."); } } private void Destroy() { if ((Object)(object)_root != (Object)null) { try { Object.Destroy((Object)(object)_root); } catch { } _root = null; } _mf = null; _mr = null; } internal void Dispose() { Destroy(); if ((Object)(object)_mat != (Object)null) { try { Object.Destroy((Object)(object)_mat); } catch { } _mat = null; } _builtSig = null; } } internal sealed class PlayAreaController { private const float GraceSeconds = 10f; private static readonly string[] OobClips = new string[4] { "beep", "alarm", "warning", "alert" }; private readonly GameModeController _ctl; private float _outsideSince = -1f; private float _nextBeep; internal bool LocalOutside { get; private set; } internal float GraceLeft { get; private set; } internal PlayAreaController(GameModeController ctl) { _ctl = ctl; } internal void Tick() { //IL_009d: 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_00a3: 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_0156: Unknown result type (might be due to invalid IL or missing references) LocalOutside = false; GraceLeft = 0f; GameState state = _ctl.State; if (state == null || state.AreaRadius <= 0f) { _outsideSince = -1f; return; } if (_ctl.Phase != RoundPhase.Hiding && _ctl.Phase != RoundPhase.Hunting) { _outsideSince = -1f; return; } PlayerRole localRole = _ctl.LocalRole; if (localRole != PlayerRole.Hider && localRole != PlayerRole.Hunter) { _outsideSince = -1f; return; } try { Player local = Player.Local; if ((Object)(object)local == (Object)null) { return; } Vector3 position = ((Component)local).transform.position; float num = position.x - state.AreaX; float num2 = position.z - state.AreaZ; if (Mathf.Sqrt(num * num + num2 * num2) > state.AreaRadius) { LocalOutside = true; if (_outsideSince < 0f) { _outsideSince = Time.time; } GraceLeft = Mathf.Max(0f, 10f - (Time.time - _outsideSince)); if (Time.time >= _nextBeep) { _nextBeep = Time.time + Mathf.Lerp(0.3f, 1f, Mathf.Clamp01(GraceLeft / 10f)); try { TauntSounds.PlayFx(OobClips, position, 0.6f); } catch { } } if (GraceLeft <= 0f) { if (localRole == PlayerRole.Hunter) { RoundEnvironment.TeleportLocalInto(state.AreaX, state.AreaY, state.AreaZ, _ctl.LocalId); } else { _ctl.ReportOutOfBounds(); } _outsideSince = Time.time; } } else { _outsideSince = -1f; } } catch (Exception) { } } } } namespace PropHunt.Phone { internal static class PhoneScreens { internal const int TabMatch = 0; internal const int TabPlayers = 1; internal const int TabSettings = 2; internal const int TabStats = 3; internal static readonly string[] TabLabels = new string[4] { "Match", "Players", "Settings", "Stats" }; internal static void Build(Transform body, GameModeController ctl, int tab, bool isHost, Transform dialogRoot) { ScrollRect val = default(ScrollRect); RectTransform list = Components.ScrollList(body, ref val, 8f); SmoothScroll.Attach(val); switch (tab) { case 1: BuildPlayers((Transform)(object)list, ctl, isHost); break; case 2: BuildSettings((Transform)(object)list, ctl, isHost); break; case 3: BuildStats((Transform)(object)list, ctl); break; default: BuildMatch((Transform)(object)list, ctl, isHost, dialogRoot); break; } try { Interactions.PolishButtons(body, true); } catch { } } private static void BuildMatch(Transform list, GameModeController ctl, bool isHost, Transform dialogRoot) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: 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_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Unknown result type (might be due to invalid IL or missing references) //IL_0310: 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_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) RoundPhase phase = ctl.Phase; int num = ((phase == RoundPhase.Lobby) ? ctl.LobbyMemberCount : ctl.State.Players.Count); switch (phase) { case RoundPhase.Lobby: Section(list, "Lobby"); Label(list, $"Players in the lobby: {num}", 13, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); if (isHost) { bool flag = num >= 2; Button(list, flag ? "START MATCH" : "START MATCH - need 2+ players", Theme.Accent, flag, 56f, delegate { ctl.BeginMatch(); }); Label(list, "Set the rules in the Settings tab, then start. Everyone in the lobby joins automatically.", 11, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); } else { Label(list, "Waiting for the host to start the match...", 16, Theme.TextPrimary, (FontStyle)1, (TextAnchor)4); } break; case RoundPhase.Safehouse: Section(list, $"Between rounds - next: round {ctl.State.RoundNumber + 1}"); Label(list, "Map: " + ctl.SafehouseName(ctl.State.SafehouseCode), 16, Theme.TextPrimary, (FontStyle)1, (TextAnchor)0); if (isHost) { Label(list, $"{ctl.SafehouseOptionCount} maps fit {num} players", 11, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); MapSwitchRow(list, ctl); Button(list, "START NEXT ROUND", Theme.Accent, enabled: true, 56f, delegate { ctl.BeginNextRound(); }); bool auto = ctl.Settings.AutoStartNextRound; Button(list, "Auto-start next round: " + (auto ? "ON" : "OFF"), auto ? Theme.Success : Theme.SurfaceInput, enabled: true, 44f, delegate { ctl.SetSetting("autostart", auto ? "0" : "1"); }); Label(list, "Tweak the rules in the Settings tab - changes apply to this next round.", 11, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); } else { Label(list, $"The host is setting up round {ctl.State.RoundNumber + 1}...", 13, Theme.TextMuted, (FontStyle)0, (TextAnchor)4); } if (ctl.State.SafehouseReady) { Label(list, "Doors opening - get ready!", 16, Theme.SuccessText, (FontStyle)1, (TextAnchor)4); } break; case RoundPhase.Hiding: case RoundPhase.Hunting: Section(list, $"Round {ctl.State.RoundNumber} - {phase}"); Label(list, (ctl.SecondsLeft > 0) ? $"Time left: {ctl.SecondsLeft}s" : "In progress", 16, Theme.TextPrimary, (FontStyle)1, (TextAnchor)0); Label(list, $"Hiders left: {ctl.AliveHiderCount}", 13, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); if (isHost) { ReturnToHubButton(list, ctl, dialogRoot, "End the match and return everyone to the Side Hustle hub?"); } else { Label(list, "The host runs the match. Track it here live.", 11, Theme.TextMuted, (FontStyle)0, (TextAnchor)4); } break; case RoundPhase.RoundEnd: WinnerHeadline(list, ctl); Label(list, (ctl.SecondsLeft > 0) ? $"Next round in {ctl.SecondsLeft}s..." : "Loading next round...", 13, Theme.TextMuted, (FontStyle)0, (TextAnchor)4); Label(list, "Full results are on the Stats tab.", 11, Theme.TextMuted, (FontStyle)0, (TextAnchor)4); break; case RoundPhase.MatchEnd: Section(list, "Match over"); WinnerHeadline(list, ctl); if (isHost) { ReturnToHubButton(list, ctl, dialogRoot, "Return everyone to the Side Hustle hub?"); } else { Label(list, "Returning to the hub...", 13, Theme.TextMuted, (FontStyle)0, (TextAnchor)4); } break; } } private static void MapSwitchRow(Transform list, GameModeController ctl) { //IL_0029: 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) GameObject val = RowGO(list, 40f); ValueTuple valueTuple = UIFactory.ButtonWithLabel("prevmap", "< Prev map", val.transform, Theme.Button, 0f, 36f); GameObject item = valueTuple.Item1; Button item2 = valueTuple.Item2; LayoutElement obj = item.AddComponent(); obj.flexibleWidth = 1f; obj.minHeight = 36f; ValueTuple valueTuple2 = UIFactory.ButtonWithLabel("nextmap", "Next map >", val.transform, Theme.Button, 0f, 36f); GameObject item3 = valueTuple2.Item1; Button item4 = valueTuple2.Item2; LayoutElement obj2 = item3.AddComponent(); obj2.flexibleWidth = 1f; obj2.minHeight = 36f; ((UnityEvent)item2.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { try { ctl.SwitchSafehouse(-1); } catch { } })); ((UnityEvent)item4.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { try { ctl.SwitchSafehouse(1); } catch { } })); } private static void ReturnToHubButton(Transform list, GameModeController ctl, Transform dialogRoot, string message) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) Button(list, "Return to hub", Theme.Danger, enabled: true, 48f, delegate { Components.ConfirmDialog(dialogRoot, "Return to hub", message, "Return to hub", (Action)delegate { ctl.RequestReturnToHub(); }); }); } private static void WinnerHeadline(Transform list, GameModeController ctl) { //IL_003c: 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_0046: 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_002e: Unknown result type (might be due to invalid IL or missing references) int winner = ctl.State.Winner; Label(list, winner switch { 1 => "HIDERS WIN", 0 => "HUNTERS WIN", _ => "ROUND OVER", }, 20, (Color)(winner switch { 1 => Theme.SuccessText, 0 => Theme.DangerText, _ => Theme.TextPrimary, }), (FontStyle)1, (TextAnchor)4); } private static void BuildPlayers(Transform list, GameModeController ctl, bool isHost) { //IL_00bb: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_019b: 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_01c0: Unknown result type (might be due to invalid IL or missing references) try { PlayerRegistry.Refresh(); } catch { } GameState state = ctl.State; RoundPhase phase = ctl.Phase; ulong localId = ctl.LocalId; List list2 = new List(state.Players.Values); list2.Sort((PlayerState a, PlayerState b) => RoleRank(a).CompareTo(RoleRank(b))); Section(list, $"Players ({list2.Count})"); if (list2.Count == 0) { Label(list, "No players yet.", 13, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); return; } foreach (PlayerState item in list2) { GameObject val = RowGO(list, 30f); bool flag = item.SteamId == localId; string text = NameOf(item) + (flag ? " (you)" : ""); Text obj2 = Col(val.transform, text, flag ? Theme.AccentBorder : Theme.TextPrimary, 0f, 1f, (TextAnchor)3, (FontStyle)(flag ? 1 : 0)); obj2.horizontalOverflow = (HorizontalWrapMode)0; obj2.verticalOverflow = (VerticalWrapMode)0; LayoutElement component = ((Component)obj2).gameObject.GetComponent(); if ((Object)(object)component != (Object)null) { component.minWidth = 0f; component.preferredWidth = 0f; } RoleChip(item, out var text2, out var fill, out var txt); ChipCol(val.transform, text2, fill, txt, 78f); Col(val.transform, DetailFor(ctl, item, phase, flag), Theme.TextMuted, (isHost && !flag) ? 96f : 140f, 0f, (TextAnchor)5, (FontStyle)0, 11); if (isHost && !flag && item.SteamId != 0L) { ulong target = item.SteamId; KickCol(val.transform, delegate { ctl.KickPlayer(target); }); } } } private static string DetailFor(GameModeController ctl, PlayerState p, RoundPhase phase, bool isMe) { bool flag = phase == RoundPhase.Hiding || phase == RoundPhase.Hunting; if (p.Role == PlayerRole.Hunter) { return $"{p.CatchesMade} catches"; } if (p.Role == PlayerRole.Hider) { if (p.Eliminated) { return "caught"; } if (isMe && flag) { string localPropName = ctl.LocalPropName; string text = $"{Mathf.Max(0, p.MaxHits - p.Hits)}/{p.MaxHits} HP"; if (!string.IsNullOrEmpty(localPropName)) { return localPropName + " - " + text; } return text; } if (!flag) { return "hider"; } return "hidden"; } if (!p.Eliminated) { return "waiting"; } return "spectating"; } private static void BuildSettings(Transform list, GameModeController ctl, bool isHost) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) bool flag = isHost; if (!isHost) { Label(list, "VIEW ONLY - the host runs the match.", 13, Theme.WarningText, (FontStyle)1, (TextAnchor)0); } else { Label(list, "Changes apply to the next round.", 11, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); } Dictionary dictionary = ctl.Settings.ToValues(); string text = null; SettingDescriptor[] array = PropHuntSettingsSpec.Build(); foreach (SettingDescriptor val in array) { if (!string.IsNullOrEmpty(val.Category) && val.Category != text) { Section(list, val.Category); text = val.Category; } string value; string val2 = (dictionary.TryGetValue(val.Key, out value) ? value : val.Default); if (flag) { BuildEditableRow(list, ctl, val, val2); } else { BuildReadonlyRow(list, val, val2); } } } private static void BuildEditableRow(Transform list, GameModeController ctl, SettingDescriptor s, string val) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0045: Expected I4, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_0190: 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_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Expected O, but got Unknown //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_058a: Unknown result type (might be due to invalid IL or missing references) //IL_05e3: Unknown result type (might be due to invalid IL or missing references) CultureInfo ci = CultureInfo.InvariantCulture; SettingType type = s.Type; switch ((int)type) { case 0: { Transform val3 = default(Transform); Components.FormRow(list, s.Label, s.Hint, ref val3, false, 50f); float num = ParseFloat(val, s.Min); float num2 = ((s.Step > 0f) ? s.Step : (s.WholeNumbers ? 1f : 0f)); Text lbl = UIFactory.Text("val", Fmt(num, s.WholeNumbers, s.Unit), val3, 14, (TextAnchor)5, (FontStyle)0); ((Graphic)lbl).color = Theme.TextPrimary; ((Graphic)lbl).raycastTarget = false; RectTransform rectTransform = ((Graphic)lbl).rectTransform; rectTransform.anchorMin = new Vector2(1f, 0f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.pivot = new Vector2(1f, 0.5f); rectTransform.sizeDelta = new Vector2(54f, 0f); rectTransform.anchoredPosition = new Vector2(-2f, 0f); RectTransform component = ((Component)Components.Slider(val3, s.Min, s.Max, num, (Action)delegate(float v) { lbl.text = Fmt(v, s.WholeNumbers, s.Unit); ctl.SetSetting(s.Key, s.WholeNumbers ? Mathf.RoundToInt(v).ToString(ci) : v.ToString("0.##", ci)); }, num2)).GetComponent(); component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.offsetMin = new Vector2(0f, -4f); component.offsetMax = new Vector2(-58f, 4f); break; } case 1: { Transform val4 = default(Transform); Components.FormRow(list, s.Label, s.Hint, ref val4, false, 50f); bool flag = val == "1" || string.Equals(val, "true", StringComparison.OrdinalIgnoreCase); RectTransform component2 = ((Component)Components.Toggle(val4, flag, (Action)delegate(bool v) { ctl.SetSetting(s.Key, v ? "1" : "0"); })).GetComponent(); component2.anchorMin = new Vector2(1f, 0.5f); component2.anchorMax = new Vector2(1f, 0.5f); component2.pivot = new Vector2(1f, 0.5f); component2.anchoredPosition = new Vector2(-2f, 0f); break; } case 2: { string[] opts2 = s.Options ?? new string[2] { "Off", "On" }; string[] vals2 = s.Values ?? opts2; int num3 = Math.Max(0, Array.IndexOf(vals2, val)); Transform val7 = default(Transform); Components.FormRow(list, s.Label, s.Hint, ref val7, opts2.Length > 2, 50f); Button[] array = default(Button[]); Fill(Components.Segmented(val7, opts2, num3, (Action)delegate(int i) { ctl.SetSetting(s.Key, (i >= 0 && i < vals2.Length) ? vals2[i] : opts2[i]); }, ref array, false, 6f, (Texture2D[])null)); break; } case 4: { string[] opts = s.Options ?? new string[2] { "Off", "On" }; string[] vals = s.Values ?? opts; int idx = Math.Max(0, Array.IndexOf(vals, val)); Transform val5 = default(Transform); Components.FormRow(list, s.Label, s.Hint, ref val5, false, 50f); GameObject val6 = new GameObject("dropdown"); val6.transform.SetParent(val5, false); val6.AddComponent(); Fill(val6); HorizontalLayoutGroup obj = val6.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = true; ((LayoutGroup)obj).childAlignment = (TextAnchor)5; ValueTuple valueTuple = UIFactory.ButtonWithLabel("prev", "<", val6.transform, Theme.Button, 36f, 30f); GameObject item = valueTuple.Item1; Button item2 = valueTuple.Item2; LayoutElement obj2 = item.AddComponent(); obj2.minWidth = 36f; obj2.preferredWidth = 36f; obj2.flexibleWidth = 0f; Text dl = UIFactory.Text("val", opts[idx], val6.transform, 14, (TextAnchor)4, (FontStyle)1); ((Graphic)dl).color = Theme.TextPrimary; ((Graphic)dl).raycastTarget = false; LayoutElement obj3 = ((Component)dl).gameObject.AddComponent(); obj3.minWidth = 100f; obj3.preferredWidth = 150f; obj3.flexibleWidth = 0f; ValueTuple valueTuple2 = UIFactory.ButtonWithLabel("next", ">", val6.transform, Theme.Button, 36f, 30f); GameObject item3 = valueTuple2.Item1; Button item4 = valueTuple2.Item2; LayoutElement obj4 = item3.AddComponent(); obj4.minWidth = 36f; obj4.preferredWidth = 36f; obj4.flexibleWidth = 0f; Action set = delegate(int i) { idx = (i % opts.Length + opts.Length) % opts.Length; dl.text = opts[idx]; ctl.SetSetting(s.Key, (idx < vals.Length) ? vals[idx] : opts[idx]); }; ((UnityEvent)item2.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { set(idx - 1); })); ((UnityEvent)item4.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { set(idx + 1); })); break; } case 3: { Transform val2 = default(Transform); Components.FormRow(list, s.Label, s.Hint, ref val2, true, 50f); Fill(((Component)Components.TextInput(val2, val ?? "", (Action)delegate(string t) { ctl.SetSetting(s.Key, t); }, (string)null, 64, false)).gameObject, 6f); break; } } } private static void BuildReadonlyRow(Transform list, SettingDescriptor s, string val) { //IL_0032: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Transform val2 = default(Transform); Components.FormRow(list, s.Label, s.Hint, ref val2, false, 50f); Text obj = UIFactory.Text("val", DisplayValue(s, val), val2, 14, (TextAnchor)5, (FontStyle)1); ((Graphic)obj).color = Theme.TextPrimary; ((Graphic)obj).raycastTarget = false; RectTransform rectTransform = ((Graphic)obj).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = new Vector2(0f, 0f); rectTransform.offsetMax = new Vector2(-4f, 0f); } private static string DisplayValue(SettingDescriptor s, string val) { //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) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected I4, but got Unknown SettingType type = s.Type; switch ((int)type) { case 1: if (!(val == "1") && !string.Equals(val, "true", StringComparison.OrdinalIgnoreCase)) { return "Off"; } return "On"; case 0: return Fmt(ParseFloat(val, s.Min), s.WholeNumbers, s.Unit); case 2: case 4: { string[] array = s.Values ?? s.Options; string[] array2 = s.Options ?? s.Values; if (array != null && array2 != null) { int num = Array.IndexOf(array, val); if (num >= 0 && num < array2.Length) { return array2[num]; } } if (!string.IsNullOrEmpty(val)) { return val; } return "None"; } default: if (!string.IsNullOrEmpty(val)) { return val; } return "-"; } } private static void BuildStats(Transform list, GameModeController ctl) { //IL_00dc: 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_0124: 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_00b8: 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_01bb: 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_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) try { PlayerRegistry.Refresh(); } catch { } List list2 = new List(ctl.State.Players.Values); list2.Sort((PlayerState a, PlayerState b) => b.SessScore.CompareTo(a.SessScore)); List list3 = BuildAwards(list2); if (list3.Count > 0) { Section(list, "Round awards"); foreach (string item in list3) { Label(list, item, 13, Theme.WarningText, (FontStyle)1, (TextAnchor)0); } } Section(list, "Leaderboard"); if (list2.Count == 0) { Label(list, "No players yet.", 13, Theme.TextMuted, (FontStyle)0, (TextAnchor)0); return; } GameObject obj2 = RowGO(list, 24f); Col(obj2.transform, "Player", Theme.TextMuted, 0f, 1f, (TextAnchor)3, (FontStyle)1, 11); Col(obj2.transform, "Catches", Theme.TextMuted, 64f, 0f, (TextAnchor)4, (FontStyle)1, 11); Col(obj2.transform, "Survived", Theme.TextMuted, 70f, 0f, (TextAnchor)4, (FontStyle)1, 11); Col(obj2.transform, "Score", Theme.TextMuted, 56f, 0f, (TextAnchor)5, (FontStyle)1, 11); int num = 1; foreach (PlayerState item2 in list2) { GameObject obj3 = RowGO(list, 28f); Col(obj3.transform, $"{num}. {NameOf(item2)}", Theme.TextPrimary, 0f, 1f, (TextAnchor)3, (FontStyle)0); Col(obj3.transform, item2.CatchesMade.ToString(), Theme.TextMuted, 64f, 0f, (TextAnchor)4, (FontStyle)0); Col(obj3.transform, item2.SurvivedSeconds + "s", Theme.TextMuted, 70f, 0f, (TextAnchor)4, (FontStyle)0); Col(obj3.transform, item2.SessScore.ToString(), Theme.AccentBorder, 56f, 0f, (TextAnchor)5, (FontStyle)1); num++; } } private static List BuildAwards(List players) { List list = new List(); AddAward(list, players, "Top Hunter", (PlayerState p) => p.CatchesMade, (PlayerState p, int v) => $"{NameOf(p)} - {v} catches"); AddAward(list, players, "Survivor", (PlayerState p) => (p.Role == PlayerRole.Hider) ? p.SurvivedSeconds : 0, (PlayerState p, int v) => $"{NameOf(p)} - {v}s alive"); AddAward(list, players, "Trickster", (PlayerState p) => p.DecoyBaits, (PlayerState p, int v) => $"{NameOf(p)} - {v} decoy baits"); AddAward(list, players, "Shocker", (PlayerState p) => p.StunsLanded, (PlayerState p, int v) => $"{NameOf(p)} - {v} stuns"); return list; } private static void AddAward(List list, List players, string title, Func sel, Func fmt) { PlayerState playerState = null; int num = 0; foreach (PlayerState player in players) { int num2 = sel(player); if (num2 > num) { num = num2; playerState = player; } } if (playerState != null && num > 0) { list.Add(title + ": " + fmt(playerState, num)); } } private static void Section(Transform list, string title) { Components.SectionHeader(list, title); } private static Text Label(Transform list, string text, int size, Color color, FontStyle style = (FontStyle)0, TextAnchor anchor = (TextAnchor)0) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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) Text obj = UIFactory.Text("label", text, list, size, anchor, style); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } private static Button Button(Transform list, string label, Color bg, bool enabled, float height, Action onClick) { //IL_001f: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) ValueTuple valueTuple = UIFactory.ButtonWithLabel("btn", label, list, enabled ? bg : Theme.Button, 0f, height); GameObject item = valueTuple.Item1; Button item2 = valueTuple.Item2; Text item3 = valueTuple.Item3; LayoutElement obj = item.AddComponent(); obj.minHeight = height; obj.preferredHeight = height; obj.flexibleWidth = 1f; Image component = item.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = Theme.RoundedSprite(); component.type = (Type)1; } if ((Object)(object)item3 != (Object)null) { ((Graphic)item3).color = (enabled ? Theme.TextPrimary : Theme.TextDisabled); item3.fontSize = 16; } ((Selectable)item2).interactable = enabled; if (enabled && onClick != null) { ((UnityEvent)item2.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { try { onClick(); } catch { } })); } return item2; } private static GameObject RowGO(Transform list, float height) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown GameObject val = new GameObject("row"); val.transform.SetParent(list, false); val.AddComponent(); LayoutElement obj = val.AddComponent(); obj.minHeight = height; obj.preferredHeight = height; obj.flexibleWidth = 1f; HorizontalLayoutGroup obj2 = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true; ((LayoutGroup)obj2).childAlignment = (TextAnchor)3; return val; } private static Text Col(Transform row, string text, Color color, float width, float flex, TextAnchor anchor, FontStyle style = (FontStyle)0, int size = 13) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Text obj = UIFactory.Text("c", text, row, size, anchor, style); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; obj.horizontalOverflow = (HorizontalWrapMode)1; obj.verticalOverflow = (VerticalWrapMode)0; LayoutElement val = ((Component)obj).gameObject.AddComponent(); if (width > 0f) { val.minWidth = width; val.preferredWidth = width; } val.flexibleWidth = flex; return obj; } private static void ChipCol(Transform row, string text, Color fill, Color textColor, float width) { //IL_0006: 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_0092: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) GameObject val = UIFactory.Panel("chip", row, fill, (Vector2?)null, (Vector2?)null, false); Image component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = Theme.RoundedSprite(); component.type = (Type)1; ((Graphic)component).raycastTarget = false; } LayoutElement obj = val.AddComponent(); obj.minWidth = width; obj.preferredWidth = width; obj.flexibleWidth = 0f; Text obj2 = UIFactory.Text("t", text, val.transform, 11, (TextAnchor)4, (FontStyle)1); ((Graphic)obj2).color = textColor; ((Graphic)obj2).raycastTarget = false; RectTransform rectTransform = ((Graphic)obj2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; } private static void KickCol(Transform row, Action onClick) { //IL_0018: 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) ValueTuple valueTuple = UIFactory.ButtonWithLabel("kick", "Kick", row, Theme.DangerSubtle, 0f, 26f); GameObject item = valueTuple.Item1; Button item2 = valueTuple.Item2; Text item3 = valueTuple.Item3; LayoutElement obj = item.AddComponent(); obj.minWidth = 52f; obj.preferredWidth = 52f; obj.flexibleWidth = 0f; obj.minHeight = 26f; obj.preferredHeight = 26f; Image component = item.GetComponent(); if ((Object)(object)component != (Object)null) { component.sprite = Theme.RoundedSprite(); component.type = (Type)1; } if ((Object)(object)item3 != (Object)null) { ((Graphic)item3).color = Theme.DangerText; item3.fontSize = 11; } if (onClick == null) { return; } ((UnityEvent)item2.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { try { onClick(); } catch { } })); } private static void RoleChip(PlayerState p, out string text, out Color fill, out Color txt) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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 (p.Role == PlayerRole.Hunter) { text = "HUNTER"; fill = Theme.DangerSubtle; txt = Theme.DangerText; } else if (p.Role == PlayerRole.Hider) { if (p.Eliminated) { text = "CAUGHT"; fill = Theme.WarningSubtle; txt = Theme.WarningText; } else { text = "HIDER"; fill = Theme.SuccessSubtle; txt = Theme.SuccessText; } } else { text = "SPEC"; fill = Theme.Button; txt = Theme.TextMuted; } } private static int RoleRank(PlayerState p) { if (p.Role == PlayerRole.Hunter) { return 0; } if (p.Role == PlayerRole.Hider) { if (!p.Eliminated) { return 1; } return 2; } return 3; } private static string NameOf(PlayerState p) { try { Player val = PlayerRegistry.Get(p.SteamId); if ((Object)(object)val != (Object)null) { string playerName = val.PlayerName; if (!string.IsNullOrEmpty(playerName)) { return playerName; } } } catch { } return "Player " + p.SteamId % 10000; } private static void Fill(GameObject go, float vInset = 0f) { //IL_001c: 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: 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) RectTransform component = go.GetComponent(); if (!((Object)(object)component == (Object)null)) { component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.offsetMin = new Vector2(0f, vInset); component.offsetMax = new Vector2(0f, 0f - vInset); } } private static string Fmt(float v, bool whole, string unit) { string text = (whole ? Mathf.RoundToInt(v).ToString() : v.ToString("0.##", CultureInfo.InvariantCulture)); if (!string.IsNullOrEmpty(unit)) { return text + " " + unit; } return text; } private static float ParseFloat(string s, float fallback) { if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return fallback; } return result; } } public class PropHuntPhoneApp : PhoneApp { private static Sprite _icon; private static bool _iconAbsent; private Text _title; private Text _status; private Text _badge; private GameObject _contentRegion; private GameObject _body; private Transform _dialogRoot; private GameObject _container; private bool _activated; private Button[] _tabButtons; private int _tab; private string _lastSig; internal static PropHuntPhoneApp Instance { get; private set; } protected override string AppName => "PropHuntApp"; protected override string AppTitle => "PropHunt"; protected override string IconLabel => "PropHunt"; protected override string IconFileName => "PropHunt.png"; protected override Sprite IconSprite { get { if ((Object)(object)_icon != (Object)null) { return _icon; } if (_iconAbsent) { return null; } _icon = LoadEmbeddedIcon(); if ((Object)(object)_icon == (Object)null) { _iconAbsent = true; } return _icon; } } private static Sprite LoadEmbeddedIcon() { //IL_004f: 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_005c: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PropHunt.Assets.phone_icon.png"); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { filterMode = (FilterMode)1 }; ((Object)val).hideFlags = (HideFlags)32; if (ImageConversion.LoadImage(val, Il2CppStructArray.op_Implicit(array))) { Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); if ((Object)(object)val2 != (Object)null) { ((Object)val2).hideFlags = (HideFlags)32; } return val2; } return null; } catch (Exception ex) { Core.Log.Warning("[PropHunt] phone icon load failed: " + ex.Message); return null; } } protected override void OnCreatedUI(GameObject container) { Instance = this; _container = container; try { BuildUI(container); } catch (Exception ex) { Core.Log.Warning("[PropHunt] phone app build failed: " + ex.Message); } } private static GameObject Band(string name, Transform parent, Color color, float y0, float y1) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0031: 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) GameObject obj = UIFactory.Panel(name, parent, color, (Vector2?)new Vector2(0f, y0), (Vector2?)new Vector2(1f, y1), false); RectTransform component = obj.GetComponent(); component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; return obj; } private void BuildUI(GameObject container) { //IL_000b: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00df: 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_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) GameObject val = UIFactory.Panel("ph_root", container.transform, Theme.BgBase, (Vector2?)null, (Vector2?)null, true); ((Transform)val.GetComponent()).localScale = Vector3.one; _dialogRoot = val.transform; GameObject obj = UIFactory.Panel("ph_safe", val.transform, Theme.Clear, (Vector2?)null, (Vector2?)null, true); RectTransform component = obj.GetComponent(); float num; if (!((Object)(object)container.GetComponent() != (Object)null)) { num = 0f; } else { Rect rect = container.GetComponent().rect; num = ((Rect)(ref rect)).width; } float num2 = num; if (num2 > 1f) { float num3 = num2 * 0.012f; component.offsetMin = new Vector2(num3, num3); component.offsetMax = new Vector2(0f - num3, 0f - num3); } Transform transform = obj.transform; GameObject val2 = Band("ph_header", transform, Theme.BgPanel, 0.9f, 1f); _title = UIFactory.Text("ph_title", "PropHunt", val2.transform, 16, (TextAnchor)3, (FontStyle)1); ((Graphic)_title).color = Theme.Accent; AnchorText(_title, new Vector2(0f, 0f), new Vector2(0.32f, 1f), 12f); _status = UIFactory.Text("ph_status", "", val2.transform, 16, (TextAnchor)4, (FontStyle)1); ((Graphic)_status).color = Theme.TextPrimary; AnchorText(_status, new Vector2(0.32f, 0f), new Vector2(0.74f, 1f), 4f); _badge = UIFactory.Text("ph_badge", "", val2.transform, 11, (TextAnchor)5, (FontStyle)1); ((Graphic)_badge).color = Theme.TextMuted; AnchorText(_badge, new Vector2(0.74f, 0f), new Vector2(1f, 1f), 12f); GameObject val3 = Band("ph_tabs", transform, Theme.BgBase, 0.82f, 0.9f); _tabButtons = BuildTabs(val3.transform); _contentRegion = Band("ph_content", transform, Theme.BgBase, 0f, 0.82f); RebuildTab(); RefreshHeader(); try { Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate(val.GetComponent()); Il2CppArrayBase componentsInChildren = val.GetComponentsInChildren(true); if (componentsInChildren == null) { return; } foreach (Text item in componentsInChildren) { if ((Object)(object)item != (Object)null) { ((Graphic)item).SetAllDirty(); } } } catch { } } internal void Tick() { try { if (!((PhoneApp)this).IsOpen()) { return; } if (!_activated) { _activated = true; if ((Object)(object)_container != (Object)null) { try { UIFactory.ClearChildren(_container.transform); BuildUI(_container); } catch (Exception ex) { Core.Log.Warning("[PropHunt] phone UI rebuild failed: " + ex.Message); } } try { GuideQuest.OnAppOpened(); } catch { } } RefreshHeader(); string text = Signature(); if (text != _lastSig) { _lastSig = text; RebuildTab(); } SmoothScroll.Tick(PhoneCamera()); } catch { } } private void SwitchTab(int tab) { if (tab != _tab) { _tab = tab; RecolorTabs(); _lastSig = null; RebuildTab(); } } private Button[] BuildTabs(Transform tabBar) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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) int num = PhoneScreens.TabLabels.Length; Button[] array = (Button[])(object)new Button[num]; for (int i = 0; i < num; i++) { int idx = i; ValueTuple valueTuple = UIFactory.ButtonWithLabel("seg_" + i, PhoneScreens.TabLabels[i], tabBar, (i == _tab) ? Theme.Accent : Theme.Button, 0f, 0f); GameObject item = valueTuple.Item1; Button item2 = valueTuple.Item2; Text item3 = valueTuple.Item3; RectTransform component = item.GetComponent(); component.anchorMin = new Vector2((float)i / (float)num, 0f); component.anchorMax = new Vector2((float)(i + 1) / (float)num, 1f); component.offsetMin = new Vector2((i == 0) ? 0f : 3f, 4f); component.offsetMax = new Vector2((i == num - 1) ? 0f : (-3f), -4f); Image component2 = item.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sprite = Theme.RoundedSprite(); component2.type = (Type)1; } if ((Object)(object)item3 != (Object)null) { item3.fontSize = 14; ((Graphic)item3).color = Theme.TextPrimary; item3.horizontalOverflow = (HorizontalWrapMode)1; } ((UnityEvent)item2.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { SwitchTab(idx); })); array[i] = item2; } return array; } private void RecolorTabs() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (_tabButtons == null) { return; } for (int i = 0; i < _tabButtons.Length; i++) { if (!((Object)(object)_tabButtons[i] == (Object)null)) { Image val = ((Component)_tabButtons[i]).GetComponent(); if ((Object)(object)val == (Object)null) { Graphic targetGraphic = ((Selectable)_tabButtons[i]).targetGraphic; val = (Image)(object)((targetGraphic is Image) ? targetGraphic : null); } if ((Object)(object)val != (Object)null) { ((Graphic)val).color = ((i == _tab) ? Theme.Accent : Theme.Button); } } } } private void RefreshHeader() { //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_status == (Object)null) { return; } GameModeController active = GameModeController.Active; if (active == null) { _status.text = "No active match"; if ((Object)(object)_badge != (Object)null) { _badge.text = ""; } return; } int secondsLeft = active.SecondsLeft; _status.text = ((secondsLeft > 0) ? $"{active.Phase} - {secondsLeft}s" : active.Phase.ToString()); if ((Object)(object)_badge != (Object)null) { _badge.text = (active.IsHost ? "HOST" : "VIEW ONLY"); } if ((Object)(object)_badge != (Object)null) { ((Graphic)_badge).color = (active.IsHost ? Theme.Accent : Theme.WarningText); } } private void RebuildTab() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_contentRegion == (Object)null) { return; } SmoothScroll.Clear(); GameObject body = _body; _body = UIFactory.Panel("ph_body", _contentRegion.transform, Theme.BgBase, (Vector2?)null, (Vector2?)null, true); GameModeController active = GameModeController.Active; if (active == null) { BuildEmptyState(_body.transform); } else { try { PhoneScreens.Build(_body.transform, active, _tab, active.IsHost, _dialogRoot); } catch (Exception ex) { Core.Log.Warning("[PropHunt] phone tab build failed: " + ex.Message); } } _lastSig = Signature(); if ((Object)(object)body != (Object)null) { Object.Destroy((Object)(object)body); } } private static void BuildEmptyState(Transform parent) { //IL_0015: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) Text obj = UIFactory.Text("empty", "No PropHunt match active.\n\nLaunch one from the main menu:\nSide Hustle -> PropHunt.", parent, 13, (TextAnchor)4, (FontStyle)0); ((Graphic)obj).color = Theme.TextMuted; ((Graphic)obj).raycastTarget = false; ((Graphic)obj).rectTransform.anchorMin = Vector2.zero; ((Graphic)obj).rectTransform.anchorMax = Vector2.one; ((Graphic)obj).rectTransform.offsetMin = new Vector2(16f, 16f); ((Graphic)obj).rectTransform.offsetMax = new Vector2(-16f, -16f); } private string Signature() { GameModeController active = GameModeController.Active; if (active == null) { return "none|" + _tab; } GameState state = active.State; string text = $"{_tab}|{state.Phase}|{state.RoundNumber}|{state.Winner}|{state.Players.Count}|{active.AliveHiderCount}|{active.IsHost}|{state.SafehouseCode}|{state.SafehouseReady}"; if (_tab == 1 || _tab == 3) { text = text + "|" + Mathf.FloorToInt(Time.unscaledTime); } if (_tab == 0) { if (state.Phase == RoundPhase.Lobby) { text = text + "|lm" + active.LobbyMemberCount; } text = text + "|as" + ((active.Settings != null && active.Settings.AutoStartNextRound) ? 1 : 0); } if (_tab == 2 && !active.IsHost) { text = text + "|" + state.SettingsBlob; } return text; } private static Camera PhoneCamera() { try { GameplayMenu instance = Singleton.Instance; return ((Object)(object)instance != (Object)null) ? instance.OverlayCamera : null; } catch { return null; } } private static void AnchorText(Text t, Vector2 min, Vector2 max, float inset) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) RectTransform rectTransform = ((Graphic)t).rectTransform; rectTransform.anchorMin = min; rectTransform.anchorMax = max; rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.offsetMin = new Vector2(inset, 0f); rectTransform.offsetMax = new Vector2(0f - inset, 0f); } } } namespace PropHunt.Patches { [HarmonyPatch(typeof(GameInput), "OnToggleFlashlight")] internal static class FlashlightSuppressPatch { private static bool Prefix() { GameModeController active = GameModeController.Active; if (active != null) { return !active.RoundActive; } return true; } } [HarmonyPatch(typeof(FXManager), "CreateImpactFX")] internal static class ImpactFxSuppressPatch { private static bool Prefix(IDamageable target) { try { GameModeController active = GameModeController.Active; if (active == null || !active.RoundActive) { return true; } if (target != null && (Object)(object)((Il2CppObjectBase)target).TryCast() != (Object)null) { return false; } } catch { } return true; } } [HarmonyPatch(typeof(PlayerCamera), "ViewAvatar")] internal static class HunterNoThirdPersonPrefix { private static bool Prefix() { try { GameModeController active = GameModeController.Active; if (active == null) { return true; } if (active.LocalRole == PlayerRole.Hunter) { return false; } return true; } catch { return true; } } } internal static class RoundInteractionGate { internal static bool RoundActive => GameModeController.Active?.RoundActive ?? false; } [HarmonyPatch(typeof(InteractableObject), "ShowMessage")] internal static class HideInteractionPromptPatch { private static bool Prefix() { return !RoundInteractionGate.RoundActive; } } [HarmonyPatch(typeof(InteractionManager), "CheckInteraction")] internal static class BlockPickupInteractionPatch { private static bool Prefix(InteractionManager __instance) { try { if (!RoundInteractionGate.RoundActive) { return true; } InteractableObject hoveredInteractableObject = __instance.HoveredInteractableObject; if ((Object)(object)hoveredInteractableObject == (Object)null) { return true; } if (Equippable_TrashGrabber.IsEquipped && IsTrash(hoveredInteractableObject)) { return true; } if (IsPickup(hoveredInteractableObject)) { return false; } } catch { } return true; } private static bool IsTrash(InteractableObject io) { try { return (Object)(object)((Component)io).GetComponentInParent() != (Object)null; } catch { return false; } } private static bool IsPickup(InteractableObject io) { try { if ((Object)(object)((Component)io).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)io).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)io).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)io).GetComponentInParent() != (Object)null) { return true; } } catch { } return false; } } [HarmonyPatch(typeof(InteractionManager), "CheckRightClick")] internal static class BlockRightClickPickupPatch { private static bool Prefix() { return !RoundInteractionGate.RoundActive; } } [HarmonyPatch(typeof(POI), "Update")] internal static class MapVisibilityPatch { private static void Postfix(POI __instance) { try { RectTransform uI = __instance.UI; if ((Object)(object)uI == (Object)null) { return; } Player val = OwnerOf(__instance); if ((Object)(object)val == (Object)null) { return; } bool flag = true; GameModeController active = GameModeController.Active; if (active != null && active.RoundActive) { ulong num = PlayerRegistry.IdForPlayer(val); if (num != 0L && num != active.LocalId) { flag = CanLocalSeeOnMap(active.LocalRole, active.RoleOf(num), active.Settings); } } GameObject gameObject = ((Component)uI).gameObject; if (gameObject.activeSelf != flag) { gameObject.SetActive(flag); } } catch { } } private static Player OwnerOf(POI poi) { try { List playerList = Player.PlayerList; if (playerList != null) { for (int i = 0; i < playerList.Count; i++) { Player val = playerList[i]; if ((Object)(object)val != (Object)null && (Object)(object)val.PoI == (Object)(object)poi) { return val; } } } } catch { } return null; } private static bool CanLocalSeeOnMap(PlayerRole local, PlayerRole target, RoundSettings set) { switch (local) { case PlayerRole.Spectator: return true; case PlayerRole.Hunter: return target != PlayerRole.Hider; case PlayerRole.Hider: switch (target) { case PlayerRole.Hunter: return true; case PlayerRole.Hider: if (set != null) { return set.Caught != CaughtBehavior.Infection; } return true; default: return true; } default: return true; } } } [HarmonyPatch(typeof(Player), "PassOut")] internal static class PassOutKnockbackPatch { private const float Impulse = 30f; private static void Postfix(Player __instance) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) try { GameModeController active = GameModeController.Active; if (active == null || !active.RoundActive || (Object)(object)__instance == (Object)null) { return; } ulong id = PlayerRegistry.IdForPlayer(__instance); if (active.TryGetKnock(id, out var kx, out var kz)) { Avatar avatar = __instance.Avatar; Rigidbody val = ((avatar != null) ? avatar.MiddleSpineRB : null); if (!((Object)(object)val == (Object)null)) { val.AddForce(-((Component)__instance).transform.forward * 30f, (ForceMode)2); Vector3 val2 = new Vector3(kx, 0f, kz); val.AddForce(((Vector3)(ref val2)).normalized * 30f, (ForceMode)2); } } } catch { } } } [HarmonyPatch(typeof(PassOutScreen), "Open")] internal static class PassOutScreenGatePatch { private static bool Prefix() { GameModeController active = GameModeController.Active; if (active != null) { return !active.RoundActive; } return true; } } [HarmonyPatch(typeof(PlayerCamera), "LateUpdate")] internal static class PlayerCameraThirdPersonPatch { private static float _tpResolved; private static void Postfix(PlayerCamera __instance) { //IL_0166: 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_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00c6: 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) //IL_00ca: 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) //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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0140: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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_01fb: 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_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: 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_021b: Unknown result type (might be due to invalid IL or missing references) if (BodyCam.Active) { BodyCam.Track(__instance); return; } if (!SpectatorCam.Active && !ThirdPersonView.Active) { _tpResolved = 0f; return; } try { Camera camera = __instance.Camera; if ((Object)(object)camera == (Object)null) { return; } Transform transform = ((Component)camera).transform; if (SpectatorCam.Active && (Object)(object)SpectatorCam.Target != (Object)null) { Vector3 val = SpectatorCam.Target.position + Vector3.up * 1.2f; Vector3 forward = SpectatorCam.Target.forward; if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { forward = Vector3.forward; } Vector3 val2 = val - forward * SpectatorCam.Distance + Vector3.up * SpectatorCam.Height; Vector3 val3 = val2 - val; float magnitude = ((Vector3)(ref val3)).magnitude; RaycastHit val4 = default(RaycastHit); if (magnitude > 0.01f && Physics.Raycast(val, val3 / magnitude, ref val4, magnitude)) { val2 = ((RaycastHit)(ref val4)).point - val3 / magnitude * 0.2f; } transform.position = val2; Vector3 val5 = val - val2; if (((Vector3)(ref val5)).sqrMagnitude > 0.0001f) { transform.rotation = Quaternion.LookRotation(((Vector3)(ref val5)).normalized, Vector3.up); } } else if (ThirdPersonView.Active) { Vector3 position = transform.position; Vector3 val6 = -transform.forward; float num = ThirdPersonView.Distance; RaycastHit val7 = default(RaycastHit); if (Physics.Raycast(position, val6, ref val7, num + 0.3f)) { num = Mathf.Max(0.3f, ((RaycastHit)(ref val7)).distance - 0.3f); } if (_tpResolved <= 0f) { _tpResolved = num; } float num2 = ((num < _tpResolved) ? 40f : 8f); _tpResolved = Mathf.Lerp(_tpResolved, num, 1f - Mathf.Exp((0f - num2) * Time.deltaTime)); transform.position = position + val6 * _tpResolved + Vector3.up * ThirdPersonView.Height; } } catch { } } } internal static class PropCollisionState { internal static float TargetHeight; } internal static class SlowWalk { private const float CrouchFactor = 0.5f; private static float _roleFactor = 1f; private static bool _slow; private static bool _applied; private static float _base = 1f; internal static void SetRoleFactor(float factor) { _roleFactor = ((factor <= 0f) ? 1f : factor); Apply(); } internal static void Set(bool slow) { _slow = slow; Apply(); } private static void Apply() { try { float num = _roleFactor * (_slow ? 0.5f : 1f); if (num > 0.999f && num < 1.001f) { if (_applied) { PlayerMovement.StaticMoveSpeedMultiplier = _base; _applied = false; } return; } if (!_applied) { _base = PlayerMovement.StaticMoveSpeedMultiplier; _applied = true; } PlayerMovement.StaticMoveSpeedMultiplier = _base * num; } catch { _applied = false; } } internal static void Restore() { _slow = false; _roleFactor = 1f; Apply(); } } [HarmonyPatch(typeof(PlayerMovement), "TryToggleCrouch")] internal static class PlayerCrouchBlockPrefix { private static bool Prefix() { try { GameModeController active = GameModeController.Active; if (active == null) { return true; } if (active.LocalRole != PlayerRole.Hider) { return true; } if (active.LocalPropId < 0) { return true; } return false; } catch { return true; } } } [HarmonyPatch(typeof(PauseMenu), "StuckButtonClicked")] internal static class BlockStuckButtonPatch { private static bool Prefix() { GameModeController active = GameModeController.Active; if (active == null) { return true; } RoundPhase phase = active.Phase; if (phase != RoundPhase.Safehouse) { return phase != RoundPhase.Lobby; } return false; } } [HarmonyPatch(typeof(PhysicsDamageable), "ReceiveImpact")] internal static class BlockPhysicsImpactPatch { private static bool Prefix() { return !RoundInteractionGate.RoundActive; } } [HarmonyPatch(typeof(TrashItem), "SetPhysicsActive")] internal static class FreezeTrashPatch { private static bool Prefix(TrashItem __instance, bool active) { if (!RoundInteractionGate.RoundActive) { return true; } if (active) { try { Rigidbody component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { component.isKinematic = true; } } catch { } return false; } return true; } } internal static class WeaponPatchGate { internal static bool HunterInRound() { GameModeController active = GameModeController.Active; if (active != null && active.RoundActive) { return active.LocalRole == PlayerRole.Hunter; } return false; } } [HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")] internal static class TasedNoFirePatch { private static bool Prefix() { GameModeController active = GameModeController.Active; if (active == null || !active.RoundActive) { return true; } if (active.LocalDowned) { return false; } Player local = Player.Local; if ((Object)(object)local != (Object)null) { return !local.IsTased; } return true; } } [HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")] internal static class HunterRangedCatchPatch { private static void Postfix() { if (!WeaponPatchGate.HunterInRound()) { return; } try { GameModeController.Active?.OnLocalHunterFired(150f); } catch { } } } [HarmonyPatch(typeof(Equippable_MeleeWeapon), "ExecuteHit")] internal static class HunterMeleeCatchPatch { private static void Postfix() { if (!WeaponPatchGate.HunterInRound()) { return; } try { GameModeController.Active?.OnLocalHunterFired(4f); } catch { } } } [HarmonyPatch(typeof(Equippable_RangedWeapon), "GetMagazine")] internal static class HunterInfiniteMagazinePatch { private static void Postfix(Equippable_RangedWeapon __instance, ref bool __result, ref StorableItemInstance mag) { if (!WeaponPatchGate.HunterInRound()) { return; } int num = ((__instance.MagazineSize > 0) ? __instance.MagazineSize : 7) * 5; if (__result && mag != null) { try { IntegerItemInstance val = ((Il2CppObjectBase)mag).TryCast(); if (val != null) { val.SetValue(num); } return; } catch { return; } } try { StorableItemDefinition magazine = __instance.Magazine; if ((Object)(object)magazine == (Object)null) { return; } ItemInstance defaultInstance = ((ItemDefinition)magazine).GetDefaultInstance(num); if (defaultInstance != null) { IntegerItemInstance val2 = ((Il2CppObjectBase)defaultInstance).TryCast(); if (val2 != null) { val2.SetValue(num); } StorableItemInstance val3 = ((Il2CppObjectBase)defaultInstance).TryCast(); if (val3 != null) { mag = val3; __result = true; } } } catch { } } } } namespace PropHunt.Net { internal static class MsgCodec { internal static string Str(byte[] d) { return Encoding.UTF8.GetString(d ?? Array.Empty()); } internal static byte[] Bytes(string s) { return Encoding.UTF8.GetBytes(s ?? string.Empty); } internal static int I(string s) { if (!int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return 0; } return result; } internal static ulong U(string s) { if (!ulong.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return 0uL; } return result; } internal static string Of(int v) { return v.ToString(CultureInfo.InvariantCulture); } internal static string Of(ulong v) { return v.ToString(CultureInfo.InvariantCulture); } internal static float F(string s) { if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return 0f; } return result; } internal static string Of(float v) { return v.ToString(CultureInfo.InvariantCulture); } } public class SelectPropMessage : P2PMessage { public override string MessageType => "PH_SELECT"; public int PropId { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes(MsgCodec.Of(PropId)); } public override void Deserialize(byte[] data) { PropId = MsgCodec.I(MsgCodec.Str(data)); } } public class LockPropMessage : P2PMessage { public override string MessageType => "PH_LOCK"; public bool Locked { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes(Locked ? "1" : "0"); } public override void Deserialize(byte[] data) { Locked = MsgCodec.Str(data) == "1"; } } public class RotatePropMessage : P2PMessage { public override string MessageType => "PH_ROT"; public float Yaw { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes(MsgCodec.Of(Yaw)); } public override void Deserialize(byte[] data) { Yaw = MsgCodec.F(MsgCodec.Str(data)); } } public class DropDecoyMessage : P2PMessage { public override string MessageType => "PH_DECOY"; public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public float Yaw { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes($"{MsgCodec.Of(X)};{MsgCodec.Of(Y)};{MsgCodec.Of(Z)};{MsgCodec.Of(Yaw)}"); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(';'); if (array.Length >= 4) { X = MsgCodec.F(array[0]); Y = MsgCodec.F(array[1]); Z = MsgCodec.F(array[2]); Yaw = MsgCodec.F(array[3]); } } } public class ConcussMessage : P2PMessage { public override string MessageType => "PH_CONC"; public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes($"{MsgCodec.Of(X)};{MsgCodec.Of(Y)};{MsgCodec.Of(Z)}"); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(';'); if (array.Length >= 3) { X = MsgCodec.F(array[0]); Y = MsgCodec.F(array[1]); Z = MsgCodec.F(array[2]); } } } public class ClaimTagMessage : P2PMessage { public override string MessageType => "PH_TAG"; public ulong VictimSteamId { get; set; } public float DirX { get; set; } public float DirY { get; set; } public float DirZ { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes($"{MsgCodec.Of(VictimSteamId)};{MsgCodec.Of(DirX)};{MsgCodec.Of(DirY)};{MsgCodec.Of(DirZ)}"); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(';'); if (array.Length >= 1) { VictimSteamId = MsgCodec.U(array[0]); } if (array.Length >= 4) { DirX = MsgCodec.F(array[1]); DirY = MsgCodec.F(array[2]); DirZ = MsgCodec.F(array[3]); } } } public class HitHunterMessage : P2PMessage { public override string MessageType => "PH_FF"; public ulong VictimSteamId { get; set; } public float DirX { get; set; } public float DirY { get; set; } public float DirZ { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes($"{MsgCodec.Of(VictimSteamId)};{MsgCodec.Of(DirX)};{MsgCodec.Of(DirY)};{MsgCodec.Of(DirZ)}"); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(';'); if (array.Length >= 1) { VictimSteamId = MsgCodec.U(array[0]); } if (array.Length >= 4) { DirX = MsgCodec.F(array[1]); DirY = MsgCodec.F(array[2]); DirZ = MsgCodec.F(array[3]); } } } public class OutOfBoundsMessage : P2PMessage { public override string MessageType => "PH_OOB"; public override byte[] Serialize() { return MsgCodec.Bytes("1"); } public override void Deserialize(byte[] data) { } } public class DecoyHitMessage : P2PMessage { public override string MessageType => "PH_DECOY_HIT"; public int DecoyIndex { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes(MsgCodec.Of(DecoyIndex)); } public override void Deserialize(byte[] data) { DecoyIndex = MsgCodec.I(MsgCodec.Str(data)); } } public class ManualTauntMessage : P2PMessage { public override string MessageType => "PH_TAUNT_REQ"; public string Sound { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes(string.IsNullOrEmpty(Sound) ? "*" : Sound); } public override void Deserialize(byte[] data) { string text = MsgCodec.Str(data); Sound = ((text == "*") ? null : text); } } public class TauntMessage : P2PMessage { public override string MessageType => "PH_TAUNT"; public ulong SteamId { get; set; } public string Sound { get; set; } public bool IsWhistle { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes(MsgCodec.Of(SteamId) + ";" + Sound + ";" + (IsWhistle ? "1" : "0")); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(new char[1] { ';' }, 3); SteamId = MsgCodec.U(array[0]); Sound = ((array.Length >= 2) ? array[1] : ""); IsWhistle = array.Length >= 3 && array[2] == "1"; } } public class CatchFxMessage : P2PMessage { public override string MessageType => "PH_FX_CATCH"; public ulong HunterId { get; set; } public ulong VictimId { get; set; } public bool Caught { get; set; } public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes($"{MsgCodec.Of(HunterId)};{MsgCodec.Of(VictimId)};{(Caught ? "1" : "0")};{MsgCodec.Of(X)};{MsgCodec.Of(Y)};{MsgCodec.Of(Z)}"); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(';'); if (array.Length >= 6) { HunterId = MsgCodec.U(array[0]); VictimId = MsgCodec.U(array[1]); Caught = array[2] == "1"; X = MsgCodec.F(array[3]); Y = MsgCodec.F(array[4]); Z = MsgCodec.F(array[5]); } } } public class StunFxMessage : P2PMessage { public override string MessageType => "PH_FX_STUN"; public ulong ThrowerId { get; set; } public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes($"{MsgCodec.Of(ThrowerId)};{MsgCodec.Of(X)};{MsgCodec.Of(Y)};{MsgCodec.Of(Z)}"); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(';'); if (array.Length >= 4) { ThrowerId = MsgCodec.U(array[0]); X = MsgCodec.F(array[1]); Y = MsgCodec.F(array[2]); Z = MsgCodec.F(array[3]); } } } public class DecoyFxMessage : P2PMessage { public override string MessageType => "PH_FX_DECOY"; public ulong HunterId { get; set; } public float X { get; set; } public float Y { get; set; } public float Z { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes($"{MsgCodec.Of(HunterId)};{MsgCodec.Of(X)};{MsgCodec.Of(Y)};{MsgCodec.Of(Z)}"); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(';'); if (array.Length >= 4) { HunterId = MsgCodec.U(array[0]); X = MsgCodec.F(array[1]); Y = MsgCodec.F(array[2]); Z = MsgCodec.F(array[3]); } } } internal static class NetKeys { internal const string State = "ph_state"; } internal static class PropHuntNet { private static SteamNetworkClient _client; private static bool _ready; private static int _idlePump; internal static bool Ready => _ready; internal static SteamNetworkClient Client => _client; internal static ulong LocalSteamId { get { try { return _ready ? _client.LocalPlayerId64 : 0; } catch { return 0uL; } } } internal static bool InLobby { get { try { return _ready && _client.IsInLobby; } catch { return false; } } } internal static bool IsHost { get { try { return _ready && _client.IsHost; } catch { return false; } } } internal static void Initialize() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown if (_ready) { return; } try { _client = new SteamNetworkClient(); SteamNetworkException ex = default(SteamNetworkException); if (_client.TryInitialize(ref ex)) { _ready = true; Core.Log.Msg("[Net] SteamNetworkLib ready (auto-attaches to the game's Steam lobby)."); } else { _client = null; } } catch (Exception ex2) { Core.Log.Warning("[Net] init failed: " + ex2.Message); _client = null; } } internal static void Tick() { if (!_ready || (!InLobby && (++_idlePump & 0x1F) != 0)) { return; } try { _client.ProcessIncomingMessages(); } catch (Exception) { } } internal static int MemberCount() { try { return _client.GetLobbyMembers().Count; } catch { return -1; } } } public class SafehouseDoorLockMessage : P2PMessage { public override string MessageType => "PH_SH_DOOR"; public string PropertyCode { get; set; } public bool Locked { get; set; } public override byte[] Serialize() { return MsgCodec.Bytes(PropertyCode + ";" + (Locked ? "1" : "0")); } public override void Deserialize(byte[] data) { string[] array = MsgCodec.Str(data).Split(new char[1] { ';' }, 2); PropertyCode = array[0]; Locked = array.Length >= 2 && array[1] == "1"; } } } namespace PropHunt.Music { internal static class RoundMusicController { private static string _active; private static bool _muted; private static float _userVolume = -1f; private static float _target = -1f; private static bool _fading; private const float FadeSeconds = 1.6f; internal static string Active => _active ?? ""; internal static void Play(string trackName) { if (string.IsNullOrEmpty(trackName)) { return; } try { MusicManager instance = Singleton.Instance; if ((Object)(object)instance == (Object)null) { return; } if (!string.IsNullOrEmpty(_active) && _active != trackName) { try { instance.StopTrack(_active); } catch { } } instance.SetTrackEnabled(trackName, true); _active = trackName; if (_muted) { _muted = false; if (_userVolume >= 0f) { FadeTo(_userVolume); } } } catch (Exception) { } } internal static void MuteForHunt() { if (!_muted && !_fading) { float num = ReadUserVolume(); if (num >= 0f) { _userVolume = num; } } if (!(_userVolume < 0f)) { _muted = true; FadeTo(0f); } } internal static void Tick(float dt) { if (!_fading) { return; } try { AudioManager instance = Singleton.Instance; if ((Object)(object)instance == (Object)null) { _fading = false; return; } float volume = instance.GetVolume((EAudioType)4, false); float num = ((_userVolume > 0.0001f) ? _userVolume : 1f); float num2 = Mathf.MoveTowards(volume, _target, num / 1.6f * dt); instance.SetVolume((EAudioType)4, num2); if (Mathf.Approximately(num2, _target)) { _fading = false; } } catch { _fading = false; } } private static float ReadUserVolume() { try { AudioManager instance = Singleton.Instance; if ((Object)(object)instance != (Object)null) { return instance.GetVolume((EAudioType)4, false); } } catch { } return -1f; } private static void FadeTo(float target) { _target = target; _fading = true; } internal static void Stop() { _fading = false; try { AudioManager instance = Singleton.Instance; if ((Object)(object)instance != (Object)null && _userVolume >= 0f) { instance.SetVolume((EAudioType)4, _userVolume); } } catch { } try { MusicManager instance2 = Singleton.Instance; if ((Object)(object)instance2 != (Object)null && !string.IsNullOrEmpty(_active)) { instance2.SetTrackEnabled(_active, false); instance2.StopTrack(_active); } } catch { } _active = null; _muted = false; _userVolume = -1f; _target = -1f; } [Conditional("DEBUG")] private static void LogState(string ctx) { try { float value = -1f; try { AudioManager instance = Singleton.Instance; if ((Object)(object)instance != (Object)null) { value = instance.GetVolume((EAudioType)4, false); } } catch { } Il2CppArrayBase val = Resources.FindObjectsOfTypeAll(); StringBuilder stringBuilder = new StringBuilder(); if (val != null) { foreach (MusicTrack item in val) { try { if ((Object)(object)item != (Object)null && (item.Enabled || item.IsPlaying)) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(20, 4, stringBuilder2); handler.AppendLiteral(" ["); handler.AppendFormatted(item.TrackName); handler.AppendLiteral(" prio="); handler.AppendFormatted(item.Priority); handler.AppendLiteral(" en="); handler.AppendFormatted(item.Enabled ? 1 : 0); handler.AppendLiteral(" play="); handler.AppendFormatted(item.IsPlaying ? 1 : 0); handler.AppendLiteral("]"); stringBuilder2.Append(ref handler); } } catch { } } } Core.Log.Msg($"[PropHunt] music state ({ctx}): active='{_active}' muted={_muted} fading={_fading} user={_userVolume:F2} target={_target:F2} musicVol={value:F2}{((stringBuilder.Length > 0) ? stringBuilder.ToString() : " (none enabled/playing)")}"); } catch { } } } } namespace PropHunt.Game { internal sealed class GameModeController { private static bool _handlersRegistered; private readonly LaunchContext _ctx; private readonly bool _isHost; private RoundSettings _settings = new RoundSettings(); private bool _settingsDirty; private string _armedWeaponId; private float _lastSettingsPush; private GameState _state = new GameState(); private HostSyncVar _stateVar; private DisguiseController _disguise; private DecoyController _decoy; private PropPicker _picker; private PropHighlighter _highlighter; private ThirdPersonController _thirdPerson; private CatchController _catch; private PropPassthrough _passthrough; private PlayAreaController _playArea; private PlayAreaBorder _border; private TauntController _taunt; private TauntWheel _tauntWheel; private Onboarding _onboarding; private SpectatorController _spectator; private float _lastTauntTime; private RoundPhase _loggedPhase = (RoundPhase)(-1); private bool _matchStarted; private bool _returnRequested; private bool _disposed; private bool _appliedFrozen; private bool _appliedBlind; private bool _appliedHotbar = true; private int _lastEffectKey = int.MinValue; private int _lastLocalProp = int.MinValue; private float _localYaw; private static readonly string[] HitClips = new string[4] { "bullet_impact", "impact", "flesh", "thud" }; private static readonly string[] CatchClips = new string[4] { "bullet_impact", "impact", "thud", "hit" }; private static readonly string[] StunClips = new string[5] { "taze", "electric", "shock", "zap", "stun" }; private static readonly string[] DecoyClips = new string[4] { "glass", "shatter", "break", "pop" }; private string _fxText; private Color _fxColor = Color.white; private float _fxUntil; private string _appliedSafehouseCode = ""; private const float SafehouseDoorRadius = 22f; private int _lastShotFrame = -1; private bool _localDownedApplied; private readonly Dictionary _lastTauntScoreUnix = new Dictionary(); private const float MinPlayAreaRadius = 50f; private const string TrashGrabberId = "trashgrabber"; internal static GameModeController Active { get; private set; } internal bool IsHost => _isHost; internal RoundSettings Settings => _settings; internal bool ConfiguredByHostForm { get { LaunchContext ctx = _ctx; object value; if (ctx == null) { value = null; } else { MultiplayerInfo multiplayer = ctx.Multiplayer; value = ((multiplayer != null) ? multiplayer.ConfigBlob : null); } return !string.IsNullOrEmpty((string?)value); } } internal GameState State => _state; internal RoundPhase Phase => _state.Phase; internal ulong LocalId => PropHuntNet.LocalSteamId; internal int AliveHiderCount => RoundLogic.AliveHiders(_state); internal int LobbyMemberCount { get { int count = GetMemberIds().Count; if (count <= 0) { return _state.Players.Count; } return count; } } internal bool LocalOutside { get { if (_playArea != null) { return _playArea.LocalOutside; } return false; } } internal float OobGrace { get { if (_playArea == null) { return 0f; } return _playArea.GraceLeft; } } internal float LastTauntTime => _lastTauntTime; internal int SecondsToWhistle { get { if (_state.Phase != RoundPhase.Hunting) { return -1; } int tauntIntervalSeconds = _settings.TauntIntervalSeconds; if (tauntIntervalSeconds <= 0) { return -1; } long num = NowUnix(); long num2 = _state.PhaseEndsAtUnix - _settings.HuntSeconds; long num3 = num - num2; if (num3 < 0) { num3 = 0L; } long num4 = num2 + tauntIntervalSeconds * (num3 / tauntIntervalSeconds + 1); if (num4 >= _state.PhaseEndsAtUnix) { return -1; } return (int)Math.Max(0L, num4 - num); } } internal string LookTargetName { get { if (_picker == null) { return null; } return _picker.CurrentTargetName; } } internal int LookTargetId { get { if (_picker == null) { return -1; } return _picker.CurrentTargetId; } } internal bool LocalAimingBecomable { get { if (_picker != null) { return _picker.CurrentTargetId >= 0; } return false; } } internal bool ThirdPersonOn { get { if (_thirdPerson != null) { return _thirdPerson.IsOn; } return false; } } internal bool LocalSpectating { get { if (_spectator != null) { return _spectator.Active; } return false; } } internal string SpectatorHudText { get { if (_spectator == null) { return null; } return _spectator.HudText; } } internal Onboarding Onboarding => _onboarding; internal bool TauntWheelOpen { get { if (_tauntWheel != null) { return _tauntWheel.MenuOpen; } return false; } } internal bool RoundActive { get { if (_state.Phase != RoundPhase.Hiding && _state.Phase != RoundPhase.Hunting && _state.Phase != RoundPhase.RoundEnd) { return _state.Phase == RoundPhase.Safehouse; } return true; } } internal PlayerRole LocalRole => RoleOf(LocalId); internal int LocalHits { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return 0; } return value.Hits; } } internal int LocalMaxHits { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return 1; } return value.MaxHits; } } internal int LocalHunterHits { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return 0; } return value.HunterHits; } } internal int LocalHunterMaxHits { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return Math.Max(1, _settings.HunterHitsToDown); } return Math.Max(1, value.HunterMaxHits); } } internal bool LocalDowned { get { ulong localId = LocalId; if (localId != 0L && _state.Players.TryGetValue(localId, out var value)) { return value.Downed; } return false; } } internal int LocalDownedSecondsLeft { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value) || !value.Downed) { return 0; } return (int)Math.Max(0L, value.DownedUntilUnix - NowUnix()); } } internal int LocalChanges { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return 0; } return value.Changes; } } internal float LocalPropYaw => _localYaw; internal int LocalDecoysUsed { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return 0; } return value.DecoysUsed; } } internal int LocalConcussUsed { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return 0; } return value.ConcussUsed; } } internal int LocalPropId { get { ulong localId = LocalId; if (localId == 0L || !_state.Players.TryGetValue(localId, out var value)) { return -1; } return value.PropId; } } internal string LocalPropName { get { int localPropId = LocalPropId; if (localPropId < 0) { return null; } return PropCatalog.ById(localPropId)?.Name; } } internal bool LocalLocked { get { ulong localId = LocalId; if (localId != 0L && _state.Players.TryGetValue(localId, out var value)) { return value.Locked; } return false; } } internal int SecondsLeft { get { if (_state.PhaseEndsAtUnix > 0) { return (int)Math.Max(0L, _state.PhaseEndsAtUnix - NowUnix()); } return 0; } } internal int SecondsUntilNextRound => RoundLogic.SecondsUntilNextRound(_state, _settings, NowUnix()); internal bool FxActive { get { if (Time.time < _fxUntil) { return !string.IsNullOrEmpty(_fxText); } return false; } } internal string FxText => _fxText; internal Color FxColor => _fxColor; internal int SafehouseOptionCount => SafehouseSelector.AvailableForPlayerCount(_state.Players.Count).Count; internal GameModeController(LaunchContext ctx, bool isHost) { //IL_003b: 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) _ctx = ctx; _isHost = isHost; } internal PlayerRole RoleOf(ulong id) { if (id == 0L || !_state.Players.TryGetValue(id, out var value)) { return PlayerRole.Unassigned; } return value.Role; } internal int PropIdOf(ulong id) { if (id == 0L || !_state.Players.TryGetValue(id, out var value)) { return -1; } return value.PropId; } private static long NowUnix() { return DateTimeOffset.UtcNow.ToUnixTimeSeconds(); } internal void NotifyTaunt(ulong steamId, string sound, bool isWhistle = false) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) _lastTauntTime = Time.time; try { Player val = ((steamId == LocalId) ? Player.Local : PlayerRegistry.Get(steamId)); if (!((Object)(object)val == (Object)null)) { string clipName = (string.IsNullOrEmpty(sound) ? TauntSounds.PickDefault() : sound); if (isWhistle) { TauntSounds.PlayWhistle(clipName, ((Component)val).transform.position); } else { TauntSounds.Play(clipName, ((Component)val).transform.position); } } } catch (Exception) { } } private void SetFx(string text, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) _fxText = text; _fxColor = color; _fxUntil = Time.time + 1.2f; } private static void BroadcastFx(P2PMessage msg) { try { SteamNetworkClient client = PropHuntNet.Client; if (client != null) { client.BroadcastMessage(msg); } } catch { } } internal void NotifyCatchFx(ulong hunterId, ulong victimId, bool caught, Vector3 pos) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) try { TauntSounds.PlayFx(caught ? CatchClips : HitClips, pos, 0.8f); } catch { } _ = LocalId; } internal void NotifyStunFx(ulong throwerId, Vector3 pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) try { TauntSounds.PlayFx(StunClips, pos, 0.85f); } catch { } if (LocalId == throwerId) { SetFx("STUN!", Color.cyan); } else { if (LocalRole != PlayerRole.Hunter) { return; } try { Player local = Player.Local; if ((Object)(object)local != (Object)null && Vector3.Distance(((Component)local).transform.position, pos) <= _settings.ConcussRadius + 1f) { SetFx("STUNNED!", new Color(1f, 0.4f, 1f)); } } catch { } } } internal void NotifyDecoyFx(ulong hunterId, Vector3 pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { TauntSounds.PlayFx(DecoyClips, pos, 0.8f); } catch { } } internal void DrawGui() { try { _tauntWheel?.DrawGui(); } catch { } } internal void StartAsHost() { Active = this; _settings = BuildSettings(); EnsureHandlers(); EnsureStateVar(); PropCatalog.BuildIfNeeded(); _disguise = new DisguiseController(); _decoy = new DecoyController(); _picker = new PropPicker(this); _highlighter = new PropHighlighter(this); EyeBlink.ResetState(); BodyCam.Stop(); _thirdPerson = new ThirdPersonController(this); _catch = new CatchController(this); _passthrough = new PropPassthrough(this); _playArea = new PlayAreaController(this); _border = new PlayAreaBorder(this); _taunt = new TauntController(this); _tauntWheel = new TauntWheel(this); _onboarding = new Onboarding(this); _spectator = new SpectatorController(this); _state = new GameState { Phase = RoundPhase.Lobby, SettingsBlob = _settings.Serialize(), CatalogHash = PropCatalog.Hash }; RoundLogic.SyncRoster(_state, GetMemberIds()); PushState(); Core.Log.Msg($"[PropHunt] host session started (Lobby). Settings: {_settings}"); } private RoundSettings BuildSettings() { RoundSettings roundSettings = PropHuntPreferences.BuildRoundSettings(); LaunchContext ctx = _ctx; object obj; if (ctx == null) { obj = null; } else { MultiplayerInfo multiplayer = ctx.Multiplayer; obj = ((multiplayer != null) ? multiplayer.ConfigBlob : null); } string text = (string)obj; if (!string.IsNullOrEmpty(text)) { return RoundSettings.Parse(text, roundSettings); } return roundSettings; } internal void StartAsClient() { Active = this; EnsureHandlers(); EnsureStateVar(); PropCatalog.BuildIfNeeded(); _disguise = new DisguiseController(); _decoy = new DecoyController(); _picker = new PropPicker(this); _highlighter = new PropHighlighter(this); EyeBlink.ResetState(); BodyCam.Stop(); _thirdPerson = new ThirdPersonController(this); _catch = new CatchController(this); _passthrough = new PropPassthrough(this); _playArea = new PlayAreaController(this); _border = new PlayAreaBorder(this); _taunt = new TauntController(this); _tauntWheel = new TauntWheel(this); _onboarding = new Onboarding(this); _spectator = new SpectatorController(this); try { string text = _stateVar?.Value; if (!string.IsNullOrEmpty(text)) { ApplyStateString(text); } } catch { } Core.Log.Msg("[PropHunt] client session started; waiting for host state."); } internal void BeginMatch() { if (!_isHost) { Core.Log.Warning("[PropHunt] BeginMatch ignored - not host."); return; } if (GetMemberIds().Count < 2) { Core.Log.Msg("[PropHunt] need at least 2 players to start - waiting for more to join."); return; } if (_matchStarted && _state.Phase != RoundPhase.Lobby) { Core.Log.Msg("[PropHunt] match already running."); return; } _matchStarted = true; _state.SettingsBlob = _settings.Serialize(); _state.CatalogHash = PropCatalog.Hash; SetPlayArea(); _state.SafehouseCode = SafehouseSelector.SelectForPlayerCount(GetMemberIds().Count); if (!string.IsNullOrEmpty(_state.SafehouseCode)) { CenterPlayAreaOnSafehouse(_state.SafehouseCode); } RoundLogic.BeginMatch(_state, _settings, NowUnix(), GetMemberIds()); PushState(); RoundEnvironment.ApplyHostWorld(_settings); Core.Log.Msg($"[PropHunt] match begun. {_settings}"); } internal void BeginNextRound() { if (_isHost && _state.Phase == RoundPhase.Safehouse) { _state.SettingsBlob = _settings.Serialize(); RoundLogic.ConfirmSafehouseReady(_state, NowUnix()); PushState(); Core.Log.Msg($"[PropHunt] host starting next round. {_settings}"); } } private void ApplySafehousePresence() { if (_state.Phase == RoundPhase.Safehouse) { if (_state.SafehouseCode == _appliedSafehouseCode) { return; } if (_isHost && !string.IsNullOrEmpty(_appliedSafehouseCode)) { ApplyDoorAccess(_appliedSafehouseCode, locked: false, swing: true); } _appliedSafehouseCode = _state.SafehouseCode; if (!string.IsNullOrEmpty(_appliedSafehouseCode)) { if (_isHost) { CenterPlayAreaOnSafehouse(_appliedSafehouseCode); _state.SafehouseSeed = Random.Range(1, int.MaxValue); SetSafehouseDoorAccess(_appliedSafehouseCode, locked: true); PushState(); } else { ApplyDoorAccess(_appliedSafehouseCode, locked: true, swing: false); } TeleportLocalToSafehouse(_appliedSafehouseCode); TurnOnSafehouseLights(_appliedSafehouseCode); } } else if (!string.IsNullOrEmpty(_appliedSafehouseCode)) { if (_isHost) { SetSafehouseDoorAccess(_appliedSafehouseCode, locked: false); } else { ApplyDoorAccess(_appliedSafehouseCode, locked: false, swing: false); } _appliedSafehouseCode = ""; } } private void CenterPlayAreaOnSafehouse(string code) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) try { Property val = FindProperty(code); if (!((Object)(object)val == (Object)null)) { Transform val2 = (((Object)(object)val.InteriorSpawnPoint != (Object)null) ? val.InteriorSpawnPoint : val.SpawnPoint); Vector3 val3 = (((Object)(object)val2 != (Object)null) ? val2.position : ((Component)val).transform.position); _state.AreaX = val3.x; _state.AreaY = val3.y; _state.AreaZ = val3.z; _state.AreaRadius = Mathf.Max(_settings.PlayAreaRadius, 50f); } } catch { } } internal void SwitchSafehouse(int dir) { if (_isHost && _state.Phase == RoundPhase.Safehouse) { List list = SafehouseSelector.AvailableForPlayerCount(_state.Players.Count); if (list.Count != 0) { int num = list.IndexOf(_state.SafehouseCode); int index = ((num >= 0) ? (((num + dir) % list.Count + list.Count) % list.Count) : 0); _state.SafehouseCode = list[index]; PushState(); Core.Log.Msg($"[PropHunt] host switched safehouse -> '{_state.SafehouseCode}' ({list.Count} options for {_state.Players.Count})."); } } } internal string SafehouseName(string code) { Property val = FindProperty(code); string text; if (!((Object)(object)val != (Object)null)) { text = code; if (text == null) { return ""; } } else { text = val.PropertyName; } return text; } private void TeleportLocalToSafehouse(string code) { //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_00c8: 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_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(code)) { return; } try { Property val = FindProperty(code); if ((Object)(object)val == (Object)null) { Core.Log.Warning("[PropHunt] safehouse '" + code + "' not found in scene."); } else if (SpawnStore.HasSpawns(code)) { List spawns = SpawnStore.GetSpawns(code); List list = new List(_state.Players.Keys); list.Sort(); int num = list.IndexOf(LocalId); if (num < 0) { num = (int)(LocalId % (ulong)Math.Max(1, spawns.Count)); } int num2 = ShuffledSpawnIndex(num, spawns.Count, _state.SafehouseSeed); SpawnStore.SpawnPoint spawnPoint = spawns[num2]; RoundEnvironment.TeleportLocalTo(spawnPoint.Pos + Vector3.up * 1f, spawnPoint.Yaw); Core.Log.Msg($"[PropHunt] entered safehouse '{code}' (authored point {num2 + 1}/{spawns.Count}, rank {num}, seed {_state.SafehouseSeed})."); } else { Transform val2 = (((Object)(object)val.InteriorSpawnPoint != (Object)null) ? val.InteriorSpawnPoint : val.SpawnPoint); Vector3 val3 = (((Object)(object)val2 != (Object)null) ? val2.position : ((Component)val).transform.position); ulong localId = LocalId; float num3 = (float)(localId % 360) * ((float)Math.PI / 180f); float num4 = 0.3f + (float)(localId % 3) * 0.35f; RoundEnvironment.TeleportLocalTo(val3 + new Vector3(Mathf.Cos(num3) * num4, 0f, Mathf.Sin(num3) * num4)); Core.Log.Msg("[PropHunt] entered safehouse '" + code + "' (ring fallback - no authored points)."); } } catch (Exception ex) { Core.Log.Warning("[PropHunt] TeleportLocalToSafehouse failed: " + ex.Message); } } private static void TurnOnSafehouseLights(string code) { if (string.IsNullOrEmpty(code)) { return; } try { Property val = FindProperty(code); if ((Object)(object)val == (Object)null) { return; } int num = 0; List switches = val.Switches; if (switches != null) { for (int i = 0; i < switches.Count; i++) { ModularSwitch val2 = switches[i]; if (!((Object)(object)val2 == (Object)null)) { try { val2.SwitchOn(); num++; } catch { } } } } try { Il2CppArrayBase componentsInChildren = ((Component)val).GetComponentsInChildren(true); if (componentsInChildren == null) { return; } for (int j = 0; j < componentsInChildren.Length; j++) { ToggleableLight val3 = componentsInChildren[j]; if ((Object)(object)val3 != (Object)null) { try { val3.TurnOn(); } catch { } } } } catch { } } catch (Exception) { } } private void SetSafehouseDoorAccess(string code, bool locked) { ApplyDoorAccess(code, locked, swing: true); BroadcastSafehouseDoorLock(code, locked); } private static void ApplyDoorAccess(string code, bool locked, bool swing) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) //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_005e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(code)) { return; } try { Property val = FindProperty(code); Vector3 val2 = Vector3.zero; bool flag = false; if ((Object)(object)val != (Object)null) { Transform val3 = (((Object)(object)val.InteriorSpawnPoint != (Object)null) ? val.InteriorSpawnPoint : val.SpawnPoint); val2 = (((Object)(object)val3 != (Object)null) ? val3.position : ((Component)val).transform.position); flag = true; } int num = 0; Il2CppArrayBase val4 = Object.FindObjectsOfType(); if (val4 == null) { return; } for (int i = 0; i < val4.Length; i++) { DoorController val5 = val4[i]; if ((Object)(object)val5 == (Object)null) { continue; } PropertyDoorController val6 = ((Il2CppObjectBase)val5).TryCast(); if (!((!((Object)(object)val6 != (Object)null)) ? (flag && Vector3.Distance(((Component)val5).transform.position, val2) <= 22f) : ((Object)(object)val6.Property != (Object)null && val6.Property.PropertyCode == code))) { continue; } num++; val5.PlayerAccess = (EDoorAccess)(locked ? 1 : 0); if (swing) { try { val5.SetIsOpen_Server(!locked, (EDoorSide)0, false); } catch { } } } } catch (Exception) { } } private static Property FindProperty(string code) { try { List properties = Property.Properties; if (properties != null) { for (int i = 0; i < properties.Count; i++) { Property val = properties[i]; if ((Object)(object)val != (Object)null && val.PropertyCode == code) { return val; } } } } catch { } return null; } private static int ShuffledSpawnIndex(int rank, int count, int seed) { if (count <= 1) { return 0; } int[] array = new int[count]; for (int i = 0; i < count; i++) { array[i] = i; } uint num = (uint)seed; if (num == 0) { num = 1u; } for (int num2 = count - 1; num2 > 0; num2--) { num = num * 1664525 + 1013904223; int num3 = (int)(num % (uint)(num2 + 1)); int num4 = array[num2]; array[num2] = array[num3]; array[num3] = num4; } return array[(rank % count + count) % count]; } private void BroadcastSafehouseDoorLock(string code, bool locked) { if (!_isHost) { return; } try { SteamNetworkClient client = PropHuntNet.Client; if (client != null) { client.BroadcastMessage((P2PMessage)(object)new SafehouseDoorLockMessage { PropertyCode = code, Locked = locked }); } } catch { } } private void HandleSafehouseDoorLock(string code, bool locked) { if (!_isHost) { ApplyDoorAccess(code, locked, swing: false); } } internal void Tick(float dt) { if (_disposed) { return; } if (_stateVar == null) { EnsureStateVar(); if (_stateVar == null) { return; } } if (!_handlersRegistered) { EnsureHandlers(); } RoundMusicController.Tick(dt); if (_isHost) { bool flag = RoundLogic.SyncRoster(_state, GetMemberIds()); if (_matchStarted) { if (_state.Phase == RoundPhase.RoundEnd && _settings.Structure == RoundStructure.Continuous && !SafehouseSelector.Fits(_state.SafehouseCode, _state.Players.Count)) { _state.SafehouseCode = SafehouseSelector.SelectForPlayerCount(_state.Players.Count); } if (RoundLogic.TickHost(_state, _settings, NowUnix())) { flag = true; } } if (flag) { _state.SettingsBlob = _settings.Serialize(); _settingsDirty = false; PushState(); } } if (_isHost && _settingsDirty && Time.unscaledTime - _lastSettingsPush > 0.4f) { _settingsDirty = false; _lastSettingsPush = Time.unscaledTime; _state.SettingsBlob = _settings.Serialize(); PushState(); } if (_state.Phase != _loggedPhase) { RoundPhase loggedPhase = _loggedPhase; _loggedPhase = _state.Phase; Core.Log.Msg($"[PropHunt] phase -> {_state.Phase} (round {_state.RoundNumber}, you={LocalRole}, {SecondsLeft}s, hunters={RoundLogic.CountRole(_state, PlayerRole.Hunter)}, hiders={AliveHiderCount}, winner={_state.Winner})"); if (_state.Phase == RoundPhase.Hiding) { if (_isHost) { RoundEnvironment.ApplyHostWorld(_settings); } PropCatalog.Build(); if (_isHost && _state.CatalogHash != PropCatalog.Hash) { _state.CatalogHash = PropCatalog.Hash; PushState(); } if (loggedPhase != RoundPhase.Safehouse) { RoundEnvironment.TeleportLocalInto(_state.AreaX, _state.AreaY, _state.AreaZ, LocalId); } } if (_state.Phase == RoundPhase.Safehouse || _state.Phase == RoundPhase.RoundEnd || _state.Phase == RoundPhase.MatchEnd) { _thirdPerson?.ForceOff(); } string musicTrack = PropHuntPreferences.MusicTrack; if (!string.IsNullOrEmpty(musicTrack)) { if (_state.Phase == RoundPhase.Hunting) { RoundMusicController.MuteForHunt(); } else { RoundMusicController.Play(musicTrack); } } } ApplySafehousePresence(); bool roundActive = RoundActive; if (roundActive) { RoundEnvironment.ClearLocalCrime(); } if (_isHost && roundActive) { RoundEnvironment.SuppressPolice(); } ApplyLocalEffects(); _picker?.Tick(); _highlighter?.Tick(); _spectator?.Tick(); _thirdPerson?.Tick(); _catch?.Tick(); _passthrough?.Tick(); _border?.Tick(); _tauntWheel?.Tick(); _onboarding?.Tick(); _playArea?.Tick(); _taunt?.Tick(); _disguise?.Apply(_state); _decoy?.Apply(_state); DriveLocalRagdoll(); int localPropId = LocalPropId; if (localPropId != _lastLocalProp) { _lastLocalProp = localPropId; ulong localId = LocalId; _localYaw = ((localId != 0L && _state.Players.TryGetValue(localId, out var value)) ? value.PropYaw : 0f); UpdatePropCollisionHeight(localPropId); } GuideQuest.Tick(); if (_state.Phase == RoundPhase.MatchEnd) { RequestReturnToHub(); } } internal void LateTick() { if (_disposed) { return; } try { _disguise?.LateApply(_state, LocalId, _localYaw); } catch { } } internal void Dispose() { if (_disposed) { return; } _disposed = true; if (Active == this) { Active = null; } PropCollisionState.TargetHeight = 0f; try { SlowWalk.Restore(); } catch { } if (_isHost) { RoundEnvironment.RestoreWorld(); } RestoreLocalEffects(); try { _disguise?.Dispose(); } catch { } try { _decoy?.Dispose(); } catch { } try { _highlighter?.Dispose(); } catch { } try { _thirdPerson?.Dispose(); } catch { } try { _spectator?.ForceExit(); } catch { } try { _passthrough?.Dispose(); } catch { } try { _border?.Dispose(); } catch { } try { _tauntWheel?.Dispose(); } catch { } try { RoundMusicController.Stop(); } catch { } try { if (_localDownedApplied) { _localDownedApplied = false; Player local = Player.Local; if (local != null) { local.SendPassOutRecovery(); } Player.Activate(); FreezeLocalRoot(freeze: false); } } catch { } try { BodyCam.Stop(); } catch { } try { EyeBlink.ResetState(); } catch { } try { GuideQuest.Stop(); } catch { } _disguise = null; _decoy = null; _picker = null; _highlighter = null; _thirdPerson = null; _catch = null; _passthrough = null; _playArea = null; _border = null; _taunt = null; _tauntWheel = null; _onboarding = null; _spectator = null; try { _stateVar?.Dispose(); } catch { } _stateVar = null; Core.Log.Msg("[PropHunt] session disposed."); } private void EnsureStateVar() { if (_stateVar != null || !PropHuntNet.Ready || PropHuntNet.Client == null) { return; } try { _stateVar = PropHuntNet.Client.CreateHostSyncVar("ph_state", "", (NetworkSyncOptions)null, (ISyncValidator)null); _stateVar.OnValueChanged += OnStateVarChanged; } catch (Exception ex) { Core.Log.Warning("[PropHunt] CreateHostSyncVar failed: " + ex.Message); } } private void OnStateVarChanged(string oldV, string newV) { if (_isHost) { return; } try { ApplyStateString(newV); } catch (Exception ex) { Core.Log.Warning("[PropHunt] state apply failed: " + ex.Message); } } private void ApplyStateString(string blob) { _state = GameState.Parse(blob); if (!string.IsNullOrEmpty(_state.SettingsBlob)) { _settings = RoundSettings.Parse(_state.SettingsBlob); } ApplyLocalEffects(); } private void PushState() { if (!_isHost || _stateVar == null) { return; } try { _stateVar.Value = _state.Serialize(); } catch (Exception ex) { Core.Log.Warning("[PropHunt] PushState failed: " + ex.Message); } } private static void EnsureHandlers() { if (_handlersRegistered) { return; } SteamNetworkClient client = PropHuntNet.Client; if (client == null) { return; } try { client.RegisterMessageHandler((Action)delegate(SelectPropMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleSelectProp(s.m_SteamID, m.PropId); }); client.RegisterMessageHandler((Action)delegate(LockPropMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleLock(s.m_SteamID, m.Locked); }); client.RegisterMessageHandler((Action)delegate(RotatePropMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleRotate(s.m_SteamID, m.Yaw); }); client.RegisterMessageHandler((Action)delegate(DropDecoyMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleDropDecoy(s.m_SteamID, m.X, m.Y, m.Z, m.Yaw); }); client.RegisterMessageHandler((Action)delegate(ConcussMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleConcuss(s.m_SteamID, m.X, m.Y, m.Z); }); client.RegisterMessageHandler((Action)delegate(ClaimTagMessage m, CSteamID s) { //IL_000a: 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) Active?.HandleClaimTag(s.m_SteamID, m.VictimSteamId, new Vector3(m.DirX, m.DirY, m.DirZ)); }); client.RegisterMessageHandler((Action)delegate(HitHunterMessage m, CSteamID s) { //IL_000a: 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) Active?.HandleHitHunter(s.m_SteamID, m.VictimSteamId, new Vector3(m.DirX, m.DirY, m.DirZ)); }); client.RegisterMessageHandler((Action)delegate(OutOfBoundsMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleOutOfBounds(s.m_SteamID); }); client.RegisterMessageHandler((Action)delegate(TauntMessage m, CSteamID s) { Active?.NotifyTaunt(m.SteamId, m.Sound, m.IsWhistle); }); client.RegisterMessageHandler((Action)delegate(ManualTauntMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleManualTaunt(s.m_SteamID, m.Sound); }); client.RegisterMessageHandler((Action)delegate(DecoyHitMessage m, CSteamID s) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Active?.HandleDecoyHit(s.m_SteamID, m.DecoyIndex); }); client.RegisterMessageHandler((Action)delegate(CatchFxMessage m, CSteamID s) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) Active?.NotifyCatchFx(m.HunterId, m.VictimId, m.Caught, new Vector3(m.X, m.Y, m.Z)); }); client.RegisterMessageHandler((Action)delegate(StunFxMessage m, CSteamID s) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Active?.NotifyStunFx(m.ThrowerId, new Vector3(m.X, m.Y, m.Z)); }); client.RegisterMessageHandler((Action)delegate(DecoyFxMessage m, CSteamID s) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) Active?.NotifyDecoyFx(m.HunterId, new Vector3(m.X, m.Y, m.Z)); }); client.RegisterMessageHandler((Action)delegate(SafehouseDoorLockMessage m, CSteamID s) { Active?.HandleSafehouseDoorLock(m.PropertyCode, m.Locked); }); _handlersRegistered = true; } catch (Exception ex) { Core.Log.Warning("[PropHunt] handler registration failed: " + ex.Message); } } private void SendToHost(P2PMessage msg) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) try { SteamNetworkClient client = PropHuntNet.Client; MemberInfo val = ((client != null) ? client.GetHostMember() : null); if (val != null) { PropHuntNet.Client.SendMessageToPlayerAsync(val.SteamId, msg); } } catch (Exception ex) { Core.Log.Warning("[PropHunt] SendToHost failed: " + ex.Message); } } internal void RequestSelectProp(int propId) { if (_isHost) { HandleSelectProp(LocalId, propId); return; } SendToHost((P2PMessage)(object)new SelectPropMessage { PropId = propId }); } internal void RequestSelectRandomProp() { int num = PropCatalog.RandomId(LocalPropId); if (num >= 0) { RequestSelectProp(num); } } internal void SetLocalYaw(float yaw) { _localYaw = yaw; } internal void RequestRotate(float yaw) { _localYaw = yaw; if (_isHost) { HandleRotate(LocalId, yaw); return; } SendToHost((P2PMessage)(object)new RotatePropMessage { Yaw = yaw }); } internal void RequestDropDecoy() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0039: Unknown result type (might be due to invalid IL or missing references) Player local = Player.Local; if (!((Object)(object)local == (Object)null)) { Vector3 position = ((Component)local).transform.position; float y = RoundEnvironment.FeetY(local); if (_isHost) { HandleDropDecoy(LocalId, position.x, y, position.z, _localYaw); return; } SendToHost((P2PMessage)(object)new DropDecoyMessage { X = position.x, Y = y, Z = position.z, Yaw = _localYaw }); } } internal void RequestConcuss() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0031: 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) Player local = Player.Local; if (!((Object)(object)local == (Object)null)) { Vector3 position = ((Component)local).transform.position; if (_isHost) { HandleConcuss(LocalId, position.x, position.y, position.z); return; } SendToHost((P2PMessage)(object)new ConcussMessage { X = position.x, Y = position.y, Z = position.z }); } } internal void RequestLock(bool locked) { if (_isHost) { HandleLock(LocalId, locked); return; } SendToHost((P2PMessage)(object)new LockPropMessage { Locked = locked }); } internal void RequestClaimTag(ulong victimSteamId, Vector3 aimDir) { //IL_0025: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (_isHost) { HandleClaimTag(LocalId, victimSteamId, aimDir); return; } SendToHost((P2PMessage)(object)new ClaimTagMessage { VictimSteamId = victimSteamId, DirX = aimDir.x, DirY = aimDir.y, DirZ = aimDir.z }); } internal void RequestHitHunter(ulong victimSteamId, Vector3 aimDir) { //IL_0025: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (_isHost) { HandleHitHunter(LocalId, victimSteamId, aimDir); return; } SendToHost((P2PMessage)(object)new HitHunterMessage { VictimSteamId = victimSteamId, DirX = aimDir.x, DirY = aimDir.y, DirZ = aimDir.z }); } private void DriveLocalRagdoll() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) bool localDowned = LocalDowned; if (localDowned == _localDownedApplied) { return; } _localDownedApplied = localDowned; try { Player local = Player.Local; if (!((Object)(object)local == (Object)null)) { if (localDowned) { local.SendPassOut(); BodyCam.Start(); FreezeLocalRoot(freeze: true); SetFx("KNOCKED DOWN", new Color(0.95f, 0.55f, 0.2f)); } else { local.SendPassOutRecovery(); FreezeLocalRoot(freeze: false); Player.Activate(); BodyCam.Stop(); } } } catch (Exception) { } } internal void OnLocalHunterFired(float maxRange) { if (Time.frameCount == _lastShotFrame) { return; } _lastShotFrame = Time.frameCount; try { _catch?.ResolveShot(maxRange); } catch { } } internal void SetSetting(string key, string value) { if (_isHost) { _settings.ApplyKeyValue(key, value); _settingsDirty = true; } } internal void ReportOutOfBounds() { if (_isHost) { HandleOutOfBounds(LocalId); } else { SendToHost((P2PMessage)(object)new OutOfBoundsMessage()); } } internal void KickPlayer(ulong steamId) { if (!_isHost || steamId == 0L || steamId == LocalId) { return; } try { API.KickPlayer(steamId, "Kicked by host"); } catch (Exception) { } } internal void RequestManualTaunt(string sound) { if (_isHost) { HandleManualTaunt(LocalId, sound); return; } SendToHost((P2PMessage)(object)new ManualTauntMessage { Sound = sound }); } private void HandleManualTaunt(ulong sender, string sound) { if (!_isHost || sender == 0L || !_state.Players.TryGetValue(sender, out var value) || value.Eliminated) { return; } if (string.IsNullOrEmpty(sound)) { sound = TauntSounds.PickDefault(); } try { SteamNetworkClient client = PropHuntNet.Client; if (client != null) { client.BroadcastMessage((P2PMessage)(object)new TauntMessage { SteamId = sender, Sound = sound }); } } catch { } NotifyTaunt(sender, sound); if (value.Role == PlayerRole.Hider && (_state.Phase == RoundPhase.Hiding || _state.Phase == RoundPhase.Hunting)) { long num = NowUnix(); if (!_lastTauntScoreUnix.TryGetValue(sender, out var value2) || num - value2 >= 15) { _lastTauntScoreUnix[sender] = num; value.Taunts++; PushState(); } } } private void HandleSelectProp(ulong sender, int propId) { if (_isHost) { int maxHits = ComputeMaxHits(propId); bool freeChange = _settings.FreeChangesInHiding && _state.Phase == RoundPhase.Hiding; bool num = RoundLogic.ApplySelectProp(_state, sender, propId, maxHits, _settings.MaxPropChanges, freeChange); _state.Players.TryGetValue(sender, out var _); if (num) { PushState(); } } } private int ComputeMaxHits(int propId) { return Mathf.Clamp(Mathf.RoundToInt(PropCatalog.SizeOf(propId) * (float)Mathf.Max(1, _settings.HitsToCatch)), 1, Mathf.Max(1, _settings.HiderMaxHp)); } private void HandleLock(ulong sender, bool locked) { if (_isHost && RoundLogic.ApplyLock(_state, sender, locked)) { PushState(); } } private void HandleRotate(ulong sender, float yaw) { if (_isHost && RoundLogic.ApplyRotate(_state, sender, yaw)) { PushState(); } } private void HandleDropDecoy(ulong sender, float x, float y, float z, float yaw) { if (_isHost) { _state.Players.TryGetValue(sender, out var value); int num = ((value == null) ? 1 : ComputeMaxHits(value.PropId)); if (RoundLogic.ApplyDropDecoy(_state, _settings, sender, x, y, z, yaw, num)) { Core.Log.Msg($"[PropHunt] {sender} dropped a decoy (hp={num}, {_state.Decoys.Count} total)."); PushState(); } else { Core.Log.Msg($"[PropHunt] decoy from {sender} rejected (phase={_state.Phase}, used={value?.DecoysUsed ?? (-1)}/{_settings.MaxDecoys}, propId={value?.PropId ?? (-99)})"); } } } private void HandleConcuss(ulong sender, float x, float y, float z) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (_isHost) { if (RoundLogic.ApplyConcuss(_state, _settings, sender)) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(x, y, z); ApplyConcussionEffect(val, sender); BroadcastFx((P2PMessage)(object)new StunFxMessage { ThrowerId = sender, X = x, Y = y, Z = z }); NotifyStunFx(sender, val); PushState(); } else { _state.Players.TryGetValue(sender, out var value); Core.Log.Msg($"[PropHunt] concussion from {sender} rejected (phase={_state.Phase}, used={value?.ConcussUsed ?? (-1)}/{_settings.ConcussCharges})"); } } } private void ApplyConcussionEffect(Vector3 center, ulong hiderId) { //IL_0070: 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) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) try { PlayerRegistry.Refresh(); float concussRadius = _settings.ConcussRadius; int num = Math.Max(1, (int)Math.Round(_settings.ConcussStunSeconds)); long now = NowUnix(); int num2 = 0; List playerList = Player.PlayerList; if (playerList == null) { return; } for (int i = 0; i < playerList.Count; i++) { Player val = playerList[i]; if (!((Object)(object)val == (Object)null)) { ulong num3 = PlayerRegistry.IdForPlayer(val); if (RoleOf(num3) == PlayerRole.Hunter && !(Vector3.Distance(center, ((Component)val).transform.position) > concussRadius) && RoundLogic.ApplyConcussDown(_state, num3, num, now)) { SetKnockback(num3, ((Component)val).transform.position - center); num2++; } } } if (num2 > 0 && _state.Players.TryGetValue(hiderId, out var value)) { value.StunsLanded += num2; } Core.Log.Msg($"[PropHunt] concussion by {hiderId} - knocked down {num2} hunter(s) within {concussRadius}m for {num}s."); } catch (Exception ex) { Core.Log.Warning("[PropHunt] concussion effect failed: " + ex.Message); } } private void HandleClaimTag(ulong hunter, ulong victim, Vector3 aimDir) { //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: 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_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (!_isHost || _state.Phase != RoundPhase.Hunting) { return; } PlayerRegistry.Refresh(); Player val = PlayerRegistry.Get(hunter); Player val2 = PlayerRegistry.Get(victim); if (!RoundLogic.ApplyCatch(_state, _settings, hunter, victim, NowUnix())) { return; } bool flag = RoundLogic.IsCaught(_state, victim); if (flag) { Core.Log.Msg($"[PropHunt] {hunter} CAUGHT {victim} ({_settings.Caught})."); } else { Core.Log.Msg($"[PropHunt] {hunter} hit {victim} ({_state.Players[victim].Hits}/{_state.Players[victim].MaxHits})."); } Vector3 val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).transform.position : (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : Vector3.zero)); try { if (val2 != null) { PlayerHealth health = val2.Health; if (health != null) { health.PlayBloodMist(); } } } catch { } BroadcastFx((P2PMessage)(object)new CatchFxMessage { HunterId = hunter, VictimId = victim, Caught = flag, X = val3.x, Y = val3.y, Z = val3.z }); NotifyCatchFx(hunter, victim, flag, val3); PushState(); } private void HandleHitHunter(ulong shooter, ulong victim, Vector3 aimDir) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_00c1: 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) //IL_0082: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!_isHost || _state.Phase != RoundPhase.Hunting || !_settings.FriendlyFire) { return; } PlayerRegistry.Refresh(); Player val = PlayerRegistry.Get(shooter); Player val2 = PlayerRegistry.Get(victim); if (!RoundLogic.ApplyHitHunter(_state, _settings, shooter, victim, NowUnix(), out var newlyDowned)) { return; } Vector3 val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).transform.position : (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : Vector3.zero)); try { if (val2 != null) { PlayerHealth health = val2.Health; if (health != null) { health.PlayBloodMist(); } } } catch { } if (newlyDowned) { if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { SetKnockback(victim, ((Component)val2).transform.position - ((Component)val).transform.position); } BroadcastFx((P2PMessage)(object)new StunFxMessage { ThrowerId = shooter, X = val3.x, Y = val3.y, Z = val3.z }); NotifyStunFx(shooter, val3); Core.Log.Msg($"[PropHunt] {shooter} knocked down hunter {victim} (friendly fire)."); } PushState(); } internal void SetKnockback(ulong id, Vector3 dir) { //IL_004f: 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) if (_state.Players.TryGetValue(id, out var value)) { dir.y = 0f; if (((Vector3)(ref dir)).sqrMagnitude < 0.0001f) { value.KnockX = 0f; value.KnockZ = 0f; } else { ((Vector3)(ref dir)).Normalize(); value.KnockX = dir.x; value.KnockZ = dir.z; } } } internal bool TryGetKnock(ulong id, out float kx, out float kz) { kx = 0f; kz = 0f; if (id == 0L || !_state.Players.TryGetValue(id, out var value)) { return false; } kx = value.KnockX; kz = value.KnockZ; if (kx == 0f) { return kz != 0f; } return true; } private void HandleOutOfBounds(ulong sender) { //IL_0036: 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) if (!_isHost) { return; } PlayerRegistry.Refresh(); Player val = PlayerRegistry.Get(sender); if ((Object)(object)val != (Object)null && _state.AreaRadius > 0f) { Vector3 position = ((Component)val).transform.position; float num = position.x - _state.AreaX; float num2 = position.z - _state.AreaZ; if (Mathf.Sqrt(num * num + num2 * num2) <= _state.AreaRadius + 3f) { return; } } if (RoundLogic.ApplyOutOfBounds(_state, _settings, sender, NowUnix())) { Core.Log.Msg($"[PropHunt] {sender} eliminated (left the play area)."); PushState(); } } private void UpdatePropCollisionHeight(int lpid) { if (LocalRole != PlayerRole.Hider) { PropCollisionState.TargetHeight = 0f; return; } if (lpid < 0) { PropCollisionState.TargetHeight = 0f; return; } try { float num = PropCatalog.SizeOf(lpid); PropCollisionState.TargetHeight = ((num > 0f) ? Mathf.Clamp(num, 0.5f, 1.85f) : 0f); try { PlayerMovement instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null && instance.IsCrouched) { instance.SetCrouched(false); } } catch (Exception) { } } catch (Exception) { } } internal void RequestHitDecoy(int idx) { if (_isHost) { HandleDecoyHit(LocalId, idx); return; } SendToHost((P2PMessage)(object)new DecoyHitMessage { DecoyIndex = idx }); } private void HandleDecoyHit(ulong hunter, int decoyIndex) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) if (_isHost && _state.Phase == RoundPhase.Hunting && _state.Players.TryGetValue(hunter, out var value) && value.Role == PlayerRole.Hunter && decoyIndex >= 0 && decoyIndex < _state.Decoys.Count && !_state.Decoys[decoyIndex].Destroyed && RoundLogic.ApplyHitDecoy(_state, decoyIndex)) { DecoyState decoyState = _state.Decoys[decoyIndex]; if (decoyState.Destroyed) { value.DecoysSmashed++; Core.Log.Msg($"[PropHunt] hunter {hunter} DESTROYED decoy {decoyIndex} (FAKE!) hits={decoyState.Hits}/{decoyState.MaxHits}."); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(decoyState.X, decoyState.Y, decoyState.Z); BroadcastFx((P2PMessage)(object)new DecoyFxMessage { HunterId = hunter, X = val.x, Y = val.y, Z = val.z }); NotifyDecoyFx(hunter, val); } else { Core.Log.Msg($"[PropHunt] hunter {hunter} hit decoy {decoyIndex} ({decoyState.Hits}/{decoyState.MaxHits})."); } PushState(); } } internal void RequestReturnToHub() { if (_returnRequested) { return; } _returnRequested = true; try { LaunchContext ctx = _ctx; if (ctx != null) { ctx.ReturnToHub(); } } catch (Exception ex) { Core.Log.Warning("[PropHunt] ReturnToHub failed: " + ex.Message); } } private List GetMemberIds() { List list = new List(); try { SteamNetworkClient client = PropHuntNet.Client; List list2 = ((client != null) ? client.GetLobbyMembers() : null); if (list2 != null) { foreach (MemberInfo item in list2) { if (item.SteamId64 != 0L) { list.Add(item.SteamId64); } } } } catch { } return list; } private void SetPlayArea() { //IL_0015: 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_0021: 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_0043: Unknown result type (might be due to invalid IL or missing references) try { Player local = Player.Local; if ((Object)(object)local != (Object)null) { Vector3 position = ((Component)local).transform.position; _state.AreaX = position.x; _state.AreaY = position.y; _state.AreaZ = position.z; } } catch { } _state.AreaRadius = Mathf.Max(_settings.PlayAreaRadius, 50f); } private void ApplyLocalEffects() { PlayerRole localRole = LocalRole; RoundPhase phase = _state.Phase; int num = (int)((int)phase * 16 + localRole); if (num == _lastEffectKey) { return; } _lastEffectKey = num; bool flag = phase == RoundPhase.Hiding && localRole == PlayerRole.Hunter; bool blind = flag; if (phase == RoundPhase.Lobby || phase == RoundPhase.MatchEnd || phase == RoundPhase.Safehouse) { flag = false; blind = false; } bool hotbar = localRole != PlayerRole.Hider || (phase != RoundPhase.Hiding && phase != RoundPhase.Hunting); SetFrozen(flag); SetBlind(blind); SetHotbar(hotbar); SlowWalk.SetRoleFactor((localRole == PlayerRole.Hider && (phase == RoundPhase.Hiding || phase == RoundPhase.Hunting)) ? Mathf.Clamp((float)_settings.HiderSpeedPercent / 100f, 0.5f, 1f) : 1f); if (localRole == PlayerRole.Hunter && phase == RoundPhase.Hunting) { if (!string.IsNullOrEmpty(_armedWeaponId) && _armedWeaponId != _settings.HunterWeapon) { RoundEnvironment.RemoveWeapon(_armedWeaponId); } RoundEnvironment.GiveWeapon(_settings.HunterWeapon); RoundEnvironment.GiveWeapon("trashgrabber"); _armedWeaponId = _settings.HunterWeapon; } else if (localRole != PlayerRole.Hunter) { RoundEnvironment.RemoveWeapon(_settings.HunterWeapon); if (!string.IsNullOrEmpty(_armedWeaponId) && _armedWeaponId != _settings.HunterWeapon) { RoundEnvironment.RemoveWeapon(_armedWeaponId); } RoundEnvironment.RemoveWeapon("trashgrabber"); _armedWeaponId = null; } switch (localRole) { case PlayerRole.Hunter: _thirdPerson?.ForceOff(); break; case PlayerRole.Hider: if (phase == RoundPhase.Hiding || phase == RoundPhase.Hunting) { _thirdPerson?.ForceOn(); } break; } } private void RestoreLocalEffects() { _lastEffectKey = int.MinValue; SetFrozen(frozen: false); SetBlind(blind: false); SetHotbar(enabled: true); try { PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(true); } } catch { } } private void SetHotbar(bool enabled) { if (enabled == _appliedHotbar) { return; } _appliedHotbar = enabled; try { PlayerInventory instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.HotbarEnabled = enabled; instance.SetEquippingEnabled(enabled); } } catch (Exception) { } } private void SetFrozen(bool frozen) { if (frozen == _appliedFrozen) { return; } _appliedFrozen = frozen; try { PlayerMovement instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.CanMove = !frozen; } } catch (Exception) { } } private void FreezeLocalRoot(bool freeze) { try { PlayerMovement instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.Controller != (Object)null) { ((Collider)instance.Controller).enabled = !freeze; } } catch (Exception) { } } private void SetBlind(bool blind) { if (blind != _appliedBlind) { _appliedBlind = blind; if (blind) { EyeBlink.Blind(); } else { EyeBlink.Unblind(); } } } } internal sealed class PlayerState { internal ulong SteamId; internal PlayerRole Role; internal int PropId = -1; internal bool Locked; internal bool Eliminated; internal int Hits; internal int MaxHits = 1; internal int Changes; internal float PropYaw; internal int DecoysUsed; internal int ConcussUsed; internal int HunterHits; internal int HunterMaxHits = 3; internal bool Downed; internal long DownedUntilUnix; internal float KnockX; internal float KnockZ; internal int CatchesMade; internal int HitsDealt; internal int DecoyBaits; internal int StunsLanded; internal int SurvivedSeconds; internal int DecoysSmashed; internal int Taunts; internal int SessScore; internal PlayerState() { } internal PlayerState(ulong id) { SteamId = id; } } internal sealed class DecoyState { internal float X; internal float Y; internal float Z; internal float Yaw; internal int PropId; internal int Hits; internal int MaxHits; internal bool Destroyed; internal ulong OwnerSteamId; } internal sealed class GameState { internal RoundPhase Phase; internal long PhaseEndsAtUnix; internal int RoundNumber; internal int CatalogHash; internal float AreaX; internal float AreaY; internal float AreaZ; internal float AreaRadius; internal int Winner = -1; internal string SettingsBlob = ""; internal string SafehouseCode = ""; internal bool SafehouseReady; internal int SafehouseSeed; internal long HuntStartUnix; internal readonly Dictionary Players = new Dictionary(); internal readonly List Decoys = new List(); internal PlayerState GetOrAdd(ulong id) { if (!Players.TryGetValue(id, out var value)) { value = new PlayerState(id); Players[id] = value; } return value; } internal string Serialize() { CultureInfo invariantCulture = CultureInfo.InvariantCulture; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append((int)Phase).Append('|').Append(PhaseEndsAtUnix.ToString(invariantCulture)) .Append('|') .Append(RoundNumber.ToString(invariantCulture)) .Append('|') .Append(CatalogHash.ToString(invariantCulture)) .Append('|') .Append(AreaX.ToString(invariantCulture)) .Append('|') .Append(AreaZ.ToString(invariantCulture)) .Append('|') .Append(AreaRadius.ToString(invariantCulture)) .Append('|') .Append(Winner.ToString(invariantCulture)) .Append('|') .Append(AreaY.ToString(invariantCulture)) .Append('|') .Append(SafehouseCode ?? "") .Append('|') .Append(SafehouseReady ? '1' : '0') .Append('|') .Append(SafehouseSeed.ToString(invariantCulture)) .Append('|') .Append(HuntStartUnix.ToString(invariantCulture)); stringBuilder.Append('\n').Append(SettingsBlob ?? ""); foreach (PlayerState value in Players.Values) { stringBuilder.Append('\n').Append(value.SteamId.ToString(invariantCulture)).Append('|') .Append((int)value.Role) .Append('|') .Append(value.PropId.ToString(invariantCulture)) .Append('|') .Append(value.Locked ? '1' : '0') .Append('|') .Append(value.Eliminated ? '1' : '0') .Append('|') .Append(value.Hits.ToString(invariantCulture)) .Append('|') .Append(value.MaxHits.ToString(invariantCulture)) .Append('|') .Append(value.Changes.ToString(invariantCulture)) .Append('|') .Append(value.PropYaw.ToString(invariantCulture)) .Append('|') .Append(value.DecoysUsed.ToString(invariantCulture)) .Append('|') .Append(value.ConcussUsed.ToString(invariantCulture)) .Append('|') .Append(value.CatchesMade.ToString(invariantCulture)) .Append('|') .Append(value.HitsDealt.ToString(invariantCulture)) .Append('|') .Append(value.DecoyBaits.ToString(invariantCulture)) .Append('|') .Append(value.StunsLanded.ToString(invariantCulture)) .Append('|') .Append(value.SurvivedSeconds.ToString(invariantCulture)) .Append('|') .Append(value.SessScore.ToString(invariantCulture)) .Append('|') .Append(value.DecoysSmashed.ToString(invariantCulture)) .Append('|') .Append(value.Taunts.ToString(invariantCulture)) .Append('|') .Append(value.HunterHits.ToString(invariantCulture)) .Append('|') .Append(value.HunterMaxHits.ToString(invariantCulture)) .Append('|') .Append(value.Downed ? '1' : '0') .Append('|') .Append(value.DownedUntilUnix.ToString(invariantCulture)) .Append('|') .Append(value.KnockX.ToString(invariantCulture)) .Append('|') .Append(value.KnockZ.ToString(invariantCulture)); } foreach (DecoyState decoy in Decoys) { stringBuilder.Append('\n').Append("D|").Append(decoy.X.ToString(invariantCulture)) .Append('|') .Append(decoy.Y.ToString(invariantCulture)) .Append('|') .Append(decoy.Z.ToString(invariantCulture)) .Append('|') .Append(decoy.Yaw.ToString(invariantCulture)) .Append('|') .Append(decoy.PropId.ToString(invariantCulture)) .Append('|') .Append(decoy.Hits.ToString(invariantCulture)) .Append('|') .Append(decoy.MaxHits.ToString(invariantCulture)) .Append('|') .Append(decoy.Destroyed ? '1' : '0') .Append('|') .Append(decoy.OwnerSteamId.ToString(invariantCulture)); } return stringBuilder.ToString(); } internal static GameState Parse(string blob) { GameState gameState = new GameState(); if (string.IsNullOrEmpty(blob)) { return gameState; } CultureInfo invariantCulture = CultureInfo.InvariantCulture; string[] array = blob.Split('\n'); if (array.Length != 0) { string[] array2 = array[0].Split('|'); if (array2.Length >= 8) { gameState.Phase = (RoundPhase)SafeInt(array2[0]); long.TryParse(array2[1], NumberStyles.Integer, invariantCulture, out gameState.PhaseEndsAtUnix); gameState.RoundNumber = SafeInt(array2[2]); gameState.CatalogHash = SafeInt(array2[3]); gameState.AreaX = SafeFloat(array2[4]); gameState.AreaZ = SafeFloat(array2[5]); gameState.AreaRadius = SafeFloat(array2[6]); gameState.Winner = SafeInt(array2[7]); if (array2.Length >= 9) { gameState.AreaY = SafeFloat(array2[8]); } if (array2.Length >= 10) { gameState.SafehouseCode = array2[9] ?? ""; } if (array2.Length >= 11) { gameState.SafehouseReady = array2[10] == "1"; } if (array2.Length >= 12) { gameState.SafehouseSeed = SafeInt(array2[11]); } if (array2.Length >= 13) { long.TryParse(array2[12], NumberStyles.Integer, invariantCulture, out gameState.HuntStartUnix); } } } if (array.Length > 1) { gameState.SettingsBlob = array[1]; } for (int i = 2; i < array.Length; i++) { string[] array3 = array[i].Split('|'); ulong result; if (array3.Length >= 1 && array3[0] == "D") { if (array3.Length >= 6) { DecoyState item = new DecoyState { X = SafeFloat(array3[1]), Y = SafeFloat(array3[2]), Z = SafeFloat(array3[3]), Yaw = SafeFloat(array3[4]), PropId = SafeInt(array3[5]), Hits = ((array3.Length >= 7) ? SafeInt(array3[6]) : 0), MaxHits = ((array3.Length < 8) ? 1 : SafeInt(array3[7])), Destroyed = (array3.Length >= 9 && array3[8] == "1"), OwnerSteamId = ((array3.Length >= 10) ? SafeULong(array3[9]) : 0) }; gameState.Decoys.Add(item); } } else if (array3.Length >= 5 && ulong.TryParse(array3[0], NumberStyles.Integer, invariantCulture, out result)) { PlayerState orAdd = gameState.GetOrAdd(result); orAdd.Role = (PlayerRole)SafeInt(array3[1]); orAdd.PropId = SafeInt(array3[2]); orAdd.Locked = array3[3] == "1"; orAdd.Eliminated = array3[4] == "1"; if (array3.Length >= 6) { orAdd.Hits = SafeInt(array3[5]); } if (array3.Length >= 7) { orAdd.MaxHits = SafeInt(array3[6]); } if (array3.Length >= 8) { orAdd.Changes = SafeInt(array3[7]); } if (array3.Length >= 9) { orAdd.PropYaw = SafeFloat(array3[8]); } if (array3.Length >= 10) { orAdd.DecoysUsed = SafeInt(array3[9]); } if (array3.Length >= 11) { orAdd.ConcussUsed = SafeInt(array3[10]); } if (array3.Length >= 12) { orAdd.CatchesMade = SafeInt(array3[11]); } if (array3.Length >= 13) { orAdd.HitsDealt = SafeInt(array3[12]); } if (array3.Length >= 14) { orAdd.DecoyBaits = SafeInt(array3[13]); } if (array3.Length >= 15) { orAdd.StunsLanded = SafeInt(array3[14]); } if (array3.Length >= 16) { orAdd.SurvivedSeconds = SafeInt(array3[15]); } if (array3.Length >= 17) { orAdd.SessScore = SafeInt(array3[16]); } if (array3.Length >= 18) { orAdd.DecoysSmashed = SafeInt(array3[17]); } if (array3.Length >= 19) { orAdd.Taunts = SafeInt(array3[18]); } if (array3.Length >= 20) { orAdd.HunterHits = SafeInt(array3[19]); } if (array3.Length >= 21) { orAdd.HunterMaxHits = SafeInt(array3[20]); } if (array3.Length >= 22) { orAdd.Downed = array3[21] == "1"; } if (array3.Length >= 23) { long.TryParse(array3[22], NumberStyles.Integer, invariantCulture, out orAdd.DownedUntilUnix); } if (array3.Length >= 24) { orAdd.KnockX = SafeFloat(array3[23]); } if (array3.Length >= 25) { orAdd.KnockZ = SafeFloat(array3[24]); } } } return gameState; } private static int SafeInt(string s) { if (!int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return 0; } return result; } private static ulong SafeULong(string s) { if (!ulong.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return 0uL; } return result; } private static float SafeFloat(string s) { if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return 0f; } return result; } } internal enum RoundPhase { Lobby, Hiding, Hunting, RoundEnd, Safehouse, MatchEnd } internal enum PlayerRole { Unassigned, Hider, Hunter, Spectator } internal enum CaughtBehavior { Spectator, Infection } internal enum RoundStructure { Continuous, Single } internal static class PlayerRegistry { private static readonly Dictionary _byId = new Dictionary(); internal static void Refresh() { _byId.Clear(); try { List playerList = Player.PlayerList; if (playerList == null) { return; } for (int i = 0; i < playerList.Count; i++) { Player val = playerList[i]; if (!((Object)(object)val == (Object)null)) { ulong num = SteamIdOf(val); if (num != 0L) { _byId[num] = val; } } } } catch { } } internal static Player Get(ulong id) { if (id == 0L) { return null; } if (_byId.TryGetValue(id, out var value) && (Object)(object)value != (Object)null) { return value; } try { List playerList = Player.PlayerList; if (playerList != null) { for (int i = 0; i < playerList.Count; i++) { Player val = playerList[i]; if ((Object)(object)val != (Object)null && SteamIdOf(val) == id) { _byId[id] = val; return val; } } } } catch { } return null; } internal static ulong IdForPlayer(Player player) { return SteamIdOf(player); } internal static ulong SteamIdOf(Player player) { if ((Object)(object)player == (Object)null) { return 0uL; } try { string playerCode = player.PlayerCode; if (!string.IsNullOrEmpty(playerCode) && ulong.TryParse(playerCode, out var result) && result != 0L) { return result; } } catch { } return 0uL; } } internal static class RoundEnvironment { private static readonly HashSet _suppressedOfficers = new HashSet(); internal static int GroundMode = 3; internal const int GroundModeCount = 4; internal static float FixedFeetDrop = 0.97f; private static float _localFeetOffset = -1f; internal static string GroundModeName { get { if (GroundMode != 1) { if (GroundMode != 2) { if (GroundMode != 3) { return "follow"; } return "fixed"; } return "floor-ray"; } return "capsule"; } } internal static void ApplyHostWorld(RoundSettings s) { try { TimeManager instance = NetworkSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetTimeAndSync(s.TimeOfDay); instance.SetTimeSpeedMultiplier(s.FreezeTime ? 0f : 1f); } Core.Log.Msg($"[PropHunt] world: time set to {s.TimeOfDay}{(s.FreezeTime ? ", progression frozen" : ", progression running")}."); } catch (Exception ex) { Core.Log.Warning("[PropHunt] ApplyHostWorld failed: " + ex.Message); } } internal static void RestoreWorld() { try { TimeManager instance = NetworkSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetTimeSpeedMultiplier(1f); } } catch { } _suppressedOfficers.Clear(); } internal static void LockTimeOfDay(int hhmm) { try { TimeManager instance = NetworkSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetTimeAndSync(hhmm); instance.SetTimeSpeedMultiplier(0f); } } catch (Exception) { } } internal static void RestoreTimeProgression() { try { TimeManager instance = NetworkSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetTimeSpeedMultiplier(1f); } } catch (Exception) { } } internal static void SuppressPolice() { try { List officers = PoliceOfficer.Officers; if (officers == null) { return; } for (int i = 0; i < officers.Count; i++) { PoliceOfficer val = officers[i]; if (!((Object)(object)val == (Object)null)) { int instanceID = ((Object)val).GetInstanceID(); if (!_suppressedOfficers.Contains(instanceID)) { val.SetIgnorePlayers(true); _suppressedOfficers.Add(instanceID); } } } } catch (Exception) { } } internal static void ClearLocalCrime() { try { Player local = Player.Local; PlayerCrimeData val = (((Object)(object)local != (Object)null) ? local.CrimeData : null); if ((Object)(object)val != (Object)null) { val.ClearCrimes(); val.SetPursuitLevel((EPursuitLevel)0); } } catch (Exception) { } } internal static void TeleportLocalInto(float x, float y, float z, ulong steamId) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) float num = (float)(steamId % 360) * ((float)Math.PI / 180f); float num2 = 3f + (float)(steamId % 4); TeleportLocalTo(new Vector3(x + Mathf.Cos(num) * num2, y, z + Mathf.Sin(num) * num2)); } internal static void TeleportLocalTo(Vector3 pos) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) EyeBlink.Teleport(delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) TeleportLocalToInstant(pos); }); } internal static void TeleportLocalTo(Vector3 pos, float yaw) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) EyeBlink.Teleport(delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) TeleportLocalToInstant(pos); try { Player local = Player.Local; if ((Object)(object)local != (Object)null) { ((Component)local).transform.rotation = Quaternion.Euler(0f, yaw, 0f); } } catch { } }); } internal static void TeleportLocalToInstant(Vector3 pos) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) try { Player local = Player.Local; if (!((Object)(object)local == (Object)null)) { PlayerTeleporter component = ((Component)local).GetComponent(); if ((Object)(object)component != (Object)null) { GameObject val = new GameObject("ph_tp"); val.transform.position = pos; component.Teleport(val.transform); Object.Destroy((Object)(object)val); } else { ((Component)local).transform.position = pos; } } } catch (Exception) { } } internal static float FeetY(Player p) { //IL_0015: 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_00b6: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_0040: 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_0053: 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) if ((Object)(object)p == (Object)null) { return 0f; } Vector3 position = ((Component)p).transform.position; Bounds bounds; try { Player local = Player.Local; if ((Object)(object)local != (Object)null) { CharacterController componentInChildren = ((Component)local).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { bounds = ((Collider)componentInChildren).bounds; _localFeetOffset = ((Bounds)(ref bounds)).min.y - ((Component)local).transform.position.y; } } } catch { } switch (GroundMode) { case 1: try { CharacterController componentInChildren2 = ((Component)p).GetComponentInChildren(); if ((Object)(object)componentInChildren2 != (Object)null) { bounds = ((Collider)componentInChildren2).bounds; return ((Bounds)(ref bounds)).min.y; } } catch { } return position.y + _localFeetOffset; case 2: return FloorRaycastY(position); case 3: return position.y - FixedFeetDrop; default: return position.y + _localFeetOffset; } } private static float FloorRaycastY(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0093: Unknown result type (might be due to invalid IL or missing references) try { Il2CppStructArray val = Physics.RaycastAll(pos + Vector3.up * 0.3f, Vector3.down, 5f); if (val != null && ((Il2CppArrayBase)(object)val).Length > 0) { Array.Sort(Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)val), (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int num = 0; num < ((Il2CppArrayBase)(object)val).Length; num++) { RaycastHit val2 = ((Il2CppArrayBase)(object)val)[num]; Collider collider = ((RaycastHit)(ref val2)).collider; if (!((Object)(object)collider == (Object)null) && !((Object)(object)((Component)collider).GetComponentInParent() != (Object)null)) { val2 = ((Il2CppArrayBase)(object)val)[num]; return ((RaycastHit)(ref val2)).point.y; } } } } catch { } return pos.y - 1f; } internal static void GiveWeapon(string id) { if (string.IsNullOrEmpty(id)) { return; } try { PlayerInventory instance = PlayerSingleton.Instance; if ((Object)(object)instance == (Object)null || instance.GetAmountOfItem(id) != 0) { return; } ItemDefinition val = null; try { val = Registry.GetItem(id); } catch { } if ((Object)(object)val == (Object)null) { Core.Log.Warning("[PropHunt] weapon '" + id + "' not in the item registry."); return; } ItemInstance defaultInstance = val.GetDefaultInstance(1); if (defaultInstance != null && instance.CanItemFitInInventory(defaultInstance, 1)) { instance.AddItemToInventory(defaultInstance); Core.Log.Msg("[PropHunt] armed hunter with '" + id + "'."); } } catch (Exception ex) { Core.Log.Warning("[PropHunt] GiveWeapon failed: " + ex.Message); } } internal static void RemoveWeapon(string id) { if (string.IsNullOrEmpty(id)) { return; } try { PlayerInventory instance = PlayerSingleton.Instance; if (!((Object)(object)instance == (Object)null) && instance.GetAmountOfItem(id) != 0) { instance.RemoveAmountOfItem(id, 99u); Core.Log.Msg("[PropHunt] disarmed former hunter ('" + id + "')."); } } catch (Exception ex) { Core.Log.Warning("[PropHunt] RemoveWeapon failed: " + ex.Message); } } } internal static class RoundLogic { private const int AutoStartPauseSeconds = 10; internal const int DoorsOpenSeconds = 3; internal static bool SyncRoster(GameState s, IEnumerable memberIds) { bool result = false; HashSet present = new HashSet(); if (memberIds != null) { foreach (ulong memberId in memberIds) { if (memberId != 0L) { present.Add(memberId); if (!s.Players.ContainsKey(memberId)) { s.GetOrAdd(memberId).Role = PlayerRole.Spectator; result = true; } } } } foreach (ulong item in s.Players.Keys.Where((ulong k) => !present.Contains(k)).ToList()) { s.Players.Remove(item); result = true; } return result; } internal static int AliveHiders(GameState s) { return s.Players.Values.Count((PlayerState p) => p.Role == PlayerRole.Hider && !p.Eliminated); } internal static int CountRole(GameState s, PlayerRole r) { return s.Players.Values.Count((PlayerState p) => p.Role == r); } internal static void AssignRoles(GameState s, RoundSettings set, int round) { List list = s.Players.Keys.ToList(); list.Sort(); int count = list.Count; if (count == 0) { return; } int num = Math.Max(1, count / Math.Max(1, set.PlayersPerHunter)); if (num >= count) { num = Math.Max(1, count - 1); } int num2 = (round - 1) / Math.Max(1, set.RoundsBeforeSwap); HashSet hashSet = new HashSet(); for (int i = 0; i < num; i++) { hashSet.Add(list[(num2 + i) % count]); } foreach (ulong item in list) { PlayerState orAdd = s.GetOrAdd(item); orAdd.Role = ((!hashSet.Contains(item)) ? PlayerRole.Hider : PlayerRole.Hunter); orAdd.PropId = -1; orAdd.Locked = false; orAdd.Eliminated = false; orAdd.Hits = 0; orAdd.MaxHits = 1; orAdd.Changes = 0; orAdd.PropYaw = 0f; orAdd.DecoysUsed = 0; orAdd.ConcussUsed = 0; orAdd.CatchesMade = 0; orAdd.HitsDealt = 0; orAdd.DecoyBaits = 0; orAdd.StunsLanded = 0; orAdd.SurvivedSeconds = 0; orAdd.DecoysSmashed = 0; orAdd.Taunts = 0; orAdd.HunterHits = 0; orAdd.HunterMaxHits = Math.Max(1, set.HunterHitsToDown); orAdd.Downed = false; orAdd.DownedUntilUnix = 0L; orAdd.KnockX = 0f; orAdd.KnockZ = 0f; } } internal static void EnterHiding(GameState s, RoundSettings set, long now) { foreach (PlayerState value in s.Players.Values) { if (value.Role == PlayerRole.Hider) { value.PropId = -1; value.Locked = false; value.Eliminated = false; value.Hits = 0; value.MaxHits = 1; value.Changes = 0; value.PropYaw = 0f; value.DecoysUsed = 0; value.ConcussUsed = 0; } } if (set.RemoveDecoysBetweenRounds) { s.Decoys.Clear(); } s.Winner = -1; s.Phase = RoundPhase.Hiding; s.PhaseEndsAtUnix = now + Math.Max(1, set.HideSeconds); } internal static void EnterHunting(GameState s, RoundSettings set, long now) { s.Phase = RoundPhase.Hunting; s.PhaseEndsAtUnix = now + Math.Max(1, set.HuntSeconds); s.HuntStartUnix = now; } internal static void EndRound(GameState s, RoundSettings set, long now, bool winnerHunters) { foreach (PlayerState value in s.Players.Values) { if (value.Role == PlayerRole.Hider && !value.Eliminated && s.HuntStartUnix > 0) { value.SurvivedSeconds = (int)Math.Max(0L, now - s.HuntStartUnix); } } foreach (PlayerState value2 in s.Players.Values) { value2.SessScore += RoundScore(value2, winnerHunters); } s.Phase = RoundPhase.RoundEnd; s.Winner = ((!winnerHunters) ? 1 : 0); s.PhaseEndsAtUnix = now + Math.Max(1, set.RoundEndSeconds); } internal static int RoundScore(PlayerState p, bool huntersWon) { int num = p.CatchesMade * 10 + p.HitsDealt + p.DecoyBaits * 5 + p.StunsLanded * 5 + p.SurvivedSeconds / 5 + p.DecoysSmashed * 3 + p.Taunts * 2; if ((huntersWon ? (p.Role == PlayerRole.Hunter) : (p.Role == PlayerRole.Hider)) && !p.Eliminated) { num += 15; } return num; } internal static void BeginMatch(GameState s, RoundSettings set, long now, IEnumerable memberIds) { SyncRoster(s, memberIds); if (!string.IsNullOrEmpty(s.SafehouseCode)) { s.RoundNumber = 0; EnterSafehouse(s, now); } else { s.RoundNumber = 1; AssignRoles(s, set, s.RoundNumber); EnterHiding(s, set, now); } } internal static bool AfterRoundEnd(GameState s, RoundSettings set, long now) { if (set.RemoveDecoysBetweenRounds) { s.Decoys.Clear(); } if (set.Structure == RoundStructure.Single) { s.Phase = RoundPhase.MatchEnd; return true; } if (!string.IsNullOrEmpty(s.SafehouseCode)) { EnterSafehouse(s, now); return true; } s.RoundNumber++; AssignRoles(s, set, s.RoundNumber); EnterHiding(s, set, now); return true; } internal static void EnterSafehouse(GameState s, long now) { s.Phase = RoundPhase.Safehouse; s.SafehouseReady = false; s.PhaseEndsAtUnix = 0L; s.Winner = -1; foreach (PlayerState value in s.Players.Values) { value.PropId = -1; value.Locked = false; value.Hits = 0; value.MaxHits = 1; value.PropYaw = 0f; } } internal static void ConfirmSafehouseReady(GameState s, long now) { s.SafehouseReady = true; s.PhaseEndsAtUnix = now + 3; } internal static int SecondsUntilNextRound(GameState s, RoundSettings set, long now) { if (set == null || set.Structure != RoundStructure.Continuous) { return -1; } int num = (int)((s.PhaseEndsAtUnix > 0) ? Math.Max(0L, s.PhaseEndsAtUnix - now) : 0); switch (s.Phase) { case RoundPhase.RoundEnd: if (!set.AutoStartNextRound) { if (s.PhaseEndsAtUnix <= 0) { return -1; } return num; } return num + 10 + 3; case RoundPhase.Safehouse: if (s.SafehouseReady) { return num; } if (set.AutoStartNextRound && s.RoundNumber >= 1 && s.PhaseEndsAtUnix > 0) { return num + 3; } return -1; default: return -1; } } internal static bool TickHost(GameState s, RoundSettings set, long now) { bool num = RecoverDowned(s, now); bool flag = TickPhase(s, set, now); return num || flag; } private static bool RecoverDowned(GameState s, long now) { bool result = false; foreach (PlayerState value in s.Players.Values) { if (value.Downed && (now >= value.DownedUntilUnix || value.Role != PlayerRole.Hunter || value.Eliminated)) { value.Downed = false; value.HunterHits = 0; value.DownedUntilUnix = 0L; value.KnockX = 0f; value.KnockZ = 0f; result = true; } } return result; } internal static bool ApplyHitHunter(GameState s, RoundSettings set, ulong shooter, ulong victim, long now, out bool newlyDowned) { newlyDowned = false; if (s.Phase != RoundPhase.Hunting || !set.FriendlyFire || shooter == victim) { return false; } if (!s.Players.TryGetValue(shooter, out var value) || value.Role != PlayerRole.Hunter || value.Eliminated) { return false; } if (!s.Players.TryGetValue(victim, out var value2) || value2.Role != PlayerRole.Hunter || value2.Eliminated) { return false; } int num = Math.Max(1, set.HunterHitsToDown); int num2 = Math.Max(1, (int)Math.Round(set.HunterDownBaseSeconds)); int num3 = Math.Max(num2, (int)Math.Round(set.HunterDownMaxSeconds)); int num4 = Math.Max(0, (num3 - num2) / 2); value2.HunterMaxHits = num; if (!value2.Downed) { value2.HunterHits++; if (value2.HunterHits < num) { return true; } value2.Downed = true; value2.DownedUntilUnix = now + num2; newlyDowned = true; return true; } if (value2.HunterHits - num >= num4) { return false; } value2.HunterHits++; value2.DownedUntilUnix += 2L; return true; } internal static bool ApplyConcussDown(GameState s, ulong hunterId, int seconds, long now) { if (s.Phase != RoundPhase.Hunting) { return false; } if (!s.Players.TryGetValue(hunterId, out var value) || value.Role != PlayerRole.Hunter || value.Eliminated) { return false; } long num = now + Math.Max(1, seconds); if (value.Downed && value.DownedUntilUnix >= num) { return false; } value.Downed = true; value.DownedUntilUnix = Math.Max(value.DownedUntilUnix, num); return true; } private static bool TickPhase(GameState s, RoundSettings set, long now) { switch (s.Phase) { case RoundPhase.Hiding: if (CountRole(s, PlayerRole.Hunter) == 0) { EndRound(s, set, now, winnerHunters: false); return true; } if (AliveHiders(s) == 0) { EndRound(s, set, now, winnerHunters: true); return true; } if (now >= s.PhaseEndsAtUnix) { EnterHunting(s, set, now); return true; } break; case RoundPhase.Hunting: if (CountRole(s, PlayerRole.Hunter) == 0) { EndRound(s, set, now, winnerHunters: false); return true; } if (AliveHiders(s) == 0) { EndRound(s, set, now, winnerHunters: true); return true; } if (now >= s.PhaseEndsAtUnix) { EndRound(s, set, now, winnerHunters: false); return true; } break; case RoundPhase.RoundEnd: if (now >= s.PhaseEndsAtUnix) { AfterRoundEnd(s, set, now); return true; } break; case RoundPhase.Safehouse: if (set.AutoStartNextRound && !s.SafehouseReady && s.RoundNumber >= 1) { if (s.PhaseEndsAtUnix <= 0) { s.PhaseEndsAtUnix = now + 10; } else if (now >= s.PhaseEndsAtUnix) { ConfirmSafehouseReady(s, now); return true; } } if (s.SafehouseReady && s.PhaseEndsAtUnix > 0 && now >= s.PhaseEndsAtUnix) { s.RoundNumber++; AssignRoles(s, set, s.RoundNumber); EnterHiding(s, set, now); return true; } break; } return false; } private static bool CanDisguise(RoundPhase phase) { if (phase != RoundPhase.Hiding) { return phase == RoundPhase.Hunting; } return true; } internal static bool ApplySelectProp(GameState s, ulong sender, int propId, int maxHits, int maxChanges, bool freeChange = false) { if (!CanDisguise(s.Phase)) { return false; } if (!s.Players.TryGetValue(sender, out var value) || value.Role != PlayerRole.Hider || value.Eliminated) { return false; } if (!freeChange && maxChanges > 0 && value.Changes >= maxChanges) { return false; } value.PropId = propId; value.MaxHits = Math.Max(1, maxHits); value.Hits = 0; value.DecoysUsed = 0; value.ConcussUsed = 0; if (!freeChange) { value.Changes++; } return true; } internal static bool ApplyLock(GameState s, ulong sender, bool locked) { if (!CanDisguise(s.Phase)) { return false; } if (!s.Players.TryGetValue(sender, out var value) || value.Role != PlayerRole.Hider || value.Eliminated) { return false; } if (locked && value.PropId < 0) { return false; } value.Locked = locked; return true; } internal static bool ApplyCatch(GameState s, RoundSettings set, ulong hunter, ulong victim, long now) { if (s.Phase != RoundPhase.Hunting) { return false; } if (!s.Players.TryGetValue(hunter, out var value) || value.Role != PlayerRole.Hunter || value.Eliminated) { return false; } if (!s.Players.TryGetValue(victim, out var value2) || value2.Role != PlayerRole.Hider || value2.Eliminated) { return false; } value2.Hits++; value.HitsDealt++; if (value2.Hits < Math.Max(1, value2.MaxHits)) { return true; } value.CatchesMade++; if (s.HuntStartUnix > 0) { value2.SurvivedSeconds = (int)Math.Max(0L, now - s.HuntStartUnix); } if (set.Caught == CaughtBehavior.Infection) { value2.Role = PlayerRole.Hunter; value2.PropId = -1; value2.Locked = false; value2.Eliminated = false; value2.Hits = 0; value2.MaxHits = 1; value2.Changes = 0; value2.PropYaw = 0f; value2.DecoysUsed = 0; value2.ConcussUsed = 0; value2.HunterHits = 0; value2.HunterMaxHits = Math.Max(1, set.HunterHitsToDown); value2.Downed = false; value2.DownedUntilUnix = 0L; value2.KnockX = 0f; value2.KnockZ = 0f; } else { value2.Eliminated = true; } if (AliveHiders(s) == 0) { EndRound(s, set, now, winnerHunters: true); } return true; } internal static bool ApplyRotate(GameState s, ulong sender, float yaw) { if (!CanDisguise(s.Phase)) { return false; } if (!s.Players.TryGetValue(sender, out var value) || value.Role != PlayerRole.Hider || value.Eliminated || value.PropId < 0) { return false; } value.PropYaw = yaw; return true; } internal static bool ApplyDropDecoy(GameState s, RoundSettings set, ulong sender, float x, float y, float z, float yaw, int maxHits) { if (s.Phase != RoundPhase.Hiding && s.Phase != RoundPhase.Hunting) { return false; } if (!s.Players.TryGetValue(sender, out var value) || value.Role != PlayerRole.Hider || value.Eliminated || value.PropId < 0) { return false; } if (set.MaxDecoys > 0 && value.DecoysUsed >= set.MaxDecoys) { return false; } s.Decoys.Add(new DecoyState { X = x, Y = y, Z = z, Yaw = yaw, PropId = value.PropId, MaxHits = Math.Max(1, maxHits), OwnerSteamId = sender }); value.DecoysUsed++; return true; } internal static bool ApplyHitDecoy(GameState s, int decoyIndex) { if (s.Phase != RoundPhase.Hunting) { return false; } if (decoyIndex < 0 || decoyIndex >= s.Decoys.Count) { return false; } DecoyState decoyState = s.Decoys[decoyIndex]; if (decoyState.Destroyed) { return false; } decoyState.Hits++; if (decoyState.OwnerSteamId != 0L && s.Players.TryGetValue(decoyState.OwnerSteamId, out var value) && value.Role == PlayerRole.Hider) { value.DecoyBaits++; } if (decoyState.Hits >= Math.Max(1, decoyState.MaxHits)) { decoyState.Destroyed = true; } return true; } internal static bool ApplyConcuss(GameState s, RoundSettings set, ulong sender) { if (s.Phase != RoundPhase.Hunting) { return false; } if (!s.Players.TryGetValue(sender, out var value) || value.Role != PlayerRole.Hider || value.Eliminated) { return false; } if (set.ConcussCharges > 0 && value.ConcussUsed >= set.ConcussCharges) { return false; } value.ConcussUsed++; return true; } internal static bool IsCaught(GameState s, ulong victim) { if (s.Players.TryGetValue(victim, out var value)) { if (!value.Eliminated) { return value.Role != PlayerRole.Hider; } return true; } return false; } internal static bool ApplyOutOfBounds(GameState s, RoundSettings set, ulong id, long now) { if (s.Phase != RoundPhase.Hiding && s.Phase != RoundPhase.Hunting) { return false; } if (!s.Players.TryGetValue(id, out var value) || value.Eliminated) { return false; } if (value.Role != PlayerRole.Hider) { return false; } value.Eliminated = true; if (s.Phase == RoundPhase.Hunting && AliveHiders(s) == 0) { EndRound(s, set, now, winnerHunters: true); } return true; } } internal sealed class RoundSettings { internal int HideSeconds = 30; internal int HuntSeconds = 300; internal int RoundEndSeconds = 15; internal int PlayersPerHunter = 5; internal int RoundsBeforeSwap = 1; internal int HiderSpeedPercent = 90; internal float TagRange = 4f; internal int TauntIntervalSeconds = 30; internal float WhistleStaggerSeconds = 0.3f; internal float PlayAreaRadius = 75f; internal int HitsToCatch = 2; internal int HiderMaxHp = 4; internal int MaxPropChanges = 5; internal int MaxDecoys = 4; internal int ConcussCharges = 1; internal float ConcussRadius = 7f; internal CaughtBehavior Caught; internal RoundStructure Structure; internal int TimeOfDay = 1200; internal string HunterWeapon = "pumpshotgun"; internal bool FriendlyFire = true; internal int HunterHitsToDown = 3; internal float HunterDownBaseSeconds = 3f; internal float HunterDownMaxSeconds = 10f; internal float ConcussStunSeconds = 2f; internal bool RemoveDecoysBetweenRounds = true; internal bool AllowRandomChange = true; internal bool FreeChangesInHiding = true; internal bool FreezeTime = true; internal bool AutoStartNextRound = true; internal static CaughtBehavior ParseCaught(string s) { if (!string.Equals(s, "Infection", StringComparison.OrdinalIgnoreCase)) { return CaughtBehavior.Spectator; } return CaughtBehavior.Infection; } internal static RoundStructure ParseStructure(string s) { if (!string.Equals(s, "Single", StringComparison.OrdinalIgnoreCase)) { return RoundStructure.Continuous; } return RoundStructure.Single; } internal string Serialize() { CultureInfo invariantCulture = CultureInfo.InvariantCulture; return string.Join(";", "hide=" + HideSeconds.ToString(invariantCulture), "hunt=" + HuntSeconds.ToString(invariantCulture), "end=" + RoundEndSeconds.ToString(invariantCulture), "pph=" + PlayersPerHunter.ToString(invariantCulture), "swap=" + RoundsBeforeSwap.ToString(invariantCulture), "hiderspeed=" + HiderSpeedPercent.ToString(invariantCulture), "tag=" + TagRange.ToString(invariantCulture), "taunt=" + TauntIntervalSeconds.ToString(invariantCulture), "wstag=" + WhistleStaggerSeconds.ToString(invariantCulture), "area=" + PlayAreaRadius.ToString(invariantCulture), "hits=" + HitsToCatch.ToString(invariantCulture), "hidermaxhp=" + HiderMaxHp.ToString(invariantCulture), "chg=" + MaxPropChanges.ToString(invariantCulture), "decoy=" + MaxDecoys.ToString(invariantCulture), "conc=" + ConcussCharges.ToString(invariantCulture), "concr=" + ConcussRadius.ToString(invariantCulture), "caught=" + Caught, "round=" + Structure, "time=" + TimeOfDay.ToString(invariantCulture), "weapon=" + HunterWeapon, "ff=" + (FriendlyFire ? "1" : "0"), "hhp=" + HunterHitsToDown.ToString(invariantCulture), "downb=" + HunterDownBaseSeconds.ToString(invariantCulture), "downx=" + HunterDownMaxSeconds.ToString(invariantCulture), "stun=" + ConcussStunSeconds.ToString(invariantCulture), "rmdecoy=" + (RemoveDecoysBetweenRounds ? "1" : "0"), "rnd=" + (AllowRandomChange ? "1" : "0"), "freechg=" + (FreeChangesInHiding ? "1" : "0"), "freeze=" + (FreezeTime ? "1" : "0"), "autostart=" + (AutoStartNextRound ? "1" : "0")); } internal static RoundSettings Parse(string blob) { return Parse(blob, new RoundSettings()); } internal static RoundSettings Parse(string blob, RoundSettings defaults) { RoundSettings roundSettings = defaults ?? new RoundSettings(); if (string.IsNullOrEmpty(blob)) { return roundSettings; } string[] array = blob.Split(';'); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { roundSettings.ApplyKeyValue(text.Substring(0, num), text.Substring(num + 1)); } } return roundSettings; } internal void ApplyKeyValue(string k, string v) { CultureInfo invariantCulture = CultureInfo.InvariantCulture; if (k == null) { return; } switch (k.Length) { case 4: switch (k[2]) { case 'd': { if (k == "hide" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result7)) { HideSeconds = result7; } break; } case 'n': { int result12; if (!(k == "hunt")) { if (k == "conc" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result11)) { ConcussCharges = result11; } } else if (int.TryParse(v, NumberStyles.Integer, invariantCulture, out result12)) { HuntSeconds = result12; } break; } case 'a': { if (k == "swap" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result8)) { RoundsBeforeSwap = result8; } break; } case 'e': { if (k == "area" && float.TryParse(v, NumberStyles.Float, invariantCulture, out var result10)) { PlayAreaRadius = result10; } break; } case 't': { if (k == "hits" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result13)) { HitsToCatch = result13; } break; } case 'm': { if (k == "time" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result9)) { TimeOfDay = result9; } break; } case 'u': { if (k == "stun" && float.TryParse(v, NumberStyles.Float, invariantCulture, out var result6)) { ConcussStunSeconds = result6; } break; } } break; case 3: switch (k[0]) { case 'e': { if (k == "end" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result3)) { RoundEndSeconds = result3; } break; } case 'p': { if (k == "pph" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result)) { PlayersPerHunter = result; } break; } case 't': { if (k == "tag" && float.TryParse(v, NumberStyles.Float, invariantCulture, out var result4)) { TagRange = result4; } break; } case 'c': { if (k == "chg" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result5)) { MaxPropChanges = result5; } break; } case 'h': { if (k == "hhp" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result2)) { HunterHitsToDown = result2; } break; } case 'r': if (k == "rnd") { AllowRandomChange = v == "1"; } break; } break; case 10: switch (k[5]) { case 's': { if (k == "hiderspeed" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result21)) { HiderSpeedPercent = result21; } break; } case 'm': { if (k == "hidermaxhp" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result20)) { HiderMaxHp = result20; } break; } } break; case 5: switch (k[4]) { case 't': { if (k == "taunt" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result19)) { TauntIntervalSeconds = result19; } break; } case 'g': { if (k == "wstag" && float.TryParse(v, NumberStyles.Float, invariantCulture, out var result18)) { WhistleStaggerSeconds = result18; } break; } case 'y': { if (k == "decoy" && int.TryParse(v, NumberStyles.Integer, invariantCulture, out var result15)) { MaxDecoys = result15; } break; } case 'r': { if (k == "concr" && float.TryParse(v, NumberStyles.Float, invariantCulture, out var result16)) { ConcussRadius = result16; } break; } case 'd': if (k == "round") { Structure = ParseStructure(v); } break; case 'b': { if (k == "downb" && float.TryParse(v, NumberStyles.Float, invariantCulture, out var result17)) { HunterDownBaseSeconds = result17; } break; } case 'x': { if (k == "downx" && float.TryParse(v, NumberStyles.Float, invariantCulture, out var result14)) { HunterDownMaxSeconds = result14; } break; } } break; case 6: switch (k[0]) { case 'c': if (k == "caught") { Caught = ParseCaught(v); } break; case 'w': if (k == "weapon") { HunterWeapon = v; } break; case 'f': if (k == "freeze") { FreezeTime = v == "1"; } break; } break; case 7: switch (k[0]) { case 'r': if (k == "rmdecoy") { RemoveDecoysBetweenRounds = v == "1"; } break; case 'f': if (k == "freechg") { FreeChangesInHiding = v == "1"; } break; } break; case 2: if (k == "ff") { FriendlyFire = v == "1"; } break; case 9: if (k == "autostart") { AutoStartNextRound = v == "1"; } break; case 8: break; } } internal Dictionary ToValues() { Dictionary dictionary = new Dictionary(StringComparer.Ordinal); string[] array = Serialize().Split(';'); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { dictionary[text.Substring(0, num)] = text.Substring(num + 1); } } return dictionary; } public override string ToString() { return $"hide={HideSeconds}s hunt={HuntSeconds}s pph={PlayersPerHunter} caught={Caught} round={Structure} tag={TagRange} hits={HitsToCatch} area={PlayAreaRadius}"; } } internal static class SafehouseSelector { private static readonly string[] Tiers = new string[8] { "motelroom", "storageunit", "sweatshop", "seweroffice", "bungalow", "barn", "dockswarehouse", "manor" }; private const int MaxLobby = 16; private const float AreaPerPlayer = 14f; internal static int Capacity(int area) { int num = Mathf.RoundToInt((float)area / 14f); if (num >= 2) { return num; } return 2; } internal static string SelectForPlayerCount(int playerCount) { List list = OrderedDefaults(); if (list.Count == 0) { return ""; } int num = Mathf.RoundToInt((float)(((playerCount < 2) ? 2 : ((playerCount > 16) ? 16 : playerCount)) - 2) / 14f * (float)(list.Count - 1)); if (num < 0) { num = 0; } if (num > list.Count - 1) { num = list.Count - 1; } return list[num]; } internal static List AvailableForPlayerCount(int playerCount) { int num = ((playerCount < 2) ? 2 : playerCount); Dictionary dictionary = GatherUsable(); List> list = new List>(); foreach (KeyValuePair item in dictionary) { if (Capacity(item.Value) >= num) { list.Add(item); } } if (list.Count == 0) { list.AddRange(dictionary); } list.Sort((KeyValuePair a, KeyValuePair b) => a.Value.CompareTo(b.Value)); List list2 = new List(); foreach (KeyValuePair item2 in list) { list2.Add(item2.Key); } return list2; } internal static bool Fits(string code, int playerCount) { if (string.IsNullOrEmpty(code)) { return false; } if (GatherUsable().TryGetValue(code, out var value)) { return Capacity(value) >= ((playerCount < 2) ? 2 : playerCount); } return false; } private static List OrderedDefaults() { Dictionary dictionary = GatherUsable(); List list = new List(); for (int i = 0; i < Tiers.Length; i++) { if (dictionary.ContainsKey(Tiers[i])) { list.Add(Tiers[i]); } } if (list.Count > 0) { return list; } List> list2 = new List>(dictionary); list2.Sort((KeyValuePair a, KeyValuePair b) => a.Value.CompareTo(b.Value)); foreach (KeyValuePair item in list2) { list.Add(item.Key); } return list; } private static Dictionary GatherUsable() { Dictionary dictionary = new Dictionary(); try { List properties = Property.Properties; if (properties == null) { return dictionary; } for (int i = 0; i < properties.Count; i++) { Property val = properties[i]; if (!((Object)(object)val == (Object)null) && (!((Object)(object)val.InteriorSpawnPoint == (Object)null) || !((Object)(object)val.SpawnPoint == (Object)null))) { string propertyCode = val.PropertyCode; if (!string.IsNullOrEmpty(propertyCode)) { dictionary[propertyCode] = GridArea(val); } } } } catch (Exception) { } return dictionary; } internal static int GridArea(Property p) { int num = 0; try { List grids = p.Grids; if (grids != null) { for (int i = 0; i < grids.Count; i++) { Grid val = grids[i]; if ((Object)(object)val != (Object)null) { num += val.Width * val.Height; } } } } catch { } return num; } } internal static class SpawnStore { internal readonly struct SpawnPoint { internal readonly Vector3 Pos; internal readonly float Yaw; internal SpawnPoint(Vector3 pos, float yaw) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Pos = pos; Yaw = yaw; } } private static readonly Dictionary> _spawns = new Dictionary>(); private static bool _loaded; private static string SpawnsPath => Path.Combine(MelonEnvironment.UserDataDirectory, "PropHunt", "spawns.txt"); internal static bool HasSpawns(string code) { if (!_loaded) { Load(); } if (!string.IsNullOrEmpty(code) && _spawns.TryGetValue(code, out var value)) { return value.Count > 0; } return false; } internal static List GetSpawns(string code) { if (!_loaded) { Load(); } if (!_spawns.TryGetValue(code, out var value)) { return null; } return value; } internal static void Add(string code, Vector3 pos, float yaw) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!_loaded) { Load(); } if (!_spawns.TryGetValue(code, out var value)) { value = new List(); _spawns[code] = value; } value.Add(new SpawnPoint(pos, yaw)); } internal static void ClearCode(string code) { if (!_loaded) { Load(); } _spawns.Remove(code); } internal static void Save() { try { string spawnsPath = SpawnsPath; Directory.CreateDirectory(Path.GetDirectoryName(spawnsPath)); CultureInfo invariantCulture = CultureInfo.InvariantCulture; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# PropHunt safehouse spawn points. Format: code|x|y|z|yaw"); stringBuilder.AppendLine("# Authored with the phspawn in-game editor. Copy to Assets/spawns.txt to bake in."); foreach (KeyValuePair> spawn in _spawns) { foreach (SpawnPoint item in spawn.Value) { stringBuilder.Append(spawn.Key).Append('|').Append(item.Pos.x.ToString("F3", invariantCulture)) .Append('|') .Append(item.Pos.y.ToString("F3", invariantCulture)) .Append('|') .Append(item.Pos.z.ToString("F3", invariantCulture)) .Append('|') .Append(item.Yaw.ToString("F1", invariantCulture)) .Append('\n'); } } File.WriteAllText(spawnsPath, stringBuilder.ToString()); Core.Log.Msg("[PropHunt] spawns saved -> " + spawnsPath); } catch (Exception ex) { Core.Log.Warning("[PropHunt] SpawnStore.Save failed: " + ex.Message); } } internal static void Reload() { _loaded = false; _spawns.Clear(); Load(); } private static void Load() { _loaded = true; _spawns.Clear(); try { string spawnsPath = SpawnsPath; string[] array = ((!File.Exists(spawnsPath)) ? ReadShipped() : File.ReadAllLines(spawnsPath)); if (array == null) { return; } Parse(array); int num = 0; foreach (List value in _spawns.Values) { num += value.Count; } } catch (Exception ex) { Core.Log.Warning("[PropHunt] SpawnStore.Load failed: " + ex.Message); } } private static void Parse(string[] lines) { //IL_00c9: Unknown result type (might be due to invalid IL or missing references) CultureInfo invariantCulture = CultureInfo.InvariantCulture; NumberStyles style = NumberStyles.Float; for (int i = 0; i < lines.Length; i++) { string text = lines[i].Trim(); if (text.Length == 0 || text.StartsWith("#")) { continue; } string[] array = text.Split('|'); if (array.Length < 5) { continue; } string text2 = array[0].Trim(); if (!string.IsNullOrEmpty(text2) && float.TryParse(array[1], style, invariantCulture, out var result) && float.TryParse(array[2], style, invariantCulture, out var result2) && float.TryParse(array[3], style, invariantCulture, out var result3) && float.TryParse(array[4], style, invariantCulture, out var result4)) { if (!_spawns.TryGetValue(text2, out var value)) { value = new List(); _spawns[text2] = value; } value.Add(new SpawnPoint(new Vector3(result, result2, result3), result4)); } } } private static string[] ReadShipped() { try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PropHunt.Assets.spawns.txt"); if (stream == null) { return null; } using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd().Split('\n'); } catch { return null; } } } } namespace PropHunt.Disguise { internal sealed class DecoyController { private readonly List _decoys = new List(); private string _builtSig; internal void Apply(GameState state) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0158: 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_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) if (state == null) { return; } try { string text = BuildSig(state); if (text == _builtSig) { return; } Clear(); for (int i = 0; i < state.Decoys.Count; i++) { DecoyState decoyState = state.Decoys[i]; if (decoyState.Destroyed) { _decoys.Add(null); continue; } PropEntry propEntry = PropCatalog.ById(decoyState.PropId); if (propEntry == null || (Object)(object)propEntry.SourceRoot == (Object)null) { _decoys.Add(null); continue; } GameObject val = PropClone.Build(propEntry, "ph_decoy_" + i); if ((Object)(object)val == (Object)null) { _decoys.Add(null); continue; } val.transform.localScale = propEntry.SourceRoot.transform.lossyScale; val.transform.rotation = Quaternion.Euler(0f, decoyState.Yaw, 0f) * propEntry.SourceRoot.transform.rotation; val.transform.position = new Vector3(decoyState.X, decoyState.Y, decoyState.Z); if (PropClone.TryGetPropBoundsFromSource(propEntry, out var local)) { Bounds val2 = PropClone.LocalToWorldBounds(val.transform, local); Transform transform = val.transform; transform.position += new Vector3(decoyState.X - ((Bounds)(ref val2)).center.x, decoyState.Y - ((Bounds)(ref val2)).min.y, decoyState.Z - ((Bounds)(ref val2)).center.z); PropClone.AddTriggerHitbox(val, local); } else { if (PropClone.TryGetWorldBounds(val, out var bounds)) { Transform transform2 = val.transform; transform2.position += new Vector3(decoyState.X - ((Bounds)(ref bounds)).center.x, decoyState.Y - ((Bounds)(ref bounds)).min.y, decoyState.Z - ((Bounds)(ref bounds)).center.z); } PropClone.AddTriggerHitbox(val); } _decoys.Add(val); } _builtSig = text; } catch (Exception) { } } private static string BuildSig(GameState state) { if (state.Decoys.Count == 0) { return "0:"; } StringBuilder stringBuilder = new StringBuilder(state.Decoys.Count * 2 + 4); stringBuilder.Append(state.Decoys.Count).Append(':'); for (int i = 0; i < state.Decoys.Count; i++) { stringBuilder.Append(state.Decoys[i].Destroyed ? '1' : '0'); } return stringBuilder.ToString(); } private int ActiveCount() { int num = 0; for (int i = 0; i < _decoys.Count; i++) { if ((Object)(object)_decoys[i] != (Object)null) { num++; } } return num; } private void Clear() { for (int i = 0; i < _decoys.Count; i++) { GameObject val = _decoys[i]; if ((Object)(object)val != (Object)null) { try { Object.Destroy((Object)(object)val); } catch { } } } _decoys.Clear(); } internal void Dispose() { try { Clear(); } catch { } _builtSig = null; } } internal sealed class DisguiseController { private readonly Dictionary _props = new Dictionary(); private readonly Dictionary _appliedPropId = new Dictionary(); private readonly Dictionary _sourceRot = new Dictionary(); private readonly Dictionary _cc = new Dictionary(); private readonly Dictionary _yaw = new Dictionary(); private readonly Dictionary _localBounds = new Dictionary(); private readonly Dictionary _nakedOriginal = new Dictionary(); private readonly HashSet _naked = new HashSet(); private readonly HashSet _warnedUnresolved = new HashSet(); private const float HiderScale = 0.7f; private bool _warnedHashMismatch; internal void Apply(GameState state) { if (state == null) { return; } try { if (!_warnedHashMismatch && state.CatalogHash != 0 && state.CatalogHash != PropCatalog.Hash) { _warnedHashMismatch = true; Core.Log.Warning($"[PropHunt] prop-catalog hash mismatch (host {state.CatalogHash} vs local {PropCatalog.Hash}) - disguises may differ."); } PlayerRegistry.Refresh(); ulong localSteamId = PropHuntNet.LocalSteamId; Player local = Player.Local; bool flag = state.Phase == RoundPhase.Hiding || state.Phase == RoundPhase.Hunting; foreach (PlayerState value3 in state.Players.Values) { Player val = ((value3.SteamId == localSteamId && (Object)(object)local != (Object)null) ? local : PlayerRegistry.Get(value3.SteamId)); bool flag2 = value3.Role == PlayerRole.Hider && !value3.Eliminated && flag; bool flag3 = flag2 && value3.PropId >= 0; bool flag4 = value3.Role == PlayerRole.Hider && value3.Eliminated && flag; if ((Object)(object)val == (Object)null) { if (flag3 && _warnedUnresolved.Add(value3.SteamId)) { Core.Log.Warning($"[PropHunt] disguise: no game Player resolved for {value3.SteamId} (prop {value3.PropId}) - cannot render. " + "PlayerCode not yet replicated for this peer? (retries each tick)"); } continue; } _warnedUnresolved.Remove(value3.SteamId); if (flag4) { RemoveProp(value3.SteamId, val); SetHiderScale(val, 1f); SetBodyVisible(val, visible: false, value3.SteamId == localSteamId); continue; } if (flag2) { EnsureNaked(value3.SteamId, val); } else { RestoreAppearance(value3.SteamId, val); } if (flag3) { EnsureProp(value3.SteamId, val, value3.PropId); } else { RemoveProp(value3.SteamId, val); } SetHiderScale(val, flag2 ? 0.7f : 1f); } List list = null; foreach (ulong key in _props.Keys) { if (!state.Players.TryGetValue(key, out var value) || value.PropId < 0 || value.Eliminated || value.Role != PlayerRole.Hider) { (list ?? (list = new List())).Add(key); } } if (list != null) { foreach (ulong item in list) { RemoveProp(item, PlayerRegistry.Get(item)); } } List list2 = null; foreach (ulong item2 in _naked) { if (!state.Players.TryGetValue(item2, out var value2) || value2.Role != PlayerRole.Hider || value2.Eliminated) { (list2 ?? (list2 = new List())).Add(item2); } } if (list2 == null) { return; } foreach (ulong item3 in list2) { RestoreAppearance(item3, (item3 == localSteamId) ? local : PlayerRegistry.Get(item3)); } } catch (Exception) { } } private void EnsureProp(ulong id, Player player, int propId) { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0135: 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_00be: 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_00eb: Unknown result type (might be due to invalid IL or missing references) if (_appliedPropId.TryGetValue(id, out var value) && value == propId && _props.ContainsKey(id)) { return; } RemoveProp(id, player); PropEntry propEntry = PropCatalog.ById(propId); if (propEntry == null || (Object)(object)propEntry.SourceRoot == (Object)null) { return; } try { bool isLocal = id == PropHuntNet.LocalSteamId; SetBodyVisible(player, visible: false, isLocal); GameObject val = PropClone.Build(propEntry, "ph_prop_" + id); if ((Object)(object)val == (Object)null) { SetBodyVisible(player, visible: true, isLocal); return; } val.transform.SetParent((Transform)null, false); val.transform.localScale = propEntry.SourceRoot.transform.lossyScale; _sourceRot[id] = propEntry.SourceRoot.transform.rotation; val.transform.rotation = _sourceRot[id]; try { val.transform.position = ((Component)player).transform.position; } catch { } if (PropClone.TryGetPropBoundsFromSource(propEntry, out var local)) { _localBounds[id] = local; PropClone.AddTriggerHitbox(val, local); } else { PropClone.AddTriggerHitbox(val); if (PropClone.TryGetPropLocalBounds(val, out var local2)) { _localBounds[id] = local2; } } _props[id] = val; _appliedPropId[id] = propId; } catch (Exception) { } } internal void LateApply(GameState state, ulong localId, float localYaw) { if (state == null) { return; } try { Player local = Player.Local; foreach (PlayerState value in state.Players.Values) { if (value.PropId >= 0 && !value.Eliminated && value.Role == PlayerRole.Hider && _props.ContainsKey(value.SteamId)) { bool flag = value.SteamId == localId; Player player = ((flag && (Object)(object)local != (Object)null) ? local : PlayerRegistry.Get(value.SteamId)); UpdatePropTransform(value.SteamId, player, flag ? localYaw : value.PropYaw, flag); } } } catch (Exception) { } } private void UpdatePropTransform(ulong id, Player player, float yaw, bool isLocal) { //IL_003b: 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_003c: 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_00a1: 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_00db: 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_00e2: 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_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_011f: 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_0124: 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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !_props.TryGetValue(id, out var value) || (Object)(object)value == (Object)null) { return; } Quaternion value2; Quaternion val = (_sourceRot.TryGetValue(id, out value2) ? value2 : Quaternion.identity); float num; if (isLocal) { num = yaw; _yaw[id] = yaw; } else { num = Mathf.LerpAngle(_yaw.TryGetValue(id, out var value3) ? value3 : yaw, yaw, Mathf.Clamp01(Time.deltaTime * 12f)); _yaw[id] = num; } value.transform.rotation = Quaternion.Euler(0f, num, 0f) * val; if (!_localBounds.TryGetValue(id, out var value4)) { if (!PropClone.TryGetPropLocalBounds(value, out value4)) { return; } _localBounds[id] = value4; } Bounds val2 = PropClone.LocalToWorldBounds(value.transform, value4); float num2 = RoundEnvironment.FeetY(player); CharacterController val3 = (isLocal ? ResolveController(id, player) : null); Vector3 val4; if (!((Object)(object)val3 != (Object)null)) { val4 = ((Component)player).transform.position; } else { Bounds bounds = ((Collider)val3).bounds; val4 = ((Bounds)(ref bounds)).center; } Vector3 val5 = val4; Transform transform = value.transform; transform.position += new Vector3(val5.x - ((Bounds)(ref val2)).center.x, num2 - ((Bounds)(ref val2)).min.y, val5.z - ((Bounds)(ref val2)).center.z); } private CharacterController ResolveController(ulong id, Player player) { if (_cc.TryGetValue(id, out var value) && (Object)(object)value != (Object)null) { return value; } _cc.Remove(id); try { value = ((Component)player).GetComponentInChildren(); } catch { value = null; } if ((Object)(object)value != (Object)null) { _cc[id] = value; } return value; } private void RemoveProp(ulong id, Player player) { if (_props.TryGetValue(id, out var value) && (Object)(object)value != (Object)null) { try { Object.Destroy((Object)(object)value); } catch { } } _props.Remove(id); _appliedPropId.Remove(id); _sourceRot.Remove(id); _cc.Remove(id); _yaw.Remove(id); _localBounds.Remove(id); if ((Object)(object)player != (Object)null) { SetBodyVisible(player, visible: true, id == PropHuntNet.LocalSteamId); } } private void EnsureNaked(ulong id, Player player) { if (_naked.Contains(id)) { return; } try { Avatar val = (((Object)(object)player != (Object)null) ? player.Avatar : null); if (!((Object)(object)val == (Object)null)) { AvatarSettings currentSettings = val.CurrentSettings; if (!((Object)(object)currentSettings == (Object)null)) { _nakedOriginal[id] = currentSettings; val.LoadNakedSettings(currentSettings, 19); _naked.Add(id); } } } catch (Exception) { } } private void RestoreAppearance(ulong id, Player player) { if (!_naked.Contains(id)) { return; } try { Avatar val = (((Object)(object)player != (Object)null) ? player.Avatar : null); if ((Object)(object)val != (Object)null && _nakedOriginal.TryGetValue(id, out var value) && (Object)(object)value != (Object)null) { val.LoadAvatarSettings(value); } } catch (Exception) { } _naked.Remove(id); _nakedOriginal.Remove(id); } private static void SetHiderScale(Player player, float scale) { //IL_002c: 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_003e: 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_0051: Unknown result type (might be due to invalid IL or missing references) try { Avatar val = (((Object)(object)player != (Object)null) ? player.Avatar : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).transform == (Object)null)) { Vector3 val2 = Vector3.one * scale; if (((Component)val).transform.localScale != val2) { ((Component)val).transform.localScale = val2; } } } catch { } } private static void SetBodyVisible(Player player, bool visible, bool isLocal) { try { player.SetThirdPersonMeshesVisibility(visible); } catch { } if (!isLocal) { try { player.SetVisibleToLocalPlayer(visible); } catch { } } } internal void Dispose() { foreach (KeyValuePair prop in _props) { if ((Object)(object)prop.Value != (Object)null) { try { Object.Destroy((Object)(object)prop.Value); } catch { } } } _props.Clear(); _appliedPropId.Clear(); _sourceRot.Clear(); _cc.Clear(); _yaw.Clear(); _localBounds.Clear(); if (_naked.Count > 0) { ulong localSteamId = PropHuntNet.LocalSteamId; foreach (ulong item in new List(_naked)) { RestoreAppearance(item, (item == localSteamId) ? Player.Local : PlayerRegistry.Get(item)); } } _naked.Clear(); _nakedOriginal.Clear(); try { List playerList = Player.PlayerList; if (playerList == null) { return; } for (int i = 0; i < playerList.Count; i++) { Player val = playerList[i]; if ((Object)(object)val != (Object)null) { SetBodyVisible(val, visible: true, (Object)(object)val == (Object)(object)Player.Local); SetHiderScale(val, 1f); } } } catch { } } } internal static class OutlineShader { private const string ResourceName = "PropHunt.Assets.Bundles.propoutline"; private const string ShaderName = "PropHunt/PropOutline"; private static bool _tried; private static Shader _shader; internal static Material TryCreateMaterial(Color color, float width) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return TryCreateMaterial(color, width, color, 2.6f, 2.4f, 2.2f, 0.3f, 0.16f); } internal static Material TryCreateMaterial(Color color, float widthPixels, Color rimColor, float rimPower, float rimIntensity, float pulseSpeed, float pulseAmount, float fillAlpha) { //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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown Shader shader = GetShader(); if ((Object)(object)shader == (Object)null) { return null; } try { Material val = new Material(shader); TrySetColor(val, "_OutlineColor", color); TrySetColor(val, "_RimColor", rimColor); TrySetFloat(val, "_RimPower", rimPower); TrySetFloat(val, "_RimIntensity", rimIntensity); TrySetFloat(val, "_PulseSpeed", pulseSpeed); TrySetFloat(val, "_PulseAmount", pulseAmount); TrySetFloat(val, "_CoreAlpha", fillAlpha); val.renderQueue = 3100; return val; } catch { return null; } } private static void TrySetColor(Material m, string name, Color c) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { m.SetColor(name, c); } catch { } } private static void TrySetFloat(Material m, string name, float f) { try { m.SetFloat(name, f); } catch { } } private static Shader GetShader() { if (_tried) { return _shader; } _tried = true; try { WrappedAssetBundle assetBundleFromStream = AssetLoader.GetAssetBundleFromStream("PropHunt.Assets.Bundles.propoutline", Assembly.GetExecutingAssembly()); if (assetBundleFromStream == null) { Instance log = Core.Log; if (log != null) { log.Warning("[PropHunt] outline shader: bundle is null after load - resource name mismatch?"); } return null; } Shader[] array = assetBundleFromStream.LoadAllAssets(); _shader = ((array != null && array.Length != 0) ? array[0] : null); if (!((Object)(object)_shader != (Object)null)) { Instance log2 = Core.Log; if (log2 != null) { log2.Warning("[PropHunt] outline shader: LoadAllAssets returned empty - trying LoadAsset by name"); } _shader = assetBundleFromStream.LoadAsset("PropOutline"); if ((Object)(object)_shader == (Object)null) { _shader = assetBundleFromStream.LoadAsset("PropHunt/PropOutline"); } if (!((Object)(object)_shader != (Object)null)) { Instance log3 = Core.Log; if (log3 != null) { log3.Warning("[PropHunt] outline shader: not found by LoadAllAssets or LoadAsset - using glow fallback"); } } } } catch (Exception ex) { Instance log4 = Core.Log; if (log4 != null) { log4.Warning("[PropHunt] outline shader load failed (using glow fallback): " + ex.Message); } _shader = null; } return _shader; } } internal sealed class PropEntry { internal int Id; internal string Name; internal string Key; internal MeshFilter Source; internal MeshRenderer SourceRenderer; internal LODGroup SourceLodGroup; internal GameObject SourceRoot; internal bool CloneWholeRoot; } internal static class PropCatalog { private static readonly string[] _badNames = new string[2] { "ReverseLight", "Case" }; private static readonly List _entries = new List(); private static readonly Dictionary _byId = new Dictionary(); private static int _hash; private static readonly Dictionary _curation = new Dictionary(); private static bool _curationLoaded; internal static int Hash => _hash; internal static int Count => _entries.Count; internal static bool Curated => _curation.Count > 0; private static string CurationPath => Path.Combine(MelonEnvironment.UserDataDirectory, "PropHunt", "prop_curation.txt"); internal static PropEntry ById(int id) { if (!_byId.TryGetValue(id, out var value)) { return null; } return value; } internal static string MeshKey(Mesh m) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m == (Object)null) { return null; } Bounds bounds = m.bounds; Vector3 size = ((Bounds)(ref bounds)).size; return $"{((Object)m).name}|{m.vertexCount}|{size.x:F1}x{size.y:F1}x{size.z:F1}"; } internal static bool IsJunkMeshName(string n) { if (string.IsNullOrEmpty(n)) { return true; } if (n.StartsWith("ph_")) { return true; } if (n.IndexOf("Combined Mesh", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (n.IndexOf("Collider", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } internal static void BuildIfNeeded() { if (_entries.Count == 0) { Build(); } } internal static void Build() { _entries.Clear(); _byId.Clear(); if (!_curationLoaded) { LoadCuration(); } bool flag = _curation.Count > 0; Stopwatch stopwatch = Stopwatch.StartNew(); int value = 0; int num = 0; try { HashSet hashSet = new HashSet(); List list = new List(); Il2CppArrayBase val = Object.FindObjectsOfType(); value = val?.Length ?? 0; if (val != null) { for (int i = 0; i < val.Length; i++) { MeshFilter val2 = val[i]; if ((Object)(object)val2 == (Object)null) { continue; } Mesh sharedMesh = val2.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { continue; } string name = ((Object)sharedMesh).name; if (IsJunkMeshName(name) || sharedMesh.vertexCount < 8) { continue; } MeshRenderer component = ((Component)val2).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)((Renderer)component).sharedMaterial == (Object)null)) { string text = MeshKey(sharedMesh); if (text != null && hashSet.Add(text) && _curation.TryGetValue(text, out var value2) && value2 && !IsCharacterMesh(val2) && !IsDoorMesh(val2) && !IsVehicleMesh(val2)) { num++; LODGroup componentInParent = ((Component)val2).GetComponentInParent(); list.Add(new PropEntry { Name = name, Key = text, Source = val2, SourceRenderer = component, SourceLodGroup = componentInParent, SourceRoot = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).gameObject : ((Component)val2).gameObject) }); } } } } IngestCompositeSources(list, hashSet); list.Sort((PropEntry a, PropEntry c) => string.CompareOrdinal(a.Key, c.Key)); for (int num2 = 0; num2 < list.Count; num2++) { int num3 = StableHash(list[num2].Key); if (!_byId.ContainsKey(num3)) { list[num2].Id = num3; _byId[num3] = list[num2]; _entries.Add(list[num2]); } } if (_entries.Count == 0) { AddPrimitiveFallback(); } } catch (Exception ex) { Core.Log.Warning("[PropHunt] catalog build failed: " + ex.Message); if (_entries.Count == 0) { AddPrimitiveFallback(); } } ComputeHash(); stopwatch.Stop(); int num4 = 0; foreach (PropEntry entry in _entries) { if ((Object)(object)entry.SourceLodGroup != (Object)null) { num4++; } } Core.Log.Msg($"[PropHunt] prop catalog: {_entries.Count} props ({num4} with LODGroup, hash {_hash}){(flag ? " [curated allowlist]" : "")} - scanned {value} filters, {num} survivors, {stopwatch.ElapsedMilliseconds}ms."); } internal static List EnumerateAllCandidates() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(); HashSet hashSet2 = new HashSet(); List list = new List(); try { Il2CppArrayBase val = Resources.FindObjectsOfTypeAll(); if (val != null) { for (int i = 0; i < val.Length; i++) { MeshFilter val2 = val[i]; if ((Object)(object)val2 == (Object)null) { continue; } Mesh sharedMesh = val2.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { continue; } Scene scene = ((Component)val2).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { continue; } string name = ((Object)sharedMesh).name; if (IsJunkMeshName(name) || sharedMesh.vertexCount < 8) { continue; } MeshRenderer component = ((Component)val2).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)((Renderer)component).sharedMaterial == (Object)null || IsCharacterMesh(val2) || IsDoorMesh(val2) || IsVehicleMesh(val2)) { continue; } LODGroup componentInParent = ((Component)val2).GetComponentInParent(); string text; if ((Object)(object)componentInParent != (Object)null) { text = LodTypeKey(componentInParent); if (text == null || !hashSet2.Add(text)) { continue; } } else { text = MeshKey(sharedMesh); if (text == null || !hashSet.Add(text)) { continue; } } list.Add(new PropEntry { Id = StableHash(text), Key = text, Name = name, Source = val2, SourceRenderer = component, SourceLodGroup = componentInParent, SourceRoot = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).gameObject : ((Component)val2).gameObject) }); } } } catch (Exception ex) { Core.Log.Warning("[PropHunt] EnumerateAllCandidates failed: " + ex.Message); } list.Sort((PropEntry a, PropEntry c) => string.CompareOrdinal(a.Key, c.Key)); return list; } private static string LodTypeKey(LODGroup lg) { string text = null; try { Il2CppArrayBase componentsInChildren = ((Component)lg).GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { Mesh val = (((Object)(object)componentsInChildren[i] != (Object)null) ? componentsInChildren[i].sharedMesh : null); if ((Object)(object)val != (Object)null && !IsJunkMeshName(((Object)val).name) && (Object)(object)((Component)componentsInChildren[i]).GetComponent() != (Object)null) { string text2 = MeshKey(val); if (text2 != null && (text == null || string.CompareOrdinal(text2, text) < 0)) { text = text2; } } } } } catch { } string text3 = text; if (text3 == null) { if (!((Object)(object)((Component)lg).gameObject != (Object)null)) { return "lod_unknown"; } text3 = ((Object)((Component)lg).gameObject).name; } return text3; } private static bool IsCharacterMesh(MeshFilter mf) { try { return (Object)(object)((Component)mf).GetComponentInParent() != (Object)null; } catch { return false; } } private static bool IsDoorMesh(MeshFilter mf) { try { return (Object)(object)((Component)mf).GetComponentInParent() != (Object)null; } catch { return false; } } private static bool IsVehicleMesh(MeshFilter mf) { try { return (Object)(object)((Component)mf).GetComponentInParent() != (Object)null; } catch { return false; } } private static void IngestCompositeSources(List tmp, HashSet seen) { try { List list = new List(); list.AddRange(PropSources.EnumerateBuildables()); list.AddRange(PropSources.EnumerateVehicles()); list.AddRange(PropSources.EnumerateWorldObjects()); int num = 0; for (int i = 0; i < list.Count; i++) { PropEntry propEntry = list[i]; if (propEntry != null && !string.IsNullOrEmpty(propEntry.Key) && _curation.TryGetValue(propEntry.Key, out var value) && value && seen.Add(propEntry.Key)) { tmp.Add(propEntry); num++; } } _ = 0; } catch (Exception ex) { Core.Log.Warning("[PropHunt] IngestCompositeSources failed: " + ex.Message); } } internal static void LoadCuration() { _curationLoaded = true; _curation.Clear(); try { string curationPath = CurationPath; string[] array = ((!File.Exists(curationPath)) ? ReadShippedCuration() : File.ReadAllLines(curationPath)); if (array != null) { ParseCurationLines(array); } } catch (Exception ex) { Core.Log.Warning("[PropHunt] LoadCuration failed: " + ex.Message); } } private static void ParseCurationLines(string[] lines) { for (int i = 0; i < lines.Length; i++) { string text = lines[i].Trim(); if (text.Length == 0 || text.StartsWith("#")) { continue; } int num = text.LastIndexOf('='); if (num > 0) { string text2 = text.Substring(0, num).Trim(); string text3 = text.Substring(num + 1).Trim(); if (text2.Length > 0) { _curation[text2] = text3 == "1"; } } } } private static string[] ReadShippedCuration() { try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PropHunt.Assets.prop_curation.txt"); if (stream == null) { return null; } using StreamReader streamReader = new StreamReader(stream); return streamReader.ReadToEnd().Split('\n'); } catch { return null; } } internal static void SaveCuration() { try { string curationPath = CurationPath; Directory.CreateDirectory(Path.GetDirectoryName(curationPath)); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# PropHunt becomable-prop curation. key=1 keep, key=0 skip. Edit in-game with the phcurate console command."); stringBuilder.AppendLine("# key = meshName|vertexCount|wFxhFxdF (content signature; LOD props use the lex-min key across LODs)."); foreach (KeyValuePair item in _curation) { stringBuilder.Append(item.Key).Append('=').Append(item.Value ? '1' : '0') .Append('\n'); } File.WriteAllText(curationPath, stringBuilder.ToString()); } catch (Exception ex) { Core.Log.Warning("[PropHunt] SaveCuration failed: " + ex.Message); } } internal static void SetDecision(string key, bool keep) { if (!string.IsNullOrEmpty(key)) { if (!_curationLoaded) { LoadCuration(); } _curation[key] = keep; SaveCuration(); } } internal static bool? DecisionOf(string key) { if (!_curationLoaded) { LoadCuration(); } if (!_curation.TryGetValue(key, out var value)) { return null; } return value; } internal static int KeepCount() { int num = 0; foreach (KeyValuePair item in _curation) { if (item.Value) { num++; } } return num; } private static bool IsUsablePropName(string n) { if (string.IsNullOrEmpty(n) || n.StartsWith("ph_")) { return false; } if (n.IndexOf("Combined Mesh", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (n.IndexOf("Collider", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } for (int i = 0; i < _badNames.Length; i++) { if (n.IndexOf(_badNames[i], StringComparison.OrdinalIgnoreCase) >= 0) { return false; } } return true; } private static void AddPrimitiveFallback() { AddPrimitive((PrimitiveType)3, "ph_cube"); AddPrimitive((PrimitiveType)2, "ph_cylinder"); AddPrimitive((PrimitiveType)0, "ph_sphere"); } private static void AddPrimitive(PrimitiveType t, string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) try { GameObject obj = GameObject.CreatePrimitive(t); MeshFilter component = obj.GetComponent(); MeshRenderer component2 = obj.GetComponent(); obj.SetActive(false); Object.DontDestroyOnLoad((Object)(object)obj); string text = MeshKey(((Object)(object)component != (Object)null) ? component.sharedMesh : null) ?? name; int num = StableHash(text); PropEntry propEntry = new PropEntry { Id = num, Key = text, Name = name, Source = component, SourceRenderer = component2 }; _byId[num] = propEntry; _entries.Add(propEntry); } catch { } } private static int StableHash(string s) { uint num = 2166136261u; for (int i = 0; i < s.Length; i++) { num ^= s[i]; num *= 16777619; } return (int)(num & 0x7FFFFFFF); } private static void ComputeHash() { int num = 17; foreach (PropEntry entry in _entries) { num = num * 31 + StableHash(entry.Key); } _hash = num; } internal static float SizeOf(int id) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00a9: 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_00b7: 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_0041: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) PropEntry propEntry = ById(id); if (propEntry == null) { return 0f; } Bounds bounds; if ((Object)(object)propEntry.Source != (Object)null && (Object)(object)propEntry.Source.sharedMesh != (Object)null) { bounds = propEntry.Source.sharedMesh.bounds; Vector3 val = Vector3.Scale(((Bounds)(ref bounds)).size, ((Component)propEntry.Source).transform.lossyScale); float num = Mathf.Max(val.x, Mathf.Max(val.y, val.z)); if (num > 0.001f) { return num; } } if ((Object)(object)propEntry.SourceRenderer != (Object)null) { bounds = ((Renderer)propEntry.SourceRenderer).bounds; Vector3 size = ((Bounds)(ref bounds)).size; float num2 = Mathf.Max(size.x, Mathf.Max(size.y, size.z)); if (num2 > 0.001f) { return num2; } } if ((Object)(object)propEntry.SourceLodGroup != (Object)null) { try { float size2 = propEntry.SourceLodGroup.size; if (size2 > 0f) { return size2; } } catch { } } return 0f; } internal static List LodMeshKeys(LODGroup lg) { List list = new List(); if ((Object)(object)lg == (Object)null) { return list; } try { Il2CppArrayBase componentsInChildren = ((Component)lg).GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { Mesh val = (((Object)(object)componentsInChildren[i] != (Object)null) ? componentsInChildren[i].sharedMesh : null); if (!((Object)(object)val == (Object)null) && !IsJunkMeshName(((Object)val).name) && !((Object)(object)((Component)componentsInChildren[i]).GetComponent() == (Object)null)) { string text = MeshKey(val); if (text != null && !list.Contains(text)) { list.Add(text); } } } } } catch { } return list; } internal static int RandomId(int exclude = -1) { if (_entries.Count == 0) { return -1; } if (_entries.Count == 1) { return _entries[0].Id; } for (int i = 0; i < 8; i++) { int id = _entries[Random.Range(0, _entries.Count)].Id; if (id != exclude) { return id; } } return _entries[Random.Range(0, _entries.Count)].Id; } internal static int IdForMesh(Mesh m) { if ((Object)(object)m == (Object)null) { return -1; } string text = MeshKey(m); if (text == null) { return -1; } int num = StableHash(text); if (!_byId.TryGetValue(num, out var value) || !(value.Key == text)) { return -1; } return num; } internal static int IdForMeshFilter(MeshFilter mf) { if ((Object)(object)mf == (Object)null || (Object)(object)mf.sharedMesh == (Object)null) { return -1; } int num = IdForMesh(mf.sharedMesh); if (num >= 0) { return num; } try { string text = PropSources.CompositeKeyFor(mf); if (!string.IsNullOrEmpty(text)) { int num2 = StableHash(text); if (_byId.TryGetValue(num2, out var value) && value.Key == text) { return num2; } } } catch { } return -1; } internal static void Reset() { _entries.Clear(); _byId.Clear(); _hash = 0; } } internal static class PropClone { internal static GameObject Build(PropEntry e, string name) { if (e == null) { return null; } try { if (e.CloneWholeRoot && (Object)(object)e.SourceRoot != (Object)null) { return BuildSubtree(e, name); } return ((Object)(object)e.SourceLodGroup != (Object)null) ? BuildLod(e, name) : BuildSingle(e, name); } catch (Exception) { return null; } } private static GameObject BuildSubtree(PropEntry e, string name) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown GameObject sourceRoot = e.SourceRoot; if ((Object)(object)sourceRoot == (Object)null) { if (!((Object)(object)e.SourceLodGroup != (Object)null)) { return BuildSingle(e, name); } return BuildLod(e, name); } GameObject val = null; try { val = new GameObject("ph_holder"); val.SetActive(false); GameObject obj = Object.Instantiate(sourceRoot, val.transform); ((Object)obj).name = name; Strip(obj); obj.transform.SetParent((Transform)null, false); obj.SetActive(true); EnableAllVisuals(obj); return obj; } catch (Exception) { return ((Object)(object)e.SourceLodGroup != (Object)null) ? BuildLod(e, name) : BuildSingle(e, name); } finally { if ((Object)(object)val != (Object)null) { try { Object.Destroy((Object)(object)val); } catch { } } } } internal static bool TryGetWorldMeshBounds(GameObject go, out Bounds bounds) { //IL_0001: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_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) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); if ((Object)(object)go == (Object)null) { return false; } Il2CppArrayBase componentsInChildren = go.GetComponentsInChildren(true); if (componentsInChildren == null) { return false; } bool flag = false; for (int i = 0; i < componentsInChildren.Length; i++) { MeshFilter val = componentsInChildren[i]; if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || PropCatalog.IsJunkMeshName(((Object)val.sharedMesh).name)) { continue; } MeshRenderer component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null || !((Renderer)component).enabled || !((Component)component).gameObject.activeInHierarchy) { continue; } Transform transform = ((Component)val).transform; Bounds bounds2 = val.sharedMesh.bounds; Vector3 center = ((Bounds)(ref bounds2)).center; Vector3 extents = ((Bounds)(ref bounds2)).extents; for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { for (int l = -1; l <= 1; l += 2) { Vector3 val2 = transform.TransformPoint(center + new Vector3((float)j * extents.x, (float)k * extents.y, (float)l * extents.z)); if (!flag) { bounds = new Bounds(val2, Vector3.zero); flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val2); } } } } } return flag; } internal static bool TryGetWorldBounds(GameObject go, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0065: 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) bounds = default(Bounds); if ((Object)(object)go == (Object)null) { return false; } MeshRenderer component = go.GetComponent(); if ((Object)(object)component != (Object)null) { bounds = ((Renderer)component).bounds; return true; } Il2CppArrayBase componentsInChildren = go.GetComponentsInChildren(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return false; } bool flag = false; for (int i = 0; i < componentsInChildren.Length; i++) { if (!((Object)(object)componentsInChildren[i] == (Object)null)) { if (!flag) { bounds = componentsInChildren[i].bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } } } return flag; } internal static BoxCollider AddTriggerHitbox(GameObject go) { //IL_002a: 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) if ((Object)(object)go == (Object)null) { return null; } try { if (!TryGetPropLocalBounds(go, out var local)) { return null; } BoxCollider obj = go.AddComponent(); ((Collider)obj).isTrigger = true; obj.center = ((Bounds)(ref local)).center; obj.size = ((Bounds)(ref local)).size; return obj; } catch (Exception) { return null; } } internal static bool TryGetLocalBounds(GameObject root, out Bounds local) { //IL_0001: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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_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) local = default(Bounds); if ((Object)(object)root == (Object)null) { return false; } Transform transform = root.transform; Il2CppArrayBase componentsInChildren = root.GetComponentsInChildren(true); if (componentsInChildren == null) { return false; } bool flag = false; for (int i = 0; i < componentsInChildren.Length; i++) { MeshFilter val = componentsInChildren[i]; if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || PropCatalog.IsJunkMeshName(((Object)val.sharedMesh).name)) { continue; } MeshRenderer component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null || !((Renderer)component).enabled || !((Component)component).gameObject.activeInHierarchy) { continue; } Transform transform2 = ((Component)val).transform; Bounds bounds = val.sharedMesh.bounds; Vector3 center = ((Bounds)(ref bounds)).center; Vector3 extents = ((Bounds)(ref bounds)).extents; for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { for (int l = -1; l <= 1; l += 2) { Vector3 val2 = transform2.TransformPoint(center + new Vector3((float)j * extents.x, (float)k * extents.y, (float)l * extents.z)); Vector3 val3 = transform.InverseTransformPoint(val2); if (!flag) { local = new Bounds(val3, Vector3.zero); flag = true; } else { ((Bounds)(ref local)).Encapsulate(val3); } } } } } return flag; } internal static Bounds LocalToWorldBounds(Transform t, Bounds local) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) Vector3 center = ((Bounds)(ref local)).center; Vector3 extents = ((Bounds)(ref local)).extents; Bounds result = default(Bounds); bool flag = false; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val = t.TransformPoint(center + new Vector3((float)i * extents.x, (float)j * extents.y, (float)k * extents.z)); if (!flag) { ((Bounds)(ref result))..ctor(val, Vector3.zero); flag = true; } else { ((Bounds)(ref result)).Encapsulate(val); } } } } return result; } internal static bool TryGetPropLocalBounds(GameObject root, out Bounds local) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) local = default(Bounds); if ((Object)(object)root == (Object)null) { return false; } Transform transform = root.transform; bool any = false; MeshRenderer component = root.GetComponent(); MeshFilter component2 = root.GetComponent(); if ((Object)(object)component != (Object)null && ((Renderer)component).enabled && ((Component)component).gameObject.activeInHierarchy && (Object)(object)component2 != (Object)null && (Object)(object)component2.sharedMesh != (Object)null) { EncapsulateMeshLocal(component2, transform, ref local, ref any); if (any) { return true; } } Il2CppArrayBase componentsInChildren = root.GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { MeshRenderer val = componentsInChildren[i]; if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled && ((Component)val).gameObject.activeInHierarchy) { MeshFilter component3 = ((Component)val).GetComponent(); if (!((Object)(object)component3 == (Object)null) && !((Object)(object)component3.sharedMesh == (Object)null)) { EncapsulateMeshLocal(component3, transform, ref local, ref any); } } } } return any; } internal static bool TryGetSourceLocalBounds(PropEntry e, out Bounds local) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00c8: 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_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_00df: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) local = default(Bounds); if (e == null || (Object)(object)e.Source == (Object)null) { return false; } Mesh sharedMesh = e.Source.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { return false; } Transform val = (((Object)(object)e.SourceLodGroup != (Object)null) ? ((Component)e.SourceLodGroup).transform : ((Component)e.Source).transform); if ((Object)(object)val == (Object)null) { return false; } try { Matrix4x4 val2 = val.worldToLocalMatrix * ((Component)e.Source).transform.localToWorldMatrix; Bounds bounds = sharedMesh.bounds; Vector3 center = ((Bounds)(ref bounds)).center; Vector3 extents = ((Bounds)(ref bounds)).extents; bool flag = false; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(center + new Vector3((float)i * extents.x, (float)j * extents.y, (float)k * extents.z)); if (!flag) { local = new Bounds(val3, Vector3.zero); flag = true; } else { ((Bounds)(ref local)).Encapsulate(val3); } } } } return flag; } catch { return false; } } internal static bool TryGetPropBoundsFromSource(PropEntry e, out Bounds local) { //IL_0001: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0120: 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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) local = default(Bounds); if (e == null || (Object)(object)e.Source == (Object)null || (Object)(object)e.Source.sharedMesh == (Object)null) { return false; } if (e.CloneWholeRoot && (Object)(object)e.SourceRoot != (Object)null && TryGetWholeRootBoundsFromSource(e, out local)) { return true; } if ((Object)(object)e.SourceLodGroup == (Object)null) { return TryGetSourceLocalBounds(e, out local); } try { LODGroup sourceLodGroup = e.SourceLodGroup; Transform transform = ((Component)sourceLodGroup).transform; Vector3 localReferencePoint = sourceLodGroup.localReferencePoint; float num = sourceLodGroup.size; if (num < 0.01f) { num = 4f; } float num2 = Mathf.Max(num * 2f + 2f, 5f); float num3 = num2 * num2; Il2CppArrayBase componentsInChildren = ((Component)sourceLodGroup).GetComponentsInChildren(true); bool any = false; if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { MeshFilter val = componentsInChildren[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && !((Object)(object)((Component)val).GetComponent() == (Object)null) && !PropCatalog.IsJunkMeshName(((Object)val.sharedMesh).name)) { Transform transform2 = ((Component)val).transform; Bounds bounds = val.sharedMesh.bounds; Vector3 val2 = transform.InverseTransformPoint(transform2.TransformPoint(((Bounds)(ref bounds)).center)) - localReferencePoint; if (!(((Vector3)(ref val2)).sqrMagnitude > num3)) { EncapsulateMeshLocal(val, transform, ref local, ref any); } } } } if (any) { return true; } } catch (Exception) { } return TryGetSourceLocalBounds(e, out local); } internal static bool TryGetWholeRootBoundsFromSource(PropEntry e, out Bounds local) { //IL_0001: 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_0046: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00c0: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) local = default(Bounds); if (e == null || (Object)(object)e.SourceRoot == (Object)null) { return false; } try { Transform transform = e.SourceRoot.transform; Il2CppArrayBase componentsInChildren = e.SourceRoot.GetComponentsInChildren(true); if (componentsInChildren == null) { return false; } bool flag = false; Vector3 val = Vector3.zero; float num = 0f; Bounds bounds; if ((Object)(object)e.Source != (Object)null && (Object)(object)e.Source.sharedMesh != (Object)null) { Transform transform2 = ((Component)e.Source).transform; bounds = e.Source.sharedMesh.bounds; val = transform.InverseTransformPoint(transform2.TransformPoint(((Bounds)(ref bounds)).center)); bounds = e.Source.sharedMesh.bounds; Vector3 extents = ((Bounds)(ref bounds)).extents; float num2 = Mathf.Max(Mathf.Max(extents.x, Mathf.Max(extents.y, extents.z)) * 2f * 3f + 2f, 6f); num = num2 * num2; flag = true; } bool flag2 = e.Key != null && e.Key.StartsWith("reg:"); bool any = false; for (int i = 0; i < componentsInChildren.Length; i++) { MeshFilter val2 = componentsInChildren[i]; if ((Object)(object)val2 == (Object)null || (Object)(object)val2.sharedMesh == (Object)null || (flag2 && !((Component)val2).gameObject.activeSelf)) { continue; } MeshRenderer component = ((Component)val2).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)((Renderer)component).sharedMaterial == (Object)null || PropCatalog.IsJunkMeshName(((Object)val2.sharedMesh).name) || IsPlacementVizMesh(val2)) { continue; } Transform transform3 = ((Component)val2).transform; bounds = val2.sharedMesh.bounds; Vector3 val3 = transform.InverseTransformPoint(transform3.TransformPoint(((Bounds)(ref bounds)).center)); if (flag) { Vector3 val4 = val3 - val; if (((Vector3)(ref val4)).sqrMagnitude > num) { continue; } } EncapsulateMeshLocal(val2, transform, ref local, ref any); } return any; } catch (Exception) { return false; } } private static bool IsPlacementVizMesh(MeshFilter mf) { try { if ((Object)(object)((Component)mf).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)mf).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)mf).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)mf).GetComponentInParent() != (Object)null) { return true; } } catch { } return false; } internal static BoxCollider AddTriggerHitbox(GameObject go, Bounds localBounds) { //IL_001c: 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 ((Object)(object)go == (Object)null) { return null; } try { BoxCollider obj = go.AddComponent(); ((Collider)obj).isTrigger = true; obj.center = ((Bounds)(ref localBounds)).center; obj.size = ((Bounds)(ref localBounds)).size; return obj; } catch (Exception) { return null; } } private static void EncapsulateMeshLocal(MeshFilter mf, Transform rt, ref Bounds local, ref bool any) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_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_0037: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) //IL_007d: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)mf).transform; Bounds bounds = mf.sharedMesh.bounds; Vector3 center = ((Bounds)(ref bounds)).center; Vector3 extents = ((Bounds)(ref bounds)).extents; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val = rt.InverseTransformPoint(transform.TransformPoint(center + new Vector3((float)i * extents.x, (float)j * extents.y, (float)k * extents.z))); if (!any) { local = new Bounds(val, Vector3.zero); any = true; } else { ((Bounds)(ref local)).Encapsulate(val); } } } } } private static GameObject BuildLod(PropEntry e, string name) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown GameObject val = (((Object)(object)e.SourceLodGroup != (Object)null) ? ((Component)e.SourceLodGroup).gameObject : null); if ((Object)(object)val == (Object)null) { return BuildSingle(e, name); } GameObject val2 = null; try { val2 = new GameObject("ph_holder"); val2.SetActive(false); GameObject obj = Object.Instantiate(val, val2.transform); ((Object)obj).name = name; Strip(obj); obj.transform.SetParent((Transform)null, false); obj.SetActive(true); EnableAllVisuals(obj); return obj; } catch (Exception) { return BuildSingle(e, name); } finally { if ((Object)(object)val2 != (Object)null) { try { Object.Destroy((Object)(object)val2); } catch { } } } } private static void EnableAllVisuals(GameObject go) { try { Il2CppArrayBase componentsInChildren = go.GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { try { if ((Object)(object)componentsInChildren[i] != (Object)null && !((Component)componentsInChildren[i]).gameObject.activeSelf) { ((Component)componentsInChildren[i]).gameObject.SetActive(true); } } catch { } } } Il2CppArrayBase componentsInChildren2 = go.GetComponentsInChildren(true); if (componentsInChildren2 != null) { for (int j = 0; j < componentsInChildren2.Length; j++) { try { if ((Object)(object)componentsInChildren2[j] != (Object)null) { componentsInChildren2[j].ForceMeshUpdate(false, false); } } catch { } } } Il2CppArrayBase componentsInChildren3 = go.GetComponentsInChildren(true); if (componentsInChildren3 == null) { return; } for (int k = 0; k < componentsInChildren3.Length; k++) { LODGroup val = componentsInChildren3[k]; if (!((Object)(object)val == (Object)null)) { try { val.RecalculateBounds(); val.ForceLOD(0); } catch { } } } } catch { } } private static GameObject BuildSingle(PropEntry e, string name) { //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) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)e.Source == (Object)null || (Object)(object)e.Source.sharedMesh == (Object)null) { return null; } GameObject val = new GameObject(name); val.AddComponent().sharedMesh = e.Source.sharedMesh; MeshRenderer val2 = val.AddComponent(); if ((Object)(object)e.SourceRenderer != (Object)null) { ((Renderer)val2).sharedMaterials = ((Renderer)e.SourceRenderer).sharedMaterials; ((Renderer)val2).shadowCastingMode = ((Renderer)e.SourceRenderer).shadowCastingMode; ((Renderer)val2).receiveShadows = ((Renderer)e.SourceRenderer).receiveShadows; } return val; } private static void Strip(GameObject go) { try { go.isStatic = false; } catch { } try { Il2CppArrayBase componentsInChildren = go.GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { try { if ((Object)(object)componentsInChildren[i] != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)componentsInChildren[i]).gameObject); } } catch { } } } Il2CppArrayBase componentsInChildren2 = go.GetComponentsInChildren(true); if (componentsInChildren2 != null) { for (int j = 0; j < componentsInChildren2.Length; j++) { try { if ((Object)(object)componentsInChildren2[j] != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)componentsInChildren2[j]).gameObject); } } catch { } } } Il2CppArrayBase componentsInChildren3 = go.GetComponentsInChildren(true); if (componentsInChildren3 != null) { for (int k = 0; k < componentsInChildren3.Length; k++) { try { if ((Object)(object)componentsInChildren3[k] != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)componentsInChildren3[k]).gameObject); } } catch { } } } Il2CppArrayBase componentsInChildren4 = go.GetComponentsInChildren(true); if (componentsInChildren4 != null) { for (int l = 0; l < componentsInChildren4.Length; l++) { try { if ((Object)(object)componentsInChildren4[l] != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)componentsInChildren4[l]).gameObject); } } catch { } } } } catch { } Il2CppArrayBase componentsInChildren5 = go.GetComponentsInChildren(true); if (componentsInChildren5 != null) { for (int m = 0; m < componentsInChildren5.Length; m++) { if ((Object)(object)componentsInChildren5[m] == (Object)null) { continue; } try { ((Component)componentsInChildren5[m]).gameObject.isStatic = false; } catch { } string name = ((Object)componentsInChildren5[m]).name; if ((Object)(object)componentsInChildren5[m] != (Object)(object)go.transform && !string.IsNullOrEmpty(name) && name.StartsWith("ph_")) { try { Object.DestroyImmediate((Object)(object)((Component)componentsInChildren5[m]).gameObject); } catch { } } } } Il2CppArrayBase componentsInChildren6 = go.GetComponentsInChildren(true); if (componentsInChildren6 != null) { for (int n = 0; n < componentsInChildren6.Length; n++) { try { if ((Object)(object)componentsInChildren6[n] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren6[n]); } } catch { } } } Il2CppArrayBase componentsInChildren7 = go.GetComponentsInChildren(true); if (componentsInChildren7 != null) { for (int num = 0; num < componentsInChildren7.Length; num++) { try { if ((Object)(object)componentsInChildren7[num] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren7[num]); } } catch { } } } Il2CppArrayBase componentsInChildren8 = go.GetComponentsInChildren(true); if (componentsInChildren8 != null) { for (int num2 = 0; num2 < componentsInChildren8.Length; num2++) { try { if ((Object)(object)componentsInChildren8[num2] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren8[num2]); } } catch { } } } Il2CppArrayBase componentsInChildren9 = go.GetComponentsInChildren(true); if (componentsInChildren9 != null) { for (int num3 = 0; num3 < componentsInChildren9.Length; num3++) { try { if ((Object)(object)componentsInChildren9[num3] != (Object)null) { Object.DestroyImmediate((Object)(object)componentsInChildren9[num3]); } } catch { } } } Il2CppArrayBase componentsInChildren10 = go.GetComponentsInChildren(true); if (componentsInChildren10 == null) { return; } for (int num4 = 0; num4 < componentsInChildren10.Length; num4++) { try { MonoBehaviour val = componentsInChildren10[num4]; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Il2CppObjectBase)val).TryCast() != (Object)null)) { Object.DestroyImmediate((Object)(object)val); } } catch { } } } } internal sealed class PropHighlighter { private sealed class Hl { internal GameObject Go; internal Material Mat; internal bool Outline; } private readonly GameModeController _ctl; private readonly Dictionary _shells = new Dictionary(); private readonly HashSet _inRange = new HashSet(); private readonly List _candidates = new List(); private float _nextScan; private int _lastLoggedCount = -1; private bool _failed; private bool _active; private bool _enabled = true; private const float ScanRadius = 22f; private const float ScanInterval = 0.4f; private const int MaxHighlights = 40; internal int HighlightedCount => _shells.Count; internal PropHighlighter(GameModeController ctl) { _ctl = ctl; } internal void Tick() { if (_failed) { return; } int num; if ((_ctl.Phase == RoundPhase.Hiding || _ctl.Phase == RoundPhase.Hunting) && _ctl.LocalRole == PlayerRole.Hider) { num = ((PropCatalog.Count > 0) ? 1 : 0); if (num != 0 && Input.GetKeyDown((KeyCode)98)) { _enabled = !_enabled; } } else { num = 0; } if (num == 0 || !_enabled) { if (_active) { ClearAll(); _lastLoggedCount = -1; } _active = false; return; } _active = true; try { if (Time.time >= _nextScan) { _nextScan = Time.time + 0.4f; Rescan(); } Pulse(); } catch (Exception ex) { Fail("highlighter tick failed: " + ex.Message); } } private static bool IsOurClone(Transform t) { while ((Object)(object)t != (Object)null) { string name = ((Object)t).name; if (!string.IsNullOrEmpty(name) && name.StartsWith("ph_")) { return true; } t = t.parent; } return false; } private void Rescan() { //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_0033: Unknown result type (might be due to invalid IL or missing references) Player local = Player.Local; if ((Object)(object)local == (Object)null) { return; } Vector3 center = ((Component)local).transform.position; _candidates.Clear(); Il2CppReferenceArray val = Physics.OverlapSphere(center, 22f); HashSet hashSet = new HashSet(); if (val != null) { for (int i = 0; i < ((Il2CppArrayBase)(object)val).Length; i++) { Collider val2 = ((Il2CppArrayBase)(object)val)[i]; if (!((Object)(object)val2 == (Object)null)) { MeshFilter val3 = ((Component)val2).GetComponentInParent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)val2).GetComponentInChildren(); } if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMesh == (Object)null) && !((Object)(object)((Component)val3).GetComponent() == (Object)null) && !((Object)(object)((Component)val3).GetComponentInParent() != (Object)null) && !IsOurClone(((Component)val3).transform) && PropCatalog.IdForMeshFilter(val3) >= 0 && hashSet.Add(((Object)((Component)val3).gameObject).GetInstanceID())) { _candidates.Add(val3); } } } } _candidates.Sort(delegate(MeshFilter a, MeshFilter b) { //IL_0006: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_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) Vector3 val5 = ((Component)a).transform.position - center; float sqrMagnitude = ((Vector3)(ref val5)).sqrMagnitude; val5 = ((Component)b).transform.position - center; return sqrMagnitude.CompareTo(((Vector3)(ref val5)).sqrMagnitude); }); _inRange.Clear(); int num = Mathf.Min(_candidates.Count, 40); for (int num2 = 0; num2 < num; num2++) { MeshFilter val4 = _candidates[num2]; int instanceID = ((Object)((Component)val4).gameObject).GetInstanceID(); _inRange.Add(instanceID); if (!_shells.ContainsKey(instanceID)) { AddShell(instanceID, val4, ((Component)val4).GetComponent()); } } List list = null; foreach (KeyValuePair shell in _shells) { if (!_inRange.Contains(shell.Key)) { (list ?? (list = new List())).Add(shell.Key); } } if (list != null) { foreach (int item in list) { RemoveShell(item); } } if (_shells.Count != _lastLoggedCount) { _lastLoggedCount = _shells.Count; } } private void AddShell(int gid, MeshFilter mf, MeshRenderer srcRend) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) try { Color color = new Color(0.1f, 0.85f, 1f, 0.55f); Color rimColor = default(Color); ((Color)(ref rimColor))..ctor(0.5f, 1f, 1f, 0.9f); Material val = OutlineShader.TryCreateMaterial(color, 0f, rimColor, 2.2f, 3.5f, 2.2f, 0.25f, 0.2f); if ((Object)(object)val != (Object)null) { AddShellGo(gid, mf, val, outline: true); return; } Material val2 = null; Material sharedMaterial = ((Renderer)srcRend).sharedMaterial; if ((Object)(object)sharedMaterial != (Object)null) { try { val2 = new Material(sharedMaterial); } catch { val2 = null; } } if (!((Object)(object)val2 == (Object)null)) { try { val2.mainTexture = null; } catch { } try { val2.SetTexture("_BaseMap", (Texture)null); } catch { } try { val2.SetTexture("_MainTex", (Texture)null); } catch { } Color val3 = default(Color); ((Color)(ref val3))..ctor(1f, 1f, 1f, 0.45f); val2.color = val3; try { val2.SetColor("_BaseColor", val3); } catch { } try { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", Color.white); } catch { } try { val2.SetFloat("_Surface", 1f); val2.SetFloat("_Blend", 0f); val2.SetOverrideTag("RenderType", "Transparent"); val2.SetInt("_SrcBlend", 5); val2.SetInt("_DstBlend", 10); val2.SetInt("_ZWrite", 0); val2.DisableKeyword("_ALPHATEST_ON"); val2.EnableKeyword("_ALPHABLEND_ON"); val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); } catch { } try { val2.SetInt("_ZTest", 8); } catch { } val2.renderQueue = 3100; AddShellGo(gid, mf, val2, outline: false); } } catch (Exception ex) { Fail("AddShell failed: " + ex.Message); } } private void AddShellGo(int gid, MeshFilter mf, Material mat, bool outline) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) GameObject val = new GameObject("ph_hl"); val.transform.SetParent(((Component)mf).transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; val.AddComponent().sharedMesh = mf.sharedMesh; MeshRenderer obj = val.AddComponent(); ((Renderer)obj).sharedMaterial = mat; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; _shells[gid] = new Hl { Go = val, Mat = mat, Outline = outline }; } private void RemoveShell(int gid) { if (_shells.TryGetValue(gid, out var value)) { if ((Object)(object)value.Go != (Object)null) { try { Object.Destroy((Object)(object)value.Go); } catch { } } if ((Object)(object)value.Mat != (Object)null) { try { Object.Destroy((Object)(object)value.Mat); } catch { } } } _shells.Remove(gid); } private void Pulse() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0079: Unknown result type (might be due to invalid IL or missing references) if (_shells.Count == 0) { return; } float num = 0.55f + 0.45f * Mathf.PingPong(Time.time * 1.6f, 1f); Color val = Color.white * num; foreach (Hl value in _shells.Values) { if (!((Object)(object)value.Mat == (Object)null) && !value.Outline) { try { value.Mat.SetColor("_EmissionColor", val); } catch { } } } } private void ClearAll() { foreach (int item in new List(_shells.Keys)) { RemoveShell(item); } _shells.Clear(); _inRange.Clear(); } private void Fail(string why) { _failed = true; Core.Log.Warning("[PropHunt] " + why + " - prop highlight disabled (HUD look-at hint still works)."); try { ClearAll(); } catch { } } internal void Dispose() { try { ClearAll(); } catch { } } } internal sealed class PropPassthrough { private readonly GameModeController _ctl; private readonly List _ignored = new List(); private CharacterController _cc; private CapsuleCollider _capCol; private Vector3 _lastScanPos; private float _activeHeight; private bool _active; private const float ScanRadius = 12f; private const float RescanMoveSqr = 4f; internal PropPassthrough(GameModeController ctl) { _ctl = ctl; } internal void Tick() { //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) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) try { float targetHeight = PropCollisionState.TargetHeight; if (_ctl.LocalRole != PlayerRole.Hider || _ctl.LocalPropId < 0 || !(targetHeight > 0f) || !(targetHeight < 1.8f)) { if (_active) { Clear(); } return; } EnsureRefs(); if ((Object)(object)_cc == (Object)null) { return; } Player local = Player.Local; if ((Object)(object)local == (Object)null) { return; } Vector3 position = ((Component)local).transform.position; if (_active && _activeHeight == targetHeight) { Vector3 val = position - _lastScanPos; if (!(((Vector3)(ref val)).sqrMagnitude > 4f)) { return; } } Clear(); Scan(position, targetHeight); _active = true; _activeHeight = targetHeight; _lastScanPos = position; } catch (Exception) { } } private void EnsureRefs() { try { if ((Object)(object)_cc == (Object)null) { PlayerMovement instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { _cc = instance.Controller; } } if ((Object)(object)_capCol == (Object)null) { Player local = Player.Local; if ((Object)(object)local != (Object)null) { _capCol = local.CapCol; } } } catch { } } private void Scan(Vector3 pos, float propHeight) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_013d: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) float y = pos.y; float num = y + propHeight; Il2CppReferenceArray val = Physics.OverlapSphere(pos, 12f, -1, (QueryTriggerInteraction)1); if (val == null) { return; } int num2 = 0; int num3 = 0; int num4 = 0; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < ((Il2CppArrayBase)(object)val).Length; i++) { Collider val2 = ((Il2CppArrayBase)(object)val)[i]; if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger) { num3++; Bounds bounds = val2.bounds; if (num4 < 40) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(17, 5, stringBuilder2); handler.AppendLiteral("\n '"); handler.AppendFormatted(TrimName(((Object)val2).name)); handler.AppendLiteral("' L"); handler.AppendFormatted(((Component)val2).gameObject.layer); handler.AppendLiteral(" y["); handler.AppendFormatted(((Bounds)(ref bounds)).min.y, "F2"); handler.AppendLiteral(".."); handler.AppendFormatted(((Bounds)(ref bounds)).max.y, "F2"); handler.AppendLiteral("] d="); handler.AppendFormatted(Vector3.Distance(pos, ((Bounds)(ref bounds)).ClosestPoint(pos)), "F1"); stringBuilder2.Append(ref handler); num4++; } if (!(((Bounds)(ref bounds)).min.y < num - 0.15f) && !(((Bounds)(ref bounds)).min.y > y + 3f)) { Ignore(val2, ignore: true); _ignored.Add(val2); num2++; } } } } private static string TrimName(string n) { if (!string.IsNullOrEmpty(n)) { if (n.Length <= 28) { return n; } return n.Substring(0, 28); } return "?"; } private void Ignore(Collider col, bool ignore) { try { if ((Object)(object)_cc != (Object)null) { Physics.IgnoreCollision((Collider)(object)_cc, col, ignore); } } catch { } try { if ((Object)(object)_capCol != (Object)null) { Physics.IgnoreCollision((Collider)(object)_capCol, col, ignore); } } catch { } } private void Clear() { for (int i = 0; i < _ignored.Count; i++) { Collider val = _ignored[i]; if ((Object)(object)val != (Object)null) { Ignore(val, ignore: false); } } _ignored.Clear(); _active = false; _activeHeight = 0f; } internal void Dispose() { try { Clear(); } catch { } } } internal sealed class PropPicker { private readonly GameModeController _ctl; private float _holdUntil; private const float HoldTime = 0.4f; private bool _rotating; private float _yaw; private float _nextYawSend; private const float RotateSpeed = 5f; internal int CurrentTargetId { get; private set; } = -1; internal string CurrentTargetName { get; private set; } internal PropPicker(GameModeController ctl) { _ctl = ctl; } internal void Tick() { if (_ctl.Phase != RoundPhase.Hiding && _ctl.Phase != RoundPhase.Hunting) { CurrentTargetId = -1; CurrentTargetName = null; if (_rotating) { StopRotating(); } SlowWalk.Restore(); return; } try { UpdateTarget(); if (_ctl.LocalRole != PlayerRole.Hider) { if (_rotating) { StopRotating(); } SlowWalk.Restore(); return; } SlowWalk.Set(_ctl.LocalPropId >= 0 && Input.GetKey((KeyCode)306)); if (Input.GetKeyDown((KeyCode)101) && CurrentTargetId >= 0) { _ctl.RequestSelectProp(CurrentTargetId); } if (Input.GetKeyDown((KeyCode)50) && (_ctl.Settings == null || _ctl.Settings.AllowRandomChange)) { _ctl.RequestSelectRandomProp(); } if (Input.GetKeyDown((KeyCode)113) && _ctl.LocalPropId >= 0) { _ctl.RequestDropDecoy(); } if (Input.GetKeyDown((KeyCode)103)) { _ctl.RequestConcuss(); } HandleRotate(); } catch (Exception) { } } private void HandleRotate() { if (Input.GetKey((KeyCode)102) && _ctl.LocalPropId >= 0) { if (!_rotating) { _rotating = true; _yaw = _ctl.LocalPropYaw; SetCanLook(can: false); _nextYawSend = Time.time; } float axis = Input.GetAxis("Mouse X"); if (Mathf.Abs(axis) > 0.0001f) { _yaw += axis * 5f; _ctl.SetLocalYaw(_yaw); } if (Time.time >= _nextYawSend) { _nextYawSend = Time.time + 0.15f; _ctl.RequestRotate(_yaw); } } else if (_rotating) { StopRotating(); } } private void StopRotating() { _rotating = false; SetCanLook(can: true); _ctl.RequestRotate(_yaw); } private static void SetCanLook(bool can) { try { PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(can); } } catch { } } private void UpdateTarget() { //IL_003d: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.Camera == (Object)null) { CurrentTargetId = -1; CurrentTargetName = null; return; } Transform transform = ((Component)instance.Camera).transform; int num = -1; string currentTargetName = null; Il2CppStructArray val = Physics.RaycastAll(transform.position, transform.forward, 8f); if (val != null && ((Il2CppArrayBase)(object)val).Length > 0) { Array.Sort(Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)val), (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int num2 = 0; num2 < ((Il2CppArrayBase)(object)val).Length; num2++) { RaycastHit val2 = ((Il2CppArrayBase)(object)val)[num2]; if (IsOurs(((RaycastHit)(ref val2)).transform)) { continue; } MeshFilter val3 = null; if ((Object)(object)((RaycastHit)(ref val2)).collider != (Object)null) { val3 = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInChildren(); } } if ((Object)(object)val3 == (Object)null && (Object)(object)((RaycastHit)(ref val2)).transform != (Object)null) { val3 = ((Component)((RaycastHit)(ref val2)).transform).GetComponentInChildren(); } if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMesh == (Object)null)) { int num3 = PropCatalog.IdForMeshFilter(val3); if (num3 >= 0) { num = num3; currentTargetName = PropCatalog.ById(num3)?.Name; break; } } } } if (num >= 0) { CurrentTargetId = num; CurrentTargetName = currentTargetName; _holdUntil = Time.time + 0.4f; } else if (Time.time >= _holdUntil) { CurrentTargetId = -1; CurrentTargetName = null; } } private static bool IsOurs(Transform t) { for (int i = 0; i < 8; i++) { if (!((Object)(object)t != (Object)null)) { break; } string name = ((Object)t).name; if (!string.IsNullOrEmpty(name) && name.StartsWith("ph_")) { return true; } t = t.parent; } return false; } } internal static class PropSources { internal const string BuildablePrefix = "reg:"; internal const string VehiclePrefix = "veh:"; internal const string WorldPrefix = "world:"; internal static List EnumerateBuildables() { List list = new List(); try { Registry instance = Singleton.Instance; if ((Object)(object)instance == (Object)null) { Core.Log.Warning("[PropHunt] EnumerateBuildables: Registry.Instance null - load a world first."); return list; } List allItems = instance.GetAllItems(); if (allItems == null) { return list; } HashSet hashSet = new HashSet(); for (int i = 0; i < allItems.Count; i++) { ItemDefinition val = allItems[i]; if ((Object)(object)val == (Object)null) { continue; } BuildableItemDefinition val2 = ((Il2CppObjectBase)val).TryCast(); if ((Object)(object)val2 == (Object)null) { continue; } BuildableItem builtItem = val2.BuiltItem; if ((Object)(object)builtItem == (Object)null || (Object)(object)((Component)builtItem).gameObject == (Object)null) { continue; } string text = "reg:" + ((Object)val).name; if (hashSet.Add(text)) { PropEntry propEntry = MakeWholeObjectEntry(text, ((Object)val).name, ((Component)builtItem).gameObject); if (propEntry != null) { list.Add(propEntry); } } } } catch (Exception ex) { Core.Log.Warning("[PropHunt] EnumerateBuildables failed: " + ex.Message); } list.Sort((PropEntry a, PropEntry c) => string.CompareOrdinal(a.Name ?? "", c.Name ?? "")); return list; } internal static List EnumerateVehicles() { List list = new List(); try { VehicleManager instance = NetworkSingleton.Instance; if ((Object)(object)instance == (Object)null) { Core.Log.Warning("[PropHunt] EnumerateVehicles: VehicleManager.Instance null - load a world first."); return list; } List vehiclePrefabs = instance.VehiclePrefabs; if (vehiclePrefabs == null) { return list; } HashSet hashSet = new HashSet(); for (int i = 0; i < vehiclePrefabs.Count; i++) { LandVehicle val = vehiclePrefabs[i]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } string text = null; try { text = val.VehicleCode; } catch { } if (string.IsNullOrEmpty(text)) { text = ((Object)((Component)val).gameObject).name; } string text2 = "veh:" + text; if (hashSet.Add(text2)) { PropEntry propEntry = MakeWholeObjectEntry(text2, text, ((Component)val).gameObject); if (propEntry != null) { list.Add(propEntry); } } } } catch (Exception ex) { Core.Log.Warning("[PropHunt] EnumerateVehicles failed: " + ex.Message); } list.Sort((PropEntry a, PropEntry c) => string.CompareOrdinal(a.Name ?? "", c.Name ?? "")); return list; } private static PropEntry MakeWholeObjectEntry(string key, string name, GameObject root) { if ((Object)(object)root == (Object)null) { return null; } MeshFilter val = null; MeshRenderer sourceRenderer = null; int num = -1; bool flag = false; try { Il2CppArrayBase componentsInChildren = root.GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { MeshFilter val2 = componentsInChildren[i]; if ((Object)(object)val2 == (Object)null || (Object)(object)val2.sharedMesh == (Object)null) { continue; } string name2 = ((Object)val2.sharedMesh).name; if (!string.IsNullOrEmpty(name2) && name2.IndexOf("Combined Mesh", StringComparison.OrdinalIgnoreCase) >= 0) { flag = true; } if (PropCatalog.IsJunkMeshName(name2)) { continue; } MeshRenderer component = ((Component)val2).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)((Renderer)component).sharedMaterial == (Object)null)) { int vertexCount = val2.sharedMesh.vertexCount; if (vertexCount > num) { num = vertexCount; val = val2; sourceRenderer = component; } } } } } catch { } if ((Object)(object)val == (Object)null) { return null; } if (flag && num < 40) { return null; } return new PropEntry { Key = key, Name = name, Source = val, SourceRenderer = sourceRenderer, SourceLodGroup = null, SourceRoot = root, CloneWholeRoot = true }; } internal static List EnumerateWorldObjects() { Dictionary dictionary = new Dictionary(); try { AddRootsOfType(dictionary); AddRootsOfType(dictionary); AddRootsOfType(dictionary); } catch (Exception ex) { Core.Log.Warning("[PropHunt] EnumerateWorldObjects failed: " + ex.Message); } List list = new List(dictionary.Values); Dictionary dictionary2 = new Dictionary(); List list2 = new List(); for (int i = 0; i < list.Count; i++) { PropEntry propEntry = list[i]; string text = (((Object)(object)propEntry.Source != (Object)null && (Object)(object)propEntry.Source.sharedMesh != (Object)null) ? ((Object)propEntry.Source.sharedMesh).name : null); PropEntry value; if (string.IsNullOrEmpty(text) || IsGenericMeshName(text)) { list2.Add(propEntry); } else if (!dictionary2.TryGetValue(text, out value) || RepVerts(propEntry) > RepVerts(value)) { dictionary2[text] = propEntry; } } List list3 = new List(list2); list3.AddRange(dictionary2.Values); list3.Sort((PropEntry a, PropEntry c) => string.CompareOrdinal(a.Name ?? "", c.Name ?? "")); return list3; } private static int RepVerts(PropEntry e) { if (e == null || !((Object)(object)e.Source != (Object)null) || !((Object)(object)e.Source.sharedMesh != (Object)null)) { return 0; } return e.Source.sharedMesh.vertexCount; } private static bool IsGenericMeshName(string n) { if (string.IsNullOrEmpty(n)) { return true; } string text = n.ToLowerInvariant(); switch (text) { default: return text == "object"; case "cube": case "body": case "lid": case "base": case "quad": case "plane": case "sphere": case "cylinder": case "capsule": case "mesh": case "cover": case "top": case "bottom": case "panel": case "default": return true; } } private static void AddRootsOfType(Dictionary map) where T : Component { try { Il2CppArrayBase val = Resources.FindObjectsOfTypeAll(); if (val == null) { return; } for (int i = 0; i < val.Length; i++) { T val2 = val[i]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null)) { TryAddRoot(((Component)val2).gameObject, map); } } } catch { } } private static bool HasWorldMarker(GameObject g) { if ((Object)(object)g == (Object)null) { return false; } try { return (Object)(object)g.GetComponent() != (Object)null || (Object)(object)g.GetComponent() != (Object)null || (Object)(object)g.GetComponent() != (Object)null; } catch { return false; } } private static GameObject TopMarkerRoot(GameObject go) { GameObject result = go; try { Transform parent = go.transform.parent; while ((Object)(object)parent != (Object)null) { if (HasWorldMarker(((Component)parent).gameObject)) { result = ((Component)parent).gameObject; } parent = parent.parent; } } catch { } return result; } private static void TryAddRoot(GameObject markerGo, Dictionary map) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)markerGo == (Object)null) { return; } Scene scene = markerGo.scene; if (!((Scene)(ref scene)).IsValid()) { return; } GameObject val = TopMarkerRoot(markerGo); if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponentInParent() != (Object)null || (Object)(object)val.GetComponentInParent() != (Object)null || (Object)(object)val.GetComponentInParent() != (Object)null) { return; } string text = RootTypeKey(val); if (text == null) { return; } string key = "world:" + text; if (map.TryGetValue(key, out var value)) { bool activeInHierarchy = val.activeInHierarchy; bool flag = value != null && (Object)(object)value.SourceRoot != (Object)null && value.SourceRoot.activeInHierarchy; if (!activeInHierarchy || flag) { return; } } PropEntry propEntry = MakeWholeObjectEntry(key, CleanName(((Object)val).name), val); if (propEntry != null) { map[key] = propEntry; } } catch { } } private static string RootTypeKey(GameObject root) { List list = new List(); try { Il2CppArrayBase componentsInChildren = root.GetComponentsInChildren(true); if (componentsInChildren != null) { for (int i = 0; i < componentsInChildren.Length; i++) { Mesh val = (((Object)(object)componentsInChildren[i] != (Object)null) ? componentsInChildren[i].sharedMesh : null); if (!((Object)(object)val == (Object)null) && !PropCatalog.IsJunkMeshName(((Object)val).name) && !((Object)(object)((Component)componentsInChildren[i]).GetComponent() == (Object)null)) { string text = PropCatalog.MeshKey(val); if (text != null) { list.Add(text); } } } } } catch { } if (list.Count == 0) { return null; } list.Sort(StringComparer.Ordinal); StringBuilder stringBuilder = new StringBuilder(); string text2 = null; for (int j = 0; j < list.Count; j++) { if (list[j] != text2) { stringBuilder.Append(list[j]).Append(';'); text2 = list[j]; } } return Fnv(stringBuilder.ToString()); } private static string CleanName(string n) { if (string.IsNullOrEmpty(n)) { return "?"; } int num = n.LastIndexOf(" ("); if (num > 0 && n.EndsWith(")")) { n = n.Substring(0, num); } return n.Trim(); } private static string Fnv(string s) { uint num = 2166136261u; for (int i = 0; i < s.Length; i++) { num ^= s[i]; num *= 16777619; } return num.ToString("x8"); } internal static string CompositeKeyFor(MeshFilter mf) { if ((Object)(object)mf == (Object)null) { return null; } try { LandVehicle componentInParent = ((Component)mf).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { string text = null; try { text = componentInParent.VehicleCode; } catch { } if (string.IsNullOrEmpty(text)) { text = ((Object)((Component)componentInParent).gameObject).name; } return "veh:" + text; } BuildableItem componentInParent2 = ((Component)mf).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null) { string text2 = null; try { ItemInstance itemInstance = componentInParent2.ItemInstance; ItemDefinition val = ((itemInstance != null) ? itemInstance.Definition : null); text2 = (((Object)(object)val != (Object)null) ? ((Object)val).name : null); } catch { } if (!string.IsNullOrEmpty(text2)) { return "reg:" + text2; } } GameObject val2 = null; PhysicsDamageable componentInParent3 = ((Component)mf).GetComponentInParent(); if ((Object)(object)componentInParent3 != (Object)null) { val2 = ((Component)componentInParent3).gameObject; } if ((Object)(object)val2 == (Object)null) { NetworkedInteractableToggleable componentInParent4 = ((Component)mf).GetComponentInParent(); if ((Object)(object)componentInParent4 != (Object)null) { val2 = ((Component)componentInParent4).gameObject; } } if ((Object)(object)val2 == (Object)null) { StorageEntity componentInParent5 = ((Component)mf).GetComponentInParent(); if ((Object)(object)componentInParent5 != (Object)null) { val2 = ((Component)componentInParent5).gameObject; } } if ((Object)(object)val2 != (Object)null) { string text3 = RootTypeKey(TopMarkerRoot(val2)); if (!string.IsNullOrEmpty(text3)) { return "world:" + text3; } } } catch { } return null; } } } namespace PropHunt.Config { internal static class KeyBinds { internal const KeyCode Become = (KeyCode)101; internal const KeyCode RandomProp = (KeyCode)50; internal const KeyCode Rotate = (KeyCode)102; internal const KeyCode SlowWalk = (KeyCode)306; internal const KeyCode Decoy = (KeyCode)113; internal const KeyCode Concussion = (KeyCode)103; internal const KeyCode Taunt = (KeyCode)49; internal const KeyCode HighlightToggle = (KeyCode)98; internal const KeyCode ThirdPerson = (KeyCode)118; internal const KeyCode Catch = (KeyCode)323; internal const KeyCode Help = (KeyCode)104; internal const KeyCode SpectatorToggle = (KeyCode)52; internal const KeyCode SpectatorNext = (KeyCode)323; internal unsafe static string Name(KeyCode k) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected I4, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 if ((int)k <= 306) { switch (k - 49) { case 0: return "1"; case 1: return "2"; case 2: return "3"; case 3: return "4"; } if ((int)k == 306) { return "Ctrl"; } } else { if ((int)k == 323) { return "Left click"; } if ((int)k == 324) { return "Right click"; } } return ((object)(*(KeyCode*)(&k))/*cast due to .constrained prefix*/).ToString(); } } internal static class PropHuntPreferences { private const string CategoryId = "PropHunt_01_Main"; private static MelonPreferences_Category _category; private static MelonPreferences_Entry _enabled; private static MelonPreferences_Entry _hideSeconds; private static MelonPreferences_Entry _huntSeconds; private static MelonPreferences_Entry _roundEndSeconds; private static MelonPreferences_Entry _playersPerHunter; private static MelonPreferences_Entry _roundsBeforeSwap; private static MelonPreferences_Entry _hiderSpeedPercent; private static MelonPreferences_Entry _tagRange; private static MelonPreferences_Entry _hitsToCatch; private static MelonPreferences_Entry _maxPropChanges; private static MelonPreferences_Entry _maxDecoys; private static MelonPreferences_Entry _concussCharges; private static MelonPreferences_Entry _concussRadius; private static MelonPreferences_Entry _tauntIntervalSeconds; private static MelonPreferences_Entry _playAreaRadius; private static MelonPreferences_Entry _caughtBehavior; private static MelonPreferences_Entry _roundStructure; private static MelonPreferences_Entry _timeOfDay; private static MelonPreferences_Entry _hunterWeapon; private static MelonPreferences_Entry _friendlyFire; private static MelonPreferences_Entry _hunterHitsToDown; private static MelonPreferences_Entry _hiderMaxHp; private static MelonPreferences_Entry _hunterDownBaseSeconds; private static MelonPreferences_Entry _hunterDownMaxSeconds; private static MelonPreferences_Entry _concussStunSeconds; private static MelonPreferences_Entry _removeDecoysBetweenRounds; private static MelonPreferences_Entry _allowRandomChange; private static MelonPreferences_Entry _freeChangesInHiding; private static MelonPreferences_Entry _freezeTime; private static MelonPreferences_Entry _autoStartNextRound; private static MelonPreferences_Entry _musicTrack; private static MelonPreferences_Entry _customBlob; private static MelonPreferences_Entry _customBase; private static MelonPreferences_Entry _weaponCache; internal static bool Enabled => _enabled?.Value ?? true; internal static int HideSeconds => Mathf.Max(1, _hideSeconds?.Value ?? 30); internal static int HuntSeconds => Mathf.Max(1, _huntSeconds?.Value ?? 300); internal static int RoundEndSeconds => Mathf.Clamp(_roundEndSeconds?.Value ?? 15, 5, 60); internal static int PlayersPerHunter => Mathf.Max(1, _playersPerHunter?.Value ?? 5); internal static int RoundsBeforeSwap => Mathf.Max(1, _roundsBeforeSwap?.Value ?? 1); internal static int HiderSpeedPercent => Mathf.Clamp(_hiderSpeedPercent?.Value ?? 90, 50, 100); internal static float TagRange => Mathf.Max(0.5f, _tagRange?.Value ?? 4f); internal static int HitsToCatch => Mathf.Max(1, _hitsToCatch?.Value ?? 2); internal static int HiderMaxHp => Mathf.Clamp(_hiderMaxHp?.Value ?? 4, 1, 25); internal static int MaxPropChanges => Mathf.Max(0, _maxPropChanges?.Value ?? 5); internal static int MaxDecoys => Mathf.Max(0, _maxDecoys?.Value ?? 4); internal static int ConcussCharges => Mathf.Max(0, _concussCharges?.Value ?? 1); internal static float ConcussRadius => Mathf.Max(1f, _concussRadius?.Value ?? 7f); internal static int TauntIntervalSeconds => Mathf.Max(0, _tauntIntervalSeconds?.Value ?? 30); internal static float PlayAreaRadius => Mathf.Max(5f, _playAreaRadius?.Value ?? 75f); internal static string CaughtBehaviorRaw => _caughtBehavior?.Value ?? "Spectator"; internal static string RoundStructureRaw => _roundStructure?.Value ?? "Continuous"; internal static int TimeOfDay => _timeOfDay?.Value ?? 1200; internal static string HunterWeapon => _hunterWeapon?.Value ?? "pumpshotgun"; internal static bool FriendlyFire => _friendlyFire?.Value ?? true; internal static int HunterHitsToDown => Mathf.Max(1, _hunterHitsToDown?.Value ?? 3); internal static float HunterDownBaseSeconds => Mathf.Max(1f, _hunterDownBaseSeconds?.Value ?? 3f); internal static float HunterDownMaxSeconds => Mathf.Max(HunterDownBaseSeconds, _hunterDownMaxSeconds?.Value ?? 10f); internal static float ConcussStunSeconds => Mathf.Max(1f, _concussStunSeconds?.Value ?? 2f); internal static bool RemoveDecoysBetweenRounds => _removeDecoysBetweenRounds?.Value ?? true; internal static bool AllowRandomChange => _allowRandomChange?.Value ?? true; internal static bool FreeChangesInHiding => _freeChangesInHiding?.Value ?? true; internal static bool FreezeTime => _freezeTime?.Value ?? true; internal static bool AutoStartNextRound => _autoStartNextRound?.Value ?? true; internal static string MusicTrack => _musicTrack?.Value ?? ""; internal static string CustomBlob => _customBlob?.Value ?? ""; internal static string CustomBase => _customBase?.Value ?? ""; internal static string WeaponCache => _weaponCache?.Value ?? ""; internal static void Initialize() { if (_category == null) { _category = MelonPreferences.CreateCategory("PropHunt_01_Main", "PropHunt"); _enabled = CreateEntry("Enabled", defaultValue: true, "Enabled", "Enable the PropHunt gamemode."); _hideSeconds = CreateEntry("HideSeconds", 30, "Hiding phase (seconds)", "How long hiders have to find a prop and hide while hunters are frozen."); _huntSeconds = CreateEntry("HuntSeconds", 300, "Hunting phase (seconds)", "How long hunters have to find every hider before the hiders win."); _roundEndSeconds = CreateEntry("RoundEndSeconds", 15, "Scoreboard time (seconds)", "How long the round-end scoreboard is shown before the safehouse (5-60)."); _playersPerHunter = CreateEntry("PlayersPerHunter", 5, "Players per hunter", "Roughly one hunter is assigned for this many players (min one hunter). e.g. 5 = 1 hunter at 2-5 players, 2 at 6-10."); _roundsBeforeSwap = CreateEntry("RoundsBeforeSwap", 1, "Rounds before role swap", "How many rounds to play before rotating who hunts (round-robin)."); _hiderSpeedPercent = CreateEntry("HiderSpeedPercent", 90, "Hider speed (% of hunter)", "Hiders move at this percent of hunter speed (70-100; 100 = same). Lower makes hiders easier to catch."); _tagRange = CreateEntry("TagRange", 4f, "Catch range (metres)", "How close a hunter must be, looking at a hider, to catch them."); _hitsToCatch = CreateEntry("HitsToCatch", 2, "Prop HP per metre", "Disguise HP scales with prop size: a prop needs round(largest dimension * this) hits to catch, capped by Max hider HP. Bigger props tank more shots."); _hiderMaxHp = CreateEntry("HiderMaxHp", 4, "Max hider HP", "The most HP any prop disguise can have. Size still scales HP (via Prop HP per metre) up to this cap."); _maxPropChanges = CreateEntry("MaxPropChanges", 5, "Max prop changes per round", "How many times a hider may (re)pick a prop each round. Each change resets their HP. 0 = unlimited."); _maxDecoys = CreateEntry("MaxDecoys", 4, "Decoys per prop", "How many decoys ([Q]) a hider may drop per prop (refills when they change prop) - static copies to mislead hunters. 0 = disabled."); _concussCharges = CreateEntry("ConcussCharges", 1, "Concussions per prop", "How many concussions ([G]) a hider may use per prop (refills when they change prop, like CoD Prop Hunt) - stuns nearby hunters. 0 = disabled."); _concussRadius = CreateEntry("ConcussRadius", 7f, "Concussion radius (metres)", "Hunters within this distance of the hider when they trigger a concussion get stunned."); _tauntIntervalSeconds = CreateEntry("TauntIntervalSeconds", 30, "Taunt interval (seconds)", "During hunting, every hider is forced to emit a reveal sound this often. 0 disables taunts."); _playAreaRadius = CreateEntry("PlayAreaRadius", 75f, "Play-area radius (metres)", "Radius of the round's play area around the host's position. Leaving it warns, then eliminates."); _caughtBehavior = CreateEntry("CaughtBehavior", "Spectator", "Caught behavior (default)", "Default for the host setup screen. Spectator = a caught hider sits out till the round ends. Infection = a caught hider becomes a hunter."); _roundStructure = CreateEntry("RoundStructure", "Continuous", "Round structure (default)", "Default for the host setup screen. Continuous = auto-start the next round with swapped roles. Single = one round, then back to the hub."); _timeOfDay = CreateEntry("TimeOfDay", 1200, "Time of day (HHMM)", "World time locked during a round (progression frozen). 1200 = noon/day, 0100 = night."); _hunterWeapon = CreateEntry("HunterWeapon", "pumpshotgun", "Hunter weapon", "Item id given to each hunter at hunt start (e.g. pumpshotgun, m1911, machete). Empty = none."); _friendlyFire = CreateEntry("FriendlyFire", defaultValue: true, "Friendly fire (hunters)", "Whether hunters can knock each other down with friendly fire (ragdoll, never kill)."); _hunterHitsToDown = CreateEntry("HunterHitsToDown", 4, "Friendly hits to down", "Friendly-fire hits a hunter takes before being knocked down (their HP)."); _hunterDownBaseSeconds = CreateEntry("HunterDownBaseSeconds", 3f, "Knockdown time (seconds)", "How long a hunter is ragdolled when first knocked down."); _hunterDownMaxSeconds = CreateEntry("HunterDownMaxSeconds", 10f, "Max knockdown time (seconds)", "Cap on ragdoll time; each extra hit while down extends toward this."); _concussStunSeconds = CreateEntry("ConcussStunSeconds", 2f, "Concussion stun time (seconds)", "How long a concussion ([G]) knocks nearby hunters down (a short stun)."); _removeDecoysBetweenRounds = CreateEntry("RemoveDecoysBetweenRounds", defaultValue: true, "Clear decoys between rounds", "Remove every dropped decoy at the end of a round. Off = decoys carry over into the next round."); _allowRandomChange = CreateEntry("AllowRandomChange", defaultValue: true, "Allow random prop ([2])", "Let hiders press [2] to become a random prop."); _freeChangesInHiding = CreateEntry("FreeChangesInHiding", defaultValue: true, "Free changes while hiding", "Prop changes during the hiding phase are unlimited; the Max-prop-changes limit applies only during the hunt."); _freezeTime = CreateEntry("FreezeTime", defaultValue: true, "Freeze time of day", "Lock the world clock during a round. Off = set the time at round start, then let it progress."); _autoStartNextRound = CreateEntry("AutoStartNextRound", defaultValue: true, "Auto-start next round", "After a round, automatically start the next one after a short safehouse pause. Off = the host starts each round manually. Can be toggled live in the phone app."); _musicTrack = CreateEntry("MusicTrack", "Sneak Ambience", "Round music track", "The single game music track PropHunt plays continuously through every phase EXCEPT the hunt (lobby, hiding, round-end, safehouse). It fades out when the hunt starts (so hunters hear the whistles) and resumes at round end - it never restarts between phases. Empty = no music. Use the DEBUG 'phmusic' console command to list available track names."); _customBlob = CreateEntry("CustomPresetBlob", "", "Custom preset (saved)", "Internal: the last hosted custom settings, offered as a Custom preset next time. Managed automatically."); _customBase = CreateEntry("CustomPresetBase", "", "Custom preset base mode", "Internal: which base mode the saved Custom preset was derived from. Managed automatically."); _weaponCache = CreateEntry("WeaponCache", "", "Hunter weapon list (cached)", "Internal: the available weapons discovered from the game's item registry, used to fill the host-form dropdown. Managed automatically."); } } private static MelonPreferences_Entry CreateEntry(string identifier, T defaultValue, string displayName, string description = null) { return _category.CreateEntry(identifier, defaultValue, displayName, description, true, false, (ValueValidator)null, (string)null); } internal static void SaveWeaponCache(string cache) { if (_weaponCache == null) { return; } _weaponCache.Value = cache ?? ""; try { MelonPreferences.Save(); } catch { } } internal static void SaveCustomPreset(string blob, string baseMode) { if (_customBlob == null || _customBase == null) { return; } _customBlob.Value = blob ?? ""; _customBase.Value = baseMode ?? ""; try { MelonPreferences.Save(); } catch { } } internal static RoundSettings BuildRoundSettings() { return new RoundSettings { HideSeconds = HideSeconds, HuntSeconds = HuntSeconds, RoundEndSeconds = RoundEndSeconds, PlayersPerHunter = PlayersPerHunter, RoundsBeforeSwap = RoundsBeforeSwap, HiderSpeedPercent = HiderSpeedPercent, TagRange = TagRange, HitsToCatch = HitsToCatch, HiderMaxHp = HiderMaxHp, MaxPropChanges = MaxPropChanges, MaxDecoys = MaxDecoys, ConcussCharges = ConcussCharges, ConcussRadius = ConcussRadius, TauntIntervalSeconds = TauntIntervalSeconds, PlayAreaRadius = PlayAreaRadius, Caught = RoundSettings.ParseCaught(CaughtBehaviorRaw), Structure = RoundSettings.ParseStructure(RoundStructureRaw), TimeOfDay = TimeOfDay, HunterWeapon = HunterWeapon, FriendlyFire = FriendlyFire, HunterHitsToDown = HunterHitsToDown, HunterDownBaseSeconds = HunterDownBaseSeconds, HunterDownMaxSeconds = HunterDownMaxSeconds, ConcussStunSeconds = ConcussStunSeconds, RemoveDecoysBetweenRounds = RemoveDecoysBetweenRounds, AllowRandomChange = AllowRandomChange, FreeChangesInHiding = FreeChangesInHiding, FreezeTime = FreezeTime, AutoStartNextRound = AutoStartNextRound }; } } internal static class PropHuntSettingsSpec { private static readonly CultureInfo CI = CultureInfo.InvariantCulture; internal static SettingDescriptor[] Build() { (string[], string[]) tuple = WeaponChoices(); return (SettingDescriptor[])(object)new SettingDescriptor[28] { Segmented("Round", "round", "Round mode", "Continuous = auto-swap rounds; Single = one round, then the hub.", new string[2] { "Continuous", "Single" }, PropHuntPreferences.RoundStructureRaw), IntSlider("Round", "swap", "Rounds before swap", "Rounds to play before roles rotate.", 1f, 10f, 1f, null, PropHuntPreferences.RoundsBeforeSwap), IntSlider("Round", "hide", "Hiding time", "Seconds hiders get before hunters are released.", 5f, 120f, 5f, "s", PropHuntPreferences.HideSeconds), IntSlider("Round", "hunt", "Hunting time", "Seconds hunters have to find every hider.", 30f, 900f, 15f, "s", PropHuntPreferences.HuntSeconds), IntSlider("Round", "end", "Results screen", "Seconds the round-end scoreboard shows before the safehouse.", 5f, 60f, 1f, "s", PropHuntPreferences.RoundEndSeconds), IntSlider("Round", "taunt", "Taunt interval", "How often hiders are forced to make a sound (0 = off).", 0f, 120f, 5f, "s", PropHuntPreferences.TauntIntervalSeconds), Segmented("Round", "caught", "On catch", "Spectator = sit out till round end; Infection = become a hunter.", new string[2] { "Spectator", "Infection" }, PropHuntPreferences.CaughtBehaviorRaw), IntSlider("Roles & Combat", "pph", "Hunter ratio", "1 hunter per N players, rounded up.", 2f, 10f, 1f, null, PropHuntPreferences.PlayersPerHunter), IntSlider("Roles & Combat", "hiderspeed", "Hider speed", "Hiders move at this % of hunter speed (100 = same).", 70f, 100f, 5f, "%", PropHuntPreferences.HiderSpeedPercent), Dropdown("Roles & Combat", "weapon", "Hunter weapon", "Weapon each hunter gets when the hunt starts.", tuple.Item1, tuple.Item2, PropHuntPreferences.HunterWeapon), Toggle("Roles & Combat", "ff", "Friendly fire", "Hunters can knock each other down (ragdoll, never kill).", PropHuntPreferences.FriendlyFire), IntSlider("Roles & Combat", "hhp", "Friendly hits to down", "Friendly-fire hits a hunter takes before being knocked down (their HP).", 1f, 10f, 1f, null, PropHuntPreferences.HunterHitsToDown), IntSlider("Roles & Combat", "downb", "Knockdown time", "Seconds a hunter is ragdolled when first knocked down.", 1f, 20f, 1f, "s", (int)PropHuntPreferences.HunterDownBaseSeconds), IntSlider("Roles & Combat", "downx", "Max knockdown time", "Cap on ragdoll time; each extra hit while down extends toward this.", 1f, 30f, 1f, "s", (int)PropHuntPreferences.HunterDownMaxSeconds), IntSlider("Props", "hits", "Prop toughness", "Bigger props are naturally tougher at higher values (HP per metre).", 1f, 10f, 1f, null, PropHuntPreferences.HitsToCatch), IntSlider("Props", "hidermaxhp", "Max hider HP", "The most HP any prop disguise can have - size still scales HP up to this cap.", 1f, 10f, 1f, null, PropHuntPreferences.HiderMaxHp), IntSlider("Props", "chg", "Max prop changes", "Re-picks per round; each resets HP (0 = unlimited).", 0f, 20f, 1f, null, PropHuntPreferences.MaxPropChanges), Toggle("Props", "freechg", "Unlimited changes while hiding", "Prop changes during the hiding phase are unlimited; the limit applies only once the hunt starts.", PropHuntPreferences.FreeChangesInHiding), Toggle("Props", "rnd", "Random prop [2]", "Let hiders press [2] to become a random prop.", PropHuntPreferences.AllowRandomChange), IntSlider("Props", "decoy", "Decoys per prop", "Decoys [Q] a hider may drop per prop (0 = off).", 0f, 10f, 1f, null, PropHuntPreferences.MaxDecoys), IntSlider("Props", "conc", "Concussions per prop", "Concussions [G] a hider may use per prop (0 = off).", 0f, 10f, 1f, null, PropHuntPreferences.ConcussCharges), IntSlider("Props", "concr", "Concussion radius", "Hunters within this of a concussion get stunned.", 2f, 20f, 1f, "m", (int)PropHuntPreferences.ConcussRadius), IntSlider("Props", "stun", "Concussion stun time", "Seconds a concussion knocks nearby hunters down (short stun).", 1f, 10f, 1f, "s", (int)PropHuntPreferences.ConcussStunSeconds), Toggle("Props", "rmdecoy", "Clear decoys between rounds", "Remove dropped decoys at round end (off = they carry over).", PropHuntPreferences.RemoveDecoysBetweenRounds), IntSlider("World", "area", "Play-area radius", "Radius of the round's play area around the safehouse.", 50f, 200f, 5f, "m", (int)PropHuntPreferences.PlayAreaRadius), IntSlider("World", "time", "Time of day", "World time during a round (HHMM; 1200 = noon).", 0f, 2300f, 100f, null, PropHuntPreferences.TimeOfDay), Toggle("World", "freeze", "Lock time of day", "Lock the world clock during a round. Off = start at the set time, then let it run.", PropHuntPreferences.FreezeTime), Toggle("World", "autostart", "Auto-start next round", "Automatically start the next round after a short safehouse pause. Off = start each round manually. Toggle live in the phone app.", PropHuntPreferences.AutoStartNextRound) }; } private static SettingDescriptor IntSlider(string cat, string key, string label, string hint, float min, float max, float step, string unit, int def) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: 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) //IL_0023: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown return new SettingDescriptor { Category = cat, Key = key, Label = label, Hint = hint, Type = (SettingType)0, Min = min, Max = max, Step = step, WholeNumbers = true, Unit = unit, Default = def.ToString(CI) }; } private static SettingDescriptor Segmented(string cat, string key, string label, string hint, string[] options, string def) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: 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) //IL_0023: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown return new SettingDescriptor { Category = cat, Key = key, Label = label, Hint = hint, Type = (SettingType)2, Options = options, Values = options, Default = def }; } private static SettingDescriptor Toggle(string cat, string key, string label, string hint, bool def) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: 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) //IL_0023: 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_003f: Expected O, but got Unknown return new SettingDescriptor { Category = cat, Key = key, Label = label, Hint = hint, Type = (SettingType)1, Default = (def ? "1" : "0") }; } private static SettingDescriptor Dropdown(string cat, string key, string label, string hint, string[] options, string[] values, string def) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_001a: 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) //IL_0023: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown return new SettingDescriptor { Category = cat, Key = key, Label = label, Hint = hint, Type = (SettingType)4, Options = options, Values = values, Default = (def ?? "") }; } private static (string[] opts, string[] vals) WeaponChoices() { List list = new List { "None" }; List list2 = new List { "" }; List> list3 = WeaponCatalog.Weapons(); if (list3.Count > 0) { foreach (KeyValuePair item in list3) { list.Add(item.Value); list2.Add(item.Key); } } else { list.AddRange(new string[6] { "Pump Shotgun", "M1911", "Revolver", "Machete", "Baseball Bat", "Frying Pan" }); list2.AddRange(new string[6] { "pumpshotgun", "m1911", "revolver", "machete", "baseballbat", "fryingpan" }); } return (opts: list.ToArray(), vals: list2.ToArray()); } } internal static class RoundPresets { internal static SettingPreset[] Build() { SettingPreset[] array = BuildBase(); array = Array.FindAll(array, (SettingPreset p) => !p.Experimental); SettingPreset val = BuildCustom(); if (val == null) { return array; } List list = new List(array.Length + 1); list.Add(val); list.AddRange(array); return list.ToArray(); } private static SettingPreset BuildCustom() { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown string customBlob = PropHuntPreferences.CustomBlob; if (string.IsNullOrEmpty(customBlob)) { return null; } string text = PropHuntPreferences.CustomBase; if (string.IsNullOrEmpty(text)) { text = "Custom"; } Dictionary dictionary = new Dictionary(); string[] array = customBlob.Split(';'); foreach (string text2 in array) { int num = text2.IndexOf('='); if (num > 0) { dictionary[text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim(); } } return new SettingPreset { Name = "Custom - " + text, Hint = "Your last hosted settings (based on " + text + ").", Mode = text, Values = dictionary, DefaultSelected = true }; } private static SettingPreset[] BuildBase() { return (SettingPreset[])(object)new SettingPreset[9] { P("Classic Hunt", "The classic. Hiders disguise as props and hide, hunters seek. Caught hiders are out and spectate.", "hide=30;hunt=300;end=15;pph=5;swap=1;tag=4;taunt=30;area=75;hits=2;chg=5;decoy=4;conc=1;concr=7;caught=Spectator;round=Continuous;time=1200;weapon=pumpshotgun;ff=1", "Best for 4-10", 3, 12), P("Infection", "The classic with escalation: caught hiders turn into hunters. The longer it runs, the deadlier it gets for the remaining props.", "hide=30;hunt=360;end=15;pph=7;swap=1;tag=4;taunt=35;area=75;hits=2;chg=4;decoy=3;conc=1;concr=7;caught=Infection;round=Continuous;time=1200;weapon=pumpshotgun;ff=1", "Great for 6-16", 6, 20), P("Side Hustle Party", "Casual chaos with lots of hider tools. Great for bigger groups and fun, less competitive lobbies.", "hide=45;hunt=420;end=15;pph=5;swap=1;tag=4;taunt=40;area=90;hits=2;chg=8;decoy=6;conc=2;concr=8;caught=Spectator;round=Continuous;time=1200;weapon=pumpshotgun;ff=1", "Best for 8-16", 7, 20), P("Ranked Rules", "Competitive, low randomness. Fewer decoys and utility, cleaner rounds, no friendly fire. Good for fair, fixed groups.", "hide=30;hunt=300;end=15;pph=5;swap=1;tag=4;taunt=30;area=65;hits=2;chg=2;decoy=1;conc=0;concr=7;caught=Spectator;round=Continuous;time=1200;weapon=pumpshotgun;ff=0", "Best for 4-8", 4, 8), P("Panic Room", "Tiny zone, short rounds, fast action. Ideal for \"just one more quick round\".", "hide=15;hunt=150;end=15;pph=4;swap=1;tag=4;taunt=20;area=40;hits=2;chg=2;decoy=2;conc=1;concr=6;caught=Spectator;round=Continuous;time=1200;weapon=pumpshotgun;ff=1", "Best for 2-5", 2, 5), P("Deep Cover", "Long, calmer rounds. Hiders must stay convincing for longer; hunters watch more than they shoot.", "hide=60;hunt=600;end=15;pph=5;swap=1;tag=4;taunt=50;area=100;hits=2;chg=3;decoy=3;conc=1;concr=7;caught=Spectator;round=Continuous;time=1200;weapon=pumpshotgun;ff=1", "Best for 4-10", 4, 10), P("Last Prop Standing", "Endgame-focused. Standard PropHunt tuned so the closing minutes feel like a finale.", "hide=30;hunt=360;end=15;pph=5;swap=1;tag=4;taunt=30;area=75;hits=2;chg=4;decoy=3;conc=1;concr=7;caught=Spectator;round=Continuous;time=1200;weapon=pumpshotgun;ff=1", "Best for 4-10", 4, 12), P("Blend In", "A Schedule I twist where hiders mimic NPCs, not just props. Plays as Classic for now - NPC disguise is coming soon.", "hide=45;hunt=360;end=15;pph=5;swap=1;tag=4;taunt=35;area=80;hits=2;chg=5;decoy=2;conc=1;concr=7;caught=Spectator;round=Continuous;time=1200;weapon=pumpshotgun;ff=1", "Best for 4-10", 4, 12, experimental: true), P("Closing Time", "The play area shrinks over time, squeezing hiders out of safe spots. The boundary stays fixed for now - shrinking is coming soon.", "hide=30;hunt=360;end=15;pph=5;swap=1;tag=4;taunt=30;area=100;hits=2;chg=4;decoy=3;conc=1;concr=7;caught=Spectator;round=Continuous;time=1800;weapon=pumpshotgun;ff=1", "Best for 6-16", 6, 20, experimental: true) }; } private static SettingPreset P(string name, string hint, string spec, string recommended = null, int minP = 0, int maxP = 0, bool experimental = false) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00c5: 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_00d3: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown Dictionary dictionary = new Dictionary(); string[] array = spec.Split(';'); foreach (string text in array) { int num = text.IndexOf('='); if (num > 0) { dictionary[text.Substring(0, num).Trim()] = text.Substring(num + 1).Trim(); } } if (!dictionary.ContainsKey("rnd")) { dictionary["rnd"] = "1"; } if (!dictionary.ContainsKey("freechg")) { dictionary["freechg"] = "1"; } if (!dictionary.ContainsKey("freeze")) { dictionary["freeze"] = "1"; } return new SettingPreset { Name = name, Hint = hint, Values = dictionary, Mode = name, Recommended = recommended, MinPlayers = minP, MaxPlayers = maxP, Experimental = experimental }; } } internal static class WeaponCatalog { internal const string DefaultWeaponId = "pumpshotgun"; internal static List> Weapons() { List> list = new List>(); string weaponCache = PropHuntPreferences.WeaponCache; if (string.IsNullOrEmpty(weaponCache)) { return list; } string[] array = weaponCache.Split('\n'); foreach (string text in array) { if (text.Length != 0) { int num = text.IndexOf('|'); if (num > 0) { list.Add(new KeyValuePair(text.Substring(0, num), text.Substring(num + 1))); } } } return list; } internal static bool RefreshFromRegistry() { try { Registry instance = Singleton.Instance; if ((Object)(object)instance == (Object)null) { return false; } List allItems = instance.GetAllItems(); if (allItems == null || allItems.Count == 0) { return false; } HashSet hashSet = new HashSet(); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < allItems.Count; i++) { ItemDefinition val = allItems[i]; if ((Object)(object)val == (Object)null) { continue; } Equippable val2 = null; try { val2 = val.Equippable; } catch { } if ((Object)(object)val2 == (Object)null) { continue; } bool flag = false; try { flag = (Object)(object)((Il2CppObjectBase)val2).TryCast() != (Object)null || (Object)(object)((Il2CppObjectBase)val2).TryCast() != (Object)null; } catch { } if (!flag) { continue; } string text = null; string text2 = null; try { text = ((BaseItemDefinition)val).ID; text2 = ((BaseItemDefinition)val).Name; } catch { } if (!string.IsNullOrEmpty(text) && text.IndexOf("golden", StringComparison.OrdinalIgnoreCase) < 0 && hashSet.Add(text)) { if (stringBuilder.Length > 0) { stringBuilder.Append('\n'); } stringBuilder.Append(text).Append('|').Append(string.IsNullOrEmpty(text2) ? text : text2); } } string text3 = stringBuilder.ToString(); if (string.IsNullOrEmpty(text3) || text3 == PropHuntPreferences.WeaponCache) { return false; } PropHuntPreferences.SaveWeaponCache(text3); Core.Log.Msg($"[PropHunt] hunter-weapon catalog cached ({hashSet.Count} weapons): {text3.Replace('\n', ' ')}"); return true; } catch (Exception ex) { Core.Log.Warning("[PropHunt] weapon enumeration failed: " + ex.Message); return false; } } } } namespace PropHunt.Catch { internal sealed class CatchController { private readonly GameModeController _ctl; internal CatchController(GameModeController ctl) { _ctl = ctl; } internal void Tick() { } internal void ResolveShot(float maxRange) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0176: 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_0167: 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_01f8: Unknown result type (might be due to invalid IL or missing references) if (_ctl.Phase != RoundPhase.Hunting || _ctl.LocalRole != PlayerRole.Hunter) { return; } try { Player local = Player.Local; if (((Object)(object)local != (Object)null && local.IsTased) || _ctl.LocalDowned) { return; } PlayerCamera instance = PlayerSingleton.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.Camera == (Object)null) { return; } Transform transform = ((Component)instance.Camera).transform; Il2CppStructArray val = Physics.SphereCastAll(transform.position, 0.35f, transform.forward, maxRange, -1, (QueryTriggerInteraction)2); if (val == null || ((Il2CppArrayBase)(object)val).Length == 0) { return; } Array.Sort(Il2CppArrayBase.op_Implicit((Il2CppArrayBase)(object)val), (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int num = 0; num < ((Il2CppArrayBase)(object)val).Length; num++) { RaycastHit hit = ((Il2CppArrayBase)(object)val)[num]; if (!HasLineOfSight(transform.position, ((RaycastHit)(ref hit)).point)) { continue; } if (IsDecoy(((RaycastHit)(ref hit)).transform, out var idx)) { SpawnPropHitFx(((RaycastHit)(ref hit)).point); HudController.ShowHitmarker(); _ctl.RequestHitDecoy(idx); break; } if (IsDisguiseHitbox(((RaycastHit)(ref hit)).transform, out var victimId) && victimId != 0L && victimId != _ctl.LocalId) { SpawnPropHitFx(((RaycastHit)(ref hit)).point); HudController.ShowHitmarker(); _ctl.RequestClaimTag(victimId, transform.forward); break; } Player val2 = ResolvePlayer(hit); if ((Object)(object)val2 == (Object)null) { continue; } ulong num2 = PlayerRegistry.IdForPlayer(val2); if (num2 != 0L && num2 != _ctl.LocalId && _ctl.PropIdOf(num2) < 0) { if (_ctl.RoleOf(num2) != PlayerRole.Hunter) { HudController.ShowHitmarker(); _ctl.RequestClaimTag(num2, transform.forward); break; } if (_ctl.Settings != null && _ctl.Settings.FriendlyFire) { HudController.ShowHitmarker(); _ctl.RequestHitHunter(num2, transform.forward); break; } } } } catch (Exception) { } } private static bool HasLineOfSight(Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_001a: 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) try { RaycastHit val = default(RaycastHit); if (!Physics.Linecast(from, to, ref val, -1, (QueryTriggerInteraction)1)) { return true; } float distance = ((RaycastHit)(ref val)).distance; Vector3 val2 = to - from; return distance >= ((Vector3)(ref val2)).magnitude - 0.35f; } catch { return true; } } private static void SpawnPropHitFx(Vector3 point) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (point == Vector3.zero) { return; } try { FXManager instance = Singleton.Instance; if (!((Object)(object)instance == (Object)null)) { GameObject punchParticlePrefab = instance.PunchParticlePrefab; if ((Object)(object)punchParticlePrefab != (Object)null) { instance.PlayParticles(punchParticlePrefab, point, Quaternion.identity); } } } catch { } } private static bool IsDisguiseHitbox(Transform hit, out ulong victimId) { victimId = 0uL; if ((Object)(object)hit == (Object)null) { return false; } try { Transform val = hit; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } string name = ((Object)((Component)val).gameObject).name; if (name != null && name.StartsWith("ph_prop_") && ulong.TryParse(name.Substring("ph_prop_".Length), out victimId)) { return true; } val = val.parent; } } catch { } return false; } private static bool IsDecoy(Transform hit, out int idx) { idx = -1; if ((Object)(object)hit == (Object)null) { return false; } try { Transform val = hit; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } string name = ((Object)((Component)val).gameObject).name; if (name != null && name.StartsWith("ph_decoy_") && int.TryParse(name.Substring("ph_decoy_".Length), out idx)) { return true; } val = val.parent; } } catch { } return false; } private static Player ResolvePlayer(RaycastHit hit) { Player val = null; if ((Object)(object)((RaycastHit)(ref hit)).collider != (Object)null) { val = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent(); } if ((Object)(object)val == (Object)null && (Object)(object)((RaycastHit)(ref hit)).transform != (Object)null) { val = ((Component)((RaycastHit)(ref hit)).transform).GetComponentInParent(); } return val; } } }