Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PropHunt Fix v1.0.1
PropHunt_Fix.dll
Decompiled 3 hours ago
The result has been truncated due to the large size, download it to view full contents!
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<int> CfgHunterCount; internal static ConfigEntry<int> CfgRoundRoomCount; internal static ConfigEntry<bool> CfgGiveMapPlayerCountUpgrade; internal static ConfigEntry<bool> CfgRefillHuntersWhenHunterLeaves; internal static ConfigEntry<bool> CfgEnableHunterAllyNameHighlight; internal static ConfigEntry<bool> CfgWriteHunterSelectionLog; internal static ConfigEntry<float> CfgEyeRefreshInterval; internal static ConfigEntry<int> CfgDeathSoundVolumePercent; internal static ConfigEntry<int> CfgWinSoundVolumePercent; internal static ConfigEntry<int> CfgCountdownSoundVolumePercent; internal static ConfigEntry<int> CfgMainMenuMusicVolumePercent; internal static ConfigEntry<FixLanguage> 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<int>("Gameplay", "HunterCount", 1, new ConfigDescription("Hunter count per round. ラウンドごとの鬼人数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); CfgRoundRoomCount = ((BaseUnityPlugin)this).Config.Bind<int>("MapGeneration", "RoundRoomCount", 2, new ConfigDescription("Generated room count for PropHunt rounds. PropHuntラウンドの生成部屋数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); CfgGiveMapPlayerCountUpgrade = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "GiveMapPlayerCountUpgrade", true, "Give the map player count upgrade to all players in PropHunt. PropHunt中に全員へマッププレイヤーカウントアップグレードを配布"); CfgRefillHuntersWhenHunterLeaves = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "RefillHuntersWhenHunterLeaves", true, "Refill hunter slots if a hunter leaves mid-round. 鬼離脱時の補充"); CfgEnableHunterAllyNameHighlight = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "EnableHunterAllyNameHighlight", true, "Show allied hunter name tags in red for hunters. 鬼同士の赤ネームタグ表示"); CfgEyeRefreshInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "EyeRefreshInterval", 1f, "Eye color refresh interval in seconds. 目色再適用間隔(秒)"); CfgDeathSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "DeathSoundVolumePercent", 20, new ConfigDescription("Death sound volume percent. 死亡音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); CfgWinSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "WinSoundVolumePercent", 20, new ConfigDescription("Win result sound volume percent. 勝利結果音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); CfgCountdownSoundVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "CountdownSoundVolumePercent", 30, new ConfigDescription("Hunter unlock countdown beep volume percent. 鬼ロック解除カウントダウン音の音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); CfgMainMenuMusicVolumePercent = ((BaseUnityPlugin)this).Config.Bind<int>("Audio", "MainMenuMusicVolumePercent", 20, new ConfigDescription("Main menu custom music volume percent. メインメニュー独自BGM音量(%)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); CfgLanguage = ((BaseUnityPlugin)this).Config.Bind<FixLanguage>("Localization", "Language", FixLanguage.English, "Display language. AutoTranslatorConfig.ini Language is used automatically when supported. 表示言語。対応言語の場合はAutoTranslatorConfig.iniのLanguageを自動使用"); CfgWriteHunterSelectionLog = ((BaseUnityPlugin)this).Config.Bind<bool>("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<HostConfigSyncService>(); val.AddComponent<ClientConfigApplyService>(); val.AddComponent<EyeColorRefreshService>(); val.AddComponent<ReadySyncService>(); val.AddComponent<NameTagOriginalPatchDisabler>(); val.AddComponent<LocalHunterUnlockAudioService>(); val.AddComponent<PropHuntFixHudService>(); val.AddComponent<MapPlayerCountUpgradeService>(); val.AddComponent<DisguiseFlashlightSuppressService>(); val.AddComponent<PostMatchVoiceAllHearService>(); 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, object>)(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, object>)(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, object>)(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<int> CurrentHunters = new HashSet<int>(); public static readonly Dictionary<string, int> TotalHunterCountsByUserKey = new Dictionary<string, int>(); public static readonly Queue<List<string>> RecentHunterHistory = new Queue<List<string>>(); 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<string> 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<Player> selectedPlayers) { if (selectedPlayers == null || selectedPlayers.Count == 0) { return; } List<string> list = new List<string>(); 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<Player> 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<Player> SelectHunters(List<Player> activePlayers, FixConfigSnapshot snapshot, ICollection<int> excludeActorNumbers) { List<Player> list = new List<Player>(); 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<Player> list2 = new List<Player>(); 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<Player> activePlayers, List<Player> selected, FixConfigSnapshot snapshot) { try { List<string> list = new List<string>(); for (int i = 0; i < activePlayers.Count; i++) { Player val = activePlayers[i]; string identityKey = GetIdentityKey(val); list.Add(val.ActorNumber + "=" + GetTotalHunterCount(identityKey)); } List<string> list2 = new List<string>(); 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, object>)(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<HostConfigSyncService>(); 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, object>)(object)customProperties).ContainsKey("PH_Active")) { FixConfigSnapshot snapshot = PropHuntFixState.PendingSnapshot ?? FixConfigSnapshot.FromLocalConfig(); List<Player> list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive).ToList(); if (list.Count > 1) { List<Player> 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<Player> 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<Player> list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive).ToList(); if (list.Count <= 1) { return false; } HashSet<int> excludeActorNumbers = new HashSet<int>(PropHuntFixState.CurrentHunters); List<Player> 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<Player> list = PhotonNetwork.PlayerList.Where((Player p) => p != null && !p.IsInactive && !PropHuntFixState.CurrentHunters.Contains(p.ActorNumber)).ToList(); if (list.Count > 0) { List<Player> 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<Player> 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<PropDisguiseController>(); if ((Object)(object)component != (Object)null) { component.ApplyClearLocal(); } } } if (PhotonNetwork.IsMasterClient) { HashSet<int> value = Traverse.Create((object)manager).Field("_deadActors").GetValue<HashSet<int>>(); 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<int> 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<PropDisguiseController>(); 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(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<PlayerAvatar>(); 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, object>)(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<color=#ff0000><u>" + FixLocalization.Text("NotReady") + "</u></color>"; } ((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 = "<color=#ff0000><u>"; 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("</u></color>", num, StringComparison.OrdinalIgnoreCase); if (num3 < 0) { return text.Substring(0, num2); } num3 += "</u></color>".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, object>)(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<int> GetDeadActors(PropHuntManager manager) { try { if ((Object)(object)manager == (Object)null) { return new HashSet<int>(); } HashSet<int> value = Traverse.Create((object)manager).Field("_deadActors").GetValue<HashSet<int>>(); return value ?? new HashSet<int>(); } catch { return new HashSet<int>(); } } 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<int> 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<int> 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<MainMenuMusicVolumeService>(); } } 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<AudioSource>(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<string, AudioClip> ClipCache = new Dictionary<string, AudioClip>(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>(); 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<AudioClip>(); 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>(); 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<int, CountdownState> States = new Dictionary<int, CountdownState>(); 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,