using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using RepoMods.PropHunt; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOJP.PropHuntFix { [BepInPlugin("REPOJP.PropHunt_Fix", "PropHunt_Fix", "1.0.0")] public class PropHuntFixPlugin : BaseUnityPlugin { internal static PropHuntFixPlugin Instance; internal static ManualLogSource Log; internal static Harmony Harmony; internal const int RecentHunterWeight0 = 100; internal const int RecentHunterWeight1 = 50; internal const int RecentHunterWeight2 = 20; internal const int RecentHunterWeight3 = 5; internal const float LowestCountBonusMultiplier = 1.75f; internal static ConfigEntry CfgHunterCount; internal static ConfigEntry CfgRoundRoomCount; internal static ConfigEntry CfgGiveMapPlayerCountUpgrade; internal static ConfigEntry CfgRefillHuntersWhenHunterLeaves; internal static ConfigEntry CfgEnableHunterAllyNameHighlight; internal static ConfigEntry CfgWriteHunterSelectionLog; internal static ConfigEntry CfgEyeRefreshInterval; internal static ConfigEntry CfgDeathSoundVolumePercent; internal static ConfigEntry CfgWinSoundVolumePercent; internal static ConfigEntry CfgCountdownSoundVolumePercent; internal static ConfigEntry CfgMainMenuMusicVolumePercent; internal static ConfigEntry CfgLanguage; private GameObject runtimeRoot; private void Awake() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PropHuntAudioUtil.EnsureReady(); MainMenuMusicVolumeService.EnsureStarted(); CfgHunterCount = ((BaseUnityPlugin)this).Config.Bind("Gameplay", "HunterCount", 1, new ConfigDescription("Hunter count per round. ラウンドごとの鬼人数", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10), Array.Empty())); CfgRoundRoomCount = ((BaseUnityPlugin)this).Config.Bind("MapGeneration", "RoundRoomCount", 2, new ConfigDescription("Generated room count for PropHunt rounds. PropHuntラウンドの生成部屋数", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20), Array.Empty())); CfgGiveMapPlayerCountUpgrade = ((BaseUnityPlugin)this).Config.Bind("Gameplay", "GiveMapPlayerCountUpgrade", true, "Give the map player count upgrade to all players in PropHunt. PropHunt中に全員へマッププレイヤーカウントアップグレードを配布"); CfgRefillHuntersWhenHunterLeaves = ((BaseUnityPlugin)this).Config.Bind("Gameplay", "RefillHuntersWhenHunterLeaves", true, "Refill hunter slots if a hunter leaves mid-round. 鬼離脱時の補充"); CfgEnableHunterAllyNameHighlight = ((BaseUnityPlugin)this).Config.Bind("Visual", "EnableHunterAllyNameHighlight", true, "Show allied hunter name tags in red for hunters. 鬼同士の赤ネームタグ表示"); CfgEyeRefreshInterval = ((BaseUnityPlugin)this).Config.Bind("Visual", "EyeRefreshInterval", 0.75f, "Eye color refresh interval in seconds. 目色再適用間隔(秒)"); CfgDeathSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind("Audio", "DeathSoundVolumePercent", 50, new ConfigDescription("Death sound volume percent. 死亡音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); CfgWinSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind("Audio", "WinSoundVolumePercent", 50, new ConfigDescription("Win result sound volume percent. 勝利結果音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); CfgCountdownSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind("Audio", "CountdownSoundVolumePercent", 50, new ConfigDescription("Hunter unlock countdown beep volume percent. 鬼ロック解除カウントダウン音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); CfgMainMenuMusicVolumePercent = ((BaseUnityPlugin)this).Config.Bind("Audio", "MainMenuMusicVolumePercent", 50, new ConfigDescription("Main menu custom music volume percent. メインメニュー独自BGM音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); CfgLanguage = ((BaseUnityPlugin)this).Config.Bind("Localization", "Language", FixLanguage.English, "Display language. AutoTranslatorConfig.ini Language is used automatically when supported. 表示言語。対応言語の場合はAutoTranslatorConfig.iniのLanguageを自動使用"); CfgWriteHunterSelectionLog = ((BaseUnityPlugin)this).Config.Bind("Debug", "WriteHunterSelectionLog", true, "Write hunter selection logs. 抽選ログ出力"); Harmony = new Harmony("REPOJP.PropHunt_Fix"); Harmony.PatchAll(); Log.LogInfo((object)"[PropHunt_Fix] Loaded v1.0.0"); } internal static void EnsureRuntimeRoot() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown try { if (!((Object)(object)Instance == (Object)null) && !((Object)(object)Instance.runtimeRoot != (Object)null)) { GameObject val = new GameObject("PropHunt_Fix_Runtime"); val.transform.parent = null; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); val.AddComponent(); Instance.runtimeRoot = val; Log.LogInfo((object)"[PropHunt_Fix] Runtime initialized."); } } catch (Exception ex) { Log.LogWarning((object)("[PropHunt_Fix] Runtime init failed: " + ex.Message)); } } } public enum NonHunterEyeColorMode { Green, Black, Pink, Yellow, None } public enum FixLanguage { English, Japanese, Chinese, Korean, Russian, French, Spanish, German, Portuguese } internal static class FixLocalization { private static bool autoLoaded; private static bool hasAutoLanguage; private static FixLanguage autoLanguage; public static FixLanguage Current { get { LoadAutoLanguageOnce(); if (hasAutoLanguage) { return autoLanguage; } try { if (PropHuntFixPlugin.CfgLanguage != null) { return PropHuntFixPlugin.CfgLanguage.Value; } } catch { } return FixLanguage.English; } } private static void LoadAutoLanguageOnce() { if (autoLoaded) { return; } autoLoaded = true; try { string path = Path.Combine(Paths.ConfigPath, "AutoTranslatorConfig.ini"); if (!File.Exists(path)) { return; } string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i]; if (string.IsNullOrEmpty(text)) { continue; } text = text.Trim(); if (text.StartsWith("Language=", StringComparison.OrdinalIgnoreCase)) { if (TryParseLanguageCode(text.Substring("Language=".Length).Trim(), out var language)) { autoLanguage = language; hasAutoLanguage = true; } break; } } } catch { } } private static bool TryParseLanguageCode(string code, out FixLanguage language) { language = FixLanguage.English; if (string.IsNullOrEmpty(code)) { return false; } code = code.Trim().ToLowerInvariant(); int num = code.IndexOf('-'); if (num >= 0) { code = code.Substring(0, num); } if (code == "en") { language = FixLanguage.English; return true; } if (code == "ja" || code == "jp") { language = FixLanguage.Japanese; return true; } if (code == "zh" || code == "cn") { language = FixLanguage.Chinese; return true; } if (code == "ko" || code == "kr") { language = FixLanguage.Korean; return true; } switch (code) { case "ru": language = FixLanguage.Russian; return true; case "fr": language = FixLanguage.French; return true; case "es": language = FixLanguage.Spanish; return true; case "de": language = FixLanguage.German; return true; case "pt": language = FixLanguage.Portuguese; return true; default: return false; } } public static string Text(string key) { FixLanguage current = Current; return key switch { "Hunters" => Pick(current, "Hunters", "鬼", "猎人", "술래", "Охотники", "Chasseurs", "Cazadores", "Jäger", "Caçadores"), "Hunter" => Pick(current, "HUNTER", "鬼", "猎人", "술래", "ОХОТНИК", "CHASSEUR", "CAZADOR", "JÄGER", "CAÇADOR"), "Hider" => Pick(current, "HIDER", "逃げ側", "躲藏者", "도망자", "ПРЯЧУЩИЙСЯ", "CACHEUR", "OCULTO", "VERSTECKER", "ESCONDIDO"), "PropHunt" => Pick(current, "PROP HUNT", "プロップハント", "躲猫猫", "프롭 헌트", "ОХОТА НА ПРЕДМЕТЫ", "PROP HUNT", "PROP HUNT", "PROP HUNT", "PROP HUNT"), "ScanHelp" => Pick(current, "RMB: Scan | Miss penalty", "右クリック: スキャン | ミスでHP減少", "右键: 扫描 | 失误扣血", "우클릭: 스캔 | 실패 시 체력 감소", "ПКМ: Скан | Промах снимает HP", "Clic droit: scan | Échec: PV-", "Clic derecho: escanear | Fallo: PV-", "Rechtsklick: Scan | Fehlschuss: HP-", "Botão direito: escanear | Erro: HP-"), "HiderHelp" => Pick(current, "Toggle disguise / View / Lock", "変身 / 視点 / 固定", "切换伪装 / 视角 / 锁定", "변장 / 시점 / 고정", "Маскировка / Вид / Фиксация", "Déguisement / Vue / Verrou", "Disfraz / Vista / Bloqueo", "Tarnung / Ansicht / Sperre", "Disfarce / Visão / Travar"), "HideTime" => Pick(current, "Hide time", "隠れる時間", "躲藏时间", "숨는 시간", "Время прятаться", "Temps de cache", "Tiempo para esconderse", "Versteckzeit", "Tempo para esconder"), "TimeLeft" => Pick(current, "Time left", "残り時間", "剩余时间", "남은 시간", "Осталось", "Temps restant", "Tiempo restante", "Verbleibende Zeit", "Tempo restante"), "HunterLock" => Pick(current, "Hunter lock", "鬼ロック", "猎人锁定", "술래 잠금", "Блокировка охотника", "Blocage chasseur", "Bloqueo cazador", "Jägersperre", "Bloqueio do caçador"), "Disguise" => Pick(current, "Disguise", "変身", "伪装", "변장", "Маскировка", "Déguisement", "Disfraz", "Tarnung", "Disfarce"), "TargetLocked" => Pick(current, "Target locked", "対象固定済み", "目标已锁定", "대상 고정됨", "Цель выбрана", "Cible verrouillée", "Objetivo fijado", "Ziel fixiert", "Alvo travado"), "LookValuable" => Pick(current, "Look at a Valuable to lock target", "貴重品を見て対象を固定", "看向贵重品来锁定目标", "귀중품을 봐서 대상 고정", "Посмотрите на ценность", "Regardez un objet de valeur", "Mira un valioso", "Wertgegenstand ansehen", "Olhe para um valioso"), "Locked" => Pick(current, "LOCKED", "固定中", "已锁定", "고정됨", "ЗАФИКСИРОВАНО", "VERROUILLÉ", "BLOQUEADO", "GESPERRT", "TRAVADO"), "Start" => Pick(current, "START", "スタート", "开始", "시작", "СТАРТ", "DÉPART", "INICIO", "START", "INICIAR"), "NotReady" => Pick(current, "NOT READY", "未導入", "未就绪", "준비 안 됨", "НЕ ГОТОВ", "PAS PRÊT", "NO LISTO", "NICHT BEREIT", "NÃO PRONTO"), "Sec" => Pick(current, "sec", "秒", "秒", "초", "сек", "s", "seg", "Sek", "s"), "Min" => Pick(current, "min", "分", "分钟", "분", "мин", "min", "min", "Min", "min"), "HidersWin" => Pick(current, "HIDERS WIN!", "逃げ側の勝利!", "躲藏者胜利!", "도망자 승리!", "ПРЯЧУЩИЕСЯ ПОБЕДИЛИ!", "CACHEURS GAGNENT!", "¡GANAN LOS OCULTOS!", "VERSTECKER GEWINNEN!", "ESCONDIDOS VENCEM!"), "HunterWins" => Pick(current, "HUNTER WINS!", "鬼の勝利!", "猎人胜利!", "술래 승리!", "ОХОТНИК ПОБЕДИЛ!", "CHASSEUR GAGNE!", "¡GANA EL CAZADOR!", "JÄGER GEWINNT!", "CAÇADOR VENCE!"), "Draw" => Pick(current, "DRAW", "引き分け", "平局", "무승부", "НИЧЬЯ", "ÉGALITÉ", "EMPATE", "UNENTSCHIEDEN", "EMPATE"), "TimeExpired" => Pick(current, "Time expired", "時間切れ", "时间到", "시간 초과", "Время вышло", "Temps écoulé", "Tiempo agotado", "Zeit abgelaufen", "Tempo esgotado"), "HunterEliminated" => Pick(current, "Hunter eliminated", "鬼が全滅", "猎人被消灭", "술래 제거됨", "Охотник устранён", "Chasseur éliminé", "Cazador eliminado", "Jäger eliminiert", "Caçador eliminado"), "AllHidersEliminated" => Pick(current, "All hiders eliminated", "逃げ側が全滅", "躲藏者全灭", "도망자 전멸", "Все прячущиеся устранены", "Tous les cacheurs éliminés", "Todos los ocultos eliminados", "Alle Verstecker eliminiert", "Todos escondidos eliminados"), _ => key, }; } public static string TranslateMessage(string message) { if (string.IsNullOrEmpty(message)) { return message; } string text = message; text = text.Replace("HIDERS WIN!", Text("HidersWin")); text = text.Replace("HUNTER WINS!", Text("HunterWins")); text = text.Replace("DRAW", Text("Draw")); text = text.Replace("Time expired", Text("TimeExpired")); text = text.Replace("Hunter eliminated", Text("HunterEliminated")); text = text.Replace("All hiders eliminated", Text("AllHidersEliminated")); text = text.Replace("View: third-person", Pick(Current, "View: third-person", "視点: 三人称", "视角: 第三人称", "시점: 3인칭", "Вид: от третьего лица", "Vue: troisième personne", "Vista: tercera persona", "Ansicht: dritte Person", "Visão: terceira pessoa")); text = text.Replace("View: first-person", Pick(Current, "View: first-person", "視点: 一人称", "视角: 第一人称", "시점: 1인칭", "Вид: от первого лица", "Vue: première personne", "Vista: primera persona", "Ansicht: erste Person", "Visão: primeira pessoa")); text = text.Replace("Position LOCKED", Pick(Current, "Position LOCKED", "位置固定", "位置已锁定", "위치 고정", "Позиция зафиксирована", "Position verrouillée", "Posición bloqueada", "Position gesperrt", "Posição travada")); text = text.Replace("Position UNLOCKED", Pick(Current, "Position UNLOCKED", "位置固定解除", "位置解锁", "위치 해제", "Позиция разблокирована", "Position déverrouillée", "Posición desbloqueada", "Position entsperrt", "Posição destravada")); text = text.Replace("Disguise cleared.", Pick(Current, "Disguise cleared.", "変身解除", "伪装已解除", "변장 해제", "Маскировка снята", "Déguisement retiré", "Disfraz eliminado", "Tarnung aufgehoben", "Disfarce removido")); text = text.Replace("No disguise target. Look at a Valuable.", Pick(Current, "No disguise target. Look at a Valuable.", "変身対象なし。貴重品を見てください", "没有伪装目标。看向贵重品", "변장 대상 없음. 귀중품을 보세요", "Нет цели маскировки. Посмотрите на ценность", "Aucune cible. Regardez un objet de valeur", "Sin objetivo. Mira un valioso", "Kein Ziel. Wertgegenstand ansehen", "Sem alvo. Olhe para um valioso")); return text.Replace("Disguised.", Pick(Current, "Disguised.", "変身しました", "已伪装", "변장 완료", "Замаскировано", "Déguisé", "Disfrazado", "Getarnt", "Disfarçado")); } public static string PickForInternal(string en, string ja, string zh, string ko, string ru, string fr, string es, string de, string pt) { return Pick(Current, en, ja, zh, ko, ru, fr, es, de, pt); } private static string Pick(FixLanguage language, string en, string ja, string zh, string ko, string ru, string fr, string es, string de, string pt) { return language switch { FixLanguage.Japanese => ja, FixLanguage.Chinese => zh, FixLanguage.Korean => ko, FixLanguage.Russian => ru, FixLanguage.French => fr, FixLanguage.Spanish => es, FixLanguage.German => de, FixLanguage.Portuguese => pt, _ => en, }; } } internal static class OriginalPropHuntConfigBridge { private const float DefaultPreHideSeconds = 30f; private const float DefaultHunterLockSeconds = 30f; private const float DefaultRoundSeconds = 300f; private const int DefaultMissPenaltyHP = 5; private const float DefaultGunRangeMeters = 60f; private const float DefaultGunCooldownSeconds = 0.18f; private static ConfigEntryBase GetConfigEntry(string fieldName) { try { FieldInfo fieldInfo = AccessTools.Field(typeof(PropHuntPlugin), fieldName); if (fieldInfo == null) { return null; } object value = fieldInfo.GetValue(null); return (ConfigEntryBase)((value is ConfigEntryBase) ? value : null); } catch { return null; } } private static float GetFloat(string fieldName, float defaultValue) { try { ConfigEntryBase configEntry = GetConfigEntry(fieldName); if (configEntry != null && configEntry.BoxedValue != null) { object boxedValue = configEntry.BoxedValue; if (boxedValue is float result) { return result; } if (boxedValue is int) { return (int)boxedValue; } if (boxedValue is double) { return (float)(double)boxedValue; } if (boxedValue is long) { return (long)boxedValue; } if (boxedValue is string s && float.TryParse(s, out var result2)) { return result2; } } } catch { } return defaultValue; } private static int GetInt(string fieldName, int defaultValue) { try { ConfigEntryBase configEntry = GetConfigEntry(fieldName); if (configEntry != null && configEntry.BoxedValue != null) { object boxedValue = configEntry.BoxedValue; if (boxedValue is int result) { return result; } if (boxedValue is int result2) { return result2; } if (boxedValue is int result3) { return result3; } if (boxedValue is long) { return (int)(long)boxedValue; } if (boxedValue is float) { return Mathf.RoundToInt((float)boxedValue); } if (boxedValue is string s && int.TryParse(s, out var result4)) { return result4; } } } catch { } return defaultValue; } public static float GetPreHideSeconds() { return Mathf.Max(1f, GetFloat("CfgPreHideSeconds", 30f)); } public static float GetHunterLockSeconds() { return Mathf.Max(0f, GetFloat("CfgHunterLockSeconds", 30f)); } public static float GetRoundSeconds() { return Mathf.Max(5f, GetFloat("CfgRoundSeconds", 300f)); } public static int GetMissPenaltyHP() { return Mathf.Max(0, GetInt("CfgMissPenaltyHP", 5)); } public static float GetGunRangeMeters() { return Mathf.Max(1f, GetFloat("CfgGunRangeMeters", 60f)); } public static float GetGunCooldownSeconds() { return Mathf.Max(0f, GetFloat("CfgGunCooldownSeconds", 0.18f)); } public static void SubscribeToOriginalConfigChanges(EventHandler handler) { SubscribeField("CfgPreHideSeconds", handler); SubscribeField("CfgHunterLockSeconds", handler); SubscribeField("CfgRoundSeconds", handler); SubscribeField("CfgMissPenaltyHP", handler); SubscribeField("CfgGunRangeMeters", handler); SubscribeField("CfgGunCooldownSeconds", handler); } private static void SubscribeField(string fieldName, EventHandler handler) { try { ConfigEntryBase configEntry = GetConfigEntry(fieldName); if (configEntry != null) { EventInfo @event = ((object)configEntry).GetType().GetEvent("SettingChanged", BindingFlags.Instance | BindingFlags.Public); if (@event != null) { @event.AddEventHandler(configEntry, handler); } } } catch { } } } internal class FixConfigSnapshot { public float PreHideSeconds; public float HunterLockSeconds; public float RoundSeconds; public int MissPenaltyHP; public float GunRangeMeters; public float GunCooldownSeconds; public int HunterCount; public bool RefillHuntersWhenHunterLeaves; public int RecentHunterWeight0; public int RecentHunterWeight1; public int RecentHunterWeight2; public int RecentHunterWeight3; public float LowestCountBonusMultiplier; public NonHunterEyeColorMode NonHunterEyeColor; public bool EnableHunterAllyNameHighlight; public static FixConfigSnapshot FromLocalConfig() { FixConfigSnapshot fixConfigSnapshot = new FixConfigSnapshot(); fixConfigSnapshot.PreHideSeconds = OriginalPropHuntConfigBridge.GetPreHideSeconds(); fixConfigSnapshot.HunterLockSeconds = OriginalPropHuntConfigBridge.GetHunterLockSeconds(); fixConfigSnapshot.RoundSeconds = OriginalPropHuntConfigBridge.GetRoundSeconds(); fixConfigSnapshot.MissPenaltyHP = OriginalPropHuntConfigBridge.GetMissPenaltyHP(); fixConfigSnapshot.GunRangeMeters = OriginalPropHuntConfigBridge.GetGunRangeMeters(); fixConfigSnapshot.GunCooldownSeconds = OriginalPropHuntConfigBridge.GetGunCooldownSeconds(); fixConfigSnapshot.HunterCount = Mathf.Max(1, PropHuntFixPlugin.CfgHunterCount.Value); fixConfigSnapshot.RefillHuntersWhenHunterLeaves = PropHuntFixPlugin.CfgRefillHuntersWhenHunterLeaves.Value; fixConfigSnapshot.RecentHunterWeight0 = 100; fixConfigSnapshot.RecentHunterWeight1 = 50; fixConfigSnapshot.RecentHunterWeight2 = 20; fixConfigSnapshot.RecentHunterWeight3 = 5; fixConfigSnapshot.LowestCountBonusMultiplier = 1.75f; fixConfigSnapshot.NonHunterEyeColor = NonHunterEyeColorMode.None; fixConfigSnapshot.EnableHunterAllyNameHighlight = PropHuntFixPlugin.CfgEnableHunterAllyNameHighlight.Value; return fixConfigSnapshot; } public bool EqualsTo(FixConfigSnapshot other) { if (other == null) { return false; } return PreHideSeconds == other.PreHideSeconds && HunterLockSeconds == other.HunterLockSeconds && RoundSeconds == other.RoundSeconds && MissPenaltyHP == other.MissPenaltyHP && GunRangeMeters == other.GunRangeMeters && GunCooldownSeconds == other.GunCooldownSeconds && HunterCount == other.HunterCount && RefillHuntersWhenHunterLeaves == other.RefillHuntersWhenHunterLeaves && RecentHunterWeight0 == other.RecentHunterWeight0 && RecentHunterWeight1 == other.RecentHunterWeight1 && RecentHunterWeight2 == other.RecentHunterWeight2 && RecentHunterWeight3 == other.RecentHunterWeight3 && Mathf.Approximately(LowestCountBonusMultiplier, other.LowestCountBonusMultiplier) && NonHunterEyeColor == other.NonHunterEyeColor && EnableHunterAllyNameHighlight == other.EnableHunterAllyNameHighlight; } public Hashtable ToHashtable() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Hashtable val = new Hashtable(); val[(object)"PHFIX_CFG_PreHideSeconds"] = PreHideSeconds; val[(object)"PHFIX_CFG_HunterLockSeconds"] = HunterLockSeconds; val[(object)"PHFIX_CFG_RoundSeconds"] = RoundSeconds; val[(object)"PHFIX_CFG_MissPenaltyHP"] = MissPenaltyHP; val[(object)"PHFIX_CFG_GunRangeMeters"] = GunRangeMeters; val[(object)"PHFIX_CFG_GunCooldownSeconds"] = GunCooldownSeconds; val[(object)"PHFIX_CFG_HunterCount"] = HunterCount; val[(object)"PHFIX_CFG_RefillHuntersWhenHunterLeaves"] = RefillHuntersWhenHunterLeaves; val[(object)"PHFIX_CFG_RecentHunterWeight0"] = RecentHunterWeight0; val[(object)"PHFIX_CFG_RecentHunterWeight1"] = RecentHunterWeight1; val[(object)"PHFIX_CFG_RecentHunterWeight2"] = RecentHunterWeight2; val[(object)"PHFIX_CFG_RecentHunterWeight3"] = RecentHunterWeight3; val[(object)"PHFIX_CFG_LowestCountBonusMultiplier"] = LowestCountBonusMultiplier; val[(object)"PHFIX_CFG_NonHunterEyeColor"] = (int)NonHunterEyeColor; val[(object)"PHFIX_CFG_EnableHunterAllyNameHighlight"] = EnableHunterAllyNameHighlight; return val; } public static FixConfigSnapshot FromRoomProperties(Hashtable props) { if (props == null) { return null; } FixConfigSnapshot fixConfigSnapshot = new FixConfigSnapshot(); if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_PreHideSeconds", out fixConfigSnapshot.PreHideSeconds)) { return null; } if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_HunterLockSeconds", out fixConfigSnapshot.HunterLockSeconds)) { return null; } if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_RoundSeconds", out fixConfigSnapshot.RoundSeconds)) { return null; } if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_MissPenaltyHP", out fixConfigSnapshot.MissPenaltyHP)) { return null; } if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_GunRangeMeters", out fixConfigSnapshot.GunRangeMeters)) { return null; } if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_GunCooldownSeconds", out fixConfigSnapshot.GunCooldownSeconds)) { return null; } if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_HunterCount", out fixConfigSnapshot.HunterCount)) { return null; } if (!RoomPropUtil.TryGetBool(props, "PHFIX_CFG_RefillHuntersWhenHunterLeaves", out fixConfigSnapshot.RefillHuntersWhenHunterLeaves)) { return null; } if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight0", out fixConfigSnapshot.RecentHunterWeight0)) { return null; } if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight1", out fixConfigSnapshot.RecentHunterWeight1)) { return null; } if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight2", out fixConfigSnapshot.RecentHunterWeight2)) { return null; } if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_RecentHunterWeight3", out fixConfigSnapshot.RecentHunterWeight3)) { return null; } if (!RoomPropUtil.TryGetFloat(props, "PHFIX_CFG_LowestCountBonusMultiplier", out fixConfigSnapshot.LowestCountBonusMultiplier)) { return null; } if (!RoomPropUtil.TryGetInt(props, "PHFIX_CFG_NonHunterEyeColor", out var value)) { return null; } fixConfigSnapshot.NonHunterEyeColor = (NonHunterEyeColorMode)value; if (!RoomPropUtil.TryGetBool(props, "PHFIX_CFG_EnableHunterAllyNameHighlight", out fixConfigSnapshot.EnableHunterAllyNameHighlight)) { return null; } return fixConfigSnapshot; } } internal static class RoomKeys { public const string Active = "PH_Active"; public const string Hunter = "PH_Hunter"; public const string Hunters = "PH_Hunters"; public const string UnlockAt = "PHFIX_UnlockAt"; public const string UnlockSerial = "PHFIX_UnlockSerial"; public const string CfgPreHideSeconds = "PHFIX_CFG_PreHideSeconds"; public const string CfgHunterLockSeconds = "PHFIX_CFG_HunterLockSeconds"; public const string CfgRoundSeconds = "PHFIX_CFG_RoundSeconds"; public const string CfgMissPenaltyHP = "PHFIX_CFG_MissPenaltyHP"; public const string CfgGunRangeMeters = "PHFIX_CFG_GunRangeMeters"; public const string CfgGunCooldownSeconds = "PHFIX_CFG_GunCooldownSeconds"; public const string CfgHunterCount = "PHFIX_CFG_HunterCount"; public const string CfgRefillHuntersWhenHunterLeaves = "PHFIX_CFG_RefillHuntersWhenHunterLeaves"; public const string CfgRecentHunterWeight0 = "PHFIX_CFG_RecentHunterWeight0"; public const string CfgRecentHunterWeight1 = "PHFIX_CFG_RecentHunterWeight1"; public const string CfgRecentHunterWeight2 = "PHFIX_CFG_RecentHunterWeight2"; public const string CfgRecentHunterWeight3 = "PHFIX_CFG_RecentHunterWeight3"; public const string CfgLowestCountBonusMultiplier = "PHFIX_CFG_LowestCountBonusMultiplier"; public const string CfgNonHunterEyeColor = "PHFIX_CFG_NonHunterEyeColor"; public const string CfgEnableHunterAllyNameHighlight = "PHFIX_CFG_EnableHunterAllyNameHighlight"; } internal static class PlayerKeys { public const string Ready = "PHFIX_Ready"; public const string HasPropHunt = "PHFIX_HasPropHunt"; public const string HasFix = "PHFIX_HasFix"; public const string FixVersion = "PHFIX_Version"; } internal static class RoomPropUtil { public static bool TryGetInt(Hashtable props, string key, out int value) { value = 0; if (props == null || !((Dictionary)(object)props).ContainsKey(key)) { return false; } object obj = props[(object)key]; try { if (obj is int) { value = (int)obj; return true; } if (obj is byte) { value = (byte)obj; return true; } if (obj is short) { value = (short)obj; return true; } if (obj is long) { value = (int)(long)obj; return true; } if (obj is float) { value = Mathf.RoundToInt((float)obj); return true; } if (obj is double) { value = (int)(double)obj; return true; } if (obj is string && int.TryParse((string)obj, out value)) { return true; } } catch { } return false; } public static bool TryGetFloat(Hashtable props, string key, out float value) { value = 0f; if (props == null || !((Dictionary)(object)props).ContainsKey(key)) { return false; } object obj = props[(object)key]; try { if (obj is float) { value = (float)obj; return true; } if (obj is int) { value = (int)obj; return true; } if (obj is double) { value = (float)(double)obj; return true; } if (obj is long) { value = (long)obj; return true; } if (obj is string && float.TryParse((string)obj, out value)) { return true; } } catch { } return false; } public static bool TryGetBool(Hashtable props, string key, out bool value) { value = false; if (props == null || !((Dictionary)(object)props).ContainsKey(key)) { return false; } object obj = props[(object)key]; try { if (obj is bool) { value = (bool)obj; return true; } if (obj is int) { value = (int)obj != 0; return true; } if (obj is byte) { value = (byte)obj != 0; return true; } if (obj is string && bool.TryParse((string)obj, out value)) { return true; } } catch { } return false; } } internal static class PropHuntFixState { private static readonly Random Rng = new Random(); public static readonly HashSet CurrentHunters = new HashSet(); public static readonly Dictionary TotalHunterCountsByUserKey = new Dictionary(); public static readonly Queue> RecentHunterHistory = new Queue>(); public static FixConfigSnapshot AppliedSnapshot; public static FixConfigSnapshot PendingSnapshot; public static bool PendingGameplayApply; public static void ResetRoomState() { CurrentHunters.Clear(); RecentHunterHistory.Clear(); TotalHunterCountsByUserKey.Clear(); PendingSnapshot = null; AppliedSnapshot = null; PendingGameplayApply = false; } public static string GetIdentityKey(Player player) { if (player == null) { return "unknown"; } try { if (!string.IsNullOrEmpty(player.UserId)) { return "uid:" + player.UserId; } } catch { } try { object obj2 = ((AccessTools.Property(typeof(Player), "UserId") != null) ? player.UserId : null); if (obj2 != null) { return "sid:" + obj2.ToString(); } } catch { } return "actor:" + player.ActorNumber; } public static int GetRecentHunterCount(string userKey) { int num = 0; foreach (List item in RecentHunterHistory) { if (item.Contains(userKey)) { num++; } } return num; } public static int GetTotalHunterCount(string userKey) { if (TotalHunterCountsByUserKey.TryGetValue(userKey, out var value)) { return value; } return 0; } public static void CommitSelectedHunters(List selectedPlayers) { if (selectedPlayers == null || selectedPlayers.Count == 0) { return; } List list = new List(); for (int i = 0; i < selectedPlayers.Count; i++) { Player player = selectedPlayers[i]; string identityKey = GetIdentityKey(player); list.Add(identityKey); if (!TotalHunterCountsByUserKey.ContainsKey(identityKey)) { TotalHunterCountsByUserKey[identityKey] = 0; } TotalHunterCountsByUserKey[identityKey]++; } RecentHunterHistory.Enqueue(list); while (RecentHunterHistory.Count > 3) { RecentHunterHistory.Dequeue(); } } public static float BuildWeight(Player player, FixConfigSnapshot snapshot, List allCandidates) { string identityKey = GetIdentityKey(player); int recentHunterCount = GetRecentHunterCount(identityKey); int totalHunterCount = GetTotalHunterCount(identityKey); int num = int.MaxValue; bool flag = true; int num2 = int.MinValue; for (int i = 0; i < allCandidates.Count; i++) { int totalHunterCount2 = GetTotalHunterCount(GetIdentityKey(allCandidates[i])); if (i == 0) { num2 = totalHunterCount2; } else if (num2 != totalHunterCount2) { flag = false; } if (totalHunterCount2 < num) { num = totalHunterCount2; } } float num3 = Mathf.Clamp(recentHunterCount, 0, 3) switch { 0 => snapshot.RecentHunterWeight0, 1 => snapshot.RecentHunterWeight1, 2 => snapshot.RecentHunterWeight2, _ => snapshot.RecentHunterWeight3, }; if (!flag && totalHunterCount == num) { num3 *= snapshot.LowestCountBonusMultiplier; } return Mathf.Max(0.01f, num3); } public static List SelectHunters(List activePlayers, FixConfigSnapshot snapshot, ICollection excludeActorNumbers) { List list = new List(); for (int i = 0; i < activePlayers.Count; i++) { Player val = activePlayers[i]; if (val != null && !val.IsInactive && (excludeActorNumbers == null || !excludeActorNumbers.Contains(val.ActorNumber))) { list.Add(val); } } list = list.OrderBy((Player p) => p.ActorNumber).ToList(); int num = Mathf.Clamp(snapshot.HunterCount, 1, Mathf.Max(1, list.Count)); if (activePlayers.Count > 0) { num = Mathf.Min(num, Mathf.Max(1, activePlayers.Count - 1)); } List list2 = new List(); while (list2.Count < num && list.Count > 0) { float num2 = 0f; for (int j = 0; j < list.Count; j++) { num2 += BuildWeight(list[j], snapshot, list); } double num3 = Rng.NextDouble() * (double)num2; double num4 = 0.0; int index = list.Count - 1; for (int k = 0; k < list.Count; k++) { num4 += (double)BuildWeight(list[k], snapshot, list); if (num3 <= num4) { index = k; break; } } list2.Add(list[index]); list.RemoveAt(index); } if (PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { LogSelection(activePlayers, list2, snapshot); } return list2; } private static void LogSelection(List activePlayers, List selected, FixConfigSnapshot snapshot) { try { List list = new List(); for (int i = 0; i < activePlayers.Count; i++) { Player val = activePlayers[i]; string identityKey = GetIdentityKey(val); list.Add(val.ActorNumber + "=" + GetTotalHunterCount(identityKey)); } List list2 = new List(); for (int j = 0; j < selected.Count; j++) { list2.Add(selected[j].ActorNumber.ToString()); } PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Active players: " + activePlayers.Count)); PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Config hunter count: " + snapshot.HunterCount)); PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Total hunter counts: " + string.Join(", ", list.ToArray()))); PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Selected hunters: " + string.Join(", ", list2.ToArray()))); } catch (Exception ex) { PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Selection log failed: " + ex.Message)); } } public static void SyncHuntersFromRoomProperties(Hashtable props) { CurrentHunters.Clear(); if (props == null) { return; } if (((Dictionary)(object)props).ContainsKey("PH_Hunters")) { object obj = props[(object)"PH_Hunters"]; if (obj is int[]) { int[] array = (int[])obj; for (int i = 0; i < array.Length; i++) { CurrentHunters.Add(array[i]); } return; } if (obj is object[]) { object[] array2 = (object[])obj; for (int j = 0; j < array2.Length; j++) { if (TryToInt(array2[j], out var val)) { CurrentHunters.Add(val); } } return; } } if (RoomPropUtil.TryGetInt(props, "PH_Hunter", out var value)) { CurrentHunters.Add(value); } } public static bool TryToInt(object o, out int val) { try { if (o is int) { val = (int)o; return true; } if (o is byte) { val = (byte)o; return true; } if (o is short) { val = (short)o; return true; } if (o is long) { val = (int)(long)o; return true; } if (o is float) { val = (int)(float)o; return true; } if (o is double) { val = (int)(double)o; return true; } if (o is string && int.TryParse((string)o, out val)) { return true; } } catch { } val = -1; return false; } } public class ReadySyncService : MonoBehaviourPunCallbacks { public static bool IsLocalReadySent; private void Start() { TrySendReady(); } public override void OnJoinedRoom() { TrySendReady(); } private void Update() { if (!IsLocalReadySent && PhotonNetwork.InRoom) { TrySendReady(); } } private void TrySendReady() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown try { if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { bool flag = AccessTools.TypeByName("RepoMods.PropHunt.PropHuntPlugin") != null; bool flag2 = (Object)(object)PropHuntFixPlugin.Instance != (Object)null; if (flag && flag2) { Hashtable val = new Hashtable(); val[(object)"PHFIX_Ready"] = true; val[(object)"PHFIX_HasPropHunt"] = flag; val[(object)"PHFIX_HasFix"] = flag2; val[(object)"PHFIX_Version"] = "1.0.0"; PhotonNetwork.LocalPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); IsLocalReadySent = true; } } } catch { } } } public class HunterLockAudioWatcher : MonoBehaviour { } public class HostConfigSyncService : MonoBehaviourPunCallbacks { private static HostConfigSyncService Instance; private FixConfigSnapshot lastWrittenSnapshot; private void Awake() { Instance = this; SubscribeConfigChanges(); } public override void OnJoinedRoom() { TryWriteSnapshot(); } public override void OnLeftRoom() { lastWrittenSnapshot = null; } public static void RequestWriteSnapshot() { try { if ((Object)(object)Instance != (Object)null) { Instance.TryWriteSnapshot(); return; } HostConfigSyncService hostConfigSyncService = Object.FindObjectOfType(); if ((Object)(object)hostConfigSyncService != (Object)null) { hostConfigSyncService.TryWriteSnapshot(); } } catch { } } private void SubscribeConfigChanges() { OriginalPropHuntConfigBridge.SubscribeToOriginalConfigChanges(OnConfigChanged); SubscribeConfigEntry((ConfigEntryBase)(object)PropHuntFixPlugin.CfgHunterCount, OnConfigChanged); SubscribeConfigEntry((ConfigEntryBase)(object)PropHuntFixPlugin.CfgRefillHuntersWhenHunterLeaves, OnConfigChanged); SubscribeConfigEntry((ConfigEntryBase)(object)PropHuntFixPlugin.CfgEnableHunterAllyNameHighlight, OnConfigChanged); } private void SubscribeConfigEntry(ConfigEntryBase entry, EventHandler handler) { try { if (entry != null) { EventInfo @event = ((object)entry).GetType().GetEvent("SettingChanged", BindingFlags.Instance | BindingFlags.Public); if (@event != null) { @event.AddEventHandler(entry, handler); } } } catch { } } private void OnConfigChanged(object sender, EventArgs e) { TryWriteSnapshot(); } public void TryWriteSnapshot() { if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null) { return; } FixConfigSnapshot fixConfigSnapshot = FixConfigSnapshot.FromLocalConfig(); if (lastWrittenSnapshot != null && fixConfigSnapshot.EqualsTo(lastWrittenSnapshot)) { return; } try { PhotonNetwork.CurrentRoom.SetCustomProperties(fixConfigSnapshot.ToHashtable(), (Hashtable)null, (WebFlags)null); lastWrittenSnapshot = fixConfigSnapshot; if (PropHuntFixPlugin.CfgWriteHunterSelectionLog == null || PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Host config snapshot synchronized. PreHide=" + fixConfigSnapshot.PreHideSeconds.ToString("0.00") + ", HunterLock=" + fixConfigSnapshot.HunterLockSeconds.ToString("0.00") + ", Round=" + fixConfigSnapshot.RoundSeconds.ToString("0.00") + ", MissPenalty=" + fixConfigSnapshot.MissPenaltyHP + ", Range=" + fixConfigSnapshot.GunRangeMeters.ToString("0.00") + ", Cooldown=" + fixConfigSnapshot.GunCooldownSeconds.ToString("0.00") + ", HunterCount=" + fixConfigSnapshot.HunterCount)); } } catch (Exception ex) { PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Host config sync failed: " + ex.Message)); } } } public class ClientConfigApplyService : MonoBehaviourPunCallbacks { public static ClientConfigApplyService Instance; private void Awake() { Instance = this; } public override void OnJoinedRoom() { QueueSnapshotFromCurrentRoom(); ApplyPendingVisuals(); PropHuntFixPlugin.EnsureRuntimeRoot(); } public override void OnLeftRoom() { PropHuntFixState.ResetRoomState(); } public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { QueueSnapshotFromCurrentRoom(); ApplyPendingVisuals(); } public void QueueSnapshotFromCurrentRoom() { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { FixConfigSnapshot fixConfigSnapshot = FixConfigSnapshot.FromRoomProperties(((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties); if (fixConfigSnapshot != null) { PropHuntFixState.PendingSnapshot = fixConfigSnapshot; } } } public void ApplyPendingVisuals() { if (PropHuntFixState.PendingSnapshot != null) { EyeColorRefreshService.ApplyAllVisiblePlayerEyes(); NameTagPatch.RefreshAllNameTags(); } } public void RequestGameplayApplyForNextRound() { PropHuntFixState.PendingGameplayApply = true; } public void ApplyPendingGameplayIfRequested() { if (PropHuntFixState.PendingGameplayApply && PropHuntFixState.PendingSnapshot != null) { PropHuntManager instance = PropHuntManager.Instance; if (!((Object)(object)instance == (Object)null)) { FixConfigSnapshot pendingSnapshot = PropHuntFixState.PendingSnapshot; instance.PreHideSeconds = pendingSnapshot.PreHideSeconds; instance.HunterLockSeconds = pendingSnapshot.HunterLockSeconds; instance.RoundSeconds = pendingSnapshot.RoundSeconds; instance.MissPenaltyHP = pendingSnapshot.MissPenaltyHP; instance.GunRangeMeters = pendingSnapshot.GunRangeMeters; instance.GunCooldownSeconds = pendingSnapshot.GunCooldownSeconds; PropHuntFixState.AppliedSnapshot = pendingSnapshot; PropHuntFixState.PendingGameplayApply = false; EyeColorRefreshService.ApplyAllVisiblePlayerEyes(); NameTagPatch.RefreshAllNameTags(); PropHuntFixPlugin.Log.LogInfo((object)"[PropHunt_Fix] Pending gameplay config applied."); } } } } public class EyeColorRefreshService : MonoBehaviourPunCallbacks { private void Update() { ApplyAllVisiblePlayerEyes(); } private void LateUpdate() { ApplyAllVisiblePlayerEyes(); } public override void OnJoinedRoom() { ApplyAllVisiblePlayerEyes(); } public override void OnPlayerEnteredRoom(Player newPlayer) { ApplyAllVisiblePlayerEyes(); } public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { ApplyAllVisiblePlayerEyes(); } public static void ApplyAllVisiblePlayerEyes() { try { if (!((Object)(object)GameDirector.instance == (Object)null) && GameDirector.instance.PlayerList != null) { for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++) { ApplyEyeColorForAvatar(GameDirector.instance.PlayerList[i]); } } } catch { } } public static void ApplyEyeColorForAvatar(PlayerAvatar avatar) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)avatar == (Object)null || (Object)(object)avatar.photonView == (Object)null || (Object)(object)avatar.playerHealth == (Object)null || avatar.photonView.Owner == null || !TryGetEyeState(avatar.photonView.Owner.ActorNumber, out var state)) { return; } try { avatar.playerHealth.EyeMaterialOverride(state, 0.25f, 999999); } catch { } } private static bool TryGetEyeState(int actorNumber, out EyeOverrideState state) { if (PropHuntFixState.CurrentHunters.Contains(actorNumber)) { state = (EyeOverrideState)1; return true; } state = (EyeOverrideState)2; return false; } } [HarmonyPatch(typeof(PropHuntManager), "Start")] public static class Patch_PropHuntManager_Start { private static void Prefix() { if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (!((Dictionary)(object)customProperties).ContainsKey("PH_Active")) { FixConfigSnapshot snapshot = PropHuntFixState.PendingSnapshot ?? FixConfigSnapshot.FromLocalConfig(); List list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive).ToList(); if (list.Count > 1) { List list2 = PropHuntFixState.SelectHunters(list, snapshot, null); PropHuntFixState.CommitSelectedHunters(list2); SetHunterRoomProperties(list2); HunterUnlockCountdownController.PublishHostUnlockTimeForNewRound(snapshot); } } } private static void Postfix(PropHuntManager __instance) { PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { PropHuntFixPlugin.EnsureRuntimeRoot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { ClientConfigApplyService.Instance.QueueSnapshotFromCurrentRoom(); } PropHuntFixPlugin.EnsureRuntimeRoot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { ClientConfigApplyService.Instance.ApplyPendingGameplayIfRequested(); } } EyeColorRefreshService.ApplyAllVisiblePlayerEyes(); } internal static void SetHunterRoomProperties(List selected) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if (PhotonNetwork.CurrentRoom != null && selected != null && selected.Count != 0) { int[] array = new int[selected.Count]; for (int i = 0; i < selected.Count; i++) { array[i] = selected[i].ActorNumber; } Hashtable val = new Hashtable(); val[(object)"PH_Active"] = 1; val[(object)"PH_Hunter"] = array[0]; val[(object)"PH_Hunters"] = array; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } } [HarmonyPatch(typeof(PropHuntManager), "RepickHunterForNextRound")] public static class Patch_PropHuntManager_RepickHunterForNextRound { private static bool Prefix(PropHuntManager __instance) { if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return false; } FixConfigSnapshot snapshot = PropHuntFixState.PendingSnapshot ?? PropHuntFixState.AppliedSnapshot ?? FixConfigSnapshot.FromLocalConfig(); List list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive).ToList(); if (list.Count <= 1) { return false; } HashSet excludeActorNumbers = new HashSet(PropHuntFixState.CurrentHunters); List list2 = PropHuntFixState.SelectHunters(list, snapshot, null); if (list2.Count == 0) { list2 = PropHuntFixState.SelectHunters(list, snapshot, excludeActorNumbers); } PropHuntFixState.CommitSelectedHunters(list2); Patch_PropHuntManager_Start.SetHunterRoomProperties(list2); return false; } } [HarmonyPatch(typeof(PropHuntManager), "OnPlayerLeftRoom")] public static class Patch_PropHuntManager_OnPlayerLeftRoom { private static bool Prefix(PropHuntManager __instance, Player otherPlayer) { if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || otherPlayer == null) { return false; } if (!PropHuntFixState.CurrentHunters.Contains(otherPlayer.ActorNumber)) { return false; } PropHuntFixState.CurrentHunters.Remove(otherPlayer.ActorNumber); FixConfigSnapshot fixConfigSnapshot = PropHuntFixState.PendingSnapshot ?? PropHuntFixState.AppliedSnapshot ?? FixConfigSnapshot.FromLocalConfig(); if (!fixConfigSnapshot.RefillHuntersWhenHunterLeaves) { Patch_PropHuntManager_Start.SetHunterRoomProperties(PhotonNetwork.PlayerList.Where((Player p) => p != null && PropHuntFixState.CurrentHunters.Contains(p.ActorNumber)).ToList()); return false; } List list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive && !PropHuntFixState.CurrentHunters.Contains(p.ActorNumber)).ToList(); if (list.Count > 0) { List list2 = PropHuntFixState.SelectHunters(list, fixConfigSnapshot, null); if (list2.Count > 1) { list2 = list2.Take(1).ToList(); } if (list2.Count > 0) { PropHuntFixState.CurrentHunters.Add(list2[0].ActorNumber); PropHuntFixState.CommitSelectedHunters(list2); } } List list3 = PhotonNetwork.PlayerList.Where((Player p) => p != null && PropHuntFixState.CurrentHunters.Contains(p.ActorNumber)).ToList(); if (list3.Count > 0) { Patch_PropHuntManager_Start.SetHunterRoomProperties(list3); } return false; } } [HarmonyPatch(typeof(PropHuntManager), "ApplyRoomState")] public static class Patch_PropHuntManager_ApplyRoomState { private static void Postfix(PropHuntManager __instance, Hashtable props) { PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance, props); EyeColorRefreshService.ApplyAllVisiblePlayerEyes(); NameTagPatch.RefreshAllNameTags(); } } [HarmonyPatch(typeof(PropHuntManager), "OnRoomPropertiesUpdate")] public static class Patch_PropHuntManager_OnRoomPropertiesUpdate { private static void Postfix(PropHuntManager __instance) { PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { PropHuntFixPlugin.EnsureRuntimeRoot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { ClientConfigApplyService.Instance.QueueSnapshotFromCurrentRoom(); } ClientConfigApplyService.Instance.ApplyPendingVisuals(); } } } [HarmonyPatch(typeof(PropHuntManager), "OnJoinedRoom")] public static class Patch_PropHuntManager_OnJoinedRoom { private static void Postfix(PropHuntManager __instance) { PropHuntFixRuntime.ApplyRoomHuntersToManager(__instance); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { PropHuntFixPlugin.EnsureRuntimeRoot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { ClientConfigApplyService.Instance.QueueSnapshotFromCurrentRoom(); } ClientConfigApplyService.Instance.ApplyPendingVisuals(); } EyeColorRefreshService.ApplyAllVisiblePlayerEyes(); } } [HarmonyPatch(typeof(PropHuntManager), "OnPlayerPropertiesUpdate")] public static class Patch_PropHuntManager_OnPlayerPropertiesUpdate { private static void Postfix() { NameTagPatch.RefreshAllNameTags(); } } [HarmonyPatch(typeof(PropHuntManager), "OnEvent")] public static class Patch_PropHuntManager_OnEvent { private static bool Prefix(PropHuntManager __instance, EventData e) { if (e.Code == 119) { return HandleFixSoundEvent(e); } if (e.Code == 101) { return HandleKillEvent(__instance, e); } if (e.Code == 102) { return HandlePlayerDownEvent(__instance, e); } return true; } private static bool HandleFixSoundEvent(EventData e) { try { if (!(e.CustomData is object[] array) || array.Length < 2) { return false; } string text = array[0] as string; string text2 = array[1] as string; if (text == "PHFIX_SOUND" && !string.IsNullOrEmpty(text2)) { PropHuntAudioUtil.PlayLocalSound(text2); } } catch { } return false; } private static bool HandleKillEvent(PropHuntManager manager, EventData e) { if (!(e.CustomData is object[] array) || array.Length < 3) { return false; } string text = array[0] as string; if (text != "PH1") { return false; } if (!PropHuntFixState.TryToInt(array[1], out var val) || !PropHuntFixState.TryToInt(array[2], out var val2)) { return false; } if (val2 <= 0 || !PropHuntFixState.CurrentHunters.Contains(val)) { return false; } if (PhotonNetwork.LocalPlayer != null && PhotonNetwork.LocalPlayer.ActorNumber == val2) { MethodInfo methodInfo = AccessTools.Method(typeof(PropHuntManager), "KillLocalPlayerClean", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(manager, null); } } return false; } private static bool HandlePlayerDownEvent(PropHuntManager manager, EventData e) { if (!(e.CustomData is object[] array) || array.Length < 2) { return false; } string text = array[0] as string; if (text != "PH1") { return false; } if (!PropHuntFixState.TryToInt(array[1], out var val)) { return false; } PropHuntAudioUtil.PlayLocalSound("player death01"); if (PhotonNetwork.LocalPlayer != null && val == PhotonNetwork.LocalPlayer.ActorNumber) { PlayerAvatar val2 = PropHuntFixRuntime.FindLocalAvatar(); if ((Object)(object)val2 != (Object)null) { PropDisguiseController component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null) { component.ApplyClearLocal(); } } } if (PhotonNetwork.IsMasterClient) { HashSet value = Traverse.Create((object)manager).Field("_deadActors").GetValue>(); value?.Add(val); bool flag = PropHuntFixRuntime.AreAllHuntersDead(value); bool flag2 = PropHuntFixRuntime.AreAllHidersDead(value); if (flag) { Traverse.Create((object)manager).Field("_roundArmed").SetValue((object)false); PropHuntFixRuntime.BroadcastMatchEnd(manager, (PHWinner)2, "All hunters eliminated"); } else if (flag2) { Traverse.Create((object)manager).Field("_roundArmed").SetValue((object)false); PropHuntFixRuntime.BroadcastMatchEnd(manager, (PHWinner)1, "All hiders eliminated"); } } return false; } } [HarmonyPatch(typeof(PropHuntManager), "AllHidersDead")] public static class Patch_PropHuntManager_AllHidersDead { private static bool Prefix(ref bool __result) { HashSet deadActors = PropHuntFixRuntime.GetDeadActors(PropHuntManager.Instance); __result = PropHuntFixRuntime.AreAllHidersDead(deadActors); return false; } } [HarmonyPatch(typeof(PropHuntManager), "OnGUI")] public static class Patch_PropHuntManager_OnGUI_Localized { private static readonly FieldInfo FieldEnding = AccessTools.Field(typeof(PropHuntManager), "_ending"); private static readonly FieldInfo FieldEndUntil = AccessTools.Field(typeof(PropHuntManager), "_endUntil"); private static readonly FieldInfo FieldWhoWon = AccessTools.Field(typeof(PropHuntManager), "_whoWon"); private static readonly FieldInfo FieldFlashMsg = AccessTools.Field(typeof(PropHuntManager), "_flashMsg"); private static readonly FieldInfo FieldFlashMsgUntil = AccessTools.Field(typeof(PropHuntManager), "_flashMsgUntil"); private static readonly FieldInfo FieldCachedPropPhotonViewId = AccessTools.Field(typeof(PropHuntManager), "_cachedPropPhotonViewId"); private static GUIStyle boxStyle; private static GUIStyle labelStyle; private static GUIStyle centerStyle; private static GUIStyle subCenterStyle; private static bool Prefix(PropHuntManager __instance) { //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 //IL_007b: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || SemiFunc.MenuLevel() || (Object)(object)LevelGenerator.Instance == (Object)null || (Object)(object)GameDirector.instance == (Object)null || !PhotonNetwork.InRoom) { return true; } PHRole localRole = GetLocalRole(__instance); if ((int)localRole == 0) { return true; } EnsureStyles(); GUI.depth = 0; bool @bool = GetBool(FieldEnding, __instance); if (!@bool) { DrawStatusBox(__instance, localRole); } DrawFlash(__instance); if (@bool) { DrawEndBanner(__instance); } return false; } catch { return true; } } private static void DrawStatusBox(PropHuntManager manager, PHRole role) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 //IL_00fb: 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_0123: Invalid comparison between Unknown and I4 //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Invalid comparison between Unknown and I4 //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Invalid comparison between Unknown and I4 //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(20f, 20f, 720f, 180f); string text = FixLocalization.Text("PropHunt") + " — " + (((int)role == 1) ? FixLocalization.Text("Hunter") : FixLocalization.Text("Hider")); string text2 = (((int)role == 1) ? (FixLocalization.Text("ScanHelp") + ": -" + manager.MissPenaltyHP + " HP") : (((object)(KeyCode)(ref manager.KeyHiderToggle)).ToString() + ": " + FixLocalization.Text("Disguise") + " | " + ((object)(KeyCode)(ref manager.KeyDisguiseViewToggle)).ToString() + ": View | " + ((object)(KeyCode)(ref manager.KeyLockToggle)).ToString() + ": " + FixLocalization.Text("Locked"))); GUI.Box(val, text + "\n" + text2, boxStyle); float num = ((Rect)(ref val)).yMax + 6f; if ((int)role == 2 && manager.PreHidePhaseActive) { float seconds = Mathf.Max(0f, GetPrivateFloat(manager, "_preHideUntil") - Time.time); GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("HideTime") + ": " + FormatClock(seconds), labelStyle); num += 22f; } if (manager.RoundIsLive) { float seconds2 = Mathf.Max(0f, (float)(GetPrivateDouble(manager, "_roundEndRealtime") - (double)Time.time)); GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("TimeLeft") + ": " + FormatClock(seconds2), labelStyle); num += 22f; } if ((int)role == 1 && manager.IsHunterLocked) { int num2 = Mathf.CeilToInt(Mathf.Max(0f, GetPrivateFloat(manager, "_hunterLockUntil") - Time.time)); GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("HunterLock") + ": " + num2 + FixLocalization.Text("Sec"), labelStyle); num += 22f; } if ((int)role != 2) { return; } string text3 = FixLocalization.Text("LookValuable"); int privateInt = GetPrivateInt(manager, "_cachedPropPhotonViewId"); if (privateInt != 0 && (Object)(object)PhotonView.Find(privateInt) != (Object)null) { text3 = FixLocalization.Text("TargetLocked"); } PlayerAvatar val2 = PropHuntFixRuntime.FindLocalAvatar(); if ((Object)(object)val2 != (Object)null) { PropDisguiseController component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null && component.IsLocked) { text3 = text3 + " [" + FixLocalization.Text("Locked") + "]"; } } GUI.Label(new Rect(((Rect)(ref val)).x + 8f, num, ((Rect)(ref val)).width, 24f), FixLocalization.Text("Disguise") + ": " + text3, labelStyle); } private static void DrawFlash(PropHuntManager manager) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) float privateFloat = GetPrivateFloat(manager, "_flashMsgUntil"); if (!(Time.time >= privateFloat)) { string privateString = GetPrivateString(manager, "_flashMsg"); if (!string.IsNullOrEmpty(privateString)) { GUI.Label(new Rect(30f, 228f, 720f, 28f), FixLocalization.TranslateMessage(privateString), labelStyle); } } } private static void DrawEndBanner(PropHuntManager manager) { //IL_0032: 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_0049: 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_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: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Invalid comparison between Unknown and I4 //IL_00dd: 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) Rect val = default(Rect); ((Rect)(ref val))..ctor(0f, 0f, (float)Screen.width, (float)Screen.height); GUI.color = new Color(0f, 0f, 0f, 0.55f); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; PHWinner winner = GetWinner(manager); string text = (((int)winner == 2) ? FixLocalization.Text("HidersWin") : (((int)winner == 1) ? FixLocalization.Text("HunterWins") : FixLocalization.Text("Draw"))); float privateFloat = GetPrivateFloat(manager, "_endUntil"); string text2 = (PhotonNetwork.IsMasterClient ? Mathf.CeilToInt(Mathf.Max(0f, privateFloat - Time.time)).ToString() : "…"); GUI.Label(new Rect(0f, (float)Screen.height * 0.35f, (float)Screen.width, 80f), text, centerStyle); GUI.Label(new Rect(0f, (float)Screen.height * 0.35f + 68f, (float)Screen.width, 60f), FixLocalization.PickForInternal("Next round starting in", "次のラウンド開始まで", "下一回合开始倒计时", "다음 라운드 시작까지", "До следующего раунда", "Prochain round dans", "Siguiente ronda en", "Nächste Runde in", "Próxima rodada em") + " " + text2, subCenterStyle); } private static void EnsureStyles() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0095: 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_00c2: Expected O, but got Unknown //IL_010f: 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_013c: Expected O, but got Unknown //IL_0191: Unknown result type (might be due to invalid IL or missing references) if (boxStyle == null) { boxStyle = new GUIStyle(GUI.skin.box); boxStyle.alignment = (TextAnchor)0; boxStyle.fontSize = 16; boxStyle.wordWrap = true; boxStyle.normal.textColor = Color.white; } if (labelStyle == null) { labelStyle = new GUIStyle(GUI.skin.label); labelStyle.fontSize = 16; labelStyle.normal.textColor = Color.white; } if (centerStyle == null) { centerStyle = new GUIStyle(GUI.skin.label); centerStyle.alignment = (TextAnchor)4; centerStyle.fontStyle = (FontStyle)1; centerStyle.fontSize = Mathf.RoundToInt(Mathf.Clamp((float)Screen.width * 0.06f, 32f, 72f)); centerStyle.normal.textColor = Color.white; } if (subCenterStyle == null) { subCenterStyle = new GUIStyle(GUI.skin.label); subCenterStyle.alignment = (TextAnchor)4; subCenterStyle.fontSize = Mathf.RoundToInt(Mathf.Clamp((float)Screen.width * 0.03f, 18f, 36f)); subCenterStyle.normal.textColor = new Color(1f, 1f, 1f, 0.9f); } } private static PHRole GetLocalRole(PropHuntManager manager) { //IL_0038: 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_002c: 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) try { object value = Traverse.Create((object)manager).Field("_localRole").GetValue(); if (value is PHRole) { return (PHRole)value; } } catch { } return (PHRole)0; } private static PHWinner GetWinner(PropHuntManager manager) { //IL_0038: 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_002c: 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) try { object value = Traverse.Create((object)manager).Field("_whoWon").GetValue(); if (value is PHWinner) { return (PHWinner)value; } } catch { } return (PHWinner)0; } private static string FormatClock(float seconds) { int num = Mathf.CeilToInt(Mathf.Max(0f, seconds)); return (num / 60).ToString("00") + ":" + (num % 60).ToString("00"); } private static bool GetBool(FieldInfo field, object instance) { try { object obj = ((field != null) ? field.GetValue(instance) : null); return obj is bool && (bool)obj; } catch { return false; } } private static float GetPrivateFloat(PropHuntManager manager, string fieldName) { try { object value = Traverse.Create((object)manager).Field(fieldName).GetValue(); if (value is float result) { return result; } if (value is double) { return (float)(double)value; } } catch { } return 0f; } private static double GetPrivateDouble(PropHuntManager manager, string fieldName) { try { object value = Traverse.Create((object)manager).Field(fieldName).GetValue(); if (value is double result) { return result; } if (value is float) { return (float)value; } } catch { } return 0.0; } private static int GetPrivateInt(PropHuntManager manager, string fieldName) { try { object value = Traverse.Create((object)manager).Field(fieldName).GetValue(); if (value is int) { return (int)value; } } catch { } return 0; } private static string GetPrivateString(PropHuntManager manager, string fieldName) { try { object value = Traverse.Create((object)manager).Field(fieldName).GetValue(); return value as string; } catch { } return string.Empty; } } [HarmonyPatch(typeof(PropHuntManager), "Flash")] public static class Patch_PropHuntManager_Flash_Localized { private static void Prefix(ref string msg) { msg = FixLocalization.TranslateMessage(msg); } } [HarmonyPatch(typeof(PropHuntManager), "Update")] public static class Patch_PropHuntManager_Update_LockAudio { private static void Postfix(PropHuntManager __instance) { HunterUnlockCountdownController.Tick(__instance); } } [HarmonyPatch(typeof(FlashlightController), "Update")] public static class Patch_FlashlightController_Update_DisguiseSuppress { private static void Postfix(FlashlightController __instance) { DisguiseFlashlightSuppressService.SuppressControllerAfterOriginal(__instance); } } [HarmonyPatch(typeof(PropHuntManager), "StartEndBannerLocal")] public static class Patch_PropHuntManager_StartEndBannerLocal { private static void Postfix(PropHuntManager __instance) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown try { FieldInfo fieldInfo = AccessTools.Field(typeof(PropHuntManager), "_endMsg"); if (fieldInfo != null && (Object)(object)__instance != (Object)null) { string message = fieldInfo.GetValue(__instance) as string; fieldInfo.SetValue(__instance, FixLocalization.TranslateMessage(message)); } } catch { } PropHuntAudioUtil.PlayLocalSound("extraction point success"); if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null) { Hashtable val = new Hashtable(); val[(object)"PHFIX_UnlockAt"] = 0.0; val[(object)"PHFIX_UnlockSerial"] = 0; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } HostConfigSyncService.RequestWriteSnapshot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { PropHuntFixPlugin.EnsureRuntimeRoot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { ClientConfigApplyService.Instance.RequestGameplayApplyForNextRound(); } } } } [HarmonyPatch(typeof(PropHuntManager), "SafeAdvanceScene")] public static class Patch_PropHuntManager_SafeAdvanceScene { private static void Prefix() { HostConfigSyncService.RequestWriteSnapshot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { PropHuntFixPlugin.EnsureRuntimeRoot(); if ((Object)(object)ClientConfigApplyService.Instance != (Object)null) { ClientConfigApplyService.Instance.ApplyPendingGameplayIfRequested(); } } } } public class NameTagOriginalPatchDisabler : MonoBehaviour { private float nextTry; private bool done; private void Update() { if (!done && !(Time.unscaledTime < nextTry)) { nextTry = Time.unscaledTime + 1f; done = NameTagPatch.TryDisableOriginalHidePatch(); } } } [HarmonyPatch(typeof(WorldSpaceUIPlayerName), "Update")] public static class NameTagPatch { private static readonly FieldInfo FieldPlayerAvatar = AccessTools.Field(typeof(WorldSpaceUIPlayerName), "playerAvatar"); private static bool triedImmediateUnpatch; public static bool TryDisableOriginalHidePatch() { try { MethodInfo methodInfo = AccessTools.Method(typeof(WorldSpaceUIPlayerName), "Update", (Type[])null, (Type[])null); if (methodInfo == null || PropHuntFixPlugin.Harmony == null) { return false; } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); if (patchInfo != null && patchInfo.Prefixes != null) { for (int i = 0; i < patchInfo.Prefixes.Count; i++) { Patch val = patchInfo.Prefixes[i]; if (val != null && !string.IsNullOrEmpty(val.owner) && !(val.owner == "REPOJP.PropHunt_Fix")) { string text = ((val.PatchMethod != null && val.PatchMethod.DeclaringType != null) ? val.PatchMethod.DeclaringType.Name : string.Empty); if (val.owner == "omni.repo.prophunt" || text.Contains("Patch_HidePlayerNames")) { PropHuntFixPlugin.Harmony.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)1, val.owner); } } } } return true; } catch { return false; } } [HarmonyPriority(800)] private static bool Prefix() { if (!triedImmediateUnpatch) { triedImmediateUnpatch = true; TryDisableOriginalHidePatch(); } return true; } private static void Postfix(WorldSpaceUIPlayerName __instance) { try { if (PhotonNetwork.InRoom) { PropHuntFixPlugin.EnsureRuntimeRoot(); } if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.text == (Object)null)) { PlayerAvatar targetAvatar = GetTargetAvatar(__instance); if (!((Object)(object)targetAvatar == (Object)null)) { ApplyNameTagVisual(__instance, targetAvatar); } } } catch { } } public static void RefreshAllNameTags() { } private static PlayerAvatar GetTargetAvatar(WorldSpaceUIPlayerName instance) { try { if (FieldPlayerAvatar != null) { object? value = FieldPlayerAvatar.GetValue(instance); PlayerAvatar val = (PlayerAvatar)((value is PlayerAvatar) ? value : null); if ((Object)(object)val != (Object)null) { return val; } } if ((Object)(object)instance != (Object)null) { PlayerAvatar componentInParent = ((Component)instance).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } } } catch { } return null; } private static void ApplyNameTagVisual(WorldSpaceUIPlayerName instance, PlayerAvatar targetAvatar) { //IL_00b3: 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_00ba: 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_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null || (Object)(object)instance.text == (Object)null || (Object)(object)targetAvatar == (Object)null || (Object)(object)targetAvatar.photonView == (Object)null || targetAvatar.photonView.Owner == null) { return; } Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer == null) { return; } bool flag = PropHuntFixState.CurrentHunters.Contains(localPlayer.ActorNumber); bool flag2 = PropHuntFixState.CurrentHunters.Contains(targetAvatar.photonView.Owner.ActorNumber); bool flag3 = SemiFunc.MenuLevel(); bool isMasterClient = PhotonNetwork.IsMasterClient; bool targetReady = IsTargetReady(targetAvatar.photonView.Owner); Color color = ((Graphic)instance.text).color; float a = color.a; if (flag3) { ApplyReadyUnderline(instance, targetAvatar, isMasterClient, localPlayer, targetReady); return; } RemoveReadyUnderline(instance); if (!IsRoundNameTagPatchEnabled() || a <= 0.01f) { return; } if (!flag) { if (flag2) { ((Graphic)instance.text).color = new Color(1f, 0.15f, 0.15f, a); } else { ((Graphic)instance.text).color = new Color(1f, 1f, 1f, a); } } else if (flag2) { ((Graphic)instance.text).color = new Color(1f, 0.15f, 0.15f, a); } else { ((Graphic)instance.text).color = new Color(color.r, color.g, color.b, 0f); } } private static bool IsRoundNameTagPatchEnabled() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 try { if (!PhotonNetwork.InRoom || SemiFunc.MenuLevel()) { return false; } if ((Object)(object)GameDirector.instance == (Object)null || (int)GameDirector.instance.currentState != 2) { return false; } return (Object)(object)PropHuntManager.Instance != (Object)null; } catch { return false; } } private static bool IsTargetReady(Player player) { try { if (player == null || player.CustomProperties == null) { return false; } Hashtable customProperties = player.CustomProperties; bool flag = ReadBoolProperty(customProperties, "PHFIX_Ready"); bool flag2 = ReadBoolProperty(customProperties, "PHFIX_HasPropHunt"); bool flag3 = ReadBoolProperty(customProperties, "PHFIX_HasFix"); return flag && flag2 && flag3; } catch { } return false; } private static bool ReadBoolProperty(Hashtable props, string key) { try { if (props == null || !((Dictionary)(object)props).ContainsKey(key)) { return false; } object obj = props[(object)key]; if (obj is bool result) { return result; } if (obj is int) { return (int)obj != 0; } if (obj is string) { return string.Equals((string)obj, "true", StringComparison.OrdinalIgnoreCase); } } catch { } return false; } private static void ApplyReadyUnderline(WorldSpaceUIPlayerName instance, PlayerAvatar targetAvatar, bool isHostView, Player localPlayer, bool targetReady) { try { string text = ((TMP_Text)instance.text).text; if (string.IsNullOrEmpty(text)) { text = targetAvatar.photonView.Owner.NickName; } if (string.IsNullOrEmpty(text)) { text = targetAvatar.photonView.Owner.ActorNumber.ToString(); } text = StripReadyLine(text); if (isHostView && targetAvatar.photonView.Owner.ActorNumber != localPlayer.ActorNumber && !targetReady) { text = text + "\n" + FixLocalization.Text("NotReady") + ""; } ((TMP_Text)instance.text).text = text; } catch { } } private static void RemoveReadyUnderline(WorldSpaceUIPlayerName instance) { try { ((TMP_Text)instance.text).text = StripReadyLine(((TMP_Text)instance.text).text); } catch { } } private static string StripReadyLine(string text) { if (string.IsNullOrEmpty(text)) { return text; } string value = ""; int num = text.IndexOf(value, StringComparison.OrdinalIgnoreCase); if (num < 0) { return text; } int num2 = num; if (num2 > 0 && text[num2 - 1] == '\n') { num2--; } int num3 = text.IndexOf("", num, StringComparison.OrdinalIgnoreCase); if (num3 < 0) { return text.Substring(0, num2); } num3 += "".Length; return text.Remove(num2, num3 - num2); } } internal static class PropHuntFixRuntime { public static void ApplyRoomHuntersToManager(PropHuntManager manager) { Hashtable props = ((PhotonNetwork.CurrentRoom != null) ? ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties : null); ApplyRoomHuntersToManager(manager, props); } public static void ApplyRoomHuntersToManager(PropHuntManager manager, Hashtable props) { //IL_0090: 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_00ca: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)manager == (Object)null) { return; } PropHuntFixState.SyncHuntersFromRoomProperties((props != null) ? props : ((PhotonNetwork.CurrentRoom != null) ? ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties : null)); int num = ((PropHuntFixState.CurrentHunters.Count > 0) ? PropHuntFixState.CurrentHunters.First() : (-1)); Traverse.Create((object)manager).Field("_hunterActor").SetValue((object)num); if (PhotonNetwork.LocalPlayer != null) { PHRole val = (PHRole)(PropHuntFixState.CurrentHunters.Contains(PhotonNetwork.LocalPlayer.ActorNumber) ? 1 : 2); if (props != null && (!((Dictionary)(object)props).ContainsKey("PH_Active") || Convert.ToInt32(props[(object)"PH_Active"]) != 1)) { val = (PHRole)0; } Traverse.Create((object)manager).Field("_localRole").SetValue((object)val); } } public static HashSet GetDeadActors(PropHuntManager manager) { try { if ((Object)(object)manager == (Object)null) { return new HashSet(); } HashSet value = Traverse.Create((object)manager).Field("_deadActors").GetValue>(); return value ?? new HashSet(); } catch { return new HashSet(); } } public static PlayerAvatar FindLocalAvatar() { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return null; } for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++) { PlayerAvatar val = GameDirector.instance.PlayerList[i]; if ((Object)(object)val != (Object)null && (Object)(object)val.photonView != (Object)null && val.photonView.IsMine) { return val; } } return null; } public static bool AreAllHidersDead(HashSet deadActors) { Player[] playerList = PhotonNetwork.PlayerList; foreach (Player val in playerList) { if (val != null && !val.IsInactive && !PropHuntFixState.CurrentHunters.Contains(val.ActorNumber) && (deadActors == null || !deadActors.Contains(val.ActorNumber))) { return false; } } return true; } public static bool AreAllHuntersDead(HashSet deadActors) { if (PropHuntFixState.CurrentHunters.Count == 0) { return false; } foreach (int currentHunter in PropHuntFixState.CurrentHunters) { if (deadActors == null || !deadActors.Contains(currentHunter)) { return false; } } return true; } public static void BroadcastMatchEnd(PropHuntManager manager, PHWinner winner, string reason) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected I4, but got Unknown //IL_0029: 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_0030: 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_003f: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[3] { "PH1", (int)winner, reason ?? string.Empty }; PhotonNetwork.RaiseEvent((byte)103, (object)array, new RaiseEventOptions { Receivers = (ReceiverGroup)1 }, SendOptions.SendReliable); MethodInfo methodInfo = AccessTools.Method(typeof(PropHuntManager), "StartEndBannerLocal", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(manager, new object[2] { winner, reason }); } } } public class MainMenuMusicVolumeService : MonoBehaviour { private static GameObject serviceObject; private float nextApply; public static void EnsureStarted() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown try { if (!((Object)serviceObject != (Object)null)) { serviceObject = new GameObject("REPOJP_PropHuntFix_MainMenuMusicVolume"); ((Object)serviceObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)serviceObject); serviceObject.AddComponent(); } } catch { serviceObject = null; } } private void Update() { if (!(Time.unscaledTime < nextApply)) { nextApply = Time.unscaledTime + 0.25f; ApplyMainMenuMusicVolume(); } } private static void ApplyMainMenuMusicVolume() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown try { float volume = GetVolume(); AudioSource[] array = Object.FindObjectsOfType(true); foreach (AudioSource val in array) { if (!((Object)val == (Object)null) && IsMainMenuSwapSource(val)) { val.volume = volume; } } } catch { } } private static bool IsMainMenuSwapSource(AudioSource source) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown try { string text = ((Object)((Component)source).gameObject).name ?? string.Empty; string text2 = (((Object)source.clip != (Object)null) ? ((Object)source.clip).name : string.Empty); if (text.Equals("MainMenuMusic_Swap", StringComparison.OrdinalIgnoreCase)) { return true; } if (text2.Equals("Constant Music - Main Menu", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } catch { return false; } } private static float GetVolume() { try { if (PropHuntFixPlugin.CfgMainMenuMusicVolumePercent == null) { return 0.5f; } return (float)Mathf.Clamp(PropHuntFixPlugin.CfgMainMenuMusicVolumePercent.Value, 0, 100) / 100f; } catch { return 0.5f; } } } internal static class PropHuntAudioUtil { private static readonly Dictionary ClipCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static GameObject audioObject; private static AudioSource audioSource; public static void EnsureReady() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown try { if (!((Object)audioSource != (Object)null)) { audioObject = new GameObject("REPOJP_PropHuntFix_AudioSource"); ((Object)audioObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)audioObject); audioSource = audioObject.AddComponent(); audioSource.playOnAwake = false; audioSource.loop = false; audioSource.mute = false; audioSource.volume = 1f; audioSource.pitch = 1f; audioSource.spatialBlend = 0f; audioSource.priority = 0; audioSource.dopplerLevel = 0f; audioSource.rolloffMode = (AudioRolloffMode)1; } } catch { audioObject = null; audioSource = null; } } public static void PlayLocalSound(string officialClipName) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown try { if (string.IsNullOrEmpty(officialClipName)) { return; } AudioClip val = FindOfficialClip(officialClipName); if (!((Object)val == (Object)null)) { if ((Object)audioSource == (Object)null) { EnsureReady(); } if (!((Object)audioSource == (Object)null)) { audioSource.PlayOneShot(val, GetVolume(officialClipName)); } } } catch { } } private static float GetVolume(string officialClipName) { try { if (string.Equals(officialClipName, "player death01", StringComparison.OrdinalIgnoreCase)) { return (float)Mathf.Clamp(PropHuntFixPlugin.CfgDeathSoundVolumePercent.Value, 0, 100) / 100f; } if (string.Equals(officialClipName, "extraction point success", StringComparison.OrdinalIgnoreCase)) { return (float)Mathf.Clamp(PropHuntFixPlugin.CfgWinSoundVolumePercent.Value, 0, 100) / 100f; } } catch { } return 0.5f; } private static AudioClip FindOfficialClip(string officialClipName) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown if (ClipCache.TryGetValue(officialClipName, out var value) && (Object)value != (Object)null) { return value; } try { AudioClip[] array = Resources.FindObjectsOfTypeAll(); foreach (AudioClip val in array) { if ((Object)val != (Object)null && ((Object)val).name == officialClipName) { ClipCache[officialClipName] = val; return val; } } } catch { } return null; } } internal static class PropHuntCountdownBeepUtil { private static GameObject audioObject; private static AudioSource audioSource; private static AudioClip shortBeepClip; private static AudioClip longBeepClip; private static void EnsureReady() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown try { if (!((Object)audioSource != (Object)null)) { audioObject = new GameObject("REPOJP_PropHuntFix_CountdownAudioSource"); ((Object)audioObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)audioObject); audioSource = audioObject.AddComponent(); audioSource.playOnAwake = false; audioSource.loop = false; audioSource.mute = false; audioSource.volume = 1f; audioSource.pitch = 1f; audioSource.spatialBlend = 0f; audioSource.priority = 0; audioSource.dopplerLevel = 0f; audioSource.rolloffMode = (AudioRolloffMode)1; } } catch { audioObject = null; audioSource = null; } } public static void PlayShortBeep() { PlayGeneratedBeep(GetShortBeepClip()); } public static void PlayLongBeep() { PlayGeneratedBeep(GetLongBeepClip()); } private static void PlayGeneratedBeep(AudioClip clip) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown try { if (!((Object)clip == (Object)null)) { EnsureReady(); if (!((Object)audioSource == (Object)null)) { audioSource.PlayOneShot(clip, GetVolume()); } } } catch { } } private static float GetVolume() { try { if (PropHuntFixPlugin.CfgCountdownSoundVolumePercent == null) { return 0.5f; } return (float)Mathf.Clamp(PropHuntFixPlugin.CfgCountdownSoundVolumePercent.Value, 0, 100) / 100f; } catch { return 0.5f; } } private static AudioClip GetShortBeepClip() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if ((Object)shortBeepClip == (Object)null) { shortBeepClip = CreateToneClip("REPOJP_PropHuntFix_Countdown_Put", 520f, 0.12f, 44100); } return shortBeepClip; } private static AudioClip GetLongBeepClip() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown if ((Object)longBeepClip == (Object)null) { longBeepClip = CreateToneClip("REPOJP_PropHuntFix_Countdown_Pee", 780f, 0.55f, 44100); } return longBeepClip; } private static AudioClip CreateToneClip(string name, float frequency, float duration, int sampleRate) { int num = Mathf.Max(1, Mathf.CeilToInt((float)sampleRate * duration)); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / (float)sampleRate; float num3 = 1f; if (num2 < 0.01f) { num3 = num2 / 0.01f; } else if (num2 > duration - 0.03f) { num3 = Mathf.Clamp01((duration - num2) / 0.03f); } array[i] = Mathf.Sin(MathF.PI * 2f * frequency * num2) * 0.55f * num3; } AudioClip val = AudioClip.Create(name, num, 1, sampleRate, false); val.SetData(array, 0); return val; } } internal static class HunterUnlockCountdownController { private class CountdownState { public double UnlockAtPhoton; public bool Beep3Played; public bool Beep2Played; public bool Beep1Played; public bool GoPlayed; } private static readonly Dictionary States = new Dictionary(); private static double lastPublishedUnlockAt; private static readonly FieldInfo FieldHunterLockUntil = AccessTools.Field(typeof(PropHuntManager), "_hunterLockUntil"); public static void Tick(PropHuntManager manager) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)manager == (Object)null || !PhotonNetwork.InRoom) { return; } PublishHostUnlockTime(manager); double sharedUnlockPhotonTime = GetSharedUnlockPhotonTime(); if (sharedUnlockPhotonTime <= 0.0) { return; } double num = sharedUnlockPhotonTime - PhotonNetwork.Time; if (!(num < -1.5) && !(num > 10.0)) { SyncLocalHunterLock(manager, num); int instanceID = ((Object)manager).GetInstanceID(); if (!States.TryGetValue(instanceID, out var value)) { value = new CountdownState(); States[instanceID] = value; } if (Math.Abs(value.UnlockAtPhoton - sharedUnlockPhotonTime) > 0.05) { value.UnlockAtPhoton = sharedUnlockPhotonTime; value.Beep3Played = num < 2.8; value.Beep2Played = num < 1.8; value.Beep1Played = num < 0.8; value.GoPlayed = num < -0.1; } if (!value.Beep3Played && num <= 3.0 && num > 2.0) { value.Beep3Played = true; PropHuntCountdownBeepUtil.PlayShortBeep(); } if (!value.Beep2Played && num <= 2.0 && num > 1.0) { value.Beep2Played = true; PropHuntCountdownBeepUtil.PlayShortBeep(); } if (!value.Beep1Played && num <= 1.0 && num > 0.0) { value.Beep1Played = true; PropHuntCountdownBeepUtil.PlayShortBeep(); } if (!value.GoPlayed && num <= 0.0) { value.GoPlayed = true; PropHuntCountdownBeepUtil.PlayLongBeep(); SyncLocalHunterLock(manager, 0.0); } } } catch { } } public static double GetSharedRemainingSeconds() { try { if (!PhotonNetwork.InRoom) { return double.NaN; } double sharedUnlockPhotonTime = GetSharedUnlockPhotonTime(); if (sharedUnlockPhotonTime <= 0.0) { return double.NaN; } return sharedUnlockPhotonTime - PhotonNetwork.Time; } catch { return double.NaN; } } public static void PublishHostUnlockTimeForNewRound(FixConfigSnapshot snapshot) { try { if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null && snapshot != null) { float num = Mathf.Max(0f, snapshot.HunterLockSeconds); if (!(num <= 0f)) { double photonUnlockAt = PhotonNetwork.Time + (double)num; WriteSharedUnlockTime(photonUnlockAt, num, "new-round"); } } } catch { } } private static void PublishHostUnlockTime(PropHuntManager manager) { try { if (!PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null || (Object)(object)manager == (Object)null) { return; } double sharedUnlockPhotonTime = GetSharedUnlockPhotonTime(); if (!(sharedUnlockPhotonTime > PhotonNetwork.Time - 0.25) || !(sharedUnlockPhotonTime < PhotonNetwork.Time + 120.0)) { float hunterUnlockTimeLocal = GetHunterUnlockTimeLocal(manager); float num = 0f; if (hunterUnlockTimeLocal > Time.time) { num = hunterUnlockTimeLocal - Time.time; } else if (manager.PreHidePhaseActive && !manager.RoundIsLive) { num = Mathf.Clamp(Mathf.Max(0f, manager.HunterLockSeconds), 0f, Mathf.Max(0.1f, manager.PreHideSeconds)); } if (!(num <= 0f) && !(num > 120f)) { double photonUnlockAt = PhotonNetwork.Time + (double)num; WriteSharedUnlockTime(photonUnlockAt, num, "fallback"); } } } catch { } } private static void WriteSharedUnlockTime(double photonUnlockAt, float remaining, string reason) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown try { if (PhotonNetwork.CurrentRoom != null && !(Math.Abs(lastPublishedUnlockAt - photonUnlockAt) < 0.1)) { lastPublishedUnlockAt = photonUnlockAt; Hashtable val = new Hashtable(); val[(object)"PHFIX_UnlockAt"] = photonUnlockAt; val[(object)"PHFIX_UnlockSerial"] = Mathf.RoundToInt((float)(photonUnlockAt * 10.0)); PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); if (PropHuntFixPlugin.CfgWriteHunterSelectionLog != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] Sync unlock time(" + reason + "): " + photonUnlockAt.ToString("0.000") + " remaining=" + remaining.ToString("0.000"))); } } } catch { } } private static double GetSharedUnlockPhotonTime() { try { if (PhotonNetwork.CurrentRoom == null) { return 0.0; } Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (customProperties == null || !((Dictionary)(object)customProperties).ContainsKey("PHFIX_UnlockAt")) { return 0.0; } object obj = customProperties[(object)"PHFIX_UnlockAt"]; if (obj is double result) { return result; } if (obj is float) { return (float)obj; } if (obj is int) { return (int)obj; } if (obj is long) { return (long)obj; } if (obj is string && double.TryParse((string)obj, out var result2)) { return result2; } } catch { } return 0.0; } private static void SyncLocalHunterLock(PropHuntManager manager, double remaining) { try { if (!(FieldHunterLockUntil == null)) { float num = ((remaining > 0.0) ? (Time.time + (float)remaining) : 0f); FieldHunterLockUntil.SetValue(manager, num); } } catch { } } private static float GetHunterUnlockTimeLocal(PropHuntManager manager) { try { float privateFloat = GetPrivateFloat(manager, "_hunterLockUntil"); if (privateFloat > Time.time) { return privateFloat; } bool privateBool = GetPrivateBool(manager, "_preHideArmed"); float privateFloat2 = GetPrivateFloat(manager, "_preHideUntil"); if (!privateBool || privateFloat2 <= 0f) { return 0f; } float num = Mathf.Max(1f, manager.PreHideSeconds); float num2 = Mathf.Max(0f, manager.HunterLockSeconds); if (num2 <= 0f) { return 0f; } float num3 = privateFloat2 - num; float num4 = num3 + num2; if (num4 <= Time.time - 1f) { return 0f; } return num4; } catch { return 0f; } } private static bool GetPrivateBool(PropHuntManager manager, string fieldName) { FieldInfo fieldInfo = AccessTools.Field(typeof(PropHuntManager), fieldName); if (fieldInfo == null) { return false; } object value = fieldInfo.GetValue(manager); return value is bool && (bool)value; } private static float GetPrivateFloat(PropHuntManager manager, string fieldName) { FieldInfo fieldInfo = AccessTools.Field(typeof(PropHuntManager), fieldName); if (fieldInfo == null) { return 0f; } if (!(fieldInfo.GetValue(manager) is float result)) { return 0f; } return result; } } public class PropHuntFixHudService : MonoBehaviour { private GUIStyle centerStyle; private GUIStyle smallStyle; private void OnGUI() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) try { if (!PhotonNetwork.InRoom || SemiFunc.MenuLevel()) { return; } PropHuntManager instance = PropHuntManager.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)GameDirector.instance == (Object)null || (int)GameDirector.instance.currentState != 2) { return; } EnsureStyles(); if (instance.PreHidePhaseActive && !instance.RoundIsLive) { if (PhotonNetwork.CurrentRoom != null) { PropHuntFixState.SyncHuntersFromRoomProperties(((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties); } string text = FixLocalization.Text("Hunters") + ": " + Mathf.Max(0, PropHuntFixState.CurrentHunters.Count); GUI.Label(new Rect(0f, 72f, (float)Screen.width, 40f), text, smallStyle); } double sharedRemainingSeconds = HunterUnlockCountdownController.GetSharedRemainingSeconds(); bool flag = false; if (!double.IsNaN(sharedRemainingSeconds) && sharedRemainingSeconds <= 3.2 && sharedRemainingSeconds >= -0.7) { string text2 = ((sharedRemainingSeconds > 2.0) ? "3" : ((sharedRemainingSeconds > 1.0) ? "2" : ((!(sharedRemainingSeconds > 0.0)) ? FixLocalization.Text("Start") : "1"))); flag = true; GUI.Label(new Rect(0f, (float)Screen.height * 0.38f, (float)Screen.width, 96f), text2, centerStyle); } if (!flag && instance.RoundIsLive) { string roundTimeWarning = GetRoundTimeWarning(instance); if (!string.IsNullOrEmpty(roundTimeWarning)) { GUI.Label(new Rect(0f, (float)Screen.height * 0.38f, (float)Screen.width, 96f), roundTimeWarning, centerStyle); } } } catch { } } private string GetRoundTimeWarning(PropHuntManager manager) { try { double value = Traverse.Create((object)manager).Field("_roundEndRealtime").GetValue(); int num = Mathf.CeilToInt(Mathf.Max(0f, (float)(value - (double)Time.time))); int[] array = new int[5] { 300, 240, 180, 120, 60 }; for (int i = 0; i < array.Length; i++) { if (num == array[i]) { return num / 60 + FixLocalization.Text("Min"); } } if (num == 30 || num == 20 || (num >= 1 && num <= 10)) { return num + FixLocalization.Text("Sec"); } } catch { } return string.Empty; } private void EnsureStyles() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0075: 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_00a4: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) if (centerStyle == null) { centerStyle = new GUIStyle(GUI.skin.label); centerStyle.alignment = (TextAnchor)4; centerStyle.fontStyle = (FontStyle)1; centerStyle.fontSize = Mathf.RoundToInt(Mathf.Clamp((float)Screen.width * 0.07f, 40f, 96f)); centerStyle.normal.textColor = Color.white; } if (smallStyle == null) { smallStyle = new GUIStyle(GUI.skin.label); smallStyle.alignment = (TextAnchor)4; smallStyle.fontStyle = (FontStyle)1; smallStyle.fontSize = Mathf.RoundToInt(Mathf.Clamp((float)Screen.width * 0.025f, 18f, 34f)); smallStyle.normal.textColor = Color.white; } } } public class LocalHunterUnlockAudioService : MonoBehaviour { private float nextCheck; private void Update() { if (!(Time.unscaledTime < nextCheck)) { nextCheck = Time.unscaledTime + 0.02f; CheckAllManagers(); } } private void CheckAllManagers() { try { if (!PhotonNetwork.InRoom) { return; } PropHuntManager[] array = Object.FindObjectsOfType(true); if (array != null) { for (int i = 0; i < array.Length; i++) { HunterUnlockCountdownController.Tick(array[i]); } } } catch { } } } [HarmonyPatch(typeof(LevelGenerator), "TileGeneration")] public static class Patch_LevelGenerator_TileGeneration_RoomCount { private static readonly FieldInfo FieldModuleAmount = AccessTools.Field(typeof(LevelGenerator), "ModuleAmount"); private static void Prefix(LevelGenerator __instance) { try { if (!((Object)(object)__instance == (Object)null) && !(FieldModuleAmount == null) && SemiFunc.IsMasterClientOrSingleplayer() && !SemiFunc.MenuLevel()) { int num = ((PropHuntFixPlugin.CfgRoundRoomCount != null) ? Mathf.Clamp(PropHuntFixPlugin.CfgRoundRoomCount.Value, 1, 20) : 2); int num2 = Mathf.Clamp(num, 1, 20); FieldModuleAmount.SetValue(__instance, num2); if (PropHuntFixPlugin.CfgWriteHunterSelectionLog != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { PropHuntFixPlugin.Log.LogInfo((object)("[PropHunt_Fix] LevelGenerator ModuleAmount overridden to " + num2 + ". ConfigRoomCount=" + num + ".")); } } } catch (Exception ex) { if (PropHuntFixPlugin.Log != null) { PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Room count override failed: " + ex.Message)); } } } private static int GetEffectiveHunterCount() { try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { PropHuntFixState.SyncHuntersFromRoomProperties(((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties); if (PropHuntFixState.CurrentHunters.Count > 0) { return PropHuntFixState.CurrentHunters.Count; } } } catch { } try { if (PropHuntFixState.PendingSnapshot != null) { return Mathf.Max(1, PropHuntFixState.PendingSnapshot.HunterCount); } } catch { } try { return Mathf.Max(1, PropHuntFixPlugin.CfgHunterCount.Value); } catch { return 1; } } } internal static class PropHuntRoomDifficultyOverride { public const float ForcedDifficultyMultiplier = 1f; public static bool ShouldForceMaxRoomDifficulty() { try { if (!PhotonNetwork.InRoom) { return false; } if (SemiFunc.MenuLevel()) { return false; } if ((Object)(object)LevelGenerator.Instance == (Object)null) { return false; } if (PhotonNetwork.CurrentRoom != null) { Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (customProperties != null && ((Dictionary)(object)customProperties).ContainsKey("PH_Active")) { object obj = customProperties[(object)"PH_Active"]; if (obj != null && Convert.ToInt32(obj) == 1) { return true; } } } if ((Object)(object)PropHuntManager.Instance != (Object)null) { return true; } } catch { } return false; } } [HarmonyPatch(typeof(SemiFunc), "RunGetDifficultyMultiplier1")] public static class Patch_SemiFunc_RunGetDifficultyMultiplier1_PropHuntRooms { private static void Postfix(ref float __result) { if (PropHuntRoomDifficultyOverride.ShouldForceMaxRoomDifficulty()) { __result = 1f; } } } [HarmonyPatch(typeof(SemiFunc), "RunGetDifficultyMultiplier2")] public static class Patch_SemiFunc_RunGetDifficultyMultiplier2_PropHuntRooms { private static void Postfix(ref float __result) { if (PropHuntRoomDifficultyOverride.ShouldForceMaxRoomDifficulty()) { __result = 1f; } } } [HarmonyPatch(typeof(SemiFunc), "RunGetDifficultyMultiplier3")] public static class Patch_SemiFunc_RunGetDifficultyMultiplier3_PropHuntRooms { private static void Postfix(ref float __result) { if (PropHuntRoomDifficultyOverride.ShouldForceMaxRoomDifficulty()) { __result = 1f; } } } public class MapPlayerCountUpgradeService : MonoBehaviourPunCallbacks { private static readonly FieldInfo FieldSteamId = AccessTools.Field(typeof(PlayerAvatar), "steamID"); private static readonly FieldInfo FieldUpgradeMapPlayerCount = AccessTools.Field(typeof(PlayerAvatar), "upgradeMapPlayerCount"); private float nextApplyTime; private void Update() { if (!(Time.unscaledTime < nextApplyTime)) { nextApplyTime = Time.unscaledTime + 1f; ApplyToAllPlayers(); } } public override void OnJoinedRoom() { nextApplyTime = 0f; ApplyToAllPlayers(); } public override void OnPlayerEnteredRoom(Player newPlayer) { nextApplyTime = 0f; ApplyToAllPlayers(); } public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { nextApplyTime = 0f; ApplyToAllPlayers(); } private static void ApplyToAllPlayers() { try { if (PropHuntFixPlugin.CfgGiveMapPlayerCountUpgrade == null || !PropHuntFixPlugin.CfgGiveMapPlayerCountUpgrade.Value || !PhotonNetwork.InRoom || SemiFunc.MenuLevel() || (Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null || (Object)(object)StatsManager.instance == (Object)null) { return; } for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++) { PlayerAvatar val = GameDirector.instance.PlayerList[i]; if ((Object)(object)val == (Object)null) { continue; } string text = ((FieldSteamId != null) ? (FieldSteamId.GetValue(val) as string) : null); if (string.IsNullOrEmpty(text)) { continue; } if (!StatsManager.instance.playerUpgradeMapPlayerCount.ContainsKey(text)) { StatsManager.instance.playerUpgradeMapPlayerCount.Add(text, 0); } if (StatsManager.instance.playerUpgradeMapPlayerCount[text] < 1) { StatsManager.instance.playerUpgradeMapPlayerCount[text] = 1; } if (FieldUpgradeMapPlayerCount != null) { object value = FieldUpgradeMapPlayerCount.GetValue(val); int num = ((value is int) ? ((int)value) : 0); if (num < 1) { FieldUpgradeMapPlayerCount.SetValue(val, 1); } } } } catch (Exception ex) { if (PropHuntFixPlugin.Log != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Map player count upgrade apply failed: " + ex.Message)); } } } } public class DisguiseFlashlightSuppressService : MonoBehaviour { private static readonly string[] FlashNameParts = new string[5] { "flashlight", "flash_light", "headlamp", "head_lamp", "torch" }; private static readonly FieldInfo FieldHideFlashlight = AccessTools.Field(typeof(FlashlightController), "hideFlashlight"); private static readonly FieldInfo FieldActive = AccessTools.Field(typeof(FlashlightController), "active"); private static readonly FieldInfo FieldCurrentState = AccessTools.Field(typeof(FlashlightController), "currentState"); private static readonly FieldInfo FieldHiddenScale = AccessTools.Field(typeof(FlashlightController), "hiddenScale"); private static readonly HashSet DisabledControllerObjects = new HashSet(); private static readonly HashSet DisabledNamedObjects = new HashSet(); private void Update() { SuppressAllDisguisedFlashlights(); } private void LateUpdate() { SuppressAllDisguisedFlashlights(); } public static void SuppressControllerAfterOriginal(FlashlightController controller) { try { if (!((Object)(object)controller == (Object)null) && !((Object)(object)controller.PlayerAvatar == (Object)null)) { PropDisguiseController component = ((Component)controller.PlayerAvatar).GetComponent(); if (!((Object)(object)component == (Object)null) && component.IsDisguised) { ForceControllerOff(controller, deactivateGameObject: true); } } } catch { } } private static void SuppressAllDisguisedFlashlights() { try { if (!PhotonNetwork.InRoom || (Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return; } for (int i = 0; i < GameDirector.instance.PlayerList.Count; i++) { PlayerAvatar val = GameDirector.instance.PlayerList[i]; if (!((Object)(object)val == (Object)null)) { PropDisguiseController component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && component.IsDisguised) { SuppressFlashlightObjects(((Component)val).transform); } else { RestoreSuppressedFlashlightObjects(((Component)val).transform); } } } } catch { } } private static void SuppressFlashlightObjects(Transform root) { if ((Object)(object)root == (Object)null) { return; } FlashlightController[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ForceControllerOff(componentsInChildren[i], deactivateGameObject: true); } Transform[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren2) { if (!((Object)(object)val == (Object)null) && IsFlashlightName(((Object)val).name)) { ForceLightsAndMeshesOff(((Component)val).gameObject); if (((Component)val).gameObject.activeSelf) { DisabledNamedObjects.Add(((Object)((Component)val).gameObject).GetInstanceID()); ((Component)val).gameObject.SetActive(false); } } } } private static void RestoreSuppressedFlashlightObjects(Transform root) { if ((Object)(object)root == (Object)null) { return; } FlashlightController[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (FlashlightController val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } GameObject gameObject = ((Component)val).gameObject; int instanceID = ((Object)gameObject).GetInstanceID(); if (DisabledControllerObjects.Contains(instanceID)) { DisabledControllerObjects.Remove(instanceID); if (!gameObject.activeSelf) { gameObject.SetActive(true); } } if (FieldHideFlashlight != null) { FieldHideFlashlight.SetValue(val, false); } } Transform[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren2) { if ((Object)(object)val2 == (Object)null) { continue; } GameObject gameObject2 = ((Component)val2).gameObject; int instanceID2 = ((Object)gameObject2).GetInstanceID(); if (DisabledNamedObjects.Contains(instanceID2)) { DisabledNamedObjects.Remove(instanceID2); if (!gameObject2.activeSelf) { gameObject2.SetActive(true); } } } } private static void ForceControllerOff(FlashlightController controller, bool deactivateGameObject) { if ((Object)(object)controller == (Object)null) { return; } if (FieldHideFlashlight != null) { FieldHideFlashlight.SetValue(controller, true); } if (FieldActive != null) { FieldActive.SetValue(controller, false); } if (FieldCurrentState != null) { try { object value = Enum.Parse(FieldCurrentState.FieldType, "Hidden"); FieldCurrentState.SetValue(controller, value); } catch { } } if (FieldHiddenScale != null) { FieldHiddenScale.SetValue(controller, 0f); } controller.LightActive = false; if ((Object)(object)controller.mesh != (Object)null) { ((Renderer)controller.mesh).enabled = false; } if ((Object)(object)controller.spotlight != (Object)null) { ((Behaviour)controller.spotlight).enabled = false; controller.spotlight.intensity = 0f; } if ((Object)(object)controller.halo != (Object)null) { controller.halo.enabled = false; } ForceLightsAndMeshesOff(((Component)controller).gameObject); if (deactivateGameObject && ((Component)controller).gameObject.activeSelf) { DisabledControllerObjects.Add(((Object)((Component)controller).gameObject).GetInstanceID()); ((Component)controller).gameObject.SetActive(false); } } private static void ForceLightsAndMeshesOff(GameObject root) { if ((Object)(object)root == (Object)null) { return; } Light[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { ((Behaviour)componentsInChildren[i]).enabled = false; componentsInChildren[i].intensity = 0f; } } MeshRenderer[] componentsInChildren2 = root.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { if ((Object)(object)componentsInChildren2[j] != (Object)null) { ((Renderer)componentsInChildren2[j]).enabled = false; } } } private static bool IsFlashlightName(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLowerInvariant(); for (int i = 0; i < FlashNameParts.Length; i++) { if (text.Contains(FlashNameParts[i])) { return true; } } return false; } } public class LockPhaseRevealAndStaminaService : MonoBehaviour { private static readonly FieldInfo FieldValuableDiscovered = AccessTools.Field(typeof(ValuableObject), "discovered"); private static readonly FieldInfo FieldValuablePhotonView = AccessTools.Field(typeof(ValuableObject), "photonView"); private static readonly FieldInfo FieldHunterLockUntil = AccessTools.Field(typeof(PropHuntManager), "_hunterLockUntil"); private float nextValuableApplyTime; private float nextRoomApplyTime; private void Update() { ApplyLockPhaseFeatures(); } private void FixedUpdate() { ApplyInfiniteStaminaIfNeeded(); } private void ApplyLockPhaseFeatures() { if (IsLockPhaseActive()) { ApplyInfiniteStaminaIfNeeded(); if (Time.unscaledTime >= nextRoomApplyTime) { nextRoomApplyTime = Time.unscaledTime + 0.5f; ExploreAllRoomsLocal(); } if (PhotonNetwork.IsMasterClient && Time.unscaledTime >= nextValuableApplyTime) { nextValuableApplyTime = Time.unscaledTime + 0.5f; DiscoverAllValuablesHost(); } } } private static bool IsLockPhaseActive() { try { if (!PhotonNetwork.InRoom || SemiFunc.MenuLevel()) { return false; } PropHuntManager instance = PropHuntManager.Instance; if ((Object)(object)instance == (Object)null) { return false; } if (instance.IsHunterLocked) { return true; } if (FieldHunterLockUntil != null) { object value = FieldHunterLockUntil.GetValue(instance); if (value is float && (float)value > Time.time) { return true; } } if (PhotonNetwork.CurrentRoom != null) { Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (customProperties != null && ((Dictionary)(object)customProperties).ContainsKey("PHFIX_UnlockAt")) { object value2 = customProperties[(object)"PHFIX_UnlockAt"]; if (TryGetDouble(value2, out var result) && result > PhotonNetwork.Time) { return true; } } } } catch { } return false; } private static bool IsLocalHider() { try { if (PhotonNetwork.LocalPlayer == null) { return false; } return !PropHuntFixState.CurrentHunters.Contains(PhotonNetwork.LocalPlayer.ActorNumber); } catch { return false; } } private static void ApplyInfiniteStaminaIfNeeded() { try { if (IsLockPhaseActive() && IsLocalHider() && !((Object)(object)PlayerController.instance == (Object)null)) { PlayerController.instance.EnergyCurrent = PlayerController.instance.EnergyStart; } } catch { } } private static void DiscoverAllValuablesHost() { try { if ((Object)(object)ValuableDirector.instance == (Object)null || ValuableDirector.instance.valuableList == null) { return; } for (int i = 0; i < ValuableDirector.instance.valuableList.Count; i++) { ValuableObject val = ValuableDirector.instance.valuableList[i]; if (!((Object)(object)val == (Object)null) && !IsValuableDiscovered(val)) { PhotonView val2 = (PhotonView)((FieldValuablePhotonView != null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)((Component)val).GetComponent())); if ((Object)(object)val2 != (Object)null) { val2.RPC("DiscoverRPC", (RpcTarget)0, Array.Empty()); } else { val.Discover((State)0); } } } } catch (Exception ex) { if (PropHuntFixPlugin.Log != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Discover all valuables failed: " + ex.Message)); } } } private static bool IsValuableDiscovered(ValuableObject valuable) { try { if (FieldValuableDiscovered == null) { return false; } object value = FieldValuableDiscovered.GetValue(valuable); return value is bool && (bool)value; } catch { return false; } } private static void ExploreAllRoomsLocal() { try { RoomVolume[] array = Object.FindObjectsOfType(); foreach (RoomVolume val in array) { if (!((Object)(object)val == (Object)null) && !val.Truck && !val.Extraction) { val.SetExplored(); } } } catch (Exception ex) { if (PropHuntFixPlugin.Log != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Explore all rooms failed: " + ex.Message)); } } } private static bool TryGetDouble(object value, out double result) { result = 0.0; if (value is double) { result = (double)value; return true; } if (value is float) { result = (float)value; return true; } if (value is int) { result = (int)value; return true; } if (value is long) { result = (long)value; return true; } if (value is string) { return double.TryParse((string)value, out result); } return false; } } public class PostMatchVoiceAllHearService : MonoBehaviour { private static readonly FieldInfo FieldVoicePlayerAvatar = AccessTools.Field(typeof(PlayerVoiceChat), "playerAvatar"); private static readonly FieldInfo FieldEnding = AccessTools.Field(typeof(PropHuntManager), "_ending"); private bool wasForced; private float nextApplyTime; private void Update() { if (IsPostMatchActive()) { if (Time.unscaledTime >= nextApplyTime) { nextApplyTime = Time.unscaledTime + 0.25f; ApplyVoiceMixer(allHear: true); } wasForced = true; } else if (wasForced) { wasForced = false; ApplyVoiceMixer(allHear: false); } } private static bool IsPostMatchActive() { try { if (!PhotonNetwork.InRoom || SemiFunc.MenuLevel()) { return false; } PropHuntManager instance = PropHuntManager.Instance; if ((Object)(object)instance == (Object)null || FieldEnding == null) { return false; } object value = FieldEnding.GetValue(instance); return value is bool && (bool)value; } catch { return false; } } private static PlayerAvatar GetVoicePlayerAvatar(PlayerVoiceChat voiceChat) { try { if ((Object)(object)voiceChat == (Object)null || FieldVoicePlayerAvatar == null) { return null; } object? value = FieldVoicePlayerAvatar.GetValue(voiceChat); return (PlayerAvatar)((value is PlayerAvatar) ? value : null); } catch { return null; } } private static void ApplyVoiceMixer(bool allHear) { try { if ((Object)(object)RunManager.instance == (Object)null || RunManager.instance.voiceChats == null) { return; } for (int i = 0; i < RunManager.instance.voiceChats.Count; i++) { PlayerVoiceChat val = RunManager.instance.voiceChats[i]; if (!((Object)(object)val == (Object)null)) { if (allHear) { val.ToggleMixer(true, false); val.SpatialDisable(0.5f); } else if ((Object)(object)GetVoicePlayerAvatar(val) != (Object)null && !SemiFunc.MenuLevel()) { val.ToggleMixer(false, false); } } } } catch (Exception ex) { if (PropHuntFixPlugin.Log != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog != null && PropHuntFixPlugin.CfgWriteHunterSelectionLog.Value) { PropHuntFixPlugin.Log.LogWarning((object)("[PropHunt_Fix] Post match voice override failed: " + ex.Message)); } } } } }