Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of MultiplayerPVP v1.0.6
MultiplayerPVP.IL2CPP.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using DooDesch.FullHouse; using HarmonyLib; using Il2Cpp; using Il2CppFishNet; using Il2CppFishNet.Managing; using Il2CppFishNet.Object; using Il2CppFishySteamworks; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.Cartel; using Il2CppScheduleOne.Combat; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Doors; using Il2CppScheduleOne.Economy; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.FX; using Il2CppScheduleOne.GameTime; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Law; using Il2CppScheduleOne.Map; using Il2CppScheduleOne.Money; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.NPCs.Behaviour; using Il2CppScheduleOne.Networking; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.PlayerScripts.Health; using Il2CppScheduleOne.Police; using Il2CppScheduleOne.Product; using Il2CppScheduleOne.Product.Packaging; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.UI; using Il2CppScheduleOne.UI.Multiplayer; using Il2CppScheduleOne.Vision; using Il2CppSteamworks; using Il2CppSystem.Collections.Generic; using Il2CppTMPro; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using MultiplayerPVP; using MultiplayerPVP.Addons; using MultiplayerPVP.Compat; using MultiplayerPVP.Config; using MultiplayerPVP.Core; using MultiplayerPVP.Modes; using MultiplayerPVP.Net; using MultiplayerPVP.UI; using SteamNetworkLib; using SteamNetworkLib.Events; using SteamNetworkLib.Models; using SteamNetworkLib.Sync; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("MultiplayerPVP")] [assembly: AssemblyDescription("Schedule I MelonLoader Mod")] [assembly: AssemblyCompany("Virtunerd")] [assembly: AssemblyProduct("MultiplayerPVP")] [assembly: AssemblyCopyright("Copyright (c) Virtunerd 2026")] [assembly: ComVisible(false)] [assembly: Guid("f83b02a6-396b-4b34-b8b7-3d0117d8d960")] [assembly: MelonAdditionalDependencies(new string[] { "SteamNetworkLib" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: MelonInfo(typeof(MultiplayerPVPMod), "MultiplayerPVP", "1.0.6", "Virtunerd", null)] [assembly: MelonGame(null, "Schedule I")] [assembly: AssemblyFileVersion("1.0.6")] [assembly: AssemblyInformationalVersion("1.0.6")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.6.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DooDesch.FullHouse { internal static class Lobbies { internal const int DefaultCapacity = 32; private const int HardMax = 250; private const int SafeMax = 32; private const string GuardName = "___DooDesch_FullHouse___"; private static bool _installed; private static MelonPreferences_Entry<int> _capEntry; private static int _hostCap; internal static int Capacity { get { int num = ((_capEntry != null) ? _capEntry.Value : 32); if (num < 2) { num = 2; } if (num > 250) { num = 250; } return num; } } internal static int EffectiveCap => Math.Min(250, Math.Max(Capacity, _hostCap)); internal static ulong CurrentLobbyId { get { try { SteamLobbyService val = Service(); return (val != null) ? val._lobbyID : 0; } catch { return 0uL; } } } internal static int SeatCount { get { try { SteamLobbyService val = Service(); return ((Il2CppArrayBase<CSteamID>)(object)((val != null) ? val._players : null))?.Length ?? 0; } catch { return 0; } } } internal static void Install() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown if (_installed) { return; } _installed = true; try { if ((Object)(object)GameObject.Find("___DooDesch_FullHouse___") != (Object)null) { MelonLogger.Msg("[FullHouse] another copy is already active - standing down."); return; } GameObject val = new GameObject("___DooDesch_FullHouse___"); Object.DontDestroyOnLoad((Object)(object)val); ((Object)val).hideFlags = (HideFlags)61; } catch { } try { MelonPreferences_Category val2 = MelonPreferences.CreateCategory("FullHouse", "FullHouse"); _capEntry = val2.CreateEntry<int>("Capacity", 32, "Max lobby players", "Maximum co-op players FullHouse seats (2-250). Values above 32 are unsupported and may destabilise the game.", false, false, (ValueValidator)null, (string)null); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] preference registration failed: " + ex.Message); } if (Capacity > 32) { MelonLogger.Warning($"[FullHouse] capacity {Capacity} exceeds the tested maximum of {32} - expect instability."); } try { Harmony h = new Harmony("com.doodesch.fullhouse"); Patch(h, typeof(SteamLobbyService), "Initialize", null, "Service_Initialize_Postfix"); Patch(h, typeof(SteamLobbyService), "UpdateLobbyMembers", "Service_UpdateLobbyMembers_Prefix"); Patch(h, typeof(SteamLobbyService), "CreateLobby", "Service_CreateLobby_Prefix"); Patch(h, typeof(SteamLobbyService), "OnLobbyCreated", null, "Service_OnLobbyCreated_Postfix"); Patch(h, typeof(SteamLobbyService), "OnLobbyEntered", null, "Service_OnLobbyEntered_Postfix"); Patch(h, typeof(SteamLobbyService), "OpenInviteUI", "Service_OpenInviteUI_Prefix"); Patch(h, typeof(SteamLobbyService), "LeaveLobby", null, "Service_LeaveLobby_Postfix"); Patch(h, typeof(LobbyInterface), "Start", null, "LobbyInterface_Start_Postfix"); Patch(h, typeof(LobbyInterface), "UpdateUI", null, "LobbyInterface_UpdateUI_Postfix"); Patch(h, typeof(LobbyInterface), "UpdateButtons", null, "LobbyInterface_UpdateButtons_Postfix"); MelonLogger.Msg($"[FullHouse] active - lobby cap raised to {Capacity}."); } catch (Exception ex2) { MelonLogger.Error("[FullHouse] patch install failed: " + ex2); } } private static void Patch(Harmony h, Type type, string method, string prefix = null, string postfix = null) { MethodInfo methodInfo = AccessTools.Method(type, method, (Type[])null, (Type[])null); if (methodInfo == null) { MelonLogger.Warning($"[FullHouse] {type.Name}.{method} not found - skipped."); } else { h.Patch((MethodBase)methodInfo, Hook(prefix), Hook(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static HarmonyMethod Hook(string name) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return (name == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Lobbies).GetMethod(name, AccessTools.all)); } private static SteamLobbyService Service() { try { Lobby instance = Singleton<Lobby>.Instance; ILobbyService val = ((instance != null) ? instance._lobbyService : null); if (val == null) { return null; } return ((Il2CppObjectBase)val).TryCast<SteamLobbyService>(); } catch { return null; } } private static void EnsurePlayers(SteamLobbyService svc, int target) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) try { if (svc == null || target < 2) { return; } Il2CppStructArray<CSteamID> players = svc._players; int num = ((Il2CppArrayBase<CSteamID>)(object)players)?.Length ?? 0; if (num < target) { Il2CppStructArray<CSteamID> val = new Il2CppStructArray<CSteamID>((long)target); for (int i = 0; i < num; i++) { ((Il2CppArrayBase<CSteamID>)(object)val)[i] = ((Il2CppArrayBase<CSteamID>)(object)players)[i]; } svc._players = val; } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] resizing the lobby seat array failed: " + ex.Message); } } private static void Service_Initialize_Postfix(SteamLobbyService __instance) { EnsurePlayers(__instance, EffectiveCap); RaiseTransportCap(); } private static void RaiseTransportCap() { try { FishySteamworks val = Object.FindObjectOfType<FishySteamworks>(); if (!((Object)(object)val == (Object)null)) { int effectiveCap = EffectiveCap; ushort maximumClients = val._maximumClients; if (maximumClients < effectiveCap) { val._maximumClients = (ushort)effectiveCap; MelonLogger.Msg($"[FullHouse] transport client limit {maximumClients} -> {effectiveCap}."); } } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] raising the transport client limit failed: " + ex.Message); } } private static void Service_UpdateLobbyMembers_Prefix(SteamLobbyService __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) try { int val = 0; try { ulong num = ((__instance != null) ? __instance._lobbyID : 0); if (num != 0) { val = SteamMatchmaking.GetNumLobbyMembers(new CSteamID(num)); } } catch { } EnsurePlayers(__instance, Math.Max(EffectiveCap, val)); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] seat guard failed: " + ex.Message); } } private static void Service_CreateLobby_Prefix(ref int maxPlayers) { int effectiveCap = EffectiveCap; if (maxPlayers < effectiveCap) { maxPlayers = effectiveCap; } } private static void Service_OnLobbyCreated_Postfix(LobbyCreated_t result) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) try { if ((int)result.m_eResult == 1) { RaiseTransportCap(); CSteamID val = (CSteamID)result.m_ulSteamIDLobby; int effectiveCap = EffectiveCap; if (SteamMatchmaking.GetLobbyMemberLimit(val) < effectiveCap) { SteamMatchmaking.SetLobbyMemberLimit(val, effectiveCap); } int lobbyMemberLimit = SteamMatchmaking.GetLobbyMemberLimit(val); if (lobbyMemberLimit < effectiveCap) { MelonLogger.Warning($"[FullHouse] Steam kept the lobby member limit at {lobbyMemberLimit} (requested {effectiveCap}); advertising {lobbyMemberLimit}."); } SteamMatchmaking.SetLobbyData(val, "max_players", lobbyMemberLimit.ToString()); SteamMatchmaking.SetLobbyData(val, "num_slots", lobbyMemberLimit.ToString()); } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] OnLobbyCreated failed: " + ex.Message); } } private static void Service_OnLobbyEntered_Postfix(SteamLobbyService __instance, LobbyEnter_t result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) try { if (__instance == null || __instance._lobbyID == 0) { return; } CSteamID val = (CSteamID)result.m_ulSteamIDLobby; int result2 = 0; int.TryParse(SteamMatchmaking.GetLobbyData(val, "max_players"), out result2); int lobbyMemberLimit = SteamMatchmaking.GetLobbyMemberLimit(val); if (lobbyMemberLimit > 0 && result2 > lobbyMemberLimit) { result2 = lobbyMemberLimit; } if (result2 > _hostCap) { if (result2 > 32) { MelonLogger.Warning($"[FullHouse] this lobby seats {result2}, past the tested maximum of {32} - expect instability."); } _hostCap = result2; int effectiveCap = EffectiveCap; EnsurePlayers(__instance, effectiveCap); EnsureSlots(Singleton<LobbyInterface>.Instance, effectiveCap); MelonLogger.Msg($"[FullHouse] adopted host lobby cap {effectiveCap}."); } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] host-cap sync failed: " + ex.Message); } } private static void Service_LeaveLobby_Postfix() { if (_hostCap != 0) { _hostCap = 0; MelonLogger.Msg($"[FullHouse] left the lobby - back to the local cap of {Capacity}."); } } private static bool Service_OpenInviteUI_Prefix(SteamLobbyService __instance) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) try { if (__instance == null) { return true; } if (__instance._lobbyID == 0) { __instance.CreateLobby(EffectiveCap); return false; } CSteamID val = default(CSteamID); ((CSteamID)(ref val))..ctor(__instance._lobbyID); int num = EffectiveCap; int lobbyMemberLimit = SteamMatchmaking.GetLobbyMemberLimit(val); if (lobbyMemberLimit > 0 && lobbyMemberLimit < num) { num = lobbyMemberLimit; } if (SteamMatchmaking.GetNumLobbyMembers(val) >= num) { MelonLogger.Warning($"[FullHouse] lobby already at max capacity ({num})."); return false; } SteamFriends.ActivateGameOverlayInviteDialog(val); return false; } catch (Exception ex) { MelonLogger.Warning("[FullHouse] invite gate failed, falling back to vanilla: " + ex.Message); return true; } } private static void LobbyInterface_Start_Postfix(LobbyInterface __instance) { try { MelonCoroutines.Start(BuildUi(__instance)); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] UI coroutine start failed: " + ex.Message); } } private static void LobbyInterface_UpdateUI_Postfix(LobbyInterface __instance) { try { Lobby instance = Singleton<Lobby>.Instance; int num = (((Object)(object)instance != (Object)null) ? instance.PlayerCount : 0); if ((Object)(object)((__instance != null) ? __instance.LobbyTitle : null) != (Object)null) { ((TMP_Text)__instance.LobbyTitle).text = "Lobby (" + num + "/" + EffectiveCap + ")"; } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] title sync failed: " + ex.Message); } } [HarmonyPriority(600)] private static void LobbyInterface_UpdateButtons_Postfix(LobbyInterface __instance) { try { Lobby instance = Singleton<Lobby>.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)((__instance != null) ? __instance.InviteButton : null) == (Object)null)) { ((Component)__instance.InviteButton).gameObject.SetActive(instance.IsHost && instance.PlayerCount < EffectiveCap); } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] invite button sync failed: " + ex.Message); } } private static IEnumerator BuildUi(LobbyInterface ui) { while ((Object)(object)Singleton<Lobby>.Instance == (Object)null) { yield return null; } bool steamReady = true; try { steamReady = SteamManager.Initialized; } catch { } if (steamReady) { EnsurePlayers(Service(), EffectiveCap); EnsureSlots(ui, EffectiveCap); } } private static void EnsureSlots(LobbyInterface ui, int target) { if ((Object)(object)ui == (Object)null) { return; } try { Il2CppReferenceArray<RectTransform> playerSlots = ui.PlayerSlots; if (playerSlots == null || ((Il2CppArrayBase<RectTransform>)(object)playerSlots).Length == 0) { MelonLogger.Warning("[FullHouse] lobby PlayerSlots not found."); return; } int length = ((Il2CppArrayBase<RectTransform>)(object)playerSlots).Length; if (length >= target) { RefreshPlayers(ui); return; } RectTransform val = ((Il2CppArrayBase<RectTransform>)(object)playerSlots)[length - 1]; Transform parent = ((Transform)val).parent; RectTransform[] array = (RectTransform[])(object)new RectTransform[target]; for (int i = 0; i < length; i++) { array[i] = ((Il2CppArrayBase<RectTransform>)(object)playerSlots)[i]; } for (int j = length; j < target; j++) { GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent, false); ((Object)val2).name = ((Object)((Component)val).gameObject).name + " (" + j + ")"; array[j] = val2.GetComponent<RectTransform>(); } ui.PlayerSlots = Il2CppReferenceArray<RectTransform>.op_Implicit(array); RefreshPlayers(ui); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] building lobby UI failed: " + ex.Message); } } private static void RefreshPlayers(LobbyInterface ui) { try { ui.UpdatePlayers(); } catch { } } } } namespace MultiplayerPVP { internal static class ImguiCompat { private static GUIStyle _style; internal static void DrawTexture(Rect position, Texture2D image) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Blit(position, image); } internal static void DrawTexture(Rect position, Texture2D image, ScaleMode scaleMode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) Blit(Fit(position, image, scaleMode), image); } private static Rect Fit(Rect position, Texture2D image, ScaleMode scaleMode) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)image == (Object)null || (int)scaleMode == 0) { return position; } float num = ((Texture)image).width; float num2 = ((Texture)image).height; if (num <= 0f || num2 <= 0f) { return position; } float num3 = (((int)scaleMode == 2) ? Mathf.Min(((Rect)(ref position)).width / num, ((Rect)(ref position)).height / num2) : Mathf.Max(((Rect)(ref position)).width / num, ((Rect)(ref position)).height / num2)); float num4 = num * num3; float num5 = num2 * num3; return new Rect(((Rect)(ref position)).x + (((Rect)(ref position)).width - num4) * 0.5f, ((Rect)(ref position)).y + (((Rect)(ref position)).height - num5) * 0.5f, num4, num5); } private static void Blit(Rect position, Texture2D image) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown if ((Object)(object)image == (Object)null) { return; } Event current = Event.current; if (current != null && (int)current.type == 7) { if (_style == null) { _style = new GUIStyle(); } _style.normal.background = image; Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = Color.white; _style.Draw(position, false, false, false, false); GUI.backgroundColor = backgroundColor; } } } public class MultiplayerPVPMod : MelonMod { private MatchController _controller; private PvpHud _hud; private PvpNet _net; internal static MultiplayerPVPMod Instance { get; private set; } internal MatchController Controller => _controller; internal PvpNet Net => _net; public override void OnInitializeMelon() { Instance = this; Lobbies.Install(); PvpConfig.Load(); _net = new PvpNet(); _net.Init(); _net.OnSighting += SightingRelay.OnReceived; _controller = new MatchController(_net); _hud = new PvpHud(); PvpAddonManager.Init(_net); RiotChaos.Init(); MelonLogger.Msg($"[MultiplayerPVP] v{((MelonBase)this).Info.Version} ready. Press {PvpConfig.PanelKey.Value} in-game to open the host panel."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { try { RiotChaos.OnSceneLoaded(); } catch { } try { _net?.Init(); _controller?.Cleanup(); _hud?.Reset(); SightingRelay.Reset(); ViewLock.Release(); } catch (Exception ex) { MelonLogger.Warning("OnSceneWasLoaded: " + ex.Message); } try { PvpAddonManager.SceneLoaded(buildIndex, sceneName); } catch (Exception ex2) { MelonLogger.Warning("OnSceneWasLoaded(addons): " + ex2.Message); } } public override void OnDeinitializeMelon() { try { RiotChaos.Deinit(); } catch { } try { PvpAddonManager.Deinit(); } catch { } try { ViewLock.Release(); _controller?.Cleanup(); _net?.Dispose(); } catch (Exception ex) { MelonLogger.Warning("OnDeinitializeMelon: " + ex.Message); } } public override void OnUpdate() { if (_controller == null) { return; } try { if (Input.GetKeyDown((KeyCode)PvpConfig.PanelKey.Value)) { if (_controller.Phase == MatchPhase.Idle) { _hud.PanelOpen = !_hud.PanelOpen; } else if (_controller.Phase == MatchPhase.Active && !_controller.IsRemote) { _hud.EndPromptOpen = !_hud.EndPromptOpen; } } if (_controller.Phase != MatchPhase.Active) { _hud.EndPromptOpen = false; } try { Player local = Player.Local; if ((Object)(object)local != (Object)null) { _net?.SetLocalIdentity(local.PlayerCode); } } catch { } _net?.Tick(); _controller.Tick(Time.deltaTime); PvpAddonManager.Tick(Time.deltaTime, _controller.Phase, _controller.ModeType, _controller.Day); RiotChaos.Tick(Time.deltaTime, _controller); UnlimitedAmmo.Tick(_controller); DoubleJump.Tick(_controller); bool locked = _hud.PanelOpen || _hud.EndPromptOpen || (_controller.Phase == MatchPhase.EndOfDay && !_controller.IsRemote); ViewLock.Set(locked); } catch (Exception ex) { MelonLogger.Warning("OnUpdate: " + ex.Message); } } public override void OnGUI() { if (_hud == null) { return; } try { _hud.Draw(_controller); } catch (Exception ex) { MelonLogger.Warning("OnGUI: " + ex.Message); } try { PvpAddonManager.DrawGui(); } catch (Exception ex2) { MelonLogger.Warning("OnGUI(addons): " + ex2.Message); } } } } namespace MultiplayerPVP.UI { internal class PvpHud { private struct DispRow { public int ColorIdx; public string Text; public int Kills; public int Downs; public int Arrests; public int BagsCap; public int BagsLost; public int WpnLost; public int WpnWon; public int PlayerIndex; public string Days; } internal bool PanelOpen; internal bool EndPromptOpen; private static Texture2D _white; private readonly List<WorldMarker> _markers = new List<WorldMarker>(); private Camera _cam; private int _camRevalidate; private int _hoverMode = -1; private PvpMatchToggle _hoverToggle; private readonly List<DispRow> _rows = new List<DispRow>(); private static Texture2D White { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_white == (Object)null) { _white = new Texture2D(1, 1); _white.SetPixel(0, 0, Color.white); _white.Apply(); } return _white; } } private static string FormatDays(string dotted) { return string.IsNullOrEmpty(dotted) ? "" : dotted.Replace(".", ", "); } internal void Reset() { _cam = null; _camRevalidate = 0; _markers.Clear(); PanelOpen = false; EndPromptOpen = false; } internal void Draw(MatchController mc) { //IL_0147: Unknown result type (might be due to invalid IL or missing references) if (mc == null) { return; } Safe(delegate { DrawBanner(mc); }); Safe(delegate { DrawLocalBanner(mc); }); switch (mc.Phase) { case MatchPhase.Countdown: case MatchPhase.Active: { bool flag = true; Safe(delegate { DrawCountdown(mc); }); Safe(delegate { DrawScoreboard(mc, 220f); }); Safe(delegate { DrawMarkers(mc); }); if (mc.IsRemote) { Safe(delegate { DrawClientModeCard(mc); }); } break; } case MatchPhase.EndOfDay: Safe(delegate { DrawEndOfDayMenu(mc); }); break; case MatchPhase.Idle: if (PanelOpen) { Safe(delegate { DrawHostPanel(mc); }); } break; } if (EndPromptOpen && mc.Phase == MatchPhase.Active && !mc.IsRemote) { Safe(delegate { DrawEndMatchPrompt(mc); }); } GUI.color = Color.white; } private static void Safe(Action draw) { try { draw(); } catch (Exception ex) { MelonLogger.Warning("HUD draw: " + ex.Message); } } private void DrawBanner(MatchController mc) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (mc.Announcer.HasBanner) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 40, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, (float)Screen.height * 0.14f, (float)Screen.width, 60f); GUI.color = Color.black; GUI.Label(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), mc.Announcer.Banner, val); GUI.color = new Color(1f, 0.85f, 0.2f); GUI.Label(val2, mc.Announcer.Banner, val); GUI.color = Color.white; } } private void DrawLocalBanner(MatchController mc) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (mc.Announcer.HasLocalBanner) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 26, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, (float)Screen.height * 0.21f, (float)Screen.width, 44f); GUI.color = Color.black; GUI.Label(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), mc.Announcer.LocalBanner, val); GUI.color = mc.Announcer.LocalBannerColor; GUI.Label(val2, mc.Announcer.LocalBanner, val); GUI.color = Color.white; } } private void DrawCountdown(MatchController mc) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) string text; if (mc.Phase == MatchPhase.Countdown) { text = "Starting…"; } else { int num = Mathf.Max(0, Mathf.CeilToInt(mc.RemainingSeconds)); text = $"{GameModeInfo.Title(mc.ModeType)} · Day {mc.Day} · {num / 60:0}:{num % 60:00}"; } GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 20, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor((float)Screen.width * 0.5f - 220f, 70f, 440f, 28f); GUI.color = new Color(0f, 0f, 0f, 0.55f); ImguiCompat.DrawTexture(val2, White); GUI.color = Color.white; GUI.Label(val2, text, val); } private void DrawLoadoutCard(Rect anchor) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) List<string> list = StartingLoadout.Buttons(); float num = 210f; float num2 = Mathf.Max(((Rect)(ref anchor)).height, 64f + (float)list.Count * 24f + 60f); Rect position = default(Rect); ((Rect)(ref position))..ctor(((Rect)(ref anchor)).x - num - 10f, ((Rect)(ref anchor)).y, num, num2); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1 }; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 11, wordWrap = true }; GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 8f, num - 20f, 20f), "STARTING LOADOUT", val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 28f, num - 20f, 30f), "Every player gets the checked items at round start.", val2); float num3 = ((Rect)(ref position)).y + 62f; for (int i = 0; i < list.Count; i++) { string id = list[i]; bool flag = StartingLoadout.IsChecked(id); bool flag2 = GUI.Toggle(new Rect(((Rect)(ref position)).x + 12f, num3, num - 24f, 22f), flag, " " + StartingLoadout.LabelOf(id)); if (flag2 != flag) { StartingLoadout.SetChecked(id, flag2); } num3 += 24f; } num3 += 6f; GUI.color = new Color(1f, 1f, 1f, 0.15f); ImguiCompat.DrawTexture(new Rect(((Rect)(ref position)).x + 10f, num3, num - 20f, 1f), White); GUI.color = Color.white; num3 += 6f; bool flag3 = UnlimitedAmmo.Checked; bool flag4 = GUI.Toggle(new Rect(((Rect)(ref position)).x + 12f, num3, num - 24f, 22f), flag3, " unlimited ammo (this round)"); if (flag4 != flag3) { UnlimitedAmmo.SetChecked(flag4); } num3 += 24f; bool flag5 = DoubleJump.Checked; bool flag6 = GUI.Toggle(new Rect(((Rect)(ref position)).x + 12f, num3, num - 24f, 22f), flag5, " double jump (this round)"); if (flag6 != flag5) { DoubleJump.SetChecked(flag6); } } private void DrawModeInfoCard(Rect anchor) { //IL_003c: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) Rect position = default(Rect); ((Rect)(ref position))..ctor(((Rect)(ref anchor)).xMax + 10f, ((Rect)(ref anchor)).y, 240f, ((Rect)(ref anchor)).height); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, wordWrap = true }; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 12, wordWrap = true }; if (_hoverToggle != null) { GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 10f, 220f, 44f), _hoverToggle.Label + " (modifier)", val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 48f, 220f, ((Rect)(ref position)).height - 58f), _hoverToggle.Description, val2); } else if (_hoverMode >= 0) { GameModeType hoverMode = (GameModeType)_hoverMode; GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 10f, 220f, 44f), GameModeInfo.Title(hoverMode), val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 48f, 220f, ((Rect)(ref position)).height - 58f), GameModeInfo.Description(hoverMode), val2); } else { GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 10f, 220f, ((Rect)(ref position)).height - 20f), "Hover a mode button to see what it does.", val2); } } private void DrawClientModeCard(MatchController mc) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) Rect position = default(Rect); ((Rect)(ref position))..ctor(12f, 70f, 290f, 116f); GUI.color = new Color(0f, 0f, 0f, 0.6f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, wordWrap = true }; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 12, wordWrap = true }; GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 8f, 270f, 22f), GameModeInfo.Title(mc.ModeType), val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 32f, 270f, 76f), GameModeInfo.Description(mc.ModeType), val2); } private void BuildRows(MatchController mc) { _rows.Clear(); if (mc.IsRemote ? (mc.RemoteTeamRows.Count > 0) : mc.IsTeamScoredMode) { if (mc.IsRemote) { for (int i = 0; i < mc.RemoteTeamRows.Count; i++) { SnapTeamRow snapTeamRow = mc.RemoteTeamRows[i]; _rows.Add(new DispRow { ColorIdx = snapTeamRow.Team, Text = snapTeamRow.Name + " — " + snapTeamRow.Score, Kills = snapTeamRow.Kills, Downs = snapTeamRow.Downs, Arrests = snapTeamRow.Arrests, BagsCap = snapTeamRow.BagsCaptured, BagsLost = snapTeamRow.BagsLost, WpnLost = snapTeamRow.WeaponsLost, WpnWon = snapTeamRow.WeaponsWon, PlayerIndex = -1 }); } return; } int activeTeamCount = mc.ActiveTeamCount; List<PvpPlayer> players = mc.Registry.Players; for (int j = 0; j < activeTeamCount; j++) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; for (int k = 0; k < players.Count; k++) { PvpPlayer pvpPlayer = players[k]; if (pvpPlayer.Team == j) { num += pvpPlayer.Kills; num2 += pvpPlayer.Downs; num3 += pvpPlayer.Arrests; num4 += pvpPlayer.BagsCaptured; num5 += pvpPlayer.BagsLost; num6 += pvpPlayer.WeaponsLost; num7 += pvpPlayer.WeaponsWon; } } string text = ""; try { if (mc.CurrentMode != null) { text = mc.CurrentMode.TeamScoreText(mc.Context, j); } } catch { } _rows.Add(new DispRow { ColorIdx = j, Text = mc.Registry.TeamLabel(j) + " — " + text, Kills = num, Downs = num2, Arrests = num3, BagsCap = num4, BagsLost = num5, WpnLost = num6, WpnWon = num7, PlayerIndex = -1 }); } return; } if (mc.IsRemote) { for (int l = 0; l < mc.RemoteRows.Count; l++) { SnapRow snapRow = mc.RemoteRows[l]; _rows.Add(new DispRow { ColorIdx = snapRow.Index, Text = snapRow.Name + " — " + snapRow.Score, Kills = snapRow.Kills, Downs = snapRow.Downs, Arrests = snapRow.Arrests, BagsCap = snapRow.BagsCaptured, BagsLost = snapRow.BagsLost, WpnLost = snapRow.WeaponsLost, WpnWon = snapRow.WeaponsWon, PlayerIndex = snapRow.Index, Days = FormatDays(snapRow.History) }); } return; } List<PvpPlayer> players2 = mc.Registry.Players; for (int m = 0; m < players2.Count; m++) { PvpPlayer pvpPlayer2 = players2[m]; string text2 = ""; string text3 = pvpPlayer2.Name; try { if (mc.CurrentMode != null) { text2 = mc.CurrentMode.ScoreText(pvpPlayer2); text3 = mc.CurrentMode.DisplayName(pvpPlayer2); } } catch { } string days = ""; List<int> list = mc.HistoryOf(pvpPlayer2); if (list != null && list.Count >= 2) { days = string.Join(", ", list); } _rows.Add(new DispRow { ColorIdx = pvpPlayer2.Index, Text = text3 + " — " + text2, Kills = pvpPlayer2.Kills, Downs = pvpPlayer2.Downs, Arrests = pvpPlayer2.Arrests, BagsCap = pvpPlayer2.BagsCaptured, BagsLost = pvpPlayer2.BagsLost, WpnLost = pvpPlayer2.WeaponsLost, WpnWon = pvpPlayer2.WeaponsWon, PlayerIndex = pvpPlayer2.Index, Days = days }); } } private void DrawScoreboard(MatchController mc, float width) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) if (!mc.IsRemote && mc.CurrentMode == null) { return; } BuildRows(mc); int count = _rows.Count; if (count != 0) { float num = 26 + count * 22 + 8; Rect position = default(Rect); ((Rect)(ref position))..ctor((float)Screen.width - width - 12f, 50f, width, num); GUI.color = new Color(0f, 0f, 0f, 0.55f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 14, fontStyle = (FontStyle)1 }; GUI.Label(new Rect(((Rect)(ref position)).x + 8f, ((Rect)(ref position)).y + 4f, width - 16f, 20f), "SCOREBOARD", val); GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 13 }; for (int i = 0; i < count; i++) { float num2 = ((Rect)(ref position)).y + 26f + (float)(i * 22); DispRow dispRow = _rows[i]; GUI.color = PvpColors.For(dispRow.ColorIdx); ImguiCompat.DrawTexture(new Rect(((Rect)(ref position)).x + 8f, num2 + 4f, 10f, 10f), White); GUI.color = Color.white; GUI.Label(new Rect(((Rect)(ref position)).x + 24f, num2, width - 32f, 20f), dispRow.Text, val2); } } } private void DrawMarkers(MatchController mc) { //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) if (_camRevalidate-- <= 0 || (Object)(object)_cam == (Object)null) { _cam = Camera.main; _camRevalidate = 30; } if ((Object)(object)_cam == (Object)null) { return; } _markers.Clear(); if (mc.IsRemote) { List<SnapMarker> remoteMarkers = mc.RemoteMarkers; for (int i = 0; i < remoteMarkers.Count; i++) { _markers.Add(new WorldMarker(remoteMarkers[i].Pos, remoteMarkers[i].Color, remoteMarkers[i].Label, remoteMarkers[i].Team)); } } else { if (!(mc.CurrentMode is IWorldMarkers worldMarkers)) { return; } try { worldMarkers.CollectMarkers(mc.Context, mc.Registry.Local, _markers); } catch { return; } } if (_markers.Count == 0) { return; } int num = mc.LocalTeam(); GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 12, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; for (int j = 0; j < _markers.Count; j++) { WorldMarker worldMarker = _markers[j]; if (worldMarker.Team < 0 || worldMarker.Team == num) { Vector3 val2; try { val2 = _cam.WorldToScreenPoint(worldMarker.Pos); } catch { continue; } if (!(val2.z <= 0f)) { float x = val2.x; float num2 = (float)Screen.height - val2.y; GUI.color = worldMarker.Color; ImguiCompat.DrawTexture(new Rect(x - 2f, num2 - 80f, 4f, 80f), White); ImguiCompat.DrawTexture(new Rect(x - 7f, num2 - 7f, 14f, 14f), White); GUI.color = Color.black; GUI.Label(new Rect(x - 99f, num2 - 104f, 200f, 18f), worldMarker.Label, val); GUI.color = worldMarker.Color; GUI.Label(new Rect(x - 100f, num2 - 105f, 200f, 18f), worldMarker.Label, val); } } } GUI.color = Color.white; } private void DrawEndOfDayMenu(MatchController mc) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown //IL_0183: 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_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_05b4: Unknown result type (might be due to invalid IL or missing references) //IL_05b9: Unknown result type (might be due to invalid IL or missing references) //IL_05c2: Unknown result type (might be due to invalid IL or missing references) //IL_05cc: Expected O, but got Unknown //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Expected O, but got Unknown //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_059e: Unknown result type (might be due to invalid IL or missing references) //IL_065b: Unknown result type (might be due to invalid IL or missing references) //IL_0686: Unknown result type (might be due to invalid IL or missing references) //IL_0693: Unknown result type (might be due to invalid IL or missing references) //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_05e8: Unknown result type (might be due to invalid IL or missing references) //IL_0610: Unknown result type (might be due to invalid IL or missing references) //IL_0622: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_06df: Unknown result type (might be due to invalid IL or missing references) //IL_0742: Unknown result type (might be due to invalid IL or missing references) BuildRows(mc); int count = _rows.Count; float num = ModeGridHeight(); float num2 = Mathf.Max(0f, num - 104f); float num3 = 560f; float num4 = Mathf.Clamp(78f + (float)count * 46f + 200f + num2, 470f + num2, (float)(Screen.height - 40)); Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width * 0.5f - num3 / 2f, (float)Screen.height * 0.5f - num4 / 2f, num3, num4); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(val, White); GUI.color = Color.white; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 24, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 12f, num3, 32f), $"END OF DAY {mc.Day}", val2); GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = 15, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 46f, num3, 22f), mc.DayResult ?? "", val3); GUIStyle val4 = new GUIStyle(GUI.skin.label) { fontSize = 14 }; GUIStyle val5 = new GUIStyle(GUI.skin.label) { fontSize = 12 }; float num5 = ((Rect)(ref val)).y + 78f; int num6 = Mathf.Max(1, Mathf.FloorToInt((num4 - 268f - num2) / 46f)); if (count > num6) { num6 = Mathf.Max(1, num6 - 1); } int num7 = Mathf.Min(count, num6); for (int i = 0; i < num7; i++) { DispRow dispRow = _rows[i]; string text = dispRow.Text; if (!string.IsNullOrEmpty(dispRow.Days)) { text = text + " (days: " + dispRow.Days + ")"; } float num8 = num5 + (float)i * 46f; GUI.color = PvpColors.For(dispRow.ColorIdx); ImguiCompat.DrawTexture(new Rect(((Rect)(ref val)).x + 30f, num8 + 4f, 10f, 10f), White); GUI.color = Color.white; GUI.Label(new Rect(((Rect)(ref val)).x + 48f, num8, num3 - 80f, 20f), $"{i + 1}. {text}", val4); string text2 = mc.ModeType switch { GameModeType.StealTheBags => $"Bags captured {dispRow.BagsCap} · Bags lost {dispRow.BagsLost}", GameModeType.Teams => $"Kills {dispRow.Kills} · Downs {dispRow.Downs} · Weapons won {dispRow.WpnWon} · Weapons lost {dispRow.WpnLost}", _ => $"Kills {dispRow.Kills} · Downs {dispRow.Downs} · Cuffs {dispRow.Arrests}", }; GUI.color = new Color(0.78f, 0.82f, 0.9f); GUI.Label(new Rect(((Rect)(ref val)).x + 48f, num8 + 22f, num3 - 80f, 18f), text2, val5); GUI.color = Color.white; } if (count > num7) { GUIStyle val6 = new GUIStyle(GUI.skin.label) { fontSize = 12, fontStyle = (FontStyle)2 }; GUI.color = new Color(0.7f, 0.75f, 0.85f); GUI.Label(new Rect(((Rect)(ref val)).x + 48f, num5 + (float)num7 * 46f, num3 - 80f, 18f), $"+ {count - num7} more…", val6); GUI.color = Color.white; } GUIStyle val7 = new GUIStyle(GUI.skin.label) { fontSize = 13, alignment = (TextAnchor)4 }; if (mc.IsRemote) { GUI.color = new Color(1f, 0.85f, 0.3f); GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + num4 - 90f, num3, 22f), "Waiting for the host to choose the next mode…", val7); GUI.color = Color.white; return; } float num9 = ((Rect)(ref val)).y + num4 - 168f - num2; GUI.Label(new Rect(((Rect)(ref val)).x, num9 - 22f, num3, 18f), "Host: choose the next mode to start the morning", val7); DrawModeGrid(mc, new Rect(((Rect)(ref val)).x + 20f, num9, num3 - 40f, num), fresh: true); DrawModeInfoCard(val); DrawLoadoutCard(val); float num10 = ((Rect)(ref val)).y + num4 - 44f; if (mc.HasActiveMode && GUI.Button(new Rect(((Rect)(ref val)).x + 20f, num10, (num3 - 50f) / 2f, 30f), "Continue " + GameModeInfo.Title(mc.ModeType) + " (next day)")) { mc.RequestContinue(); } if (GUI.Button(new Rect(((Rect)(ref val)).x + 30f + (num3 - 50f) / 2f, num10, (num3 - 50f) / 2f, 30f), "Stop match")) { mc.RequestStop(); } } private void DrawHostPanel(MatchController mc) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) float num = ModeGridHeight(); float num2 = 540f; float num3 = 250f + Mathf.Max(0f, num - 104f); Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width * 0.5f - num2 / 2f, (float)Screen.height * 0.5f - num3 / 2f, num2, num3); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(val, White); GUI.color = Color.white; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 22, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 12f, num2, 30f), "MULTIPLAYER PVP", val2); GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = 13, alignment = (TextAnchor)4 }; GUIStyle val4 = new GUIStyle(GUI.skin.label) { fontSize = 15, alignment = (TextAnchor)4, wordWrap = true }; if (!mc.IsMultiplayer) { GUI.color = new Color(1f, 0.7f, 0.3f); GUI.Label(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 70f, num2 - 40f, 80f), "This mod is multiplayer-only.\nHost or join a co-op lobby with 2+ players,\nthen press the host key again.", val4); GUI.color = Color.white; } else if (!mc.IsHost) { GUI.color = new Color(1f, 0.7f, 0.3f); GUI.Label(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 70f, num2 - 40f, 80f), "Only the host controls the match.\nThe host picks the game mode.", val4); GUI.color = Color.white; } else { GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 44f, num2, 18f), $"{SessionUtil.PlayerCount()} player(s) · pick a mode to start", val3); Rect area = default(Rect); ((Rect)(ref area))..ctor(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 70f, num2 - 40f, num); DrawModeGrid(mc, area, fresh: true); DrawModeInfoCard(val); DrawLoadoutCard(val); } if (GUI.Button(new Rect(((Rect)(ref val)).x + num2 - 110f, ((Rect)(ref val)).y + num3 - 34f, 90f, 26f), "Close")) { PanelOpen = false; } } private void DrawEndMatchPrompt(MatchController mc) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) float num = 440f; float num2 = 180f; Rect position = default(Rect); ((Rect)(ref position))..ctor((float)Screen.width * 0.5f - num / 2f, (float)Screen.height * 0.5f - num2 / 2f, num, num2); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.95f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 20, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref position)).x, ((Rect)(ref position)).y + 16f, num, 28f), "END MATCH EARLY?", val); GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 14, alignment = (TextAnchor)4, wordWrap = true }; GUI.Label(new Rect(((Rect)(ref position)).x + 24f, ((Rect)(ref position)).y + 52f, num - 48f, 44f), "End the running match now? The countdown drops to 3 seconds and the day is scored as normal.", val2); if (GUI.Button(new Rect(((Rect)(ref position)).x + 40f, ((Rect)(ref position)).y + num2 - 64f, num - 80f, 38f), "End match early")) { EndPromptOpen = false; mc.RequestEndEarly(); } GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = 11, alignment = (TextAnchor)4 }; GUI.color = new Color(0.7f, 0.75f, 0.85f); GUI.Label(new Rect(((Rect)(ref position)).x, ((Rect)(ref position)).y + num2 - 22f, num, 16f), $"Press {PvpConfig.PanelKey.Value} again to cancel", val3); GUI.color = Color.white; } private static float ModeGridHeight() { int num = 7 + MatchToggles.Snapshot().Length; int num2 = (num + 3) / 4; return (float)num2 * 48f + (float)(num2 - 1) * 8f; } private void DrawModeGrid(MatchController mc, Rect area, bool fresh) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) int num = 7; float num2 = (((Rect)(ref area)).width - 24f) / 4f; float num3 = 48f; _hoverMode = -1; _hoverToggle = null; Vector2 val = (Vector2)((Event.current != null) ? Event.current.mousePosition : new Vector2(-1f, -1f)); Rect val2 = default(Rect); for (int i = 0; i < num; i++) { int num4 = i / 4; int num5 = i % 4; ((Rect)(ref val2))..ctor(((Rect)(ref area)).x + (float)num5 * (num2 + 8f), ((Rect)(ref area)).y + (float)num4 * (num3 + 8f), num2, num3); if (((Rect)(ref val2)).Contains(val)) { _hoverMode = i; } GameModeType gameModeType = (GameModeType)i; if (GUI.Button(val2, $"{i + 1}. {GameModeInfo.Title(gameModeType)}")) { PanelOpen = false; if (fresh) { mc.RequestStart(gameModeType); } } } PvpMatchToggle[] array = MatchToggles.Snapshot(); Rect val3 = default(Rect); for (int j = 0; j < array.Length; j++) { int num6 = num + j; int num7 = num6 / 4; int num8 = num6 % 4; ((Rect)(ref val3))..ctor(((Rect)(ref area)).x + (float)num8 * (num2 + 8f), ((Rect)(ref area)).y + (float)num7 * (num3 + 8f), num2, num3); PvpMatchToggle pvpMatchToggle = array[j]; if (((Rect)(ref val3)).Contains(val)) { _hoverToggle = pvpMatchToggle; } GUI.color = (pvpMatchToggle.Requested ? new Color(0.55f, 1f, 0.55f) : new Color(0.85f, 0.85f, 0.9f)); if (GUI.Button(val3, pvpMatchToggle.Label + "\n" + (pvpMatchToggle.Requested ? "ON (this round)" : "OFF"))) { pvpMatchToggle.Requested = !pvpMatchToggle.Requested; } GUI.color = Color.white; } } } internal static class ViewLock { private static bool _locked; internal static void Set(bool locked) { if (locked != _locked) { _locked = locked; try { PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(!locked); if (locked) { instance.FreeMouse(true); } else { instance.LockMouse(true); } } } catch { } } if (locked) { try { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } catch { } } } internal static void Release() { if (!_locked) { return; } _locked = false; try { PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(true); instance.LockMouse(true); } } catch { } } } } namespace MultiplayerPVP.Net { internal struct SnapRow { internal string Name; internal int Team; internal int Index; internal string Score; internal bool Bag; internal Vector3 Spawn; internal int Kills; internal int Downs; internal int Arrests; internal int BagsCaptured; internal int BagsLost; internal int WeaponsLost; internal int WeaponsWon; internal string History; } internal struct SnapTeamRow { internal int Team; internal string Name; internal string Score; internal int Kills; internal int Downs; internal int Arrests; internal int BagsCaptured; internal int BagsLost; internal int WeaponsLost; internal int WeaponsWon; } internal struct SnapMarker { internal Vector3 Pos; internal Color Color; internal string Label; internal int Team; } internal class MatchSnapshot { internal int Phase; internal int Mode; internal int Day; internal float Remaining; internal string Banner = ""; internal string Result = ""; internal string Loot = ""; internal bool Chaos; internal bool Ammo; internal bool Jump; internal string Loadout = ""; internal long RoundId; internal readonly List<SnapRow> Rows = new List<SnapRow>(); internal readonly List<SnapTeamRow> TeamRows = new List<SnapTeamRow>(); internal readonly List<SnapMarker> Markers = new List<SnapMarker>(); internal long Seq; private static string San(string s) { if (string.IsNullOrEmpty(s)) { return ""; } return s.Replace('|', ' ').Replace('~', ' ').Replace(';', ' ') .Replace('=', ' ') .Replace(',', ' ') .Replace('"', ' ') .Replace('\\', ' '); } private static string F(float v) { return v.ToString("0.0", CultureInfo.InvariantCulture); } internal string Serialize() { //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(192); stringBuilder.Append("v=1|sq=").Append(Seq).Append("|ph=") .Append(Phase) .Append("|md=") .Append(Mode) .Append("|day=") .Append(Day) .Append("|rs=") .Append(Remaining.ToString("0.0", CultureInfo.InvariantCulture)) .Append("|bn=") .Append(San(Banner)) .Append("|rz=") .Append(San(Result)) .Append("|lt=") .Append(Loot ?? "") .Append("|cx=") .Append(Chaos ? 1 : 0) .Append("|ua=") .Append(Ammo ? 1 : 0) .Append("|dj=") .Append(Jump ? 1 : 0) .Append("|gi=") .Append(Loadout ?? "") .Append("|gr=") .Append(RoundId) .Append("|p="); for (int i = 0; i < Rows.Count; i++) { SnapRow snapRow = Rows[i]; if (i > 0) { stringBuilder.Append(';'); } stringBuilder.Append(San(snapRow.Name)).Append('~').Append(snapRow.Team) .Append('~') .Append(snapRow.Index) .Append('~') .Append(San(snapRow.Score)) .Append('~') .Append(snapRow.Bag ? 1 : 0) .Append('~') .Append(F(snapRow.Spawn.x)) .Append('~') .Append(F(snapRow.Spawn.y)) .Append('~') .Append(F(snapRow.Spawn.z)) .Append('~') .Append(snapRow.Kills) .Append('~') .Append(snapRow.Downs) .Append('~') .Append(snapRow.Arrests) .Append('~') .Append(snapRow.BagsCaptured) .Append('~') .Append(snapRow.BagsLost) .Append('~') .Append(snapRow.WeaponsLost) .Append('~') .Append(snapRow.WeaponsWon) .Append('~') .Append(San(snapRow.History)); } stringBuilder.Append("|tr="); for (int j = 0; j < TeamRows.Count; j++) { SnapTeamRow snapTeamRow = TeamRows[j]; if (j > 0) { stringBuilder.Append(';'); } stringBuilder.Append(snapTeamRow.Team).Append('~').Append(San(snapTeamRow.Name)) .Append('~') .Append(San(snapTeamRow.Score)) .Append('~') .Append(snapTeamRow.Kills) .Append('~') .Append(snapTeamRow.Downs) .Append('~') .Append(snapTeamRow.Arrests) .Append('~') .Append(snapTeamRow.BagsCaptured) .Append('~') .Append(snapTeamRow.BagsLost) .Append('~') .Append(snapTeamRow.WeaponsLost) .Append('~') .Append(snapTeamRow.WeaponsWon); } stringBuilder.Append("|m="); for (int k = 0; k < Markers.Count; k++) { SnapMarker snapMarker = Markers[k]; if (k > 0) { stringBuilder.Append(','); } stringBuilder.Append(F(snapMarker.Pos.x)).Append('~').Append(F(snapMarker.Pos.y)) .Append('~') .Append(F(snapMarker.Pos.z)) .Append('~') .Append(F(snapMarker.Color.r)) .Append('~') .Append(F(snapMarker.Color.g)) .Append('~') .Append(F(snapMarker.Color.b)) .Append('~') .Append(San(snapMarker.Label)) .Append('~') .Append(snapMarker.Team); } return stringBuilder.ToString(); } internal static bool TryParse(string s, MatchSnapshot into) { //IL_08c7: Unknown result type (might be due to invalid IL or missing references) //IL_08cc: Unknown result type (might be due to invalid IL or missing references) //IL_08de: Unknown result type (might be due to invalid IL or missing references) //IL_08e3: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_058d: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(s) || into == null) { return false; } try { into.Rows.Clear(); into.TeamRows.Clear(); into.Markers.Clear(); into.Banner = ""; into.Result = ""; into.Loot = ""; into.Chaos = false; into.Ammo = false; into.Jump = false; into.Loadout = ""; into.RoundId = 0L; string[] array = s.Split('|'); string[] array2 = array; foreach (string text in array2) { int num = text.IndexOf('='); if (num < 0) { continue; } string text2 = text.Substring(0, num); string text3 = text.Substring(num + 1); switch (text2) { case "sq": long.TryParse(text3, out into.Seq); break; case "ph": int.TryParse(text3, out into.Phase); break; case "md": int.TryParse(text3, out into.Mode); break; case "day": int.TryParse(text3, out into.Day); break; case "rs": float.TryParse(text3, NumberStyles.Float, CultureInfo.InvariantCulture, out into.Remaining); break; case "bn": into.Banner = text3; break; case "rz": into.Result = text3; break; case "lt": into.Loot = text3; break; case "cx": into.Chaos = text3 == "1"; break; case "ua": into.Ammo = text3 == "1"; break; case "dj": into.Jump = text3 == "1"; break; case "gi": into.Loadout = text3; break; case "gr": long.TryParse(text3, out into.RoundId); break; case "p": { if (text3.Length == 0) { break; } string[] array7 = text3.Split(';'); foreach (string text6 in array7) { string[] array8 = text6.Split('~'); if (array8.Length >= 4) { SnapRow item3 = new SnapRow { Name = array8[0], Score = array8[3] }; int.TryParse(array8[1], out item3.Team); int.TryParse(array8[2], out item3.Index); if (array8.Length >= 5) { item3.Bag = array8[4] == "1"; } if (array8.Length >= 8) { float.TryParse(array8[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result7); float.TryParse(array8[6], NumberStyles.Float, CultureInfo.InvariantCulture, out var result8); float.TryParse(array8[7], NumberStyles.Float, CultureInfo.InvariantCulture, out var result9); item3.Spawn = new Vector3(result7, result8, result9); } if (array8.Length >= 11) { int.TryParse(array8[8], out item3.Kills); int.TryParse(array8[9], out item3.Downs); int.TryParse(array8[10], out item3.Arrests); } if (array8.Length >= 15) { int.TryParse(array8[11], out item3.BagsCaptured); int.TryParse(array8[12], out item3.BagsLost); int.TryParse(array8[13], out item3.WeaponsLost); int.TryParse(array8[14], out item3.WeaponsWon); } if (array8.Length >= 16) { item3.History = array8[15]; } into.Rows.Add(item3); } } break; } case "tr": { if (text3.Length == 0) { break; } string[] array5 = text3.Split(';'); foreach (string text5 in array5) { string[] array6 = text5.Split('~'); if (array6.Length >= 3) { SnapTeamRow item2 = new SnapTeamRow { Name = array6[1], Score = array6[2] }; int.TryParse(array6[0], out item2.Team); if (array6.Length >= 10) { int.TryParse(array6[3], out item2.Kills); int.TryParse(array6[4], out item2.Downs); int.TryParse(array6[5], out item2.Arrests); int.TryParse(array6[6], out item2.BagsCaptured); int.TryParse(array6[7], out item2.BagsLost); int.TryParse(array6[8], out item2.WeaponsLost); int.TryParse(array6[9], out item2.WeaponsWon); } into.TeamRows.Add(item2); } } break; } case "m": { if (text3.Length == 0) { break; } string[] array3 = text3.Split(','); foreach (string text4 in array3) { string[] array4 = text4.Split('~'); if (array4.Length >= 7) { SnapMarker item = new SnapMarker { Label = array4[6], Team = -1 }; float.TryParse(array4[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result); float.TryParse(array4[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2); float.TryParse(array4[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3); float.TryParse(array4[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4); float.TryParse(array4[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result5); float.TryParse(array4[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result6); if (array4.Length >= 8) { int.TryParse(array4[7], out item.Team); } item.Pos = new Vector3(result, result2, result3); item.Color = new Color(result4, result5, result6, 1f); into.Markers.Add(item); } } break; } } } return true; } catch { return false; } } } internal sealed class PvpNet { internal const string KeyPrefix = "mpvp_"; internal const string SnapshotKey = "snap"; internal const string ModTagKey = "mod"; internal const string LootKey = "loot"; internal const string EarnKey = "earn"; internal const string SpillKey = "spill"; internal const string IdTagKey = "idtag"; internal const string SightKey = "sight"; private SteamNetworkClient _client; private HostSyncVar<string> _snap; private ClientSyncVar<string> _modTag; private ClientSyncVar<string> _loot; private ClientSyncVar<string> _earn; private ClientSyncVar<string> _spill; private ClientSyncVar<string> _idTag; private ClientSyncVar<string> _sight; private readonly List<ClientSyncVar<string>> _addonVars = new List<ClientSyncVar<string>>(); private bool _init; private static readonly string ModTag = "MultiplayerPVP/" + ModVersion(); private bool _wasInLobby; private bool _tagSet; private string _idCode; private bool _idSet; private const float WarnInterval = 15f; private float _lastWarn = -999f; internal bool Available => _init && _client != null; internal bool IsInLobby { get { try { return Available && _client.IsInLobby; } catch { return false; } } } internal bool IsHost { get { try { return Available && _client.IsHost; } catch { return false; } } } internal ulong LocalSteamId { get { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!Available) { return 0uL; } try { foreach (MemberInfo lobbyMember in _client.GetLobbyMembers()) { if (lobbyMember != null && lobbyMember.IsLocalPlayer) { return lobbyMember.SteamId.m_SteamID; } } } catch { } return 0uL; } } internal int ModdedMemberCount { get { if (_modTag == null) { return 0; } try { int num = 0; foreach (KeyValuePair<CSteamID, string> allValue in _modTag.GetAllValues()) { if (!string.IsNullOrEmpty(allValue.Value)) { num++; } } return num; } catch { return 0; } } } internal int MemberCount { get { try { return Available ? _client.GetLobbyMembers().Count : 0; } catch { return 0; } } } internal bool AllMembersModded { get { int memberCount = MemberCount; return memberCount > 0 && ModdedMemberCount >= memberCount; } } internal event Action<string> OnSnapshot; internal event Action<ulong, string> OnLoot; internal event Action<ulong, string> OnSpill; internal event Action<ulong, string> OnSighting; internal void Init() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (_init) { return; } try { _client = new SteamNetworkClient(); if (!_client.Initialize()) { return; } try { _client.OnVersionMismatch += OnVersionMismatch; } catch { } NetworkSyncOptions val = MakeOpts(); _snap = _client.CreateHostSyncVar<string>("snap", "", val, (ISyncValidator<string>)null); _snap.OnValueChanged += OnSnapValueChanged; _snap.OnSyncError += OnSyncError; _modTag = _client.CreateClientSyncVar<string>("mod", "", val, (ISyncValidator<string>)null); _loot = _client.CreateClientSyncVar<string>("loot", "", val, (ISyncValidator<string>)null); _loot.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { this.OnLoot?.Invoke(from.m_SteamID, newV); } } catch { } }; _earn = _client.CreateClientSyncVar<string>("earn", "", val, (ISyncValidator<string>)null); _spill = _client.CreateClientSyncVar<string>("spill", "", val, (ISyncValidator<string>)null); _spill.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { this.OnSpill?.Invoke(from.m_SteamID, newV); } } catch { } }; _idTag = _client.CreateClientSyncVar<string>("idtag", "", val, (ISyncValidator<string>)null); _sight = _client.CreateClientSyncVar<string>("sight", "", val, (ISyncValidator<string>)null); _sight.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { this.OnSighting?.Invoke(from.m_SteamID, newV); } } catch { } }; _init = true; PvpLog.Debug("[MultiplayerPVP][Net] SteamNetworkClient initialized (HostSyncVar transport)."); } catch { } } private static NetworkSyncOptions MakeOpts() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown return new NetworkSyncOptions { KeyPrefix = "mpvp_", AutoSync = true, SyncOnPlayerJoin = true, MaxSyncsPerSecond = 0 }; } internal ClientSyncVar<string> CreateAddonVar(string keySuffix, Action<ulong, string> onMessage) { if (!_init || _client == null || string.IsNullOrEmpty(keySuffix)) { return null; } try { ClientSyncVar<string> val = _client.CreateClientSyncVar<string>(keySuffix, "", MakeOpts(), (ISyncValidator<string>)null); if (onMessage != null) { val.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { onMessage(from.m_SteamID, newV); } } catch { } }; } lock (_addonVars) { _addonVars.Add(val); } return val; } catch (Exception ex) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup - _lastWarn >= 15f) { _lastWarn = realtimeSinceStartup; MelonLogger.Warning("[MultiplayerPVP][Net] addon channel '" + keySuffix + "' create failed: " + ex.Message); } return null; } } internal void Tick() { if (!_init) { return; } bool isInLobby = IsInLobby; if (isInLobby && !_wasInLobby) { _tagSet = false; _idSet = false; } _wasInLobby = isInLobby; if (isInLobby && !_tagSet && _modTag != null) { try { _modTag.Value = ModTag; _tagSet = true; } catch { } } if (!isInLobby || _idSet || _idTag == null || string.IsNullOrEmpty(_idCode)) { return; } try { _idTag.Value = _idCode; _idSet = true; } catch { } } internal void SetLocalIdentity(string playerCode) { if (!string.IsNullOrEmpty(playerCode) && playerCode != _idCode) { _idCode = playerCode; _idSet = false; } } private void OnSnapValueChanged(string oldValue, string newValue) { try { if (!IsHost && !string.IsNullOrEmpty(newValue)) { this.OnSnapshot?.Invoke(newValue); } } catch (Exception ex) { MelonLogger.Warning("[MultiplayerPVP][Net] snapshot apply: " + ex.Message); } } internal void PublishSnapshot(string snapshot) { if (!Available || !IsHost || _snap == null) { return; } try { _snap.Value = snapshot; } catch (Exception ex) { OnSyncError(ex); } } internal void PublishLoot(string record) { if (!Available || _loot == null) { return; } try { _loot.Value = record; } catch { } } internal void PublishSpill(string record) { if (!Available || _spill == null) { return; } try { _spill.Value = record; } catch { } } internal void PublishEarnings(string record) { if (!Available || _earn == null) { return; } try { _earn.Value = record; } catch { } } internal List<KeyValuePair<ulong, string>> AllEarnings() { return ReadAllOf(_earn); } internal List<KeyValuePair<ulong, string>> AllLoot() { return ReadAllOf(_loot); } internal List<KeyValuePair<ulong, string>> AllSpill() { return ReadAllOf(_spill); } internal static List<KeyValuePair<ulong, string>> ReadAllOf(ClientSyncVar<string> v) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) List<KeyValuePair<ulong, string>> list = new List<KeyValuePair<ulong, string>>(); if (v == null) { return list; } try { v.Refresh(); } catch { } try { foreach (KeyValuePair<CSteamID, string> allValue in v.GetAllValues()) { if (!string.IsNullOrEmpty(allValue.Value)) { list.Add(new KeyValuePair<ulong, string>(allValue.Key.m_SteamID, allValue.Value)); } } } catch { } return list; } internal void PublishSighting(string record) { if (!Available || _sight == null) { return; } try { _sight.Value = record; } catch { } } internal Dictionary<string, ulong> AllIdentities() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, ulong> dictionary = new Dictionary<string, ulong>(); if (_idTag == null) { return dictionary; } try { foreach (KeyValuePair<CSteamID, string> allValue in _idTag.GetAllValues()) { if (!string.IsNullOrEmpty(allValue.Value)) { dictionary[allValue.Value] = allValue.Key.m_SteamID; } } } catch { } return dictionary; } internal string PersonaOf(ulong steamId) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!Available || steamId == 0) { return null; } try { foreach (MemberInfo lobbyMember in _client.GetLobbyMembers()) { if (lobbyMember != null && lobbyMember.SteamId.m_SteamID == steamId) { return lobbyMember.DisplayName; } } } catch { } return null; } private void OnVersionMismatch(object sender, VersionMismatchEventArgs e) { MelonLogger.Warning("[MultiplayerPVP][Net] SteamNetworkLib version mismatch between players — networking may be unreliable. Ensure everyone runs the same mod/lib build."); } private void OnSyncError(Exception ex) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup - _lastWarn < 15f)) { _lastWarn = realtimeSinceStartup; MelonLogger.Warning("[MultiplayerPVP][Net] snapshot sync error (throttled): " + ex.Message); } } internal void Dispose() { try { if (_snap != null) { _snap.OnValueChanged -= OnSnapValueChanged; _snap.OnSyncError -= OnSyncError; _snap.Dispose(); } } catch { } try { if (_modTag != null) { _modTag.Dispose(); } } catch { } try { if (_loot != null) { _loot.Dispose(); } } catch { } try { if (_earn != null) { _earn.Dispose(); } } catch { } try { if (_spill != null) { _spill.Dispose(); } } catch { } try { if (_idTag != null) { _idTag.Dispose(); } } catch { } try { if (_sight != null) { _sight.Dispose(); } } catch { } lock (_addonVars) { for (int i = 0; i < _addonVars.Count; i++) { try { _addonVars[i].Dispose(); } catch { } } _addonVars.Clear(); } try { if (_client != null) { _client.OnVersionMismatch -= OnVersionMismatch; _client.Dispose(); } } catch { } _snap = null; _modTag = null; _loot = null; _earn = null; _spill = null; _idTag = null; _sight = null; _client = null; _init = false; _tagSet = false; _idSet = false; _idCode = null; _wasInLobby = false; } private static string ModVersion() { try { Version version = typeof(PvpNet).Assembly.GetName().Version; return (version != null) ? version.ToString() : "1.0"; } catch { return "1.0"; } } } } namespace MultiplayerPVP.Modes { internal class FindersKeepersMode : GameModeBase, IWorldMarkers, IBagSpillHandler { private DeadDrop _pickup; private int _pickupZone = -1; private int _pickupKnown; private PvpPlayer _carrier; private int _carrierHome = -1; private int _homeBaseline; private float _transit; private bool _active; private static string BagId => BagFactory.MatchId; public override GameModeType Type => GameModeType.FindersKeepers; public override void OnMatchStart(MatchContext ctx) { _active = true; SpawnBag(ctx, announce: false); } public override void OnMatchEnd(MatchContext ctx) { _active = false; bool tie; PvpPlayer pvpPlayer = ctx.Registry.Leader(out tie); if (pvpPlayer != null) { ctx.Announcer.Announce(tie ? $"It's a draw at {pvpPlayer.Score} delivery(ies)!" : $"{pvpPlayer.Name} wins with {pvpPlayer.Score} delivery(ies)!", 6f); } } private void SpawnBag(MatchContext ctx, bool announce) { _carrier = null; _carrierHome = -1; _transit = 0f; _pickup = ctx.Drops.RandomNonZoneDrop(); _pickupZone = -1; for (int i = 0; i < ctx.Drops.Count; i++) { if ((Object)(object)ctx.Drops.Zone(i) == (Object)(object)_pickup) { _pickupZone = i; break; } } if (GameCompat.Alive((Object)(object)_pickup)) { DeadDropStash.Insert(_pickup, BagId, 1, BagFactory.Create); _pickupKnown = DeadDropStash.Count(_pickup, BagId); } else { _pickupKnown = 0; } if (announce && GameCompat.Alive((Object)(object)_pickup)) { ctx.Announcer.Announce("A fresh bag is in a dead drop — find it!", 3f); } } public bool OnCarrierSpill(MatchContext ctx, PvpPlayer victim, int count, string reason) { if (count <= 0) { return true; } if (_carrier == null) { return true; } if (victim != null && victim != _carrier) { return true; } string name = _carrier.Name; string text = ((reason == "arrested") ? "was busted" : "went down"); SpawnBag(ctx, announce: false); ctx.Announcer.Announce(name + " " + text + " — the bag dropped and reappears in a dead drop!", 4f, notify: false); return true; } public override void Tick(MatchContext ctx, float dt) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (!_active) { return; } if (_carrier == null) { if (!GameCompat.Alive((Object)(object)_pickup)) { SpawnBag(ctx, announce: false); return; } int num = DeadDropStash.Count(_pickup, BagId); if (num < _pickupKnown) { _carrier = NearestPlayer(ctx, PickupPos(ctx)); _pickupKnown = num; _transit = 0f; _carrierHome = ((_carrier != null) ? ctx.Drops.ZoneForIndex(_carrier.Index) : (-1)); DeadDrop val = ((_carrierHome >= 0) ? ctx.Drops.Zone(_carrierHome) : null); _homeBaseline = (GameCompat.Alive((Object)(object)val) ? DeadDropStash.Count(val, BagId) : 0); string text = ((_carrier != null) ? _carrier.Name : "Someone"); ctx.Announcer.Announce(text + " has the bag!"); } return; } _transit += dt; int carrierHome = _carrierHome; DeadDrop val2 = ((carrierHome >= 0) ? ctx.Drops.Zone(carrierHome) : null); if (GameCompat.Alive((Object)(object)val2) && DeadDropStash.Count(val2, BagId) > _homeBaseline) { DeadDropStash.RemoveOne(val2, BagId); ctx.Award(_carrier, 1); ctx.Announcer.Announce($"{_carrier.Name} delivered the bag! ({_carrier.Score})", 5f); SpawnBag(ctx, announce: false); } else if (_transit > 60f) { ctx.Announcer.Announce("The bag was lost — a new one appears."); SpawnBag(ctx, announce: true); } } private Vector3 PickupPos(MatchContext ctx) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (_pickupZone >= 0) { return ctx.Drops.ZonePosition(_pickupZone); } try { return GameCompat.Alive((Object)(object)_pickup) ? ((Component)_pickup).transform.position : Vector3.zero; } catch { return Vector3.zero; } } private static PvpPlayer NearestPlayer(MatchContext ctx, Vector3 pos) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) List<PvpPlayer> players = ctx.Registry.Players; PvpPlayer result = null; float num = float.MaxValue; for (int i = 0; i < players.Count; i++) { PvpPlayer pvpPlayer = players[i]; if (pvpPlayer.Valid) { float num2 = Vector3.Distance(pos, pvpPlayer.Position); if (num2 < num) { num = num2; result = pvpPlayer; } } } return result; } public override bool IsComplete(MatchContext ctx) { int num = Mathf.Max(1, PvpConfig.CtfScoreToWin.Value); List<PvpPlayer> players = ctx.Registry.Players; for (int i = 0; i < players.Count; i++) { if (players[i].Score >= num) { return true; } } return false; } public override string ScoreText(PvpPlayer p) { return p.Score + " caps" + ((_carrier == p) ? " ·BAG" : ""); } public void CollectMarkers(MatchContext ctx, PvpPlayer local, List<WorldMarker> into) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (_active && _carrier != null) { int carrierHome = _carrierHome; if (carrierHome >= 0) { into.Add(new WorldMarker(ctx.Drops.ZonePosition(carrierHome) + Vector3.up * 1.4f, PvpColors.For(_carrier.Index), "DELIVER HERE (" + _carrier.Name + ")")); } } } } internal class FreeForAllMode : GameModeBase { public override GameModeType Type => GameModeType.FreeForAll; public override void Tick(MatchContext ctx, float dt) { Combat.ProcessEliminations(ctx, teamMode: false); } public override void OnMatchEnd(MatchContext ctx) { bool tie; PvpPlayer pvpPlayer = ctx.Registry.Leader(out tie); if (pvpPlayer != null) { ctx.Announcer.Announce(tie ? $"It's a draw at {pvpPlayer.Score} eliminations!" : $"{pvpPlayer.Name} wins with {pvpPlayer.Score} eliminations!", 6f); } } public override string ScoreText(PvpPlayer p) { return p.Score + " elim"; } } internal class HideAndSeekMode : GameModeBase { private readonly HashSet<string> _originalHiders = new HashSet<string>(); private readonly Dictionary<string, int> _foundRank = new Dictionary<string, int>(); private int _foundCounter; private float _lastScan; public override GameModeType Type => GameModeType.HideAndSeek; private static string KeyOf(PvpPlayer p) { return (p != null) ? p.StableKey : ""; } private bool IsOriginalHider(PvpPlayer p) { return _originalHiders.Contains(KeyOf(p)) || (p != null && p.Name != null &&
MultiplayerPVP.MONO.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using DooDesch.FullHouse; using FishNet; using FishNet.Managing; using FishNet.Object; using FishySteamworks; using HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using MultiplayerPVP; using MultiplayerPVP.Addons; using MultiplayerPVP.Compat; using MultiplayerPVP.Config; using MultiplayerPVP.Core; using MultiplayerPVP.Modes; using MultiplayerPVP.Net; using MultiplayerPVP.UI; using ScheduleOne; using ScheduleOne.Cartel; using ScheduleOne.Combat; using ScheduleOne.Core.Items.Framework; using ScheduleOne.DevUtilities; using ScheduleOne.Doors; using ScheduleOne.Economy; using ScheduleOne.Equipping; using ScheduleOne.FX; using ScheduleOne.GameTime; using ScheduleOne.ItemFramework; using ScheduleOne.Law; using ScheduleOne.Map; using ScheduleOne.Money; using ScheduleOne.NPCs; using ScheduleOne.NPCs.Behaviour; using ScheduleOne.Networking; using ScheduleOne.PlayerScripts; using ScheduleOne.PlayerScripts.Health; using ScheduleOne.Police; using ScheduleOne.Product; using ScheduleOne.Product.Packaging; using ScheduleOne.Storage; using ScheduleOne.UI; using ScheduleOne.UI.Multiplayer; using ScheduleOne.Vision; using SteamNetworkLib; using SteamNetworkLib.Events; using SteamNetworkLib.Models; using SteamNetworkLib.Sync; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("MultiplayerPVP")] [assembly: AssemblyDescription("Schedule I MelonLoader Mod")] [assembly: AssemblyCompany("Virtunerd")] [assembly: AssemblyProduct("MultiplayerPVP")] [assembly: AssemblyCopyright("Copyright (c) Virtunerd 2026")] [assembly: ComVisible(false)] [assembly: Guid("f83b02a6-396b-4b34-b8b7-3d0117d8d960")] [assembly: MelonAdditionalDependencies(new string[] { "SteamNetworkLib" })] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: MelonInfo(typeof(MultiplayerPVPMod), "MultiplayerPVP", "1.0.6", "Virtunerd", null)] [assembly: MelonGame(null, "Schedule I")] [assembly: AssemblyFileVersion("1.0.6")] [assembly: AssemblyInformationalVersion("1.0.6")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.6.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DooDesch.FullHouse { internal static class Lobbies { internal const int DefaultCapacity = 32; private const int HardMax = 250; private const int SafeMax = 32; private const string GuardName = "___DooDesch_FullHouse___"; private static bool _installed; private static MelonPreferences_Entry<int> _capEntry; private static int _hostCap; internal static int Capacity { get { int num = ((_capEntry != null) ? _capEntry.Value : 32); if (num < 2) { num = 2; } if (num > 250) { num = 250; } return num; } } internal static int EffectiveCap => Math.Min(250, Math.Max(Capacity, _hostCap)); internal static ulong CurrentLobbyId { get { try { SteamLobbyService val = Service(); return (val != null) ? val._lobbyID : 0; } catch { return 0uL; } } } internal static int SeatCount { get { try { CSteamID[] array = Service()?._players; return (array != null) ? array.Length : 0; } catch { return 0; } } } internal static void Install() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown if (_installed) { return; } _installed = true; try { if ((Object)(object)GameObject.Find("___DooDesch_FullHouse___") != (Object)null) { MelonLogger.Msg("[FullHouse] another copy is already active - standing down."); return; } GameObject val = new GameObject("___DooDesch_FullHouse___"); Object.DontDestroyOnLoad((Object)(object)val); ((Object)val).hideFlags = (HideFlags)61; } catch { } try { MelonPreferences_Category val2 = MelonPreferences.CreateCategory("FullHouse", "FullHouse"); _capEntry = val2.CreateEntry<int>("Capacity", 32, "Max lobby players", "Maximum co-op players FullHouse seats (2-250). Values above 32 are unsupported and may destabilise the game.", false, false, (ValueValidator)null, (string)null); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] preference registration failed: " + ex.Message); } if (Capacity > 32) { MelonLogger.Warning($"[FullHouse] capacity {Capacity} exceeds the tested maximum of {32} - expect instability."); } try { Harmony h = new Harmony("com.doodesch.fullhouse"); Patch(h, typeof(SteamLobbyService), "Initialize", null, "Service_Initialize_Postfix"); Patch(h, typeof(SteamLobbyService), "UpdateLobbyMembers", "Service_UpdateLobbyMembers_Prefix"); Patch(h, typeof(SteamLobbyService), "CreateLobby", "Service_CreateLobby_Prefix"); Patch(h, typeof(SteamLobbyService), "OnLobbyCreated", null, "Service_OnLobbyCreated_Postfix"); Patch(h, typeof(SteamLobbyService), "OnLobbyEntered", null, "Service_OnLobbyEntered_Postfix"); Patch(h, typeof(SteamLobbyService), "OpenInviteUI", "Service_OpenInviteUI_Prefix"); Patch(h, typeof(SteamLobbyService), "LeaveLobby", null, "Service_LeaveLobby_Postfix"); Patch(h, typeof(LobbyInterface), "Start", null, "LobbyInterface_Start_Postfix"); Patch(h, typeof(LobbyInterface), "UpdateUI", null, "LobbyInterface_UpdateUI_Postfix"); Patch(h, typeof(LobbyInterface), "UpdateButtons", null, "LobbyInterface_UpdateButtons_Postfix"); MelonLogger.Msg($"[FullHouse] active - lobby cap raised to {Capacity}."); } catch (Exception ex2) { MelonLogger.Error("[FullHouse] patch install failed: " + ex2); } } private static void Patch(Harmony h, Type type, string method, string prefix = null, string postfix = null) { MethodInfo methodInfo = AccessTools.Method(type, method, (Type[])null, (Type[])null); if (methodInfo == null) { MelonLogger.Warning("[FullHouse] " + type.Name + "." + method + " not found - skipped."); } else { h.Patch((MethodBase)methodInfo, Hook(prefix), Hook(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static HarmonyMethod Hook(string name) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) return (name == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Lobbies).GetMethod(name, AccessTools.all)); } private static SteamLobbyService Service() { try { ILobbyService val = Singleton<Lobby>.Instance?._lobbyService; if (val == null) { return null; } return (SteamLobbyService)(object)((val is SteamLobbyService) ? val : null); } catch { return null; } } private static void EnsurePlayers(SteamLobbyService svc, int target) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) try { if (svc == null || target < 2) { return; } CSteamID[] players = svc._players; int num = ((players != null) ? players.Length : 0); if (num < target) { CSteamID[] array = (CSteamID[])(object)new CSteamID[target]; for (int i = 0; i < num; i++) { array[i] = players[i]; } svc._players = array; } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] resizing the lobby seat array failed: " + ex.Message); } } private static void Service_Initialize_Postfix(SteamLobbyService __instance) { EnsurePlayers(__instance, EffectiveCap); RaiseTransportCap(); } private static void RaiseTransportCap() { try { FishySteamworks val = Object.FindObjectOfType<FishySteamworks>(); if (!((Object)(object)val == (Object)null)) { int effectiveCap = EffectiveCap; ushort maximumClients = val._maximumClients; if (maximumClients < effectiveCap) { val._maximumClients = (ushort)effectiveCap; MelonLogger.Msg($"[FullHouse] transport client limit {maximumClients} -> {effectiveCap}."); } } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] raising the transport client limit failed: " + ex.Message); } } private static void Service_UpdateLobbyMembers_Prefix(SteamLobbyService __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) try { int val = 0; try { ulong num = ((__instance != null) ? __instance._lobbyID : 0); if (num != 0) { val = SteamMatchmaking.GetNumLobbyMembers(new CSteamID(num)); } } catch { } EnsurePlayers(__instance, Math.Max(EffectiveCap, val)); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] seat guard failed: " + ex.Message); } } private static void Service_CreateLobby_Prefix(ref int maxPlayers) { int effectiveCap = EffectiveCap; if (maxPlayers < effectiveCap) { maxPlayers = effectiveCap; } } private static void Service_OnLobbyCreated_Postfix(LobbyCreated_t result) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) try { if ((int)result.m_eResult == 1) { RaiseTransportCap(); CSteamID val = (CSteamID)result.m_ulSteamIDLobby; int effectiveCap = EffectiveCap; if (SteamMatchmaking.GetLobbyMemberLimit(val) < effectiveCap) { SteamMatchmaking.SetLobbyMemberLimit(val, effectiveCap); } int lobbyMemberLimit = SteamMatchmaking.GetLobbyMemberLimit(val); if (lobbyMemberLimit < effectiveCap) { MelonLogger.Warning($"[FullHouse] Steam kept the lobby member limit at {lobbyMemberLimit} (requested {effectiveCap}); advertising {lobbyMemberLimit}."); } SteamMatchmaking.SetLobbyData(val, "max_players", lobbyMemberLimit.ToString()); SteamMatchmaking.SetLobbyData(val, "num_slots", lobbyMemberLimit.ToString()); } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] OnLobbyCreated failed: " + ex.Message); } } private static void Service_OnLobbyEntered_Postfix(SteamLobbyService __instance, LobbyEnter_t result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) try { if (__instance == null || __instance._lobbyID == 0) { return; } CSteamID val = (CSteamID)result.m_ulSteamIDLobby; int result2 = 0; int.TryParse(SteamMatchmaking.GetLobbyData(val, "max_players"), out result2); int lobbyMemberLimit = SteamMatchmaking.GetLobbyMemberLimit(val); if (lobbyMemberLimit > 0 && result2 > lobbyMemberLimit) { result2 = lobbyMemberLimit; } if (result2 > _hostCap) { if (result2 > 32) { MelonLogger.Warning($"[FullHouse] this lobby seats {result2}, past the tested maximum of {32} - expect instability."); } _hostCap = result2; int effectiveCap = EffectiveCap; EnsurePlayers(__instance, effectiveCap); EnsureSlots(Singleton<LobbyInterface>.Instance, effectiveCap); MelonLogger.Msg($"[FullHouse] adopted host lobby cap {effectiveCap}."); } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] host-cap sync failed: " + ex.Message); } } private static void Service_LeaveLobby_Postfix() { if (_hostCap != 0) { _hostCap = 0; MelonLogger.Msg($"[FullHouse] left the lobby - back to the local cap of {Capacity}."); } } private static bool Service_OpenInviteUI_Prefix(SteamLobbyService __instance) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) try { if (__instance == null) { return true; } if (__instance._lobbyID == 0) { __instance.CreateLobby(EffectiveCap); return false; } CSteamID val = default(CSteamID); ((CSteamID)(ref val))..ctor(__instance._lobbyID); int num = EffectiveCap; int lobbyMemberLimit = SteamMatchmaking.GetLobbyMemberLimit(val); if (lobbyMemberLimit > 0 && lobbyMemberLimit < num) { num = lobbyMemberLimit; } if (SteamMatchmaking.GetNumLobbyMembers(val) >= num) { MelonLogger.Warning($"[FullHouse] lobby already at max capacity ({num})."); return false; } SteamFriends.ActivateGameOverlayInviteDialog(val); return false; } catch (Exception ex) { MelonLogger.Warning("[FullHouse] invite gate failed, falling back to vanilla: " + ex.Message); return true; } } private static void LobbyInterface_Start_Postfix(LobbyInterface __instance) { try { MelonCoroutines.Start(BuildUi(__instance)); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] UI coroutine start failed: " + ex.Message); } } private static void LobbyInterface_UpdateUI_Postfix(LobbyInterface __instance) { try { Lobby instance = Singleton<Lobby>.Instance; int num = (((Object)(object)instance != (Object)null) ? instance.PlayerCount : 0); if ((Object)(object)__instance?.LobbyTitle != (Object)null) { ((TMP_Text)__instance.LobbyTitle).text = "Lobby (" + num + "/" + EffectiveCap + ")"; } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] title sync failed: " + ex.Message); } } [HarmonyPriority(600)] private static void LobbyInterface_UpdateButtons_Postfix(LobbyInterface __instance) { try { Lobby instance = Singleton<Lobby>.Instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)__instance?.InviteButton == (Object)null)) { ((Component)__instance.InviteButton).gameObject.SetActive(instance.IsHost && instance.PlayerCount < EffectiveCap); } } catch (Exception ex) { MelonLogger.Warning("[FullHouse] invite button sync failed: " + ex.Message); } } private static IEnumerator BuildUi(LobbyInterface ui) { while ((Object)(object)Singleton<Lobby>.Instance == (Object)null) { yield return null; } bool steamReady = true; try { steamReady = SteamManager.Initialized; } catch { } if (steamReady) { EnsurePlayers(Service(), EffectiveCap); EnsureSlots(ui, EffectiveCap); } } private static void EnsureSlots(LobbyInterface ui, int target) { if ((Object)(object)ui == (Object)null) { return; } try { RectTransform[] playerSlots = ui.PlayerSlots; if (playerSlots == null || playerSlots.Length == 0) { MelonLogger.Warning("[FullHouse] lobby PlayerSlots not found."); return; } int num = playerSlots.Length; if (num >= target) { RefreshPlayers(ui); return; } RectTransform val = playerSlots[num - 1]; Transform parent = ((Transform)val).parent; RectTransform[] array = (RectTransform[])(object)new RectTransform[target]; for (int i = 0; i < num; i++) { array[i] = playerSlots[i]; } for (int j = num; j < target; j++) { GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent, false); ((Object)val2).name = ((Object)((Component)val).gameObject).name + " (" + j + ")"; array[j] = val2.GetComponent<RectTransform>(); } ui.PlayerSlots = array; RefreshPlayers(ui); } catch (Exception ex) { MelonLogger.Warning("[FullHouse] building lobby UI failed: " + ex.Message); } } private static void RefreshPlayers(LobbyInterface ui) { try { AccessTools.Method(typeof(LobbyInterface), "UpdatePlayers", (Type[])null, (Type[])null)?.Invoke(ui, null); } catch { } } } } namespace MultiplayerPVP { internal static class ImguiCompat { private static GUIStyle _style; internal static void DrawTexture(Rect position, Texture2D image) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Blit(position, image); } internal static void DrawTexture(Rect position, Texture2D image, ScaleMode scaleMode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) Blit(Fit(position, image, scaleMode), image); } private static Rect Fit(Rect position, Texture2D image, ScaleMode scaleMode) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)image == (Object)null || (int)scaleMode == 0) { return position; } float num = ((Texture)image).width; float num2 = ((Texture)image).height; if (num <= 0f || num2 <= 0f) { return position; } float num3 = (((int)scaleMode == 2) ? Mathf.Min(((Rect)(ref position)).width / num, ((Rect)(ref position)).height / num2) : Mathf.Max(((Rect)(ref position)).width / num, ((Rect)(ref position)).height / num2)); float num4 = num * num3; float num5 = num2 * num3; return new Rect(((Rect)(ref position)).x + (((Rect)(ref position)).width - num4) * 0.5f, ((Rect)(ref position)).y + (((Rect)(ref position)).height - num5) * 0.5f, num4, num5); } private static void Blit(Rect position, Texture2D image) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown if ((Object)(object)image == (Object)null) { return; } Event current = Event.current; if (current != null && (int)current.type == 7) { if (_style == null) { _style = new GUIStyle(); } _style.normal.background = image; Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = Color.white; _style.Draw(position, false, false, false, false); GUI.backgroundColor = backgroundColor; } } } public class MultiplayerPVPMod : MelonMod { private MatchController _controller; private PvpHud _hud; private PvpNet _net; internal static MultiplayerPVPMod Instance { get; private set; } internal MatchController Controller => _controller; internal PvpNet Net => _net; public override void OnInitializeMelon() { Instance = this; Lobbies.Install(); PvpConfig.Load(); _net = new PvpNet(); _net.Init(); _net.OnSighting += SightingRelay.OnReceived; _controller = new MatchController(_net); _hud = new PvpHud(); PvpAddonManager.Init(_net); RiotChaos.Init(); MelonLogger.Msg($"[MultiplayerPVP] v{((MelonBase)this).Info.Version} ready. Press {(object)(KeyCode)PvpConfig.PanelKey.Value} in-game to open the host panel."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { try { RiotChaos.OnSceneLoaded(); } catch { } try { _net?.Init(); _controller?.Cleanup(); _hud?.Reset(); SightingRelay.Reset(); ViewLock.Release(); } catch (Exception ex) { MelonLogger.Warning("OnSceneWasLoaded: " + ex.Message); } try { PvpAddonManager.SceneLoaded(buildIndex, sceneName); } catch (Exception ex2) { MelonLogger.Warning("OnSceneWasLoaded(addons): " + ex2.Message); } } public override void OnDeinitializeMelon() { try { RiotChaos.Deinit(); } catch { } try { PvpAddonManager.Deinit(); } catch { } try { ViewLock.Release(); _controller?.Cleanup(); _net?.Dispose(); } catch (Exception ex) { MelonLogger.Warning("OnDeinitializeMelon: " + ex.Message); } } public override void OnUpdate() { if (_controller == null) { return; } try { if (Input.GetKeyDown((KeyCode)PvpConfig.PanelKey.Value)) { if (_controller.Phase == MatchPhase.Idle) { _hud.PanelOpen = !_hud.PanelOpen; } else if (_controller.Phase == MatchPhase.Active && !_controller.IsRemote) { _hud.EndPromptOpen = !_hud.EndPromptOpen; } } if (_controller.Phase != MatchPhase.Active) { _hud.EndPromptOpen = false; } try { Player local = Player.Local; if ((Object)(object)local != (Object)null) { _net?.SetLocalIdentity(local.PlayerCode); } } catch { } _net?.Tick(); _controller.Tick(Time.deltaTime); PvpAddonManager.Tick(Time.deltaTime, _controller.Phase, _controller.ModeType, _controller.Day); RiotChaos.Tick(Time.deltaTime, _controller); UnlimitedAmmo.Tick(_controller); DoubleJump.Tick(_controller); bool locked = _hud.PanelOpen || _hud.EndPromptOpen || (_controller.Phase == MatchPhase.EndOfDay && !_controller.IsRemote); ViewLock.Set(locked); } catch (Exception ex) { MelonLogger.Warning("OnUpdate: " + ex.Message); } } public override void OnGUI() { if (_hud == null) { return; } try { _hud.Draw(_controller); } catch (Exception ex) { MelonLogger.Warning("OnGUI: " + ex.Message); } try { PvpAddonManager.DrawGui(); } catch (Exception ex2) { MelonLogger.Warning("OnGUI(addons): " + ex2.Message); } } } } namespace MultiplayerPVP.UI { internal class PvpHud { private struct DispRow { public int ColorIdx; public string Text; public int Kills; public int Downs; public int Arrests; public int BagsCap; public int BagsLost; public int WpnLost; public int WpnWon; public int PlayerIndex; public string Days; } internal bool PanelOpen; internal bool EndPromptOpen; private static Texture2D _white; private readonly List<WorldMarker> _markers = new List<WorldMarker>(); private Camera _cam; private int _camRevalidate; private int _hoverMode = -1; private PvpMatchToggle _hoverToggle; private readonly List<DispRow> _rows = new List<DispRow>(); private static Texture2D White { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_white == (Object)null) { _white = new Texture2D(1, 1); _white.SetPixel(0, 0, Color.white); _white.Apply(); } return _white; } } private static string FormatDays(string dotted) { return string.IsNullOrEmpty(dotted) ? "" : dotted.Replace(".", ", "); } internal void Reset() { _cam = null; _camRevalidate = 0; _markers.Clear(); PanelOpen = false; EndPromptOpen = false; } internal void Draw(MatchController mc) { //IL_0147: Unknown result type (might be due to invalid IL or missing references) if (mc == null) { return; } Safe(delegate { DrawBanner(mc); }); Safe(delegate { DrawLocalBanner(mc); }); switch (mc.Phase) { case MatchPhase.Countdown: case MatchPhase.Active: { bool flag = true; Safe(delegate { DrawCountdown(mc); }); Safe(delegate { DrawScoreboard(mc, 220f); }); Safe(delegate { DrawMarkers(mc); }); if (mc.IsRemote) { Safe(delegate { DrawClientModeCard(mc); }); } break; } case MatchPhase.EndOfDay: Safe(delegate { DrawEndOfDayMenu(mc); }); break; case MatchPhase.Idle: if (PanelOpen) { Safe(delegate { DrawHostPanel(mc); }); } break; } if (EndPromptOpen && mc.Phase == MatchPhase.Active && !mc.IsRemote) { Safe(delegate { DrawEndMatchPrompt(mc); }); } GUI.color = Color.white; } private static void Safe(Action draw) { try { draw(); } catch (Exception ex) { MelonLogger.Warning("HUD draw: " + ex.Message); } } private void DrawBanner(MatchController mc) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) if (mc.Announcer.HasBanner) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 40, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, (float)Screen.height * 0.14f, (float)Screen.width, 60f); GUI.color = Color.black; GUI.Label(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), mc.Announcer.Banner, val); GUI.color = new Color(1f, 0.85f, 0.2f); GUI.Label(val2, mc.Announcer.Banner, val); GUI.color = Color.white; } } private void DrawLocalBanner(MatchController mc) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (mc.Announcer.HasLocalBanner) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 26, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, (float)Screen.height * 0.21f, (float)Screen.width, 44f); GUI.color = Color.black; GUI.Label(new Rect(((Rect)(ref val2)).x + 2f, ((Rect)(ref val2)).y + 2f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), mc.Announcer.LocalBanner, val); GUI.color = mc.Announcer.LocalBannerColor; GUI.Label(val2, mc.Announcer.LocalBanner, val); GUI.color = Color.white; } } private void DrawCountdown(MatchController mc) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) string text; if (mc.Phase == MatchPhase.Countdown) { text = "Starting…"; } else { int num = Mathf.Max(0, Mathf.CeilToInt(mc.RemainingSeconds)); text = $"{GameModeInfo.Title(mc.ModeType)} · Day {mc.Day} · {num / 60:0}:{num % 60:00}"; } GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 20, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor((float)Screen.width * 0.5f - 220f, 70f, 440f, 28f); GUI.color = new Color(0f, 0f, 0f, 0.55f); ImguiCompat.DrawTexture(val2, White); GUI.color = Color.white; GUI.Label(val2, text, val); } private void DrawLoadoutCard(Rect anchor) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) List<string> list = StartingLoadout.Buttons(); float num = 210f; float num2 = Mathf.Max(((Rect)(ref anchor)).height, 64f + (float)list.Count * 24f + 60f); Rect position = default(Rect); ((Rect)(ref position))..ctor(((Rect)(ref anchor)).x - num - 10f, ((Rect)(ref anchor)).y, num, num2); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1 }; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 11, wordWrap = true }; GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 8f, num - 20f, 20f), "STARTING LOADOUT", val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 28f, num - 20f, 30f), "Every player gets the checked items at round start.", val2); float num3 = ((Rect)(ref position)).y + 62f; for (int i = 0; i < list.Count; i++) { string id = list[i]; bool flag = StartingLoadout.IsChecked(id); bool flag2 = GUI.Toggle(new Rect(((Rect)(ref position)).x + 12f, num3, num - 24f, 22f), flag, " " + StartingLoadout.LabelOf(id)); if (flag2 != flag) { StartingLoadout.SetChecked(id, flag2); } num3 += 24f; } num3 += 6f; GUI.color = new Color(1f, 1f, 1f, 0.15f); ImguiCompat.DrawTexture(new Rect(((Rect)(ref position)).x + 10f, num3, num - 20f, 1f), White); GUI.color = Color.white; num3 += 6f; bool flag3 = UnlimitedAmmo.Checked; bool flag4 = GUI.Toggle(new Rect(((Rect)(ref position)).x + 12f, num3, num - 24f, 22f), flag3, " unlimited ammo (this round)"); if (flag4 != flag3) { UnlimitedAmmo.SetChecked(flag4); } num3 += 24f; bool flag5 = DoubleJump.Checked; bool flag6 = GUI.Toggle(new Rect(((Rect)(ref position)).x + 12f, num3, num - 24f, 22f), flag5, " double jump (this round)"); if (flag6 != flag5) { DoubleJump.SetChecked(flag6); } } private void DrawModeInfoCard(Rect anchor) { //IL_003c: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) Rect position = default(Rect); ((Rect)(ref position))..ctor(((Rect)(ref anchor)).xMax + 10f, ((Rect)(ref anchor)).y, 240f, ((Rect)(ref anchor)).height); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, wordWrap = true }; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 12, wordWrap = true }; if (_hoverToggle != null) { GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 10f, 220f, 44f), _hoverToggle.Label + " (modifier)", val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 48f, 220f, ((Rect)(ref position)).height - 58f), _hoverToggle.Description, val2); } else if (_hoverMode >= 0) { GameModeType hoverMode = (GameModeType)_hoverMode; GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 10f, 220f, 44f), GameModeInfo.Title(hoverMode), val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 48f, 220f, ((Rect)(ref position)).height - 58f), GameModeInfo.Description(hoverMode), val2); } else { GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 10f, 220f, ((Rect)(ref position)).height - 20f), "Hover a mode button to see what it does.", val2); } } private void DrawClientModeCard(MatchController mc) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) Rect position = default(Rect); ((Rect)(ref position))..ctor(12f, 70f, 290f, 116f); GUI.color = new Color(0f, 0f, 0f, 0.6f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 15, fontStyle = (FontStyle)1, wordWrap = true }; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 12, wordWrap = true }; GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 8f, 270f, 22f), GameModeInfo.Title(mc.ModeType), val); GUI.Label(new Rect(((Rect)(ref position)).x + 10f, ((Rect)(ref position)).y + 32f, 270f, 76f), GameModeInfo.Description(mc.ModeType), val2); } private void BuildRows(MatchController mc) { _rows.Clear(); if (mc.IsRemote ? (mc.RemoteTeamRows.Count > 0) : mc.IsTeamScoredMode) { if (mc.IsRemote) { for (int i = 0; i < mc.RemoteTeamRows.Count; i++) { SnapTeamRow snapTeamRow = mc.RemoteTeamRows[i]; _rows.Add(new DispRow { ColorIdx = snapTeamRow.Team, Text = snapTeamRow.Name + " — " + snapTeamRow.Score, Kills = snapTeamRow.Kills, Downs = snapTeamRow.Downs, Arrests = snapTeamRow.Arrests, BagsCap = snapTeamRow.BagsCaptured, BagsLost = snapTeamRow.BagsLost, WpnLost = snapTeamRow.WeaponsLost, WpnWon = snapTeamRow.WeaponsWon, PlayerIndex = -1 }); } return; } int activeTeamCount = mc.ActiveTeamCount; List<PvpPlayer> players = mc.Registry.Players; for (int j = 0; j < activeTeamCount; j++) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; for (int k = 0; k < players.Count; k++) { PvpPlayer pvpPlayer = players[k]; if (pvpPlayer.Team == j) { num += pvpPlayer.Kills; num2 += pvpPlayer.Downs; num3 += pvpPlayer.Arrests; num4 += pvpPlayer.BagsCaptured; num5 += pvpPlayer.BagsLost; num6 += pvpPlayer.WeaponsLost; num7 += pvpPlayer.WeaponsWon; } } string text = ""; try { if (mc.CurrentMode != null) { text = mc.CurrentMode.TeamScoreText(mc.Context, j); } } catch { } _rows.Add(new DispRow { ColorIdx = j, Text = mc.Registry.TeamLabel(j) + " — " + text, Kills = num, Downs = num2, Arrests = num3, BagsCap = num4, BagsLost = num5, WpnLost = num6, WpnWon = num7, PlayerIndex = -1 }); } return; } if (mc.IsRemote) { for (int l = 0; l < mc.RemoteRows.Count; l++) { SnapRow snapRow = mc.RemoteRows[l]; _rows.Add(new DispRow { ColorIdx = snapRow.Index, Text = snapRow.Name + " — " + snapRow.Score, Kills = snapRow.Kills, Downs = snapRow.Downs, Arrests = snapRow.Arrests, BagsCap = snapRow.BagsCaptured, BagsLost = snapRow.BagsLost, WpnLost = snapRow.WeaponsLost, WpnWon = snapRow.WeaponsWon, PlayerIndex = snapRow.Index, Days = FormatDays(snapRow.History) }); } return; } List<PvpPlayer> players2 = mc.Registry.Players; for (int m = 0; m < players2.Count; m++) { PvpPlayer pvpPlayer2 = players2[m]; string text2 = ""; string text3 = pvpPlayer2.Name; try { if (mc.CurrentMode != null) { text2 = mc.CurrentMode.ScoreText(pvpPlayer2); text3 = mc.CurrentMode.DisplayName(pvpPlayer2); } } catch { } string days = ""; List<int> list = mc.HistoryOf(pvpPlayer2); if (list != null && list.Count >= 2) { days = string.Join(", ", list); } _rows.Add(new DispRow { ColorIdx = pvpPlayer2.Index, Text = text3 + " — " + text2, Kills = pvpPlayer2.Kills, Downs = pvpPlayer2.Downs, Arrests = pvpPlayer2.Arrests, BagsCap = pvpPlayer2.BagsCaptured, BagsLost = pvpPlayer2.BagsLost, WpnLost = pvpPlayer2.WeaponsLost, WpnWon = pvpPlayer2.WeaponsWon, PlayerIndex = pvpPlayer2.Index, Days = days }); } } private void DrawScoreboard(MatchController mc, float width) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) if (!mc.IsRemote && mc.CurrentMode == null) { return; } BuildRows(mc); int count = _rows.Count; if (count != 0) { float num = 26 + count * 22 + 8; Rect position = default(Rect); ((Rect)(ref position))..ctor((float)Screen.width - width - 12f, 50f, width, num); GUI.color = new Color(0f, 0f, 0f, 0.55f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 14, fontStyle = (FontStyle)1 }; GUI.Label(new Rect(((Rect)(ref position)).x + 8f, ((Rect)(ref position)).y + 4f, width - 16f, 20f), "SCOREBOARD", val); GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 13 }; for (int i = 0; i < count; i++) { float num2 = ((Rect)(ref position)).y + 26f + (float)(i * 22); DispRow dispRow = _rows[i]; GUI.color = PvpColors.For(dispRow.ColorIdx); ImguiCompat.DrawTexture(new Rect(((Rect)(ref position)).x + 8f, num2 + 4f, 10f, 10f), White); GUI.color = Color.white; GUI.Label(new Rect(((Rect)(ref position)).x + 24f, num2, width - 32f, 20f), dispRow.Text, val2); } } } private void DrawMarkers(MatchController mc) { //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) if (_camRevalidate-- <= 0 || (Object)(object)_cam == (Object)null) { _cam = Camera.main; _camRevalidate = 30; } if ((Object)(object)_cam == (Object)null) { return; } _markers.Clear(); if (mc.IsRemote) { List<SnapMarker> remoteMarkers = mc.RemoteMarkers; for (int i = 0; i < remoteMarkers.Count; i++) { _markers.Add(new WorldMarker(remoteMarkers[i].Pos, remoteMarkers[i].Color, remoteMarkers[i].Label, remoteMarkers[i].Team)); } } else { if (!(mc.CurrentMode is IWorldMarkers worldMarkers)) { return; } try { worldMarkers.CollectMarkers(mc.Context, mc.Registry.Local, _markers); } catch { return; } } if (_markers.Count == 0) { return; } int num = mc.LocalTeam(); GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 12, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; for (int j = 0; j < _markers.Count; j++) { WorldMarker worldMarker = _markers[j]; if (worldMarker.Team < 0 || worldMarker.Team == num) { Vector3 val2; try { val2 = _cam.WorldToScreenPoint(worldMarker.Pos); } catch { continue; } if (!(val2.z <= 0f)) { float x = val2.x; float num2 = (float)Screen.height - val2.y; GUI.color = worldMarker.Color; ImguiCompat.DrawTexture(new Rect(x - 2f, num2 - 80f, 4f, 80f), White); ImguiCompat.DrawTexture(new Rect(x - 7f, num2 - 7f, 14f, 14f), White); GUI.color = Color.black; GUI.Label(new Rect(x - 99f, num2 - 104f, 200f, 18f), worldMarker.Label, val); GUI.color = worldMarker.Color; GUI.Label(new Rect(x - 100f, num2 - 105f, 200f, 18f), worldMarker.Label, val); } } } GUI.color = Color.white; } private void DrawEndOfDayMenu(MatchController mc) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0298: 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_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04de: Expected O, but got Unknown //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Expected O, but got Unknown //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_056d: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) //IL_05ae: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Unknown result type (might be due to invalid IL or missing references) //IL_0534: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_0654: Unknown result type (might be due to invalid IL or missing references) BuildRows(mc); int count = _rows.Count; float num = ModeGridHeight(); float num2 = Mathf.Max(0f, num - 104f); float num3 = 560f; float num4 = Mathf.Clamp(78f + (float)count * 46f + 200f + num2, 470f + num2, (float)(Screen.height - 40)); Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width * 0.5f - num3 / 2f, (float)Screen.height * 0.5f - num4 / 2f, num3, num4); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(val, White); GUI.color = Color.white; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 24, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 12f, num3, 32f), $"END OF DAY {mc.Day}", val2); GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = 15, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 46f, num3, 22f), mc.DayResult ?? "", val3); GUIStyle val4 = new GUIStyle(GUI.skin.label) { fontSize = 14 }; GUIStyle val5 = new GUIStyle(GUI.skin.label) { fontSize = 12 }; float num5 = ((Rect)(ref val)).y + 78f; int num6 = Mathf.Max(1, Mathf.FloorToInt((num4 - 268f - num2) / 46f)); if (count > num6) { num6 = Mathf.Max(1, num6 - 1); } int num7 = Mathf.Min(count, num6); for (int i = 0; i < num7; i++) { DispRow dispRow = _rows[i]; string text = dispRow.Text; if (!string.IsNullOrEmpty(dispRow.Days)) { text = text + " (days: " + dispRow.Days + ")"; } float num8 = num5 + (float)i * 46f; GUI.color = PvpColors.For(dispRow.ColorIdx); ImguiCompat.DrawTexture(new Rect(((Rect)(ref val)).x + 30f, num8 + 4f, 10f, 10f), White); GUI.color = Color.white; GUI.Label(new Rect(((Rect)(ref val)).x + 48f, num8, num3 - 80f, 20f), $"{i + 1}. {text}", val4); string text2 = mc.ModeType switch { GameModeType.StealTheBags => $"Bags captured {dispRow.BagsCap} · Bags lost {dispRow.BagsLost}", GameModeType.Teams => $"Kills {dispRow.Kills} · Downs {dispRow.Downs} · Weapons won {dispRow.WpnWon} · Weapons lost {dispRow.WpnLost}", _ => $"Kills {dispRow.Kills} · Downs {dispRow.Downs} · Cuffs {dispRow.Arrests}", }; GUI.color = new Color(0.78f, 0.82f, 0.9f); GUI.Label(new Rect(((Rect)(ref val)).x + 48f, num8 + 22f, num3 - 80f, 18f), text2, val5); GUI.color = Color.white; } if (count > num7) { GUIStyle val6 = new GUIStyle(GUI.skin.label) { fontSize = 12, fontStyle = (FontStyle)2 }; GUI.color = new Color(0.7f, 0.75f, 0.85f); GUI.Label(new Rect(((Rect)(ref val)).x + 48f, num5 + (float)num7 * 46f, num3 - 80f, 18f), $"+ {count - num7} more…", val6); GUI.color = Color.white; } GUIStyle val7 = new GUIStyle(GUI.skin.label) { fontSize = 13, alignment = (TextAnchor)4 }; if (mc.IsRemote) { GUI.color = new Color(1f, 0.85f, 0.3f); GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + num4 - 90f, num3, 22f), "Waiting for the host to choose the next mode…", val7); GUI.color = Color.white; return; } float num9 = ((Rect)(ref val)).y + num4 - 168f - num2; GUI.Label(new Rect(((Rect)(ref val)).x, num9 - 22f, num3, 18f), "Host: choose the next mode to start the morning", val7); DrawModeGrid(mc, new Rect(((Rect)(ref val)).x + 20f, num9, num3 - 40f, num), fresh: true); DrawModeInfoCard(val); DrawLoadoutCard(val); float num10 = ((Rect)(ref val)).y + num4 - 44f; if (mc.HasActiveMode && GUI.Button(new Rect(((Rect)(ref val)).x + 20f, num10, (num3 - 50f) / 2f, 30f), "Continue " + GameModeInfo.Title(mc.ModeType) + " (next day)")) { mc.RequestContinue(); } if (GUI.Button(new Rect(((Rect)(ref val)).x + 30f + (num3 - 50f) / 2f, num10, (num3 - 50f) / 2f, 30f), "Stop match")) { mc.RequestStop(); } } private void DrawHostPanel(MatchController mc) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) float num = ModeGridHeight(); float num2 = 540f; float num3 = 250f + Mathf.Max(0f, num - 104f); Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width * 0.5f - num2 / 2f, (float)Screen.height * 0.5f - num3 / 2f, num2, num3); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.92f); ImguiCompat.DrawTexture(val, White); GUI.color = Color.white; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 22, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 12f, num2, 30f), "MULTIPLAYER PVP", val2); GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = 13, alignment = (TextAnchor)4 }; GUIStyle val4 = new GUIStyle(GUI.skin.label) { fontSize = 15, alignment = (TextAnchor)4, wordWrap = true }; if (!mc.IsMultiplayer) { GUI.color = new Color(1f, 0.7f, 0.3f); GUI.Label(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 70f, num2 - 40f, 80f), "This mod is multiplayer-only.\nHost or join a co-op lobby with 2+ players,\nthen press the host key again.", val4); GUI.color = Color.white; } else if (!mc.IsHost) { GUI.color = new Color(1f, 0.7f, 0.3f); GUI.Label(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 70f, num2 - 40f, 80f), "Only the host controls the match.\nThe host picks the game mode.", val4); GUI.color = Color.white; } else { GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 44f, num2, 18f), $"{SessionUtil.PlayerCount()} player(s) · pick a mode to start", val3); Rect area = default(Rect); ((Rect)(ref area))..ctor(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 70f, num2 - 40f, num); DrawModeGrid(mc, area, fresh: true); DrawModeInfoCard(val); DrawLoadoutCard(val); } if (GUI.Button(new Rect(((Rect)(ref val)).x + num2 - 110f, ((Rect)(ref val)).y + num3 - 34f, 90f, 26f), "Close")) { PanelOpen = false; } } private void DrawEndMatchPrompt(MatchController mc) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) float num = 440f; float num2 = 180f; Rect position = default(Rect); ((Rect)(ref position))..ctor((float)Screen.width * 0.5f - num / 2f, (float)Screen.height * 0.5f - num2 / 2f, num, num2); GUI.color = new Color(0.05f, 0.05f, 0.08f, 0.95f); ImguiCompat.DrawTexture(position, White); GUI.color = Color.white; GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 20, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; GUI.Label(new Rect(((Rect)(ref position)).x, ((Rect)(ref position)).y + 16f, num, 28f), "END MATCH EARLY?", val); GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 14, alignment = (TextAnchor)4, wordWrap = true }; GUI.Label(new Rect(((Rect)(ref position)).x + 24f, ((Rect)(ref position)).y + 52f, num - 48f, 44f), "End the running match now? The countdown drops to 3 seconds and the day is scored as normal.", val2); if (GUI.Button(new Rect(((Rect)(ref position)).x + 40f, ((Rect)(ref position)).y + num2 - 64f, num - 80f, 38f), "End match early")) { EndPromptOpen = false; mc.RequestEndEarly(); } GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = 11, alignment = (TextAnchor)4 }; GUI.color = new Color(0.7f, 0.75f, 0.85f); GUI.Label(new Rect(((Rect)(ref position)).x, ((Rect)(ref position)).y + num2 - 22f, num, 16f), $"Press {(object)(KeyCode)PvpConfig.PanelKey.Value} again to cancel", val3); GUI.color = Color.white; } private static float ModeGridHeight() { int num = 7 + MatchToggles.Snapshot().Length; int num2 = (num + 3) / 4; return (float)num2 * 48f + (float)(num2 - 1) * 8f; } private void DrawModeGrid(MatchController mc, Rect area, bool fresh) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) int num = 7; float num2 = (((Rect)(ref area)).width - 24f) / 4f; float num3 = 48f; _hoverMode = -1; _hoverToggle = null; Vector2 val = (Vector2)((Event.current != null) ? Event.current.mousePosition : new Vector2(-1f, -1f)); Rect val2 = default(Rect); for (int i = 0; i < num; i++) { int num4 = i / 4; int num5 = i % 4; ((Rect)(ref val2))..ctor(((Rect)(ref area)).x + (float)num5 * (num2 + 8f), ((Rect)(ref area)).y + (float)num4 * (num3 + 8f), num2, num3); if (((Rect)(ref val2)).Contains(val)) { _hoverMode = i; } GameModeType gameModeType = (GameModeType)i; if (GUI.Button(val2, $"{i + 1}. {GameModeInfo.Title(gameModeType)}")) { PanelOpen = false; if (fresh) { mc.RequestStart(gameModeType); } } } PvpMatchToggle[] array = MatchToggles.Snapshot(); Rect val3 = default(Rect); for (int j = 0; j < array.Length; j++) { int num6 = num + j; int num7 = num6 / 4; int num8 = num6 % 4; ((Rect)(ref val3))..ctor(((Rect)(ref area)).x + (float)num8 * (num2 + 8f), ((Rect)(ref area)).y + (float)num7 * (num3 + 8f), num2, num3); PvpMatchToggle pvpMatchToggle = array[j]; if (((Rect)(ref val3)).Contains(val)) { _hoverToggle = pvpMatchToggle; } GUI.color = (pvpMatchToggle.Requested ? new Color(0.55f, 1f, 0.55f) : new Color(0.85f, 0.85f, 0.9f)); if (GUI.Button(val3, pvpMatchToggle.Label + "\n" + (pvpMatchToggle.Requested ? "ON (this round)" : "OFF"))) { pvpMatchToggle.Requested = !pvpMatchToggle.Requested; } GUI.color = Color.white; } } } internal static class ViewLock { private static bool _locked; internal static void Set(bool locked) { if (locked != _locked) { _locked = locked; try { PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(!locked); if (locked) { instance.FreeMouse(true); } else { instance.LockMouse(true); } } } catch { } } if (locked) { try { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } catch { } } } internal static void Release() { if (!_locked) { return; } _locked = false; try { PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance; if ((Object)(object)instance != (Object)null) { instance.SetCanLook(true); instance.LockMouse(true); } } catch { } } } } namespace MultiplayerPVP.Net { internal struct SnapRow { internal string Name; internal int Team; internal int Index; internal string Score; internal bool Bag; internal Vector3 Spawn; internal int Kills; internal int Downs; internal int Arrests; internal int BagsCaptured; internal int BagsLost; internal int WeaponsLost; internal int WeaponsWon; internal string History; } internal struct SnapTeamRow { internal int Team; internal string Name; internal string Score; internal int Kills; internal int Downs; internal int Arrests; internal int BagsCaptured; internal int BagsLost; internal int WeaponsLost; internal int WeaponsWon; } internal struct SnapMarker { internal Vector3 Pos; internal Color Color; internal string Label; internal int Team; } internal class MatchSnapshot { internal int Phase; internal int Mode; internal int Day; internal float Remaining; internal string Banner = ""; internal string Result = ""; internal string Loot = ""; internal bool Chaos; internal bool Ammo; internal bool Jump; internal string Loadout = ""; internal long RoundId; internal readonly List<SnapRow> Rows = new List<SnapRow>(); internal readonly List<SnapTeamRow> TeamRows = new List<SnapTeamRow>(); internal readonly List<SnapMarker> Markers = new List<SnapMarker>(); internal long Seq; private static string San(string s) { if (string.IsNullOrEmpty(s)) { return ""; } return s.Replace('|', ' ').Replace('~', ' ').Replace(';', ' ') .Replace('=', ' ') .Replace(',', ' ') .Replace('"', ' ') .Replace('\\', ' '); } private static string F(float v) { return v.ToString("0.0", CultureInfo.InvariantCulture); } internal string Serialize() { //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(192); stringBuilder.Append("v=1|sq=").Append(Seq).Append("|ph=") .Append(Phase) .Append("|md=") .Append(Mode) .Append("|day=") .Append(Day) .Append("|rs=") .Append(Remaining.ToString("0.0", CultureInfo.InvariantCulture)) .Append("|bn=") .Append(San(Banner)) .Append("|rz=") .Append(San(Result)) .Append("|lt=") .Append(Loot ?? "") .Append("|cx=") .Append(Chaos ? 1 : 0) .Append("|ua=") .Append(Ammo ? 1 : 0) .Append("|dj=") .Append(Jump ? 1 : 0) .Append("|gi=") .Append(Loadout ?? "") .Append("|gr=") .Append(RoundId) .Append("|p="); for (int i = 0; i < Rows.Count; i++) { SnapRow snapRow = Rows[i]; if (i > 0) { stringBuilder.Append(';'); } stringBuilder.Append(San(snapRow.Name)).Append('~').Append(snapRow.Team) .Append('~') .Append(snapRow.Index) .Append('~') .Append(San(snapRow.Score)) .Append('~') .Append(snapRow.Bag ? 1 : 0) .Append('~') .Append(F(snapRow.Spawn.x)) .Append('~') .Append(F(snapRow.Spawn.y)) .Append('~') .Append(F(snapRow.Spawn.z)) .Append('~') .Append(snapRow.Kills) .Append('~') .Append(snapRow.Downs) .Append('~') .Append(snapRow.Arrests) .Append('~') .Append(snapRow.BagsCaptured) .Append('~') .Append(snapRow.BagsLost) .Append('~') .Append(snapRow.WeaponsLost) .Append('~') .Append(snapRow.WeaponsWon) .Append('~') .Append(San(snapRow.History)); } stringBuilder.Append("|tr="); for (int j = 0; j < TeamRows.Count; j++) { SnapTeamRow snapTeamRow = TeamRows[j]; if (j > 0) { stringBuilder.Append(';'); } stringBuilder.Append(snapTeamRow.Team).Append('~').Append(San(snapTeamRow.Name)) .Append('~') .Append(San(snapTeamRow.Score)) .Append('~') .Append(snapTeamRow.Kills) .Append('~') .Append(snapTeamRow.Downs) .Append('~') .Append(snapTeamRow.Arrests) .Append('~') .Append(snapTeamRow.BagsCaptured) .Append('~') .Append(snapTeamRow.BagsLost) .Append('~') .Append(snapTeamRow.WeaponsLost) .Append('~') .Append(snapTeamRow.WeaponsWon); } stringBuilder.Append("|m="); for (int k = 0; k < Markers.Count; k++) { SnapMarker snapMarker = Markers[k]; if (k > 0) { stringBuilder.Append(','); } stringBuilder.Append(F(snapMarker.Pos.x)).Append('~').Append(F(snapMarker.Pos.y)) .Append('~') .Append(F(snapMarker.Pos.z)) .Append('~') .Append(F(snapMarker.Color.r)) .Append('~') .Append(F(snapMarker.Color.g)) .Append('~') .Append(F(snapMarker.Color.b)) .Append('~') .Append(San(snapMarker.Label)) .Append('~') .Append(snapMarker.Team); } return stringBuilder.ToString(); } internal static bool TryParse(string s, MatchSnapshot into) { //IL_08ff: Unknown result type (might be due to invalid IL or missing references) //IL_0904: Unknown result type (might be due to invalid IL or missing references) //IL_0916: Unknown result type (might be due to invalid IL or missing references) //IL_091b: Unknown result type (might be due to invalid IL or missing references) //IL_05a0: Unknown result type (might be due to invalid IL or missing references) //IL_05a5: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(s) || into == null) { return false; } try { into.Rows.Clear(); into.TeamRows.Clear(); into.Markers.Clear(); into.Banner = ""; into.Result = ""; into.Loot = ""; into.Chaos = false; into.Ammo = false; into.Jump = false; into.Loadout = ""; into.RoundId = 0L; string[] array = s.Split(new char[1] { '|' }); string[] array2 = array; foreach (string text in array2) { int num = text.IndexOf('='); if (num < 0) { continue; } string text2 = text.Substring(0, num); string text3 = text.Substring(num + 1); switch (text2) { case "sq": long.TryParse(text3, out into.Seq); break; case "ph": int.TryParse(text3, out into.Phase); break; case "md": int.TryParse(text3, out into.Mode); break; case "day": int.TryParse(text3, out into.Day); break; case "rs": float.TryParse(text3, NumberStyles.Float, CultureInfo.InvariantCulture, out into.Remaining); break; case "bn": into.Banner = text3; break; case "rz": into.Result = text3; break; case "lt": into.Loot = text3; break; case "cx": into.Chaos = text3 == "1"; break; case "ua": into.Ammo = text3 == "1"; break; case "dj": into.Jump = text3 == "1"; break; case "gi": into.Loadout = text3; break; case "gr": long.TryParse(text3, out into.RoundId); break; case "p": { if (text3.Length == 0) { break; } string[] array7 = text3.Split(new char[1] { ';' }); foreach (string text6 in array7) { string[] array8 = text6.Split(new char[1] { '~' }); if (array8.Length >= 4) { SnapRow item3 = new SnapRow { Name = array8[0], Score = array8[3] }; int.TryParse(array8[1], out item3.Team); int.TryParse(array8[2], out item3.Index); if (array8.Length >= 5) { item3.Bag = array8[4] == "1"; } if (array8.Length >= 8) { float.TryParse(array8[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result7); float.TryParse(array8[6], NumberStyles.Float, CultureInfo.InvariantCulture, out var result8); float.TryParse(array8[7], NumberStyles.Float, CultureInfo.InvariantCulture, out var result9); item3.Spawn = new Vector3(result7, result8, result9); } if (array8.Length >= 11) { int.TryParse(array8[8], out item3.Kills); int.TryParse(array8[9], out item3.Downs); int.TryParse(array8[10], out item3.Arrests); } if (array8.Length >= 15) { int.TryParse(array8[11], out item3.BagsCaptured); int.TryParse(array8[12], out item3.BagsLost); int.TryParse(array8[13], out item3.WeaponsLost); int.TryParse(array8[14], out item3.WeaponsWon); } if (array8.Length >= 16) { item3.History = array8[15]; } into.Rows.Add(item3); } } break; } case "tr": { if (text3.Length == 0) { break; } string[] array5 = text3.Split(new char[1] { ';' }); foreach (string text5 in array5) { string[] array6 = text5.Split(new char[1] { '~' }); if (array6.Length >= 3) { SnapTeamRow item2 = new SnapTeamRow { Name = array6[1], Score = array6[2] }; int.TryParse(array6[0], out item2.Team); if (array6.Length >= 10) { int.TryParse(array6[3], out item2.Kills); int.TryParse(array6[4], out item2.Downs); int.TryParse(array6[5], out item2.Arrests); int.TryParse(array6[6], out item2.BagsCaptured); int.TryParse(array6[7], out item2.BagsLost); int.TryParse(array6[8], out item2.WeaponsLost); int.TryParse(array6[9], out item2.WeaponsWon); } into.TeamRows.Add(item2); } } break; } case "m": { if (text3.Length == 0) { break; } string[] array3 = text3.Split(new char[1] { ',' }); foreach (string text4 in array3) { string[] array4 = text4.Split(new char[1] { '~' }); if (array4.Length >= 7) { SnapMarker item = new SnapMarker { Label = array4[6], Team = -1 }; float.TryParse(array4[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result); float.TryParse(array4[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2); float.TryParse(array4[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3); float.TryParse(array4[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4); float.TryParse(array4[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result5); float.TryParse(array4[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result6); if (array4.Length >= 8) { int.TryParse(array4[7], out item.Team); } item.Pos = new Vector3(result, result2, result3); item.Color = new Color(result4, result5, result6, 1f); into.Markers.Add(item); } } break; } } } return true; } catch { return false; } } } internal sealed class PvpNet { internal const string KeyPrefix = "mpvp_"; internal const string SnapshotKey = "snap"; internal const string ModTagKey = "mod"; internal const string LootKey = "loot"; internal const string EarnKey = "earn"; internal const string SpillKey = "spill"; internal const string IdTagKey = "idtag"; internal const string SightKey = "sight"; private SteamNetworkClient _client; private HostSyncVar<string> _snap; private ClientSyncVar<string> _modTag; private ClientSyncVar<string> _loot; private ClientSyncVar<string> _earn; private ClientSyncVar<string> _spill; private ClientSyncVar<string> _idTag; private ClientSyncVar<string> _sight; private readonly List<ClientSyncVar<string>> _addonVars = new List<ClientSyncVar<string>>(); private bool _init; private static readonly string ModTag = "MultiplayerPVP/" + ModVersion(); private bool _wasInLobby; private bool _tagSet; private string _idCode; private bool _idSet; private const float WarnInterval = 15f; private float _lastWarn = -999f; internal bool Available => _init && _client != null; internal bool IsInLobby { get { try { return Available && _client.IsInLobby; } catch { return false; } } } internal bool IsHost { get { try { return Available && _client.IsHost; } catch { return false; } } } internal ulong LocalSteamId { get { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!Available) { return 0uL; } try { foreach (MemberInfo lobbyMember in _client.GetLobbyMembers()) { if (lobbyMember != null && lobbyMember.IsLocalPlayer) { return lobbyMember.SteamId.m_SteamID; } } } catch { } return 0uL; } } internal int ModdedMemberCount { get { if (_modTag == null) { return 0; } try { int num = 0; foreach (KeyValuePair<CSteamID, string> allValue in _modTag.GetAllValues()) { if (!string.IsNullOrEmpty(allValue.Value)) { num++; } } return num; } catch { return 0; } } } internal int MemberCount { get { try { return Available ? _client.GetLobbyMembers().Count : 0; } catch { return 0; } } } internal bool AllMembersModded { get { int memberCount = MemberCount; return memberCount > 0 && ModdedMemberCount >= memberCount; } } internal event Action<string> OnSnapshot; internal event Action<ulong, string> OnLoot; internal event Action<ulong, string> OnSpill; internal event Action<ulong, string> OnSighting; internal void Init() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (_init) { return; } try { _client = new SteamNetworkClient(); if (!_client.Initialize()) { return; } try { _client.OnVersionMismatch += OnVersionMismatch; } catch { } NetworkSyncOptions val = MakeOpts(); _snap = _client.CreateHostSyncVar<string>("snap", "", val, (ISyncValidator<string>)null); _snap.OnValueChanged += OnSnapValueChanged; _snap.OnSyncError += OnSyncError; _modTag = _client.CreateClientSyncVar<string>("mod", "", val, (ISyncValidator<string>)null); _loot = _client.CreateClientSyncVar<string>("loot", "", val, (ISyncValidator<string>)null); _loot.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { this.OnLoot?.Invoke(from.m_SteamID, newV); } } catch { } }; _earn = _client.CreateClientSyncVar<string>("earn", "", val, (ISyncValidator<string>)null); _spill = _client.CreateClientSyncVar<string>("spill", "", val, (ISyncValidator<string>)null); _spill.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { this.OnSpill?.Invoke(from.m_SteamID, newV); } } catch { } }; _idTag = _client.CreateClientSyncVar<string>("idtag", "", val, (ISyncValidator<string>)null); _sight = _client.CreateClientSyncVar<string>("sight", "", val, (ISyncValidator<string>)null); _sight.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { this.OnSighting?.Invoke(from.m_SteamID, newV); } } catch { } }; _init = true; PvpLog.Debug("[MultiplayerPVP][Net] SteamNetworkClient initialized (HostSyncVar transport)."); } catch { } } private static NetworkSyncOptions MakeOpts() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown return new NetworkSyncOptions { KeyPrefix = "mpvp_", AutoSync = true, SyncOnPlayerJoin = true, MaxSyncsPerSecond = 0 }; } internal ClientSyncVar<string> CreateAddonVar(string keySuffix, Action<ulong, string> onMessage) { if (!_init || _client == null || string.IsNullOrEmpty(keySuffix)) { return null; } try { ClientSyncVar<string> val = _client.CreateClientSyncVar<string>(keySuffix, "", MakeOpts(), (ISyncValidator<string>)null); if (onMessage != null) { val.OnValueChanged += delegate(CSteamID from, string oldV, string newV) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) try { if (!string.IsNullOrEmpty(newV)) { onMessage(from.m_SteamID, newV); } } catch { } }; } lock (_addonVars) { _addonVars.Add(val); } return val; } catch (Exception ex) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup - _lastWarn >= 15f) { _lastWarn = realtimeSinceStartup; MelonLogger.Warning("[MultiplayerPVP][Net] addon channel '" + keySuffix + "' create failed: " + ex.Message); } return null; } } internal void Tick() { if (!_init) { return; } bool isInLobby = IsInLobby; if (isInLobby && !_wasInLobby) { _tagSet = false; _idSet = false; } _wasInLobby = isInLobby; if (isInLobby && !_tagSet && _modTag != null) { try { _modTag.Value = ModTag; _tagSet = true; } catch { } } if (!isInLobby || _idSet || _idTag == null || string.IsNullOrEmpty(_idCode)) { return; } try { _idTag.Value = _idCode; _idSet = true; } catch { } } internal void SetLocalIdentity(string playerCode) { if (!string.IsNullOrEmpty(playerCode) && playerCode != _idCode) { _idCode = playerCode; _idSet = false; } } private void OnSnapValueChanged(string oldValue, string newValue) { try { if (!IsHost && !string.IsNullOrEmpty(newValue)) { this.OnSnapshot?.Invoke(newValue); } } catch (Exception ex) { MelonLogger.Warning("[MultiplayerPVP][Net] snapshot apply: " + ex.Message); } } internal void PublishSnapshot(string snapshot) { if (!Available || !IsHost || _snap == null) { return; } try { _snap.Value = snapshot; } catch (Exception ex) { OnSyncError(ex); } } internal void PublishLoot(string record) { if (!Available || _loot == null) { return; } try { _loot.Value = record; } catch { } } internal void PublishSpill(string record) { if (!Available || _spill == null) { return; } try { _spill.Value = record; } catch { } } internal void PublishEarnings(string record) { if (!Available || _earn == null) { return; } try { _earn.Value = record; } catch { } } internal List<KeyValuePair<ulong, string>> AllEarnings() { return ReadAllOf(_earn); } internal List<KeyValuePair<ulong, string>> AllLoot() { return ReadAllOf(_loot); } internal List<KeyValuePair<ulong, string>> AllSpill() { return ReadAllOf(_spill); } internal static List<KeyValuePair<ulong, string>> ReadAllOf(ClientSyncVar<string> v) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) List<KeyValuePair<ulong, string>> list = new List<KeyValuePair<ulong, string>>(); if (v == null) { return list; } try { v.Refresh(); } catch { } try { foreach (KeyValuePair<CSteamID, string> allValue in v.GetAllValues()) { if (!string.IsNullOrEmpty(allValue.Value)) { list.Add(new KeyValuePair<ulong, string>(allValue.Key.m_SteamID, allValue.Value)); } } } catch { } return list; } internal void PublishSighting(string record) { if (!Available || _sight == null) { return; } try { _sight.Value = record; } catch { } } internal Dictionary<string, ulong> AllIdentities() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, ulong> dictionary = new Dictionary<string, ulong>(); if (_idTag == null) { return dictionary; } try { foreach (KeyValuePair<CSteamID, string> allValue in _idTag.GetAllValues()) { if (!string.IsNullOrEmpty(allValue.Value)) { dictionary[allValue.Value] = allValue.Key.m_SteamID; } } } catch { } return dictionary; } internal string PersonaOf(ulong steamId) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!Available || steamId == 0) { return null; } try { foreach (MemberInfo lobbyMember in _client.GetLobbyMembers()) { if (lobbyMember != null && lobbyMember.SteamId.m_SteamID == steamId) { return lobbyMember.DisplayName; } } } catch { } return null; } private void OnVersionMismatch(object sender, VersionMismatchEventArgs e) { MelonLogger.Warning("[MultiplayerPVP][Net] SteamNetworkLib version mismatch between players — networking may be unreliable. Ensure everyone runs the same mod/lib build."); } private void OnSyncError(Exception ex) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup - _lastWarn < 15f)) { _lastWarn = realtimeSinceStartup; MelonLogger.Warning("[MultiplayerPVP][Net] snapshot sync error (throttled): " + ex.Message); } } internal void Dispose() { try { if (_snap != null) { _snap.OnValueChanged -= OnSnapValueChanged; _snap.OnSyncError -= OnSyncError; _snap.Dispose(); } } catch { } try { if (_modTag != null) { _modTag.Dispose(); } } catch { } try { if (_loot != null) { _loot.Dispose(); } } catch { } try { if (_earn != null) { _earn.Dispose(); } } catch { } try { if (_spill != null) { _spill.Dispose(); } } catch { } try { if (_idTag != null) { _idTag.Dispose(); } } catch { } try { if (_sight != null) { _sight.Dispose(); } } catch { } lock (_addonVars) { for (int i = 0; i < _addonVars.Count; i++) { try { _addonVars[i].Dispose(); } catch { } } _addonVars.Clear(); } try { if (_client != null) { _client.OnVersionMismatch -= OnVersionMismatch; _client.Dispose(); } } catch { } _snap = null; _modTag = null; _loot = null; _earn = null; _spill = null; _idTag = null; _sight = null; _client = null; _init = false; _tagSet = false; _idSet = false; _idCode = null; _wasInLobby = false; } private static string ModVersion() { try { Version version = typeof(PvpNet).Assembly.GetName().Version; return (version != null) ? version.ToString() : "1.0"; } catch { return "1.0"; } } } } namespace MultiplayerPVP.Modes { internal class FindersKeepersMode : GameModeBase, IWorldMarkers, IBagSpillHandler { private DeadDrop _pickup; private int _pickupZone = -1; private int _pickupKnown; private PvpPlayer _carrier; private int _carrierHome = -1; private int _homeBaseline; private float _transit; private bool _active; private static string BagId => BagFactory.MatchId; public override GameModeType Type => GameModeType.FindersKeepers; public override void OnMatchStart(MatchContext ctx) { _active = true; SpawnBag(ctx, announce: false); } public override void OnMatchEnd(MatchContext ctx) { _active = false; bool tie; PvpPlayer pvpPlayer = ctx.Registry.Leader(out tie); if (pvpPlayer != null) { ctx.Announcer.Announce(tie ? $"It's a draw at {pvpPlayer.Score} delivery(ies)!" : $"{pvpPlayer.Name} wins with {pvpPlayer.Score} delivery(ies)!", 6f); } } private void SpawnBag(MatchContext ctx, bool announce) { _carrier = null; _carrierHome = -1; _transit = 0f; _pickup = ctx.Drops.RandomNonZoneDrop(); _pickupZone = -1; for (int i = 0; i < ctx.Drops.Count; i++) { if ((Object)(object)ctx.Drops.Zone(i) == (Object)(object)_pickup) { _pickupZone = i; break; } } if (GameCompat.Alive((Object)(object)_pickup)) { DeadDropStash.Insert(_pickup, BagId, 1, BagFactory.Create); _pickupKnown = DeadDropStash.Count(_pickup, BagId); } else { _pickupKnown = 0; } if (announce && GameCompat.Alive((Object)(object)_pickup)) { ctx.Announcer.Announce("A fresh bag is in a dead drop — find it!", 3f); } } public bool OnCarrierSpill(MatchContext ctx, PvpPlayer victim, int count, string reason) { if (count <= 0) { return true; } if (_carrier == null) { return true; } if (victim != null && victim != _carrier) { return true; } string name = _carrier.Name; string text = ((reason == "arrested") ? "was busted" : "went down"); SpawnBag(ctx, announce: false); ctx.Announcer.Announce(name + " " + text + " — the bag dropped and reappears in a dead drop!", 4f, notify: false); return true; } public override void Tick(MatchContext ctx, float dt) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (!_active) { return; } if (_carrier == null) { if (!GameCompat.Alive((Object)(object)_pickup)) { SpawnBag(ctx, announce: false); return; } int num = DeadDropStash.Count(_pickup, BagId); if (num < _pickupKnown) { _carrier = NearestPlayer(ctx, PickupPos(ctx)); _pickupKnown = num; _transit = 0f; _carrierHome = ((_carrier != null) ? ctx.Drops.ZoneForIndex(_carrier.Index) : (-1)); DeadDrop val = ((_carrierHome >= 0) ? ctx.Drops.Zone(_carrierHome) : null); _homeBaseline = (GameCompat.Alive((Object)(object)val) ? DeadDropStash.Count(val, BagId) : 0); string text = ((_carrier != null) ? _carrier.Name : "Someone"); ctx.Announcer.Announce(text + " has the bag!"); } } else { _transit += dt; int carrierHome = _carrierHome; DeadDrop val2 = ((carrierHome >= 0) ? ctx.Drops.Zone(carrierHome) : null); if (GameCompat.Alive((Object)(object)val2) && DeadDropStash.Count(val2, BagId) > _homeBaseline) { DeadDropStash.RemoveOne(val2, BagId); ctx.Award(_carrier, 1); ctx.Announcer.Announce($"{_carrier.Name} delivered the bag! ({_carrier.Score})", 5f); SpawnBag(ctx, announce: false); } else if (_transit > 60f) { ctx.Announcer.Announce("The bag was lost — a new one appears."); SpawnBag(ctx, announce: true); } } } private Vector3 PickupPos(MatchContext ctx) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (_pickupZone >= 0) { return ctx.Drops.ZonePosition(_pickupZone); } try { return GameCompat.Alive((Object)(object)_pickup) ? ((Component)_pickup).transform.position : Vector3.zero; } catch { return Vector3.zero; } } private static PvpPlayer NearestPlayer(MatchContext ctx, Vector3 pos) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) List<PvpPlayer> players = ctx.Registry.Players; PvpPlayer result = null; float num = float.MaxValue; for (int i = 0; i < players.Count; i++) { PvpPlayer pvpPlayer = players[i]; if (pvpPlayer.Valid) { float num2 = Vector3.Distance(pos, pvpPlayer.Position); if (num2 < num) { num = num2; result = pvpPlayer; } } } return result; } public override bool IsComplete(MatchContext ctx) { int num = Mathf.Max(1, PvpConfig.CtfScoreToWin.Value); List<PvpPlayer> players = ctx.Registry.Players; for (int i = 0; i < players.Count; i++) { if (players[i].Score >= num) { return true; } } return false; } public override string ScoreText(PvpPlayer p) { return p.Score + " caps" + ((_carrier == p) ? " ·BAG" : ""); } public void CollectMarkers(MatchContext ctx, PvpPlayer local, List<WorldMarker> into) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (_active && _carrier != null) { int carrierHome = _carrierHome; if (carrierHome >= 0) { into.Add(new WorldMarker(ctx.Drops.ZonePosition(carrierHome) + Vector3.up * 1.4f, PvpColors.For(_carrier.Index), "DELIVER HERE (" + _carrier.Name + ")")); } } } } internal class FreeForAllMode : GameModeBase { public override GameModeType Type => GameModeType.FreeForAll; public override void Tick(MatchContext ctx, float dt) { Combat.ProcessEliminations(ctx, teamMode: false); } public override void OnMatchEnd(MatchContext ctx) { bool tie; PvpPlayer pvpPlayer = ctx.Registry.Leader(out tie); if (pvpPlayer != null) { ctx.Announcer.Announce(tie ? $"It's a draw at {pvpPlayer.Score} eliminations!" : $"{pvpPlayer.Name} wins with {pvpPlayer.Score} eliminations!", 6f); } } public override string ScoreText(PvpPlayer p) { return p.Score + " elim"; } } internal class HideAndSeekMode : GameModeBase { private readonly HashSet<string> _originalHiders = new HashSet<string>(); private readonly Dictionary<string, int> _foundRank = new Dictionary<string, int>(); private int _foundCounter; private float _lastScan; public override GameModeType Type => GameModeType.HideAndSeek; private static string KeyOf(PvpPlayer p) { return (p != null) ? p.StableKey : ""; } private bool IsOriginalHider(PvpPlayer p) { return _originalHiders.Contains(KeyOf(p)) || (p != null && p.Name != null && _originalHiders.Contains(p.Name)); } private bool TryGetFoundRank(PvpPlayer p, out int rank) { if (_foundRank.TryGetValue(KeyOf(p), out rank)) { return true; } return p != null && p.Name != null && _foundRank.TryGetValue(p.Name, out rank); } public override void OnMatchStart(MatchContext ctx) { _originalHiders.Clear(); _foundRank.Clear(); _foundCounter = 0; List<PvpPlayer> players = ctx.Registry.Players; int count = players.Count; int num = Mathf.Cl
PvpCameraEsp.IL2CPP.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.PlayerScripts; using Il2CppTMPro; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiplayerPVP.Core; using PvpCameraEsp; 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: MelonAdditionalDependencies(new string[] { "MultiplayerPVP" })] [assembly: MelonOptionalDependencies(new string[] { "NetEye" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: MelonInfo(typeof(PvpCameraEspMod), "PvpCameraEsp", "1.0.3", "Virtunerd", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyFileVersion("1.0.3")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PvpCameraEsp { internal static class CameraBuildTracker { private static bool _active; private static float _graceUntil; private const float GraceSeconds = 2.5f; private static bool _hooked; internal static bool Hooked => _hooked; internal static bool LocalPlacingCamera { get { try { return _active || Time.unscaledTime < _graceUntil; } catch { return false; } } } internal static void Apply(Harmony h) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown try { Type type = ResolveBuildManager(); if (type == null) { MelonLogger.Warning("[PvpCameraEsp] BuildManager type not found — ownership falls back to proximity."); return; } MethodInfo methodInfo = FindMethod(type, "StartBuilding"); if (methodInfo == null) { MelonLogger.Warning("[PvpCameraEsp] BuildManager.StartBuilding not found — ownership falls back to proximity."); return; } MethodInfo method = typeof(CameraBuildTracker).GetMethod("StartPostfix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo2 = FindMethod(type, "StopBuilding"); if (methodInfo2 != null) { MethodInfo method2 = typeof(CameraBuildTracker).GetMethod("StopPostfix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } _hooked = true; MelonLogger.Msg("[PvpCameraEsp] camera-placement tracker armed (BuildManager hooked)."); } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] CameraBuildTracker.Apply: " + ex.Message); } } private static void StartPostfix(ItemInstance __0) { try { string text = ItemId(__0); if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] StartBuilding item='" + (text ?? "?") + "'"); } if (!string.IsNullOrEmpty(text) && text.IndexOf("NetEye", StringComparison.OrdinalIgnoreCase) >= 0 && text.IndexOf("Camera", StringComparison.OrdinalIgnoreCase) >= 0) { _active = true; _graceUntil = Time.unscaledTime + 2.5f; if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] local CAMERA placement STARTED → next new camera = mine"); } } } catch { } } private static void StopPostfix() { try { bool active = _active; _active = false; if (active) { _graceUntil = Time.unscaledTime + 2.5f; if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] local camera placement STOPPED (grace armed)"); } } } catch { } } private static string ItemId(ItemInstance item) { try { if (item == null) { return null; } object member = GetMember(item, "Definition"); if (member == null) { return null; } return GetMember(member, "ID") as string; } catch { return null; } } private static object GetMember(object target, string name) { if (target == null) { return null; } Type type = target.GetType(); try { PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (property != null) { return property.GetValue(target); } } catch { } try { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (field != null) { return field.GetValue(target); } } catch { } return null; } private static MethodInfo FindMethod(Type t, string name) { try { return t.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } catch (AmbiguousMatchException) { MethodInfo methodInfo = null; MethodInfo[] methods = t.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != name)) { if (methodInfo == null) { methodInfo = methodInfo2; } ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length == 1) { methodInfo = methodInfo2; break; } } } return methodInfo; } catch { return null; } } private static Type ResolveBuildManager() { Type type = FindType("Il2CppScheduleOne.Building.BuildManager") ?? FindType("ScheduleOne.Building.BuildManager"); if (type != null) { return type; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name != "Assembly-CSharp") { continue; } Type[] types; try { types = assembly.GetTypes(); } catch { continue; } Type[] array = types; foreach (Type type2 in array) { if (type2.Name == "BuildManager" && type2.Namespace != null && type2.Namespace.IndexOf("ScheduleOne", StringComparison.Ordinal) >= 0) { return type2; } } } } catch { } return null; } private static Type FindType(string fullName) { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = assembly.GetType(fullName); if (type != null) { return type; } } } catch { } try { return Type.GetType(fullName + ", Assembly-CSharp"); } catch { return null; } } internal static void Reset() { _active = false; _graceUntil = 0f; } } internal static class CameraGuard { internal static void Apply() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown try { Harmony h = new Harmony("com.virtunerd.pvpcameraesp"); Type typeFromHandle = typeof(BuildableItem); PatchVoid(h, typeFromHandle, "PickupItem"); PatchCan(h, typeFromHandle, "CanBePickedUp"); PatchCan(h, typeFromHandle, "CanBeDestroyed"); CameraBuildTracker.Apply(h); } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] guard apply: " + ex.Message); } } private static bool ShouldBlock(BuildableItem bi) { try { if (!EspConfig.ProtectCameras.Value) { return false; } if (!PvpApi.IsMatchActive) { return false; } if ((Object)(object)bi == (Object)null) { return false; } GameObject gameObject = ((Component)bi).gameObject; if ((Object)(object)gameObject == (Object)null) { return false; } if (!IsNetEyeCameraDeployable(gameObject)) { return false; } if (CameraOwnership.IsMine(((Object)gameObject).GetInstanceID())) { return false; } return true; } catch { return false; } } private static bool IsNetEyeCameraDeployable(GameObject go) { try { Transform transform = go.transform; int childCount = transform.childCount; for (int i = 0; i < childCount; i++) { Transform child = transform.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name != null && ((Object)child).name.StartsWith("NetEye_")) { return true; } } } catch { } return false; } private static bool BlockVoidPrefix(BuildableItem __instance) { try { if (ShouldBlock(__instance)) { return false; } } catch { } return true; } private static bool CanPrefix(BuildableItem __instance, ref string reason, ref bool __result) { try { if (ShouldBlock(__instance)) { reason = "Protected PvP camera"; __result = false; return false; } } catch { } return true; } private static void PatchVoid(Harmony h, Type t, string method) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown try { MethodInfo method2 = t.GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method2 == null) { MelonLogger.Warning("[PvpCameraEsp] guard: " + method + " not found"); return; } MethodInfo method3 = typeof(CameraGuard).GetMethod("BlockVoidPrefix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)method2, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] guard patch " + method + ": " + ex.Message); } } private static void PatchCan(Harmony h, Type t, string method) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown try { MethodInfo method2 = t.GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method2 == null)) { MethodInfo method3 = typeof(CameraGuard).GetMethod("CanPrefix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)method2, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] guard patch " + method + ": " + ex.Message); } } } internal static class CameraOwnership { private static readonly HashSet<int> _known = new HashSet<int>(); private static readonly Dictionary<int, float> _pending = new Dictionary<int, float>(); private static readonly Dictionary<int, BuildableItem> _mine = new Dictionary<int, BuildableItem>(); private const float ClaimWindow = 2.5f; private const float PlacingClaimRadius = 10f; private static readonly Dictionary<int, BuildableItem> _pendingPickup = new Dictionary<int, BuildableItem>(); private static float _nextPickupTry; private static int _pickupRounds; private const float PickupInterval = 1.5f; private const int MaxPickupRounds = 12; internal static bool PickupPending => _pendingPickup.Count > 0; internal static bool IsMine(int deployableInstanceId) { return _mine.ContainsKey(deployableInstanceId); } internal static bool IsMineCamera(Camera cam) { try { if ((Object)(object)cam == (Object)null) { return false; } BuildableItem val = FindDeployable(cam); if ((Object)(object)val == (Object)null) { return false; } return _mine.ContainsKey(((Object)((Component)val).gameObject).GetInstanceID()); } catch { return false; } } internal static void Tick(float radius) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) try { bool localPlacingCamera = CameraBuildTracker.LocalPlacingCamera; bool hooked = CameraBuildTracker.Hooked; float unscaledTime = Time.unscaledTime; Player localPlayer = PvpApi.LocalPlayer; bool flag = (Object)(object)localPlayer != (Object)null; Vector3 val = Vector3.zero; if (flag) { try { val = ((Component)localPlayer).transform.position; } catch { flag = false; } } IReadOnlyList<CamEntry> readOnlyList = NetEyeBridge.AllCameras(); for (int i = 0; i < readOnlyList.Count; i++) { Camera cam = readOnlyList[i].Cam; if ((Object)(object)cam == (Object)null) { continue; } BuildableItem val2 = FindDeployable(cam); if ((Object)(object)val2 == (Object)null) { continue; } int instanceID; try { instanceID = ((Object)((Component)val2).gameObject).GetInstanceID(); } catch { continue; } if (_mine.ContainsKey(instanceID) || _known.Contains(instanceID) || _pendingPickup.ContainsKey(instanceID)) { continue; } if (localPlacingCamera) { bool flag2 = !flag; if (flag) { try { Vector3 val3 = ((Component)val2).transform.position - val; val3.y = 0f; flag2 = ((Vector3)(ref val3)).magnitude <= 10f; } catch { flag2 = true; } } if (flag2) { _mine[instanceID] = val2; _pending.Remove(instanceID); _known.Add(instanceID); if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] claimed own camera (local build flow)"); } } continue; } if (hooked) { _known.Add(instanceID); _pending.Remove(instanceID); continue; } if (!_pending.TryGetValue(instanceID, out var value)) { _pending[instanceID] = unscaledTime; value = unscaledTime; } bool flag3 = false; if (flag) { try { Vector3 val4 = ((Component)val2).transform.position - val; val4.y = 0f; flag3 = ((Vector3)(ref val4)).magnitude <= radius; } catch { } } if (flag3) { _mine[instanceID] = val2; _pending.Remove(instanceID); _known.Add(instanceID); } else if (unscaledTime - value > 2.5f) { _pending.Remove(instanceID); _known.Add(instanceID); } } } catch { } } private static BuildableItem FindDeployable(Camera cam) { try { Transform val = ((Component)cam).transform; int num = 0; while ((Object)(object)val != (Object)null && num++ < 64) { BuildableItem component = ((Component)val).GetComponent<BuildableItem>(); if ((Object)(object)component != (Object)null) { return component; } val = val.parent; } } catch { } return null; } internal static void QueuePickUpMine() { foreach (KeyValuePair<int, BuildableItem> item in _mine) { if ((Object)(object)item.Value != (Object)null) { _pendingPickup[item.Key] = item.Value; } } _pickupRounds = 0; _nextPickupTry = 0f; _mine.Clear(); _known.Clear(); _pending.Clear(); } internal static void TickPickupRetry() { if (_pendingPickup.Count == 0) { return; } float unscaledTime = Time.unscaledTime; if (unscaledTime < _nextPickupTry) { return; } _nextPickupTry = unscaledTime + 1.5f; bool value = EspConfig.DebugLog.Value; List<int> list = new List<int>(); foreach (KeyValuePair<int, BuildableItem> item in _pendingPickup) { BuildableItem value2 = item.Value; if ((Object)(object)value2 == (Object)null) { list.Add(item.Key); continue; } bool flag = false; try { flag = value2.IsDestroyed; } catch { } if (flag) { list.Add(item.Key); continue; } string value3 = null; bool flag2 = false; try { flag2 = value2.CanBePickedUp(ref value3); } catch { } if (value) { MelonLogger.Msg($"[PvpCameraEsp] pickup-retry: can={flag2} reason='{value3}' host={PvpApi.IsHost}"); } if (!flag2) { continue; } try { value2.PickupItem(); } catch (Exception ex) { if (value) { MelonLogger.Msg("[PvpCameraEsp] pickup-retry threw: " + ex.Message); } } } for (int i = 0; i < list.Count; i++) { _pendingPickup.Remove(list[i]); } if (_pendingPickup.Count > 0 && ++_pickupRounds >= 12) { if (value) { MelonLogger.Warning($"[PvpCameraEsp] gave up restoring {_pendingPickup.Count} camera(s) after {12} tries"); } _pendingPickup.Clear(); } } internal static void AbortPickup() { _pendingPickup.Clear(); _pickupRounds = 0; } internal static void Reset() { _known.Clear(); _mine.Clear(); _pending.Clear(); _pendingPickup.Clear(); _pickupRounds = 0; } } internal struct VisibleEnemy { internal Player Player; internal int Team; internal ulong SteamId; internal string Persona; internal Vector3 ViewportFeet; internal Vector3 ViewportTop; } internal static class EnemyTracker { private static readonly List<VisibleEnemy> _result = new List<VisibleEnemy>(8); internal static List<VisibleEnemy> Scan(Camera cam) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) _result.Clear(); if ((Object)(object)cam == (Object)null) { return _result; } int localTeam = PvpApi.LocalTeam; if (localTeam < 0) { return _result; } Player localPlayer = PvpApi.LocalPlayer; List<Player> players = PvpApi.Players; float value = EspConfig.MaxDistance.Value; float num = Mathf.Max(0.5f, EspConfig.BodyHeight.Value); bool value2 = EspConfig.RequireLineOfSight.Value; Vector3 position = ((Component)cam).transform.position; ulong steamId = default(ulong); string persona = default(string); for (int i = 0; i < players.Count; i++) { Player val = players[i]; if ((Object)(object)val == (Object)null || ((Object)(object)localPlayer != (Object)null && (val == localPlayer || (Object)(object)val == (Object)(object)localPlayer))) { continue; } int team = PvpApi.GetTeam(val); if (team < 0 || team == localTeam) { continue; } Vector3 position2; Vector3 val2; Vector3 val3; try { position2 = ((Component)val).transform.position; val2 = position2 + Vector3.up * num; val3 = position2 + Vector3.up * (num * 0.5f); } catch { continue; } if (Vector3.Distance(position, val3) > value) { continue; } Vector3 val4; Vector3 val5; try { val4 = cam.WorldToViewportPoint(position2); val5 = cam.WorldToViewportPoint(val2); } catch { continue; } if (!(val4.z <= 0f) && !(val5.z <= 0f)) { float num2 = (val4.x + val5.x) * 0.5f; float num3 = (val4.y + val5.y) * 0.5f; if (!(num2 < -0.2f) && !(num2 > 1.2f) && !(num3 < -0.2f) && !(num3 > 1.2f) && (!value2 || !IsOccluded(position, val3, val))) { PvpApi.TryGetIdentity(val, ref steamId, ref persona); _result.Add(new VisibleEnemy { Player = val, Team = team, SteamId = steamId, Persona = persona, ViewportFeet = val4, ViewportTop = val5 }); } } } return _result; } private static bool IsOccluded(Vector3 from, Vector3 to, Player target) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.05f) { return false; } RaycastHit val2 = default(RaycastHit); if (!Physics.Raycast(from, val / magnitude, ref val2, magnitude - 0.3f)) { return false; } if ((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) { return false; } Player componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Player>(); return !((Object)(object)componentInParent != (Object)null) || (componentInParent != target && !((Object)(object)componentInParent == (Object)(object)target)); } catch { return false; } } } internal static class EspConfig { private static MelonPreferences_Category _cat; internal static MelonPreferences_Entry<bool> Enabled; internal static MelonPreferences_Entry<float> MaxDistance; internal static MelonPreferences_Entry<bool> RequireLineOfSight; internal static MelonPreferences_Entry<float> ReportCooldownSeconds; internal static MelonPreferences_Entry<float> RemindWhileVisibleSeconds; internal static MelonPreferences_Entry<bool> ShowBox; internal static MelonPreferences_Entry<int> BoxThickness; internal static MelonPreferences_Entry<float> BodyHeight; internal static MelonPreferences_Entry<string> BoxColorMode; internal static MelonPreferences_Entry<string> BoxColor; internal static MelonPreferences_Entry<bool> ShowLabels; internal static MelonPreferences_Entry<int> LabelFontSize; internal static MelonPreferences_Entry<bool> DebugLog; internal static MelonPreferences_Entry<bool> ProtectCameras; internal static MelonPreferences_Entry<float> OwnPlacementRadius; internal static MelonPreferences_Entry<bool> CleanupOwnCamerasOnRoundEnd; internal static MelonPreferences_Entry<bool> CleanStaleCameras; internal static void Load() { _cat = MelonPreferences.CreateCategory("PvpCameraEsp"); Enabled = _cat.CreateEntry<bool>("Enabled", true, (string)null, "Master toggle for the camera ESP.", false, false, (ValueValidator)null, (string)null); MaxDistance = _cat.CreateEntry<float>("MaxDistance", 80f, (string)null, "Max distance (m) from the camera to detect an enemy (camera far clip is ~80).", false, false, (ValueValidator)null, (string)null); RequireLineOfSight = _cat.CreateEntry<bool>("RequireLineOfSight", true, (string)null, "Only detect enemies with a clear line of sight (not behind walls). Disable if detection misses.", false, false, (ValueValidator)null, (string)null); ReportCooldownSeconds = _cat.CreateEntry<float>("ReportCooldownSeconds", 5f, (string)null, "Re-arm window: an enemy must be GONE from a camera this long before a NEW alert fires (edge-triggered, no spam while they stay in view).", false, false, (ValueValidator)null, (string)null); RemindWhileVisibleSeconds = _cat.CreateEntry<float>("RemindWhileVisibleSeconds", 0f, (string)null, "Optional: re-alert every N seconds while an enemy stays continuously in view (0 = off, alert only on enter).", false, false, (ValueValidator)null, (string)null); ShowBox = _cat.CreateEntry<bool>("ShowBox", true, (string)null, "Draw a box around each spotted enemy on the camera feed (ESP box).", false, false, (ValueValidator)null, (string)null); BoxThickness = _cat.CreateEntry<int>("BoxThickness", 2, (string)null, "Border thickness (px) of the ESP box.", false, false, (ValueValidator)null, (string)null); BodyHeight = _cat.CreateEntry<float>("BodyHeight", 2f, (string)null, "Assumed player height (m) used to size the box from feet to head.", false, false, (ValueValidator)null, (string)null); BoxColorMode = _cat.CreateEntry<string>("BoxColorMode", "enemyteam", (string)null, "Box/label colour source: 'enemyteam' (spotted enemy's team colour), 'ownteam' (your team = the camera owner's team), or 'custom' (use BoxColor).", false, false, (ValueValidator)null, (string)null); BoxColor = _cat.CreateEntry<string>("BoxColor", "FF3030", (string)null, "Custom box/label colour as hex RGB or RGBA (e.g. FF3030 or FF3030C0). Used only when BoxColorMode = custom.", false, false, (ValueValidator)null, (string)null); ShowLabels = _cat.CreateEntry<bool>("ShowLabels", true, (string)null, "Draw the enemy's Steam name above the box on the camera feed.", false, false, (ValueValidator)null, (string)null); LabelFontSize = _cat.CreateEntry<int>("LabelFontSize", 20, (string)null, "Font size of the on-feed name labels.", false, false, (ValueValidator)null, (string)null); DebugLog = _cat.CreateEntry<bool>("DebugLog", false, (string)null, "Verbose logging (cameras found, alerts) for diagnosing the live test.", false, false, (ValueValidator)null, (string)null); ProtectCameras = _cat.CreateEntry<bool>("ProtectCameras", true, (string)null, "During a Teams match, block players from picking up / demolishing cameras they didn't place (protects client cameras from the host & host-team, and vice-versa).", false, false, (ValueValidator)null, (string)null); OwnPlacementRadius = _cat.CreateEntry<float>("OwnPlacementRadius", 4f, (string)null, "FALLBACK ONLY (used if the BuildManager hook isn't available): a newly-placed camera within this horizontal distance (m) of you is treated as YOURS. Normally ownership comes from the local build flow and this is ignored.", false, false, (ValueValidator)null, (string)null); CleanupOwnCamerasOnRoundEnd = _cat.CreateEntry<bool>("CleanupOwnCamerasOnRoundEnd", true, (string)null, "Pick up your own cameras (back into your inventory) automatically when a match ends, so they don't linger in the NetEye app. Applies to both host and client.", false, false, (ValueValidator)null, (string)null); CleanStaleCameras = _cat.CreateEntry<bool>("CleanStaleCameras", true, (string)null, "HOST: remove stale camera entries (loaded from a previous session's cameras.txt, shown in the app but not backed by a live camera) while in a multiplayer match.", false, false, (ValueValidator)null, (string)null); } internal static Color ResolveBoxColor(int enemyTeam) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) string text = (BoxColorMode.Value ?? "").Trim().ToLowerInvariant(); if (text == "ownteam") { int localTeam = PvpApi.LocalTeam; return PvpApi.TeamColor((localTeam >= 0) ? localTeam : 0); } if (text == "custom") { string value = BoxColor.Value; Color result = default(Color); if (!string.IsNullOrEmpty(value) && ColorUtility.TryParseHtmlString((value[0] == '#') ? value : ("#" + value), ref result)) { return result; } return Color.red; } return PvpApi.TeamColor(enemyTeam); } } internal static class FeedOverlay { private sealed class EnemyBox { internal RectTransform Root; internal RawImage Top; internal RawImage Bottom; internal RawImage Left; internal RawImage Right; internal TextMeshProUGUI Label; } private static RawImage _bound; private static RectTransform _container; private static TMP_FontAsset _font; private static bool _fontResolved; private static bool _warnedNoFont; private static Texture2D _white; private static readonly Dictionary<string, EnemyBox> _boxes = new Dictionary<string, EnemyBox>(); private static readonly HashSet<string> _seen = new HashSet<string>(); private static Texture2D White { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_white == (Object)null) { _white = new Texture2D(1, 1); _white.SetPixel(0, 0, Color.white); _white.Apply(); } return _white; } } internal static void Update(RawImage feed, List<VisibleEnemy> enemies) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)feed == (Object)null) { HideAll(); return; } bool value = EspConfig.ShowBox.Value; bool value2 = EspConfig.ShowLabels.Value; if (!value && !value2) { HideAll(); return; } EnsureContainer(feed); if ((Object)(object)_container == (Object)null) { return; } TMP_FontAsset font = ResolveFont(); Rect rect = ((Graphic)feed).rectTransform.rect; Vector2 size = ((Rect)(ref rect)).size; int value3 = EspConfig.LabelFontSize.Value; _seen.Clear(); Vector2 val = default(Vector2); Vector2 val2 = default(Vector2); Vector2 anchoredPosition = default(Vector2); for (int i = 0; i < enemies.Count; i++) { VisibleEnemy visibleEnemy = enemies[i]; string text = ((visibleEnemy.SteamId != 0L) ? visibleEnemy.SteamId.ToString() : ("n:" + visibleEnemy.Persona)); _seen.Add(text); EnemyBox orCreate = GetOrCreate(text, font); if (orCreate == null) { continue; } ((Vector2)(ref val))..ctor((visibleEnemy.ViewportFeet.x - 0.5f) * size.x, (visibleEnemy.ViewportFeet.y - 0.5f) * size.y); ((Vector2)(ref val2))..ctor((visibleEnemy.ViewportTop.x - 0.5f) * size.x, (visibleEnemy.ViewportTop.y - 0.5f) * size.y); float num = Mathf.Max(6f, Mathf.Abs(val2.y - val.y)); float num2 = Mathf.Clamp(num * 0.4f, 6f, num); ((Vector2)(ref anchoredPosition))..ctor((val.x + val2.x) * 0.5f, (val.y + val2.y) * 0.5f); orCreate.Root.anchoredPosition = anchoredPosition; orCreate.Root.sizeDelta = new Vector2(num2, num); Color val3 = EspConfig.ResolveBoxColor(visibleEnemy.Team); SetEdge(orCreate.Top, value, val3); SetEdge(orCreate.Bottom, value, val3); SetEdge(orCreate.Left, value, val3); SetEdge(orCreate.Right, value, val3); if ((Object)(object)orCreate.Label != (Object)null) { ((Component)orCreate.Label).gameObject.SetActive(value2); if (value2) { ((TMP_Text)orCreate.Label).text = visibleEnemy.Persona; ((TMP_Text)orCreate.Label).fontSize = value3; ((Graphic)orCreate.Label).color = val3; } } if (!((Component)orCreate.Root).gameObject.activeSelf) { ((Component)orCreate.Root).gameObject.SetActive(true); } } foreach (KeyValuePair<string, EnemyBox> box in _boxes) { if (!_seen.Contains(box.Key) && (Object)(object)box.Value.Root != (Object)null && ((Component)box.Value.Root).gameObject.activeSelf) { ((Component)box.Value.Root).gameObject.SetActive(false); } } } private static void SetEdge(RawImage edge, bool show, Color col) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)edge == (Object)null)) { if (((Component)edge).gameObject.activeSelf != show) { ((Component)edge).gameObject.SetActive(show); } if (show) { ((Graphic)edge).color = col; } } } internal static void HideAll() { try { foreach (KeyValuePair<string, EnemyBox> box in _boxes) { if ((Object)(object)box.Value.Root != (Object)null && ((Component)box.Value.Root).gameObject.activeSelf) { ((Component)box.Value.Root).gameObject.SetActive(false); } } } catch { } } private static void EnsureContainer(RawImage feed) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_bound == (Object)(object)feed && (Object)(object)_container != (Object)null) { return; } _boxes.Clear(); _bound = feed; try { GameObject val = new GameObject("PvpCamEsp_Overlay"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(((Component)feed).transform, false); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; val.AddComponent<RectMask2D>(); _container = val2; if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] overlay container attached to feed"); } } catch { _container = null; } } private static EnemyBox GetOrCreate(string key, TMP_FontAsset font) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) if (_boxes.TryGetValue(key, out var value) && (Object)(object)value.Root != (Object)null) { return value; } try { int num = Mathf.Max(1, EspConfig.BoxThickness.Value); RectTransform val = NewRect("box_" + key, (Transform)(object)_container, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f)); value = new EnemyBox { Root = val }; value.Top = Edge((Transform)(object)val, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, (float)num)); value.Bottom = Edge((Transform)(object)val, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, (float)num)); value.Left = Edge((Transform)(object)val, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2((float)num, 0f)); value.Right = Edge((Transform)(object)val, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(1f, 0.5f), new Vector2((float)num, 0f)); if ((Object)(object)font != (Object)null) { RectTransform val2 = NewRect("name", (Transform)(object)val, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 0f)); val2.sizeDelta = new Vector2(260f, 28f); val2.anchoredPosition = new Vector2(0f, 4f); TextMeshProUGUI val3 = ((Component)val2).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val3).font = font; ((TMP_Text)val3).alignment = (TextAlignmentOptions)1026; ((TMP_Text)val3).enableWordWrapping = false; ((TMP_Text)val3).richText = false; ((TMP_Text)val3).fontStyle = (FontStyles)1; ((TMP_Text)val3).overflowMode = (TextOverflowModes)0; ((Graphic)val3).raycastTarget = false; value.Label = val3; } else if (!_warnedNoFont) { _warnedNoFont = true; MelonLogger.Warning("[PvpCameraEsp] No TMP font found — boxes still draw, name labels disabled."); } _boxes[key] = value; return value; } catch { return null; } } private static RectTransform NewRect(string name, Transform parent, Vector2 aMin, Vector2 aMax, Vector2 pivot) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); val2.anchorMin = aMin; val2.anchorMax = aMax; val2.pivot = pivot; val2.anchoredPosition = Vector2.zero; return val2; } private static RawImage Edge(Transform parent, Vector2 aMin, Vector2 aMax, Vector2 pivot, Vector2 sizeDelta) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) RectTransform val = NewRect("edge", parent, aMin, aMax, pivot); val.sizeDelta = sizeDelta; RawImage val2 = ((Component)val).gameObject.AddComponent<RawImage>(); val2.texture = (Texture)(object)White; ((Graphic)val2).raycastTarget = false; return val2; } private static TMP_FontAsset ResolveFont() { if (_fontResolved) { return _font; } _fontResolved = true; try { Il2CppArrayBase<TMP_FontAsset> val = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); if (val != null) { foreach (TMP_FontAsset item in val) { if ((Object)(object)item != (Object)null && ((Object)item).name != null && ((Object)item).name.Contains("OpenSans")) { _font = item; return _font; } } foreach (TMP_FontAsset item2 in val) { if ((Object)(object)item2 != (Object)null && ((Object)item2).name != null && (((Object)item2).name.Contains("Inter") || ((Object)item2).name.Contains("Roboto") || ((Object)item2).name.Contains("Liberation") || ((Object)item2).name.Contains("Arial"))) { _font = item2; return _font; } } foreach (TMP_FontAsset item3 in val) { if ((Object)(object)item3 != (Object)null) { _font = item3; return _font; } } } } catch { } return _font; } internal static void Reset() { try { if ((Object)(object)_container != (Object)null) { Object.Destroy((Object)(object)((Component)_container).gameObject); } } catch { } _container = null; _bound = null; _boxes.Clear(); } } internal struct CamEntry { internal Camera Cam; internal string Name; internal CamEntry(Camera cam, string name) { Cam = cam; Name = name; } } internal static class NetEyeBridge { internal const string RtPrefix = "NetEye_RT_"; private const string RootPrefix = "NetEye_"; private static readonly List<CamEntry> _all = new List<CamEntry>(8); private static float _nextAllScan; private static int _lastCount = -1; private static Camera _feedCam; private static RawImage _feedCache; private static readonly Dictionary<int, string> _niceCache = new Dictionary<int, string>(); private static bool _reflectInit; private static bool _reflectOk; private static FieldInfo _fInstance; private static FieldInfo _fCameras; private static FieldInfo _fUnityCam; private static FieldInfo _fName; private static FieldInfo _fLoc; private static FieldInfo _fIsVanilla; private static FieldInfo _fActiveIdx; private static MethodInfo _mDestroy; internal static IReadOnlyList<CamEntry> AllCameras() { float unscaledTime = Time.unscaledTime; if (unscaledTime >= _nextAllScan) { _nextAllScan = unscaledTime + 1f; RebuildAll(); } return _all; } private static void RebuildAll() { _all.Clear(); try { Il2CppArrayBase<Camera> val = Resources.FindObjectsOfTypeAll<Camera>(); if (val != null) { foreach (Camera item in val) { if (!((Object)(object)item == (Object)null)) { RenderTexture targetTexture = item.targetTexture; if (!((Object)(object)targetTexture == (Object)null) && ((Object)targetTexture).name != null && ((Object)targetTexture).name.StartsWith("NetEye_RT_")) { _all.Add(new CamEntry(item, ResolveName(item, targetTexture))); } } } } } catch { } if (EspConfig.DebugLog.Value && _all.Count != _lastCount) { _lastCount = _all.Count; MelonLogger.Msg("[PvpCameraEsp] NetEye cameras detected: " + _all.Count); } } internal static bool TryGetLive(out Camera cam, out RawImage feed, out string name) { cam = null; feed = null; name = null; try { IReadOnlyList<CamEntry> readOnlyList = AllCameras(); for (int i = 0; i < readOnlyList.Count; i++) { Camera cam2 = readOnlyList[i].Cam; if ((Object)(object)cam2 != (Object)null && ((Behaviour)cam2).enabled) { cam = cam2; name = readOnlyList[i].Name; break; } } if ((Object)(object)cam == (Object)null) { return false; } feed = ResolveFeed(cam); return (Object)(object)feed != (Object)null; } catch { return false; } } private static RawImage ResolveFeed(Camera cam) { if ((Object)(object)_feedCache != (Object)null && (Object)(object)_feedCam == (Object)(object)cam && (Object)(object)_feedCache.texture == (Object)(object)cam.targetTexture) { return _feedCache; } _feedCache = null; _feedCam = cam; try { Texture targetTexture = (Texture)(object)cam.targetTexture; Il2CppArrayBase<RawImage> val = Resources.FindObjectsOfTypeAll<RawImage>(); if (val != null) { foreach (RawImage item in val) { if ((Object)(object)item == (Object)null || !((Object)(object)item.texture != (Object)null) || !((Object)(object)item.texture == (Object)(object)targetTexture)) { continue; } _feedCache = item; break; } } } catch { _feedCache = null; } return _feedCache; } private static string ResolveName(Camera cam, RenderTexture rt) { int instanceID = ((Object)cam).GetInstanceID(); if (_niceCache.TryGetValue(instanceID, out var value)) { return value; } string text = TryReflectName(cam); if (!string.IsNullOrEmpty(text)) { _niceCache[instanceID] = text; return text; } return GoName(cam, rt); } private static string GoName(Camera cam, RenderTexture rt) { try { Transform val = ((Component)cam).transform; while ((Object)(object)val.parent != (Object)null) { val = val.parent; } string name = ((Object)((Component)val).gameObject).name; if (!string.IsNullOrEmpty(name) && name.StartsWith("NetEye_")) { return name.Substring("NetEye_".Length); } if ((Object)(object)rt != (Object)null && ((Object)rt).name != null && ((Object)rt).name.StartsWith("NetEye_RT_")) { return ((Object)rt).name.Substring("NetEye_RT_".Length); } return string.IsNullOrEmpty(name) ? "?" : name; } catch { return "?"; } } internal static int RemoveStaleCameras() { int num = 0; try { EnsureReflect(); if (!_reflectOk || _fIsVanilla == null || _mDestroy == null || _fCameras == null) { return 0; } object value = _fInstance.GetValue(null); if (value == null) { return 0; } if (!(_fCameras.GetValue(value) is IList list)) { return 0; } for (int num2 = list.Count - 1; num2 >= 0; num2--) { object obj = list[num2]; if (obj == null) { continue; } bool flag; try { flag = (bool)_fIsVanilla.GetValue(obj); } catch { continue; } if (!flag) { try { _mDestroy.Invoke(obj, null); } catch { } try { list.RemoveAt(num2); num++; } catch { } } } if (num > 0 && _fActiveIdx != null) { try { int num3 = (int)_fActiveIdx.GetValue(value); if (num3 >= list.Count) { _fActiveIdx.SetValue(value, list.Count - 1); } } catch { } } } catch { } return num; } private static string TryReflectName(Camera cam) { try { EnsureReflect(); if (!_reflectOk) { return null; } object value = _fInstance.GetValue(null); if (value == null) { return null; } if (!(_fCameras.GetValue(value) is IEnumerable enumerable)) { return null; } foreach (object item in enumerable) { if (item == null) { continue; } object? value2 = _fUnityCam.GetValue(item); Camera val = (Camera)((value2 is Camera) ? value2 : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)cam) { continue; } string text = _fName.GetValue(item) as string; if (string.IsNullOrEmpty(text)) { return null; } string text2 = ((_fLoc != null) ? (_fLoc.GetValue(item) as string) : null); return string.IsNullOrEmpty(text2) ? text : (text + " (" + text2 + ")"); } } catch { } return null; } private static void EnsureReflect() { if (_reflectInit) { return; } _reflectInit = true; try { Type type = FindType("NetEye.NetEyeMod", "NetEye"); Type type2 = FindType("NetEye.NetEyeCamera", "NetEye"); if (!(type == null) && !(type2 == null)) { _fInstance = type.GetField("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _fCameras = type.GetField("_cameras", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fActiveIdx = type.GetField("_activeCameraIdx", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fUnityCam = type2.GetField("UnityCam", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fName = type2.GetField("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fLoc = type2.GetField("Location", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fIsVanilla = type2.GetField("IsVanilla", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _mDestroy = type2.GetMethod("Destroy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); _reflectOk = _fInstance != null && _fCameras != null && _fUnityCam != null && _fName != null; } } catch { _reflectOk = false; } } private static Type FindType(string fullName, string asmSimpleName) { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == asmSimpleName) { Type type = assembly.GetType(fullName); if (type != null) { return type; } } } } catch { } try { return Type.GetType(fullName + ", " + asmSimpleName); } catch { return null; } } internal static void Reset() { _all.Clear(); _niceCache.Clear(); _feedCam = null; _feedCache = null; _nextAllScan = 0f; _lastCount = -1; } } public class PvpCameraEspMod : MelonMod { private float _nextSensorScan; private float _nextStaleScan; private bool _wasMatchActive; public override void OnInitializeMelon() { EspConfig.Load(); CameraGuard.Apply(); MelonLogger.Msg("[PvpCameraEsp] ready — symmetric camera ESP for MultiplayerPVP via NetEye cameras."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { try { NetEyeBridge.Reset(); FeedOverlay.Reset(); SightingReporter.Reset(); CameraOwnership.Reset(); CameraBuildTracker.Reset(); _wasMatchActive = false; } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] OnSceneWasLoaded: " + ex.Message); } } public override void OnUpdate() { try { if (!EspConfig.Enabled.Value) { FeedOverlay.HideAll(); _wasMatchActive = false; return; } float unscaledTime = Time.unscaledTime; bool isHost = PvpApi.IsHost; bool isTeamsMatchActive = PvpApi.IsTeamsMatchActive; bool isMatchActive = PvpApi.IsMatchActive; CameraOwnership.Tick(EspConfig.OwnPlacementRadius.Value); if (isHost && EspConfig.CleanStaleCameras.Value && PvpApi.IsMultiplayer && unscaledTime >= _nextStaleScan) { _nextStaleScan = unscaledTime + 5f; int num = NetEyeBridge.RemoveStaleCameras(); if (num > 0 && EspConfig.DebugLog.Value) { MelonLogger.Msg($"[PvpCameraEsp] removed {num} stale camera(s)"); } } if (_wasMatchActive && !isMatchActive && EspConfig.CleanupOwnCamerasOnRoundEnd.Value) { CameraOwnership.QueuePickUpMine(); } else if (!_wasMatchActive && isMatchActive) { CameraOwnership.AbortPickup(); } _wasMatchActive = isMatchActive; CameraOwnership.TickPickupRetry(); if (!isTeamsMatchActive) { FeedOverlay.HideAll(); return; } if (unscaledTime >= _nextSensorScan) { _nextSensorScan = unscaledTime + 0.25f; IReadOnlyList<CamEntry> readOnlyList = NetEyeBridge.AllCameras(); for (int i = 0; i < readOnlyList.Count; i++) { if (CameraOwnership.IsMineCamera(readOnlyList[i].Cam)) { List<VisibleEnemy> list = EnemyTracker.Scan(readOnlyList[i].Cam); if (list.Count > 0) { SightingReporter.Report(list, readOnlyList[i].Name); } } } } if (NetEyeBridge.TryGetLive(out var cam, out var feed, out var _) && CameraOwnership.IsMineCamera(cam)) { FeedOverlay.Update(feed, EnemyTracker.Scan(cam)); } else { FeedOverlay.HideAll(); } } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] OnUpdate: " + ex.Message); } } } internal static class SightingReporter { private static readonly Dictionary<string, float> _lastSeen = new Dictionary<string, float>(); private static readonly Dictionary<string, float> _lastFired = new Dictionary<string, float>(); internal static void Report(List<VisibleEnemy> enemies, string cameraName) { float unscaledTime = Time.unscaledTime; float num = Mathf.Max(0.5f, EspConfig.ReportCooldownSeconds.Value); float value = EspConfig.RemindWhileVisibleSeconds.Value; for (int i = 0; i < enemies.Count; i++) { VisibleEnemy visibleEnemy = enemies[i]; string text = ((visibleEnemy.SteamId != 0L) ? visibleEnemy.SteamId.ToString() : ("n:" + visibleEnemy.Persona)); string key = text + "@" + cameraName; float value2; bool flag = !_lastSeen.TryGetValue(key, out value2) || unscaledTime - value2 > num; float value3; bool flag2 = value > 0f && _lastFired.TryGetValue(key, out value3) && unscaledTime - value3 >= value; _lastSeen[key] = unscaledTime; if (flag || flag2) { _lastFired[key] = unscaledTime; if (EspConfig.DebugLog.Value) { MelonLogger.Msg($"[PvpCameraEsp] ALERT{((flag2 && !flag) ? " (reminder)" : "")}: {visibleEnemy.Persona} (team {visibleEnemy.Team}, steamId {visibleEnemy.SteamId}) @ {cameraName}"); } PvpApi.ReportCameraSighting(visibleEnemy.Team, visibleEnemy.SteamId, visibleEnemy.Persona, cameraName); } } if (_lastSeen.Count > 128) { Prune(unscaledTime, num); } } private static void Prune(float now, float rearm) { List<string> list = new List<string>(); foreach (KeyValuePair<string, float> item in _lastSeen) { if (now - item.Value > rearm * 4f + 10f) { list.Add(item.Key); } } for (int i = 0; i < list.Count; i++) { _lastSeen.Remove(list[i]); _lastFired.Remove(list[i]); } } internal static void Reset() { try { _lastSeen.Clear(); _lastFired.Clear(); } catch { } } } }
PvpCameraEsp.MONO.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiplayerPVP.Core; using PvpCameraEsp; using ScheduleOne.EntityFramework; using ScheduleOne.ItemFramework; using ScheduleOne.PlayerScripts; 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: MelonAdditionalDependencies(new string[] { "MultiplayerPVP" })] [assembly: MelonOptionalDependencies(new string[] { "NetEye" })] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: MelonInfo(typeof(PvpCameraEspMod), "PvpCameraEsp", "1.0.3", "Virtunerd", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyFileVersion("1.0.3")] [assembly: AssemblyInformationalVersion("1.0.3")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PvpCameraEsp { internal static class CameraBuildTracker { private static bool _active; private static float _graceUntil; private const float GraceSeconds = 2.5f; private static bool _hooked; internal static bool Hooked => _hooked; internal static bool LocalPlacingCamera { get { try { return _active || Time.unscaledTime < _graceUntil; } catch { return false; } } } internal static void Apply(Harmony h) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown try { Type type = ResolveBuildManager(); if (type == null) { MelonLogger.Warning("[PvpCameraEsp] BuildManager type not found — ownership falls back to proximity."); return; } MethodInfo methodInfo = FindMethod(type, "StartBuilding"); if (methodInfo == null) { MelonLogger.Warning("[PvpCameraEsp] BuildManager.StartBuilding not found — ownership falls back to proximity."); return; } MethodInfo method = typeof(CameraBuildTracker).GetMethod("StartPostfix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo2 = FindMethod(type, "StopBuilding"); if (methodInfo2 != null) { MethodInfo method2 = typeof(CameraBuildTracker).GetMethod("StopPostfix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } _hooked = true; MelonLogger.Msg("[PvpCameraEsp] camera-placement tracker armed (BuildManager hooked)."); } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] CameraBuildTracker.Apply: " + ex.Message); } } private static void StartPostfix(ItemInstance __0) { try { string text = ItemId(__0); if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] StartBuilding item='" + (text ?? "?") + "'"); } if (!string.IsNullOrEmpty(text) && text.IndexOf("NetEye", StringComparison.OrdinalIgnoreCase) >= 0 && text.IndexOf("Camera", StringComparison.OrdinalIgnoreCase) >= 0) { _active = true; _graceUntil = Time.unscaledTime + 2.5f; if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] local CAMERA placement STARTED → next new camera = mine"); } } } catch { } } private static void StopPostfix() { try { bool active = _active; _active = false; if (active) { _graceUntil = Time.unscaledTime + 2.5f; if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] local camera placement STOPPED (grace armed)"); } } } catch { } } private static string ItemId(ItemInstance item) { try { if (item == null) { return null; } object member = GetMember(item, "Definition"); if (member == null) { return null; } return GetMember(member, "ID") as string; } catch { return null; } } private static object GetMember(object target, string name) { if (target == null) { return null; } Type type = target.GetType(); try { PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (property != null) { return property.GetValue(target); } } catch { } try { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); if (field != null) { return field.GetValue(target); } } catch { } return null; } private static MethodInfo FindMethod(Type t, string name) { try { return t.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } catch (AmbiguousMatchException) { MethodInfo methodInfo = null; MethodInfo[] methods = t.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != name)) { if (methodInfo == null) { methodInfo = methodInfo2; } ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length == 1) { methodInfo = methodInfo2; break; } } } return methodInfo; } catch { return null; } } private static Type ResolveBuildManager() { Type type = FindType("Il2CppScheduleOne.Building.BuildManager") ?? FindType("ScheduleOne.Building.BuildManager"); if (type != null) { return type; } try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name != "Assembly-CSharp") { continue; } Type[] types; try { types = assembly.GetTypes(); } catch { continue; } Type[] array = types; foreach (Type type2 in array) { if (type2.Name == "BuildManager" && type2.Namespace != null && type2.Namespace.IndexOf("ScheduleOne", StringComparison.Ordinal) >= 0) { return type2; } } } } catch { } return null; } private static Type FindType(string fullName) { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = assembly.GetType(fullName); if (type != null) { return type; } } } catch { } try { return Type.GetType(fullName + ", Assembly-CSharp"); } catch { return null; } } internal static void Reset() { _active = false; _graceUntil = 0f; } } internal static class CameraGuard { internal static void Apply() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown try { Harmony h = new Harmony("com.virtunerd.pvpcameraesp"); Type typeFromHandle = typeof(BuildableItem); PatchVoid(h, typeFromHandle, "PickupItem"); PatchCan(h, typeFromHandle, "CanBePickedUp"); PatchCan(h, typeFromHandle, "CanBeDestroyed"); CameraBuildTracker.Apply(h); } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] guard apply: " + ex.Message); } } private static bool ShouldBlock(BuildableItem bi) { try { if (!EspConfig.ProtectCameras.Value) { return false; } if (!PvpApi.IsMatchActive) { return false; } if ((Object)(object)bi == (Object)null) { return false; } GameObject gameObject = ((Component)bi).gameObject; if ((Object)(object)gameObject == (Object)null) { return false; } if (!IsNetEyeCameraDeployable(gameObject)) { return false; } if (CameraOwnership.IsMine(((Object)gameObject).GetInstanceID())) { return false; } return true; } catch { return false; } } private static bool IsNetEyeCameraDeployable(GameObject go) { try { Transform transform = go.transform; int childCount = transform.childCount; for (int i = 0; i < childCount; i++) { Transform child = transform.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name != null && ((Object)child).name.StartsWith("NetEye_")) { return true; } } } catch { } return false; } private static bool BlockVoidPrefix(BuildableItem __instance) { try { if (ShouldBlock(__instance)) { return false; } } catch { } return true; } private static bool CanPrefix(BuildableItem __instance, ref string reason, ref bool __result) { try { if (ShouldBlock(__instance)) { reason = "Protected PvP camera"; __result = false; return false; } } catch { } return true; } private static void PatchVoid(Harmony h, Type t, string method) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown try { MethodInfo method2 = t.GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method2 == null) { MelonLogger.Warning("[PvpCameraEsp] guard: " + method + " not found"); return; } MethodInfo method3 = typeof(CameraGuard).GetMethod("BlockVoidPrefix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)method2, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] guard patch " + method + ": " + ex.Message); } } private static void PatchCan(Harmony h, Type t, string method) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown try { MethodInfo method2 = t.GetMethod(method, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method2 == null)) { MethodInfo method3 = typeof(CameraGuard).GetMethod("CanPrefix", BindingFlags.Static | BindingFlags.NonPublic); h.Patch((MethodBase)method2, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] guard patch " + method + ": " + ex.Message); } } } internal static class CameraOwnership { private static readonly HashSet<int> _known = new HashSet<int>(); private static readonly Dictionary<int, float> _pending = new Dictionary<int, float>(); private static readonly Dictionary<int, BuildableItem> _mine = new Dictionary<int, BuildableItem>(); private const float ClaimWindow = 2.5f; private const float PlacingClaimRadius = 10f; private static readonly Dictionary<int, BuildableItem> _pendingPickup = new Dictionary<int, BuildableItem>(); private static float _nextPickupTry; private static int _pickupRounds; private const float PickupInterval = 1.5f; private const int MaxPickupRounds = 12; internal static bool PickupPending => _pendingPickup.Count > 0; internal static bool IsMine(int deployableInstanceId) { return _mine.ContainsKey(deployableInstanceId); } internal static bool IsMineCamera(Camera cam) { try { if ((Object)(object)cam == (Object)null) { return false; } BuildableItem val = FindDeployable(cam); if ((Object)(object)val == (Object)null) { return false; } return _mine.ContainsKey(((Object)((Component)val).gameObject).GetInstanceID()); } catch { return false; } } internal static void Tick(float radius) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) try { bool localPlacingCamera = CameraBuildTracker.LocalPlacingCamera; bool hooked = CameraBuildTracker.Hooked; float unscaledTime = Time.unscaledTime; Player localPlayer = PvpApi.LocalPlayer; bool flag = (Object)(object)localPlayer != (Object)null; Vector3 val = Vector3.zero; if (flag) { try { val = ((Component)localPlayer).transform.position; } catch { flag = false; } } IReadOnlyList<CamEntry> readOnlyList = NetEyeBridge.AllCameras(); for (int i = 0; i < readOnlyList.Count; i++) { Camera cam = readOnlyList[i].Cam; if ((Object)(object)cam == (Object)null) { continue; } BuildableItem val2 = FindDeployable(cam); if ((Object)(object)val2 == (Object)null) { continue; } int instanceID; try { instanceID = ((Object)((Component)val2).gameObject).GetInstanceID(); } catch { continue; } if (_mine.ContainsKey(instanceID) || _known.Contains(instanceID) || _pendingPickup.ContainsKey(instanceID)) { continue; } if (localPlacingCamera) { bool flag2 = !flag; if (flag) { try { Vector3 val3 = ((Component)val2).transform.position - val; val3.y = 0f; flag2 = ((Vector3)(ref val3)).magnitude <= 10f; } catch { flag2 = true; } } if (flag2) { _mine[instanceID] = val2; _pending.Remove(instanceID); _known.Add(instanceID); if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] claimed own camera (local build flow)"); } } continue; } if (hooked) { _known.Add(instanceID); _pending.Remove(instanceID); continue; } if (!_pending.TryGetValue(instanceID, out var value)) { _pending[instanceID] = unscaledTime; value = unscaledTime; } bool flag3 = false; if (flag) { try { Vector3 val4 = ((Component)val2).transform.position - val; val4.y = 0f; flag3 = ((Vector3)(ref val4)).magnitude <= radius; } catch { } } if (flag3) { _mine[instanceID] = val2; _pending.Remove(instanceID); _known.Add(instanceID); } else if (unscaledTime - value > 2.5f) { _pending.Remove(instanceID); _known.Add(instanceID); } } } catch { } } private static BuildableItem FindDeployable(Camera cam) { try { Transform val = ((Component)cam).transform; int num = 0; while ((Object)(object)val != (Object)null && num++ < 64) { BuildableItem component = ((Component)val).GetComponent<BuildableItem>(); if ((Object)(object)component != (Object)null) { return component; } val = val.parent; } } catch { } return null; } internal static void QueuePickUpMine() { foreach (KeyValuePair<int, BuildableItem> item in _mine) { if ((Object)(object)item.Value != (Object)null) { _pendingPickup[item.Key] = item.Value; } } _pickupRounds = 0; _nextPickupTry = 0f; _mine.Clear(); _known.Clear(); _pending.Clear(); } internal static void TickPickupRetry() { if (_pendingPickup.Count == 0) { return; } float unscaledTime = Time.unscaledTime; if (unscaledTime < _nextPickupTry) { return; } _nextPickupTry = unscaledTime + 1.5f; bool value = EspConfig.DebugLog.Value; List<int> list = new List<int>(); foreach (KeyValuePair<int, BuildableItem> item in _pendingPickup) { BuildableItem value2 = item.Value; if ((Object)(object)value2 == (Object)null) { list.Add(item.Key); continue; } bool flag = false; try { flag = value2.IsDestroyed; } catch { } if (flag) { list.Add(item.Key); continue; } string arg = null; bool flag2 = false; try { flag2 = value2.CanBePickedUp(ref arg); } catch { } if (value) { MelonLogger.Msg($"[PvpCameraEsp] pickup-retry: can={flag2} reason='{arg}' host={PvpApi.IsHost}"); } if (!flag2) { continue; } try { value2.PickupItem(); } catch (Exception ex) { if (value) { MelonLogger.Msg("[PvpCameraEsp] pickup-retry threw: " + ex.Message); } } } for (int i = 0; i < list.Count; i++) { _pendingPickup.Remove(list[i]); } if (_pendingPickup.Count > 0 && ++_pickupRounds >= 12) { if (value) { MelonLogger.Warning($"[PvpCameraEsp] gave up restoring {_pendingPickup.Count} camera(s) after {12} tries"); } _pendingPickup.Clear(); } } internal static void AbortPickup() { _pendingPickup.Clear(); _pickupRounds = 0; } internal static void Reset() { _known.Clear(); _mine.Clear(); _pending.Clear(); _pendingPickup.Clear(); _pickupRounds = 0; } } internal struct VisibleEnemy { internal Player Player; internal int Team; internal ulong SteamId; internal string Persona; internal Vector3 ViewportFeet; internal Vector3 ViewportTop; } internal static class EnemyTracker { private static readonly List<VisibleEnemy> _result = new List<VisibleEnemy>(8); internal static List<VisibleEnemy> Scan(Camera cam) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) _result.Clear(); if ((Object)(object)cam == (Object)null) { return _result; } int localTeam = PvpApi.LocalTeam; if (localTeam < 0) { return _result; } Player localPlayer = PvpApi.LocalPlayer; List<Player> players = PvpApi.Players; float value = EspConfig.MaxDistance.Value; float num = Mathf.Max(0.5f, EspConfig.BodyHeight.Value); bool value2 = EspConfig.RequireLineOfSight.Value; Vector3 position = ((Component)cam).transform.position; ulong steamId = default(ulong); string persona = default(string); for (int i = 0; i < players.Count; i++) { Player val = players[i]; if ((Object)(object)val == (Object)null || ((Object)(object)localPlayer != (Object)null && (val == localPlayer || (Object)(object)val == (Object)(object)localPlayer))) { continue; } int team = PvpApi.GetTeam(val); if (team < 0 || team == localTeam) { continue; } Vector3 position2; Vector3 val2; Vector3 val3; try { position2 = ((Component)val).transform.position; val2 = position2 + Vector3.up * num; val3 = position2 + Vector3.up * (num * 0.5f); } catch { continue; } if (Vector3.Distance(position, val3) > value) { continue; } Vector3 val4; Vector3 val5; try { val4 = cam.WorldToViewportPoint(position2); val5 = cam.WorldToViewportPoint(val2); } catch { continue; } if (!(val4.z <= 0f) && !(val5.z <= 0f)) { float num2 = (val4.x + val5.x) * 0.5f; float num3 = (val4.y + val5.y) * 0.5f; if (!(num2 < -0.2f) && !(num2 > 1.2f) && !(num3 < -0.2f) && !(num3 > 1.2f) && (!value2 || !IsOccluded(position, val3, val))) { PvpApi.TryGetIdentity(val, ref steamId, ref persona); _result.Add(new VisibleEnemy { Player = val, Team = team, SteamId = steamId, Persona = persona, ViewportFeet = val4, ViewportTop = val5 }); } } } return _result; } private static bool IsOccluded(Vector3 from, Vector3 to, Player target) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.05f) { return false; } RaycastHit val2 = default(RaycastHit); if (!Physics.Raycast(from, val / magnitude, ref val2, magnitude - 0.3f)) { return false; } if ((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) { return false; } Player componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Player>(); return !((Object)(object)componentInParent != (Object)null) || (componentInParent != target && !((Object)(object)componentInParent == (Object)(object)target)); } catch { return false; } } } internal static class EspConfig { private static MelonPreferences_Category _cat; internal static MelonPreferences_Entry<bool> Enabled; internal static MelonPreferences_Entry<float> MaxDistance; internal static MelonPreferences_Entry<bool> RequireLineOfSight; internal static MelonPreferences_Entry<float> ReportCooldownSeconds; internal static MelonPreferences_Entry<float> RemindWhileVisibleSeconds; internal static MelonPreferences_Entry<bool> ShowBox; internal static MelonPreferences_Entry<int> BoxThickness; internal static MelonPreferences_Entry<float> BodyHeight; internal static MelonPreferences_Entry<string> BoxColorMode; internal static MelonPreferences_Entry<string> BoxColor; internal static MelonPreferences_Entry<bool> ShowLabels; internal static MelonPreferences_Entry<int> LabelFontSize; internal static MelonPreferences_Entry<bool> DebugLog; internal static MelonPreferences_Entry<bool> ProtectCameras; internal static MelonPreferences_Entry<float> OwnPlacementRadius; internal static MelonPreferences_Entry<bool> CleanupOwnCamerasOnRoundEnd; internal static MelonPreferences_Entry<bool> CleanStaleCameras; internal static void Load() { _cat = MelonPreferences.CreateCategory("PvpCameraEsp"); Enabled = _cat.CreateEntry<bool>("Enabled", true, (string)null, "Master toggle for the camera ESP.", false, false, (ValueValidator)null, (string)null); MaxDistance = _cat.CreateEntry<float>("MaxDistance", 80f, (string)null, "Max distance (m) from the camera to detect an enemy (camera far clip is ~80).", false, false, (ValueValidator)null, (string)null); RequireLineOfSight = _cat.CreateEntry<bool>("RequireLineOfSight", true, (string)null, "Only detect enemies with a clear line of sight (not behind walls). Disable if detection misses.", false, false, (ValueValidator)null, (string)null); ReportCooldownSeconds = _cat.CreateEntry<float>("ReportCooldownSeconds", 5f, (string)null, "Re-arm window: an enemy must be GONE from a camera this long before a NEW alert fires (edge-triggered, no spam while they stay in view).", false, false, (ValueValidator)null, (string)null); RemindWhileVisibleSeconds = _cat.CreateEntry<float>("RemindWhileVisibleSeconds", 0f, (string)null, "Optional: re-alert every N seconds while an enemy stays continuously in view (0 = off, alert only on enter).", false, false, (ValueValidator)null, (string)null); ShowBox = _cat.CreateEntry<bool>("ShowBox", true, (string)null, "Draw a box around each spotted enemy on the camera feed (ESP box).", false, false, (ValueValidator)null, (string)null); BoxThickness = _cat.CreateEntry<int>("BoxThickness", 2, (string)null, "Border thickness (px) of the ESP box.", false, false, (ValueValidator)null, (string)null); BodyHeight = _cat.CreateEntry<float>("BodyHeight", 2f, (string)null, "Assumed player height (m) used to size the box from feet to head.", false, false, (ValueValidator)null, (string)null); BoxColorMode = _cat.CreateEntry<string>("BoxColorMode", "enemyteam", (string)null, "Box/label colour source: 'enemyteam' (spotted enemy's team colour), 'ownteam' (your team = the camera owner's team), or 'custom' (use BoxColor).", false, false, (ValueValidator)null, (string)null); BoxColor = _cat.CreateEntry<string>("BoxColor", "FF3030", (string)null, "Custom box/label colour as hex RGB or RGBA (e.g. FF3030 or FF3030C0). Used only when BoxColorMode = custom.", false, false, (ValueValidator)null, (string)null); ShowLabels = _cat.CreateEntry<bool>("ShowLabels", true, (string)null, "Draw the enemy's Steam name above the box on the camera feed.", false, false, (ValueValidator)null, (string)null); LabelFontSize = _cat.CreateEntry<int>("LabelFontSize", 20, (string)null, "Font size of the on-feed name labels.", false, false, (ValueValidator)null, (string)null); DebugLog = _cat.CreateEntry<bool>("DebugLog", false, (string)null, "Verbose logging (cameras found, alerts) for diagnosing the live test.", false, false, (ValueValidator)null, (string)null); ProtectCameras = _cat.CreateEntry<bool>("ProtectCameras", true, (string)null, "During a Teams match, block players from picking up / demolishing cameras they didn't place (protects client cameras from the host & host-team, and vice-versa).", false, false, (ValueValidator)null, (string)null); OwnPlacementRadius = _cat.CreateEntry<float>("OwnPlacementRadius", 4f, (string)null, "FALLBACK ONLY (used if the BuildManager hook isn't available): a newly-placed camera within this horizontal distance (m) of you is treated as YOURS. Normally ownership comes from the local build flow and this is ignored.", false, false, (ValueValidator)null, (string)null); CleanupOwnCamerasOnRoundEnd = _cat.CreateEntry<bool>("CleanupOwnCamerasOnRoundEnd", true, (string)null, "Pick up your own cameras (back into your inventory) automatically when a match ends, so they don't linger in the NetEye app. Applies to both host and client.", false, false, (ValueValidator)null, (string)null); CleanStaleCameras = _cat.CreateEntry<bool>("CleanStaleCameras", true, (string)null, "HOST: remove stale camera entries (loaded from a previous session's cameras.txt, shown in the app but not backed by a live camera) while in a multiplayer match.", false, false, (ValueValidator)null, (string)null); } internal static Color ResolveBoxColor(int enemyTeam) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) string text = (BoxColorMode.Value ?? "").Trim().ToLowerInvariant(); if (text == "ownteam") { int localTeam = PvpApi.LocalTeam; return PvpApi.TeamColor((localTeam >= 0) ? localTeam : 0); } if (text == "custom") { string value = BoxColor.Value; Color result = default(Color); if (!string.IsNullOrEmpty(value) && ColorUtility.TryParseHtmlString((value[0] == '#') ? value : ("#" + value), ref result)) { return result; } return Color.red; } return PvpApi.TeamColor(enemyTeam); } } internal static class FeedOverlay { private sealed class EnemyBox { internal RectTransform Root; internal RawImage Top; internal RawImage Bottom; internal RawImage Left; internal RawImage Right; internal TextMeshProUGUI Label; } private static RawImage _bound; private static RectTransform _container; private static TMP_FontAsset _font; private static bool _fontResolved; private static bool _warnedNoFont; private static Texture2D _white; private static readonly Dictionary<string, EnemyBox> _boxes = new Dictionary<string, EnemyBox>(); private static readonly HashSet<string> _seen = new HashSet<string>(); private static Texture2D White { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_white == (Object)null) { _white = new Texture2D(1, 1); _white.SetPixel(0, 0, Color.white); _white.Apply(); } return _white; } } internal static void Update(RawImage feed, List<VisibleEnemy> enemies) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)feed == (Object)null) { HideAll(); return; } bool value = EspConfig.ShowBox.Value; bool value2 = EspConfig.ShowLabels.Value; if (!value && !value2) { HideAll(); return; } EnsureContainer(feed); if ((Object)(object)_container == (Object)null) { return; } TMP_FontAsset font = ResolveFont(); Rect rect = ((Graphic)feed).rectTransform.rect; Vector2 size = ((Rect)(ref rect)).size; int value3 = EspConfig.LabelFontSize.Value; _seen.Clear(); Vector2 val = default(Vector2); Vector2 val2 = default(Vector2); Vector2 anchoredPosition = default(Vector2); for (int i = 0; i < enemies.Count; i++) { VisibleEnemy visibleEnemy = enemies[i]; string text = ((visibleEnemy.SteamId != 0L) ? visibleEnemy.SteamId.ToString() : ("n:" + visibleEnemy.Persona)); _seen.Add(text); EnemyBox orCreate = GetOrCreate(text, font); if (orCreate == null) { continue; } ((Vector2)(ref val))..ctor((visibleEnemy.ViewportFeet.x - 0.5f) * size.x, (visibleEnemy.ViewportFeet.y - 0.5f) * size.y); ((Vector2)(ref val2))..ctor((visibleEnemy.ViewportTop.x - 0.5f) * size.x, (visibleEnemy.ViewportTop.y - 0.5f) * size.y); float num = Mathf.Max(6f, Mathf.Abs(val2.y - val.y)); float num2 = Mathf.Clamp(num * 0.4f, 6f, num); ((Vector2)(ref anchoredPosition))..ctor((val.x + val2.x) * 0.5f, (val.y + val2.y) * 0.5f); orCreate.Root.anchoredPosition = anchoredPosition; orCreate.Root.sizeDelta = new Vector2(num2, num); Color val3 = EspConfig.ResolveBoxColor(visibleEnemy.Team); SetEdge(orCreate.Top, value, val3); SetEdge(orCreate.Bottom, value, val3); SetEdge(orCreate.Left, value, val3); SetEdge(orCreate.Right, value, val3); if ((Object)(object)orCreate.Label != (Object)null) { ((Component)orCreate.Label).gameObject.SetActive(value2); if (value2) { ((TMP_Text)orCreate.Label).text = visibleEnemy.Persona; ((TMP_Text)orCreate.Label).fontSize = value3; ((Graphic)orCreate.Label).color = val3; } } if (!((Component)orCreate.Root).gameObject.activeSelf) { ((Component)orCreate.Root).gameObject.SetActive(true); } } foreach (KeyValuePair<string, EnemyBox> box in _boxes) { if (!_seen.Contains(box.Key) && (Object)(object)box.Value.Root != (Object)null && ((Component)box.Value.Root).gameObject.activeSelf) { ((Component)box.Value.Root).gameObject.SetActive(false); } } } private static void SetEdge(RawImage edge, bool show, Color col) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)edge == (Object)null)) { if (((Component)edge).gameObject.activeSelf != show) { ((Component)edge).gameObject.SetActive(show); } if (show) { ((Graphic)edge).color = col; } } } internal static void HideAll() { try { foreach (KeyValuePair<string, EnemyBox> box in _boxes) { if ((Object)(object)box.Value.Root != (Object)null && ((Component)box.Value.Root).gameObject.activeSelf) { ((Component)box.Value.Root).gameObject.SetActive(false); } } } catch { } } private static void EnsureContainer(RawImage feed) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_bound == (Object)(object)feed && (Object)(object)_container != (Object)null) { return; } _boxes.Clear(); _bound = feed; try { GameObject val = new GameObject("PvpCamEsp_Overlay"); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(((Component)feed).transform, false); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; val.AddComponent<RectMask2D>(); _container = val2; if (EspConfig.DebugLog.Value) { MelonLogger.Msg("[PvpCameraEsp] overlay container attached to feed"); } } catch { _container = null; } } private static EnemyBox GetOrCreate(string key, TMP_FontAsset font) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) if (_boxes.TryGetValue(key, out var value) && (Object)(object)value.Root != (Object)null) { return value; } try { int num = Mathf.Max(1, EspConfig.BoxThickness.Value); RectTransform val = NewRect("box_" + key, (Transform)(object)_container, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f)); value = new EnemyBox { Root = val }; value.Top = Edge((Transform)(object)val, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, (float)num)); value.Bottom = Edge((Transform)(object)val, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, (float)num)); value.Left = Edge((Transform)(object)val, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0.5f), new Vector2((float)num, 0f)); value.Right = Edge((Transform)(object)val, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(1f, 0.5f), new Vector2((float)num, 0f)); if ((Object)(object)font != (Object)null) { RectTransform val2 = NewRect("name", (Transform)(object)val, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 0f)); val2.sizeDelta = new Vector2(260f, 28f); val2.anchoredPosition = new Vector2(0f, 4f); TextMeshProUGUI val3 = ((Component)val2).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val3).font = font; ((TMP_Text)val3).alignment = (TextAlignmentOptions)1026; ((TMP_Text)val3).enableWordWrapping = false; ((TMP_Text)val3).richText = false; ((TMP_Text)val3).fontStyle = (FontStyles)1; ((TMP_Text)val3).overflowMode = (TextOverflowModes)0; ((Graphic)val3).raycastTarget = false; value.Label = val3; } else if (!_warnedNoFont) { _warnedNoFont = true; MelonLogger.Warning("[PvpCameraEsp] No TMP font found — boxes still draw, name labels disabled."); } _boxes[key] = value; return value; } catch { return null; } } private static RectTransform NewRect(string name, Transform parent, Vector2 aMin, Vector2 aMax, Vector2 pivot) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); RectTransform val2 = val.AddComponent<RectTransform>(); ((Transform)val2).SetParent(parent, false); val2.anchorMin = aMin; val2.anchorMax = aMax; val2.pivot = pivot; val2.anchoredPosition = Vector2.zero; return val2; } private static RawImage Edge(Transform parent, Vector2 aMin, Vector2 aMax, Vector2 pivot, Vector2 sizeDelta) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) RectTransform val = NewRect("edge", parent, aMin, aMax, pivot); val.sizeDelta = sizeDelta; RawImage val2 = ((Component)val).gameObject.AddComponent<RawImage>(); val2.texture = (Texture)(object)White; ((Graphic)val2).raycastTarget = false; return val2; } private static TMP_FontAsset ResolveFont() { if (_fontResolved) { return _font; } _fontResolved = true; try { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); if (array != null) { TMP_FontAsset[] array2 = array; foreach (TMP_FontAsset val in array2) { if ((Object)(object)val != (Object)null && ((Object)val).name != null && ((Object)val).name.Contains("OpenSans")) { _font = val; return _font; } } TMP_FontAsset[] array3 = array; foreach (TMP_FontAsset val2 in array3) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name != null && (((Object)val2).name.Contains("Inter") || ((Object)val2).name.Contains("Roboto") || ((Object)val2).name.Contains("Liberation") || ((Object)val2).name.Contains("Arial"))) { _font = val2; return _font; } } TMP_FontAsset[] array4 = array; foreach (TMP_FontAsset val3 in array4) { if ((Object)(object)val3 != (Object)null) { _font = val3; return _font; } } } } catch { } return _font; } internal static void Reset() { try { if ((Object)(object)_container != (Object)null) { Object.Destroy((Object)(object)((Component)_container).gameObject); } } catch { } _container = null; _bound = null; _boxes.Clear(); } } internal struct CamEntry { internal Camera Cam; internal string Name; internal CamEntry(Camera cam, string name) { Cam = cam; Name = name; } } internal static class NetEyeBridge { internal const string RtPrefix = "NetEye_RT_"; private const string RootPrefix = "NetEye_"; private static readonly List<CamEntry> _all = new List<CamEntry>(8); private static float _nextAllScan; private static int _lastCount = -1; private static Camera _feedCam; private static RawImage _feedCache; private static readonly Dictionary<int, string> _niceCache = new Dictionary<int, string>(); private static bool _reflectInit; private static bool _reflectOk; private static FieldInfo _fInstance; private static FieldInfo _fCameras; private static FieldInfo _fUnityCam; private static FieldInfo _fName; private static FieldInfo _fLoc; private static FieldInfo _fIsVanilla; private static FieldInfo _fActiveIdx; private static MethodInfo _mDestroy; internal static IReadOnlyList<CamEntry> AllCameras() { float unscaledTime = Time.unscaledTime; if (unscaledTime >= _nextAllScan) { _nextAllScan = unscaledTime + 1f; RebuildAll(); } return _all; } private static void RebuildAll() { _all.Clear(); try { Camera[] array = Resources.FindObjectsOfTypeAll<Camera>(); if (array != null) { Camera[] array2 = array; foreach (Camera val in array2) { if (!((Object)(object)val == (Object)null)) { RenderTexture targetTexture = val.targetTexture; if (!((Object)(object)targetTexture == (Object)null) && ((Object)targetTexture).name != null && ((Object)targetTexture).name.StartsWith("NetEye_RT_")) { _all.Add(new CamEntry(val, ResolveName(val, targetTexture))); } } } } } catch { } if (EspConfig.DebugLog.Value && _all.Count != _lastCount) { _lastCount = _all.Count; MelonLogger.Msg("[PvpCameraEsp] NetEye cameras detected: " + _all.Count); } } internal static bool TryGetLive(out Camera cam, out RawImage feed, out string name) { cam = null; feed = null; name = null; try { IReadOnlyList<CamEntry> readOnlyList = AllCameras(); for (int i = 0; i < readOnlyList.Count; i++) { Camera cam2 = readOnlyList[i].Cam; if ((Object)(object)cam2 != (Object)null && ((Behaviour)cam2).enabled) { cam = cam2; name = readOnlyList[i].Name; break; } } if ((Object)(object)cam == (Object)null) { return false; } feed = ResolveFeed(cam); return (Object)(object)feed != (Object)null; } catch { return false; } } private static RawImage ResolveFeed(Camera cam) { if ((Object)(object)_feedCache != (Object)null && (Object)(object)_feedCam == (Object)(object)cam && (Object)(object)_feedCache.texture == (Object)(object)cam.targetTexture) { return _feedCache; } _feedCache = null; _feedCam = cam; try { Texture targetTexture = (Texture)(object)cam.targetTexture; RawImage[] array = Resources.FindObjectsOfTypeAll<RawImage>(); if (array != null) { RawImage[] array2 = array; foreach (RawImage val in array2) { if (!((Object)(object)val == (Object)null) && (Object)(object)val.texture != (Object)null && (Object)(object)val.texture == (Object)(object)targetTexture) { _feedCache = val; break; } } } } catch { _feedCache = null; } return _feedCache; } private static string ResolveName(Camera cam, RenderTexture rt) { int instanceID = ((Object)cam).GetInstanceID(); if (_niceCache.TryGetValue(instanceID, out var value)) { return value; } string text = TryReflectName(cam); if (!string.IsNullOrEmpty(text)) { _niceCache[instanceID] = text; return text; } return GoName(cam, rt); } private static string GoName(Camera cam, RenderTexture rt) { try { Transform val = ((Component)cam).transform; while ((Object)(object)val.parent != (Object)null) { val = val.parent; } string name = ((Object)((Component)val).gameObject).name; if (!string.IsNullOrEmpty(name) && name.StartsWith("NetEye_")) { return name.Substring("NetEye_".Length); } if ((Object)(object)rt != (Object)null && ((Object)rt).name != null && ((Object)rt).name.StartsWith("NetEye_RT_")) { return ((Object)rt).name.Substring("NetEye_RT_".Length); } return string.IsNullOrEmpty(name) ? "?" : name; } catch { return "?"; } } internal static int RemoveStaleCameras() { int num = 0; try { EnsureReflect(); if (!_reflectOk || _fIsVanilla == null || _mDestroy == null || _fCameras == null) { return 0; } object value = _fInstance.GetValue(null); if (value == null) { return 0; } if (!(_fCameras.GetValue(value) is IList list)) { return 0; } for (int num2 = list.Count - 1; num2 >= 0; num2--) { object obj = list[num2]; if (obj == null) { continue; } bool flag; try { flag = (bool)_fIsVanilla.GetValue(obj); } catch { continue; } if (!flag) { try { _mDestroy.Invoke(obj, null); } catch { } try { list.RemoveAt(num2); num++; } catch { } } } if (num > 0 && _fActiveIdx != null) { try { int num3 = (int)_fActiveIdx.GetValue(value); if (num3 >= list.Count) { _fActiveIdx.SetValue(value, list.Count - 1); } } catch { } } } catch { } return num; } private static string TryReflectName(Camera cam) { try { EnsureReflect(); if (!_reflectOk) { return null; } object value = _fInstance.GetValue(null); if (value == null) { return null; } if (!(_fCameras.GetValue(value) is IEnumerable enumerable)) { return null; } foreach (object item in enumerable) { if (item == null) { continue; } object? value2 = _fUnityCam.GetValue(item); Camera val = (Camera)((value2 is Camera) ? value2 : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)cam) { continue; } string text = _fName.GetValue(item) as string; if (string.IsNullOrEmpty(text)) { return null; } string text2 = ((_fLoc != null) ? (_fLoc.GetValue(item) as string) : null); return string.IsNullOrEmpty(text2) ? text : (text + " (" + text2 + ")"); } } catch { } return null; } private static void EnsureReflect() { if (_reflectInit) { return; } _reflectInit = true; try { Type type = FindType("NetEye.NetEyeMod", "NetEye"); Type type2 = FindType("NetEye.NetEyeCamera", "NetEye"); if (!(type == null) && !(type2 == null)) { _fInstance = type.GetField("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _fCameras = type.GetField("_cameras", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fActiveIdx = type.GetField("_activeCameraIdx", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fUnityCam = type2.GetField("UnityCam", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fName = type2.GetField("Name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fLoc = type2.GetField("Location", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fIsVanilla = type2.GetField("IsVanilla", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _mDestroy = type2.GetMethod("Destroy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); _reflectOk = _fInstance != null && _fCameras != null && _fUnityCam != null && _fName != null; } } catch { _reflectOk = false; } } private static Type FindType(string fullName, string asmSimpleName) { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly.GetName().Name == asmSimpleName) { Type type = assembly.GetType(fullName); if (type != null) { return type; } } } } catch { } try { return Type.GetType(fullName + ", " + asmSimpleName); } catch { return null; } } internal static void Reset() { _all.Clear(); _niceCache.Clear(); _feedCam = null; _feedCache = null; _nextAllScan = 0f; _lastCount = -1; } } public class PvpCameraEspMod : MelonMod { private float _nextSensorScan; private float _nextStaleScan; private bool _wasMatchActive; public override void OnInitializeMelon() { EspConfig.Load(); CameraGuard.Apply(); MelonLogger.Msg("[PvpCameraEsp] ready — symmetric camera ESP for MultiplayerPVP via NetEye cameras."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { try { NetEyeBridge.Reset(); FeedOverlay.Reset(); SightingReporter.Reset(); CameraOwnership.Reset(); CameraBuildTracker.Reset(); _wasMatchActive = false; } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] OnSceneWasLoaded: " + ex.Message); } } public override void OnUpdate() { try { if (!EspConfig.Enabled.Value) { FeedOverlay.HideAll(); _wasMatchActive = false; return; } float unscaledTime = Time.unscaledTime; bool isHost = PvpApi.IsHost; bool isTeamsMatchActive = PvpApi.IsTeamsMatchActive; bool isMatchActive = PvpApi.IsMatchActive; CameraOwnership.Tick(EspConfig.OwnPlacementRadius.Value); if (isHost && EspConfig.CleanStaleCameras.Value && PvpApi.IsMultiplayer && unscaledTime >= _nextStaleScan) { _nextStaleScan = unscaledTime + 5f; int num = NetEyeBridge.RemoveStaleCameras(); if (num > 0 && EspConfig.DebugLog.Value) { MelonLogger.Msg($"[PvpCameraEsp] removed {num} stale camera(s)"); } } if (_wasMatchActive && !isMatchActive && EspConfig.CleanupOwnCamerasOnRoundEnd.Value) { CameraOwnership.QueuePickUpMine(); } else if (!_wasMatchActive && isMatchActive) { CameraOwnership.AbortPickup(); } _wasMatchActive = isMatchActive; CameraOwnership.TickPickupRetry(); if (!isTeamsMatchActive) { FeedOverlay.HideAll(); return; } if (unscaledTime >= _nextSensorScan) { _nextSensorScan = unscaledTime + 0.25f; IReadOnlyList<CamEntry> readOnlyList = NetEyeBridge.AllCameras(); for (int i = 0; i < readOnlyList.Count; i++) { if (CameraOwnership.IsMineCamera(readOnlyList[i].Cam)) { List<VisibleEnemy> list = EnemyTracker.Scan(readOnlyList[i].Cam); if (list.Count > 0) { SightingReporter.Report(list, readOnlyList[i].Name); } } } } if (NetEyeBridge.TryGetLive(out var cam, out var feed, out var _) && CameraOwnership.IsMineCamera(cam)) { FeedOverlay.Update(feed, EnemyTracker.Scan(cam)); } else { FeedOverlay.HideAll(); } } catch (Exception ex) { MelonLogger.Warning("[PvpCameraEsp] OnUpdate: " + ex.Message); } } } internal static class SightingReporter { private static readonly Dictionary<string, float> _lastSeen = new Dictionary<string, float>(); private static readonly Dictionary<string, float> _lastFired = new Dictionary<string, float>(); internal static void Report(List<VisibleEnemy> enemies, string cameraName) { float unscaledTime = Time.unscaledTime; float num = Mathf.Max(0.5f, EspConfig.ReportCooldownSeconds.Value); float value = EspConfig.RemindWhileVisibleSeconds.Value; for (int i = 0; i < enemies.Count; i++) { VisibleEnemy visibleEnemy = enemies[i]; string text = ((visibleEnemy.SteamId != 0L) ? visibleEnemy.SteamId.ToString() : ("n:" + visibleEnemy.Persona)); string key = text + "@" + cameraName; float value2; bool flag = !_lastSeen.TryGetValue(key, out value2) || unscaledTime - value2 > num; float value3; bool flag2 = value > 0f && _lastFired.TryGetValue(key, out value3) && unscaledTime - value3 >= value; _lastSeen[key] = unscaledTime; if (flag || flag2) { _lastFired[key] = unscaledTime; if (EspConfig.DebugLog.Value) { MelonLogger.Msg(string.Format("[PvpCameraEsp] ALERT{0}: {1} (team {2}, steamId {3}) @ {4}", (flag2 && !flag) ? " (reminder)" : "", visibleEnemy.Persona, visibleEnemy.Team, visibleEnemy.SteamId, cameraName)); } PvpApi.ReportCameraSighting(visibleEnemy.Team, visibleEnemy.SteamId, visibleEnemy.Persona, cameraName); } } if (_lastSeen.Count > 128) { Prune(unscaledTime, num); } } private static void Prune(float now, float rearm) { List<string> list = new List<string>(); foreach (KeyValuePair<string, float> item in _lastSeen) { if (now - item.Value > rearm * 4f + 10f) { list.Add(item.Key); } } for (int i = 0; i < list.Count; i++) { _lastSeen.Remove(list[i]); _lastFired.Remove(list[i]); } } internal static void Reset() { try { _lastSeen.Clear(); _lastFired.Clear(); } catch { } } } }
PvpWhistle.IL2CPP.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.PlayerScripts.Health; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiplayerPVP.Addons; using MultiplayerPVP.Core; using PvpWhistle; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonAdditionalDependencies(new string[] { "MultiplayerPVP" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: MelonInfo(typeof(PvpWhistleMod), "PvpWhistle", "1.0.2", "Virtunerd", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyFileVersion("1.0.2")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyVersion("1.0.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PvpWhistle { public class PvpWhistleMod : MelonMod { private WhistleAddon _addon; public override void OnInitializeMelon() { _addon = new WhistleAddon(); if (PvpApi.RegisterAddon((IPvpAddon)(object)_addon)) { MelonLogger.Msg("[PvpWhistle] registered with MultiplayerPVP."); } else { MelonLogger.Warning("[PvpWhistle] registration failed — is MultiplayerPVP loaded?"); } } public override void OnDeinitializeMelon() { try { PvpApi.UnregisterAddon((IPvpAddon)(object)_addon); } catch { } } } internal sealed class WhistleAddon : PvpAddonBase { private sealed class Ping { internal Vector3 Pos; internal string Name; internal float Until; } private MelonPreferences_Entry<float> _intervalSeconds; private MelonPreferences_Entry<float> _pingSeconds; private MelonPreferences_Entry<bool> _seekersOnly; private readonly List<Ping> _pings = new List<Ping>(); private float _nextWhistle; private bool _show; private static GUIStyle _center; public override string Id => "PvpWhistle"; private float Interval => Mathf.Max(3f, _intervalSeconds.Value); private static GUIStyle CenterStyle { get { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (_center == null) { _center = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 14, fontStyle = (FontStyle)1 }; } return _center; } } public override void OnRegistered() { MelonPreferences_Category val = MelonPreferences.CreateCategory("PvpWhistle", "PVP Hider Whistle"); _intervalSeconds = val.CreateEntry<float>("WhistleIntervalSeconds", 10f, "Whistle interval (s)", "Seconds between automatic hider whistles during Hide & Seek (min 3).", false, false, (ValueValidator)null, (string)null); _pingSeconds = val.CreateEntry<float>("PingVisibleSeconds", 4f, "Ping visible (s)", "How long each whistle ping stays on screen (1-15).", false, false, (ValueValidator)null, (string)null); _seekersOnly = val.CreateEntry<bool>("SeekersOnlyDisplay", true, "Seekers only", "Only seekers see the pings (hiders just whistle). Off = everyone sees them.", false, false, (ValueValidator)null, (string)null); } public override void OnGo(GameModeType mode) { _pings.Clear(); _nextWhistle = Time.realtimeSinceStartup + Interval; } public override void OnDayEnded(GameModeType mode, int day) { _pings.Clear(); } public override void OnMatchEnded(GameModeType mode) { _pings.Clear(); } public override void OnSceneLoaded(int buildIndex, string sceneName) { _pings.Clear(); } public override void OnDeinit() { _pings.Clear(); } public override void OnUpdate(float dt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if ((int)PvpApi.Mode != 6 || (int)PvpApi.Phase != 2) { if (_pings.Count > 0) { _pings.Clear(); } return; } _show = true; if (_seekersOnly.Value) { _show = false; try { Player localPlayer = PvpApi.LocalPlayer; bool show = default(bool); if ((Object)(object)localPlayer != (Object)null && PvpApi.TryGetHideSeekRole(localPlayer, ref show)) { _show = show; } } catch { } } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= _nextWhistle) { _nextWhistle = realtimeSinceStartup + Interval; Whistle(realtimeSinceStartup); } for (int num = _pings.Count - 1; num >= 0; num--) { if (_pings[num].Until <= realtimeSinceStartup) { _pings.RemoveAt(num); } } } private void Whistle(float now) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(_pingSeconds.Value, 1f, 15f); Player localPlayer = PvpApi.LocalPlayer; List<Player> players = PvpApi.Players; bool flag = default(bool); for (int i = 0; i < players.Count; i++) { Player val = players[i]; try { if (!((Object)(object)val == (Object)null) && (!((Object)(object)localPlayer != (Object)null) || !((Object)(object)val == (Object)(object)localPlayer)) && !(!PvpApi.TryGetHideSeekRole(val, ref flag) || flag)) { PlayerHealth componentInChildren = ((Component)val).GetComponentInChildren<PlayerHealth>(true); if (!((Object)(object)componentInChildren != (Object)null) || componentInChildren.IsAlive) { _pings.Add(new Ping { Pos = ((Component)val).transform.position, Name = val.PlayerName, Until = now + num }); } } } catch { } } } public override void OnGui() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0175: 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_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) if (!_show || _pings.Count == 0 || (int)PvpApi.Phase != 2) { return; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } Vector3 val = Vector3.zero; bool flag = false; try { Player localPlayer = PvpApi.LocalPlayer; if ((Object)(object)localPlayer != (Object)null) { val = ((Component)localPlayer).transform.position; flag = true; } } catch { } float realtimeSinceStartup = Time.realtimeSinceStartup; float num = Mathf.Clamp(_pingSeconds.Value, 1f, 15f); Color color = GUI.color; Rect val3 = default(Rect); for (int i = 0; i < _pings.Count; i++) { Ping ping = _pings[i]; Vector3 val2; try { val2 = main.WorldToScreenPoint(ping.Pos + Vector3.up * 1.8f); } catch { continue; } if (!(val2.z <= 0f)) { float num2 = Mathf.Clamp01((ping.Until - realtimeSinceStartup) / num); string text = (flag ? $"♪ {ping.Name} · {Vector3.Distance(val, ping.Pos):0}m" : ("♪ " + ping.Name)); ((Rect)(ref val3))..ctor(val2.x - 80f, (float)Screen.height - val2.y - 12f, 160f, 24f); GUI.color = new Color(0f, 0f, 0f, num2 * 0.8f); GUI.Label(new Rect(((Rect)(ref val3)).x + 1f, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, CenterStyle); GUI.color = new Color(1f, 0.92f, 0.35f, num2); GUI.Label(val3, text, CenterStyle); } } GUI.color = color; } } }
PvpWhistle.MONO.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiplayerPVP.Addons; using MultiplayerPVP.Core; using PvpWhistle; using ScheduleOne.PlayerScripts; using ScheduleOne.PlayerScripts.Health; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonAdditionalDependencies(new string[] { "MultiplayerPVP" })] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: MelonInfo(typeof(PvpWhistleMod), "PvpWhistle", "1.0.2", "Virtunerd", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyFileVersion("1.0.2")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyVersion("1.0.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PvpWhistle { public class PvpWhistleMod : MelonMod { private WhistleAddon _addon; public override void OnInitializeMelon() { _addon = new WhistleAddon(); if (PvpApi.RegisterAddon((IPvpAddon)(object)_addon)) { MelonLogger.Msg("[PvpWhistle] registered with MultiplayerPVP."); } else { MelonLogger.Warning("[PvpWhistle] registration failed — is MultiplayerPVP loaded?"); } } public override void OnDeinitializeMelon() { try { PvpApi.UnregisterAddon((IPvpAddon)(object)_addon); } catch { } } } internal sealed class WhistleAddon : PvpAddonBase { private sealed class Ping { internal Vector3 Pos; internal string Name; internal float Until; } private MelonPreferences_Entry<float> _intervalSeconds; private MelonPreferences_Entry<float> _pingSeconds; private MelonPreferences_Entry<bool> _seekersOnly; private readonly List<Ping> _pings = new List<Ping>(); private float _nextWhistle; private bool _show; private static GUIStyle _center; public override string Id => "PvpWhistle"; private float Interval => Mathf.Max(3f, _intervalSeconds.Value); private static GUIStyle CenterStyle { get { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (_center == null) { _center = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 14, fontStyle = (FontStyle)1 }; } return _center; } } public override void OnRegistered() { MelonPreferences_Category val = MelonPreferences.CreateCategory("PvpWhistle", "PVP Hider Whistle"); _intervalSeconds = val.CreateEntry<float>("WhistleIntervalSeconds", 10f, "Whistle interval (s)", "Seconds between automatic hider whistles during Hide & Seek (min 3).", false, false, (ValueValidator)null, (string)null); _pingSeconds = val.CreateEntry<float>("PingVisibleSeconds", 4f, "Ping visible (s)", "How long each whistle ping stays on screen (1-15).", false, false, (ValueValidator)null, (string)null); _seekersOnly = val.CreateEntry<bool>("SeekersOnlyDisplay", true, "Seekers only", "Only seekers see the pings (hiders just whistle). Off = everyone sees them.", false, false, (ValueValidator)null, (string)null); } public override void OnGo(GameModeType mode) { _pings.Clear(); _nextWhistle = Time.realtimeSinceStartup + Interval; } public override void OnDayEnded(GameModeType mode, int day) { _pings.Clear(); } public override void OnMatchEnded(GameModeType mode) { _pings.Clear(); } public override void OnSceneLoaded(int buildIndex, string sceneName) { _pings.Clear(); } public override void OnDeinit() { _pings.Clear(); } public override void OnUpdate(float dt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if ((int)PvpApi.Mode != 6 || (int)PvpApi.Phase != 2) { if (_pings.Count > 0) { _pings.Clear(); } return; } _show = true; if (_seekersOnly.Value) { _show = false; try { Player localPlayer = PvpApi.LocalPlayer; bool show = default(bool); if ((Object)(object)localPlayer != (Object)null && PvpApi.TryGetHideSeekRole(localPlayer, ref show)) { _show = show; } } catch { } } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup >= _nextWhistle) { _nextWhistle = realtimeSinceStartup + Interval; Whistle(realtimeSinceStartup); } for (int num = _pings.Count - 1; num >= 0; num--) { if (_pings[num].Until <= realtimeSinceStartup) { _pings.RemoveAt(num); } } } private void Whistle(float now) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(_pingSeconds.Value, 1f, 15f); Player localPlayer = PvpApi.LocalPlayer; List<Player> players = PvpApi.Players; bool flag = default(bool); for (int i = 0; i < players.Count; i++) { Player val = players[i]; try { if (!((Object)(object)val == (Object)null) && (!((Object)(object)localPlayer != (Object)null) || !((Object)(object)val == (Object)(object)localPlayer)) && !(!PvpApi.TryGetHideSeekRole(val, ref flag) || flag)) { PlayerHealth componentInChildren = ((Component)val).GetComponentInChildren<PlayerHealth>(true); if (!((Object)(object)componentInChildren != (Object)null) || componentInChildren.IsAlive) { _pings.Add(new Ping { Pos = ((Component)val).transform.position, Name = val.PlayerName, Until = now + num }); } } } catch { } } } public override void OnGui() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) if (!_show || _pings.Count == 0 || (int)PvpApi.Phase != 2) { return; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } Vector3 val = Vector3.zero; bool flag = false; try { Player localPlayer = PvpApi.LocalPlayer; if ((Object)(object)localPlayer != (Object)null) { val = ((Component)localPlayer).transform.position; flag = true; } } catch { } float realtimeSinceStartup = Time.realtimeSinceStartup; float num = Mathf.Clamp(_pingSeconds.Value, 1f, 15f); Color color = GUI.color; Rect val3 = default(Rect); for (int i = 0; i < _pings.Count; i++) { Ping ping = _pings[i]; Vector3 val2; try { val2 = main.WorldToScreenPoint(ping.Pos + Vector3.up * 1.8f); } catch { continue; } if (!(val2.z <= 0f)) { float num2 = Mathf.Clamp01((ping.Until - realtimeSinceStartup) / num); string text = (flag ? $"♪ {ping.Name} · {Vector3.Distance(val, ping.Pos):0}m" : ("♪ " + ping.Name)); ((Rect)(ref val3))..ctor(val2.x - 80f, (float)Screen.height - val2.y - 12f, 160f, 24f); GUI.color = new Color(0f, 0f, 0f, num2 * 0.8f); GUI.Label(new Rect(((Rect)(ref val3)).x + 1f, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, CenterStyle); GUI.color = new Color(1f, 0.92f, 0.35f, num2); GUI.Label(val3, text, CenterStyle); } } GUI.color = color; } } }
Riot.IL2CPP.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Il2CppFishNet; using Il2CppFishNet.Managing; using Il2CppFishNet.Object; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne.Cartel; using Il2CppScheduleOne.Combat; using Il2CppScheduleOne.Doors; using Il2CppScheduleOne.NPCs; using Il2CppScheduleOne.NPCs.Behaviour; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.PlayerScripts.Health; using Il2CppScheduleOne.Police; using Il2CppSystem.Collections.Generic; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiplayerPVP.Addons; using MultiplayerPVP.Core; using Riot; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonAdditionalDependencies(new string[] { "MultiplayerPVP" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: MelonInfo(typeof(RiotMod), "Riot", "1.0.1", "Virtunerd", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Riot { internal static class ChaosDirector { private const float RETARGET_INTERVAL = 1.5f; private const float NPC_GIVE_UP = 200f; private static readonly List<NPC> _engaged = new List<NPC>(); private static readonly List<NPC> _civilians = new List<NPC>(); private static float _cd; internal static bool On { get; private set; } internal static void SetOn(bool on) { if (On != on) { On = on; if (!on) { Teardown(); } else { _cd = 0f; } MelonLogger.Msg("[Riot] CHAOS " + (on ? "ON — the city hunts the players." : "OFF.")); } } internal static void Reset() { _engaged.Clear(); _civilians.Clear(); On = false; } internal static void Tick(float dt) { //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) if (!On) { return; } try { if (!RiotCompat.IsAuthority) { SetOn(on: false); return; } _cd -= dt; if (_cd > 0f) { return; } _cd = 1.5f; float num = Mathf.Clamp(RiotConfig.ChaosRadius.Value, 15f, 200f); try { List<PoliceOfficer> officers = PoliceOfficer.Officers; if (officers != null) { for (int i = 0; i < officers.Count; i++) { try { PoliceOfficer val = officers[i]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null) { continue; } NPCHealth health = ((NPC)val).Health; if (!((Object)(object)health == (Object)null) && !health.IsDead && !health.IsKnockedOut) { Player val2 = NearestAlivePlayer(((Component)val).transform.position, num); if (!((Object)(object)val2 == (Object)null)) { SicNpc((NPC)(object)val, val2, civilian: false); } } } catch { } } } } catch { } if (!RiotConfig.CiviliansJoinChaos.Value) { return; } PruneCivilians(); int num2 = Mathf.Clamp(RiotConfig.MaxChaosCivilians.Value, 1, 16); try { List<NPC> nPCRegistry = NPCManager.NPCRegistry; if (nPCRegistry != null) { for (int j = 0; j < nPCRegistry.Count; j++) { if (_civilians.Count >= num2) { break; } try { NPC val3 = nPCRegistry[j]; if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).transform == (Object)null || (Object)(object)RiotCompat.Cast<PoliceOfficer>((Object)(object)val3) != (Object)null || (Object)(object)RiotCompat.Cast<CartelGoon>((Object)(object)val3) != (Object)null) { continue; } NPCHealth health2 = val3.Health; if (!((Object)(object)health2 == (Object)null) && !health2.IsDead && !health2.IsKnockedOut) { Player val4 = NearestAlivePlayer(((Component)val3).transform.position, num); if (!((Object)(object)val4 == (Object)null) && SicNpc(val3, val4, civilian: true) && !_civilians.Contains(val3)) { _civilians.Add(val3); } } } catch { } } } } catch { } for (int k = 0; k < _civilians.Count; k++) { try { NPC val5 = _civilians[k]; if (!((Object)(object)val5 == (Object)null) && !((Object)(object)((Component)val5).transform == (Object)null)) { Player val6 = NearestAlivePlayer(((Component)val5).transform.position, num * 2f); if ((Object)(object)val6 != (Object)null) { SicNpc(val5, val6, civilian: true); } } } catch { } } } catch (Exception ex) { MelonLogger.Warning("[Riot] Chaos tick: " + ex.Message); } } private static bool SicNpc(NPC npc, Player target, bool civilian) { try { object obj; if (target == null) { obj = null; } else { GameObject gameObject = ((Component)target).gameObject; obj = ((gameObject != null) ? gameObject.GetComponent<NetworkObject>() : null); } NetworkObject val = (NetworkObject)obj; object obj2; if (npc == null) { obj2 = null; } else { NPCBehaviour behaviour = npc.Behaviour; obj2 = ((behaviour != null) ? behaviour.CombatBehaviour : null); } CombatBehaviour val2 = (CombatBehaviour)obj2; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } try { val2.GiveUpRange = 200f; } catch { } val2.SetTargetAndEnable_Server(val); if (!_engaged.Contains(npc)) { _engaged.Add(npc); } return true; } catch { return false; } } private static void PruneCivilians() { for (int num = _civilians.Count - 1; num >= 0; num--) { try { NPC val = _civilians[num]; NPCHealth val2 = (((Object)(object)val != (Object)null) ? val.Health : null); if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null || (Object)(object)val2 == (Object)null || val2.IsDead || val2.IsKnockedOut) { _civilians.RemoveAt(num); } } catch { _civilians.RemoveAt(num); } } } internal static Player NearestAlivePlayer(Vector3 pos, float radius) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) Player result = null; float num = radius; try { List<Player> playerList = Player.PlayerList; if (playerList == null) { return null; } for (int i = 0; i < playerList.Count; i++) { try { Player val = playerList[i]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null) { continue; } PlayerHealth componentInChildren = ((Component)val).GetComponentInChildren<PlayerHealth>(true); if (!((Object)(object)componentInChildren != (Object)null) || componentInChildren.IsAlive) { float num2 = Vector3.Distance(((Component)val).transform.position, pos); if (num2 < num) { num = num2; result = val; } } } catch { } } } catch { } return result; } private static void Teardown() { for (int i = 0; i < _engaged.Count; i++) { try { NPC obj = _engaged[i]; object obj2; if (obj == null) { obj2 = null; } else { NPCBehaviour behaviour = obj.Behaviour; obj2 = ((behaviour != null) ? behaviour.CombatBehaviour : null); } CombatBehaviour val = (CombatBehaviour)obj2; if ((Object)(object)val != (Object)null) { try { ((Behaviour)val).Deactivate(); } catch { } try { ((Behaviour)val).Disable(); } catch { } } } catch { } } _engaged.Clear(); _civilians.Clear(); } } internal sealed class RiotAddon : PvpAddonBase { private PvpMatchToggle _riotToggle; private PvpMatchToggle _chaosToggle; private PvpChannel _channel; private int _seq; private readonly Dictionary<ulong, string> _seen = new Dictionary<ulong, string>(); private bool _chaosActiveLocal; private string _lastState = ""; private bool _prevRiotReq; private bool _prevChaosReq; public override string Id => "Riot"; public override void OnRegistered() { RiotConfig.Load(); _channel = PvpApi.Channel("riot"); if (_channel != null) { _channel.OnMessage += OnRiotMsg; } _riotToggle = PvpApi.RegisterMatchToggle("riot", "Riot", "City riot for this round: Benzies storm out of the door nearest each cop and brawl with the police while you play. Mutually exclusive with Chaos."); _chaosToggle = PvpApi.RegisterMatchToggle("chaos", "Chaos", "The city turns on YOU for this round: cops, Benzies and civilians hunt every player on sight until KO. NPC knock-outs confiscate weapons. Mutually exclusive with Riot."); if (_riotToggle != null) { _riotToggle.Activated += OnRiotActivated; _riotToggle.Deactivated += OnRoundDeactivated; } if (_chaosToggle != null) { _chaosToggle.Activated += OnChaosActivated; _chaosToggle.Deactivated += OnRoundDeactivated; } PvpApi.RegisterNpcKoAttributor((Func<bool>)IsKoFromChaos); } private void OnRiotActivated() { if (PvpApi.IsMultiplayer && RiotCompat.IsAuthority) { ChaosDirector.SetOn(on: false); RiotManager.SetOn(on: true); PublishState(); } } private void OnChaosActivated() { if (PvpApi.IsMultiplayer && RiotCompat.IsAuthority) { ChaosDirector.SetOn(on: true); RiotManager.SetOn(on: true); _chaosActiveLocal = true; PublishState(); } } private void OnRoundDeactivated() { bool flag = RiotManager.On || ChaosDirector.On; ChaosDirector.SetOn(on: false); RiotManager.SetOn(on: false); _chaosActiveLocal = false; if (flag) { PublishState(); } } public override void OnUpdate(float dt) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 try { if (_chaosToggle != null && _riotToggle != null) { bool requested = _riotToggle.Requested; bool requested2 = _chaosToggle.Requested; if (requested && requested2) { if (requested2 && !_prevChaosReq) { _riotToggle.Requested = false; } else { _chaosToggle.Requested = false; } } _prevRiotReq = _riotToggle.Requested; _prevChaosReq = _chaosToggle.Requested; } } catch { } bool flag = (int)PvpApi.Phase != 2 || !PvpApi.IsMultiplayer; if (ChaosDirector.On && flag) { ChaosDirector.SetOn(on: false); _chaosActiveLocal = false; } if (RiotManager.On && flag) { RiotManager.SetOn(on: false); } RiotManager.Tick(dt); ChaosDirector.Tick(dt); if (_channel != null) { List<KeyValuePair<ulong, string>> list = _channel.ReadAll(); for (int i = 0; i < list.Count; i++) { OnRiotMsg(list[i].Key, list[i].Value); } } } private void PublishState() { bool flag = RiotManager.On && !ChaosDirector.On; string text = (flag ? "1" : "0") + "~" + (ChaosDirector.On ? "1" : "0"); ShowState(flag, ChaosDirector.On); PvpChannel channel = _channel; if (channel != null) { int num = ++_seq; channel.Publish(num + "~" + text); } } private void OnRiotMsg(ulong fromSteamId, string record) { if (string.IsNullOrEmpty(record) || (_seen.TryGetValue(fromSteamId, out var value) && value == record)) { return; } _seen[fromSteamId] = record; if (!RiotCompat.IsAuthority) { string[] array = record.Split('~'); if (array.Length >= 3) { bool riot = array[1] == "1"; ShowState(riot, _chaosActiveLocal = array[2] == "1"); } } } private void ShowState(bool riot, bool chaos) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) string text = (riot ? "r" : "") + (chaos ? "c" : ""); if (!(text == _lastState)) { _lastState = text; if (chaos) { PvpApi.ShowLocalBanner("☠ CHAOS — the whole city is out for YOUR blood!", 5f, new Color(1f, 0.15f, 0.15f)); } else if (riot) { PvpApi.ShowLocalBanner("⚠ RIOT — the Benzies are out!", 5f, new Color(1f, 0.35f, 0.2f)); } else { PvpApi.ShowLocalBanner("The streets calm down.", 4f, Color.white); } } } private bool IsKoFromChaos() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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) if (!_chaosActiveLocal) { return false; } try { Player local = Player.Local; if ((Object)(object)local == (Object)null || (Object)(object)((Component)local).transform == (Object)null) { return false; } Vector3 position = ((Component)local).transform.position; float num = float.MaxValue; List<Player> playerList = Player.PlayerList; if (playerList != null) { for (int i = 0; i < playerList.Count; i++) { try { Player val = playerList[i]; if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)local || (Object)(object)((Component)val).transform == (Object)null) { continue; } PlayerHealth componentInChildren = ((Component)val).GetComponentInChildren<PlayerHealth>(true); if (!((Object)(object)componentInChildren != (Object)null) || componentInChildren.IsAlive) { float num2 = Vector3.Distance(position, ((Component)val).transform.position); if (num2 < num) { num = num2; } } } catch { } } } float num3 = float.MaxValue; try { List<PoliceOfficer> officers = PoliceOfficer.Officers; if (officers != null) { for (int j = 0; j < officers.Count; j++) { try { PoliceOfficer val2 = officers[j]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).transform == (Object)null)) { float num4 = Vector3.Distance(position, ((Component)val2).transform.position); if (num4 < num3) { num3 = num4; } } } catch { } } } } catch { } try { Il2CppArrayBase<CartelGoon> val3 = Object.FindObjectsOfType<CartelGoon>(); if (val3 != null) { for (int k = 0; k < val3.Length; k++) { try { CartelGoon val4 = val3[k]; if (!((Object)(object)val4 == (Object)null) && val4.IsGoonSpawned && !((Object)(object)((Component)val4).transform == (Object)null)) { float num5 = Vector3.Distance(position, ((Component)val4).transform.position); if (num5 < num3) { num3 = num5; } } } catch { } } } } catch { } return (num3 <= 25f && num3 < num) || num > 60f; } catch { return false; } } public override void OnSceneLoaded(int buildIndex, string sceneName) { RiotManager.Reset(); ChaosDirector.Reset(); _chaosActiveLocal = false; _seen.Clear(); _lastState = ""; } public override void OnDeinit() { ChaosDirector.SetOn(on: false); RiotManager.SetOn(on: false); RiotManager.Reset(); ChaosDirector.Reset(); try { PvpApi.UnregisterNpcKoAttributor((Func<bool>)IsKoFromChaos); } catch { } try { PvpApi.UnregisterMatchToggle(_riotToggle); } catch { } try { PvpApi.UnregisterMatchToggle(_chaosToggle); } catch { } } } internal static class RiotCompat { public static bool IsAuthority { get { try { NetworkManager networkManager = InstanceFinder.NetworkManager; if ((Object)(object)networkManager == (Object)null) { return true; } return networkManager.IsServer; } catch { return true; } } } public static T Cast<T>(Object o) where T : Object { return (o == (Object)null) ? default(T) : ((Il2CppObjectBase)o).TryCast<T>(); } public static T CastTargetable<T>(Il2CppObjectBase o) where T : Il2CppObjectBase { return (o == null) ? default(T) : o.TryCast<T>(); } } internal static class RiotConfig { internal static MelonPreferences_Entry<int> BenziesPerOfficer; internal static MelonPreferences_Entry<int> BenziesMax; internal static MelonPreferences_Entry<float> OfficerScanRadius; internal static MelonPreferences_Entry<float> DoorMaxDistance; internal static MelonPreferences_Entry<float> WaveCooldownSeconds; internal static MelonPreferences_Entry<bool> OfficersFightBack; internal static MelonPreferences_Entry<float> ChaosRadius; internal static MelonPreferences_Entry<bool> CiviliansJoinChaos; internal static MelonPreferences_Entry<int> MaxChaosCivilians; private static bool _loaded; internal static void Load() { if (!_loaded) { _loaded = true; MelonPreferences_Category val = MelonPreferences.CreateCategory("Riot", "Riot"); BenziesPerOfficer = val.CreateEntry<int>("BenziesPerOfficer", 2, "Benzies per officer", "How many Benzies gang up on each targeted officer (1-4).", false, false, (ValueValidator)null, (string)null); BenziesMax = val.CreateEntry<int>("BenziesMax", 8, "Max active Benzies", "Hard cap of simultaneously active riot Benzies (1-16).", false, false, (ValueValidator)null, (string)null); OfficerScanRadius = val.CreateEntry<float>("OfficerScanRadius", 80f, "Officer scan radius (m)", "Waves target the nearest under-staffed officer within this radius of ANY player.", false, false, (ValueValidator)null, (string)null); DoorMaxDistance = val.CreateEntry<float>("DoorMaxDistance", 80f, "Door search radius (m)", "The Benzies spawn at the door nearest to the targeted officer within this radius (ring fallback beyond).", false, false, (ValueValidator)null, (string)null); WaveCooldownSeconds = val.CreateEntry<float>("WaveCooldownSeconds", 20f, "Wave cooldown (s)", "Minimum seconds between spawn waves while the riot runs (min 5).", false, false, (ValueValidator)null, (string)null); OfficersFightBack = val.CreateEntry<bool>("OfficersFightBack", true, "Officers fight back", "Explicitly trigger officer counter-attacks (vanilla cops NEVER retaliate against NPCs on their own).", false, false, (ValueValidator)null, (string)null); ChaosRadius = val.CreateEntry<float>("ChaosRadius", 60f, "Chaos radius (m)", "CHAOS toggle: cops/civilians within this radius of a player join the hunt against the players.", false, false, (ValueValidator)null, (string)null); CiviliansJoinChaos = val.CreateEntry<bool>("CiviliansJoinChaos", true, "Civilians join chaos", "CHAOS toggle: nearby civilian NPCs also attack players (fists). CAUTION: this can pull in other mods' NPCs that stand near a player.", false, false, (ValueValidator)null, (string)null); MaxChaosCivilians = val.CreateEntry<int>("MaxChaosCivilians", 8, "Max chaos civilians", "CHAOS toggle: cap of civilians simultaneously hunting players (1-16).", false, false, (ValueValidator)null, (string)null); } } } internal static class RiotManager { private sealed class ActiveGoon { internal CartelGoon Goon; internal PoliceOfficer Target; internal Player TargetPlayer; internal float DespawnAt; } private const int POOL_RESERVE = 1; private const float GOON_GIVE_UP = 200f; private const float RETARGET_INTERVAL = 1.5f; private const float GOON_LIFETIME = 180f; private const float ORPHAN_RADIUS = 90f; private const float DOOR_FALLBACK_DIST = 18f; private static readonly List<ActiveGoon> _active = new List<ActiveGoon>(); private static readonly List<PoliceOfficer> _engagedOfficers = new List<PoliceOfficer>(); private static float _nextWave; private static float _retargetCd; internal static bool On { get; private set; } internal static int ActiveCount => _active.Count; internal static void SetOn(bool on) { if (On != on) { On = on; if (!on) { Teardown(); } else { _nextWave = 0f; _retargetCd = 0f; } MelonLogger.Msg("[Riot] " + (on ? "ON — Benzies are hunting the badges." : "OFF — streets calm down.")); } } internal static void Reset() { _active.Clear(); _engagedOfficers.Clear(); On = false; } internal static void Tick(float dt) { if (!On) { return; } try { if (!RiotCompat.IsAuthority) { SetOn(on: false); return; } float time = Time.time; Prune(time); _retargetCd -= dt; if (_retargetCd <= 0f) { _retargetCd = 1.5f; Retarget(); } if (time >= _nextWave && _active.Count < Mathf.Clamp(RiotConfig.BenziesMax.Value, 1, 16)) { _nextWave = time + Mathf.Max(5f, RiotConfig.WaveCooldownSeconds.Value); SpawnWave(); } } catch (Exception ex) { MelonLogger.Warning("[Riot] Tick: " + ex.Message); } } private static void SpawnWave() { //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(RiotConfig.BenziesPerOfficer.Value, 1, 4); int num2 = Mathf.Clamp(RiotConfig.BenziesMax.Value, 1, 16); if (_active.Count >= num2) { return; } PoliceOfficer val; Vector3 officerPos; if (ChaosDirector.On) { val = NearestOfficerToAnyPlayer(RiotConfig.OfficerScanRadius.Value, int.MaxValue, out officerPos); if ((Object)(object)val == (Object)null && !TryAnyAlivePlayerPos(out officerPos)) { return; } } else { val = NearestOfficerToAnyPlayer(RiotConfig.OfficerScanRadius.Value, num, out officerPos); if ((Object)(object)val == (Object)null) { return; } } if (!TryNearestDoor(officerPos, RiotConfig.DoorMaxDistance.Value, out var doorPos)) { doorPos = officerPos + RandomRingDir() * 18f; } doorPos = NavPoint(doorPos); GoonPool val2 = Object.FindObjectOfType<GoonPool>(true); if ((Object)(object)val2 == (Object)null) { return; } int num3; try { num3 = val2.UnspawnedGoonCount - 1; } catch { return; } int num4 = (ChaosDirector.On ? num : (num - AssignedCount(val))); int num5 = Mathf.Min(num4, Mathf.Min(num3, num2 - _active.Count)); if (num5 <= 0) { return; } List<CartelGoon> val3 = val2.SpawnMultipleGoons(doorPos, num5, false); if (val3 == null) { return; } int num6 = 0; for (int i = 0; i < val3.Count; i++) { CartelGoon val4 = val3[i]; if ((Object)(object)val4 == (Object)null) { continue; } try { NPCBehaviour behaviour = ((NPC)val4).Behaviour; CombatBehaviour val5 = ((behaviour != null) ? behaviour.CombatBehaviour : null); if ((Object)(object)val5 != (Object)null) { val5.GiveUpRange = 200f; } } catch { } ActiveGoon activeGoon = new ActiveGoon { Goon = val4, DespawnAt = Time.time + 180f }; if (ChaosDirector.On) { Player val6 = ChaosDirector.NearestAlivePlayer(doorPos, 180f); if ((Object)(object)val6 != (Object)null && SicPlayer(activeGoon, val6)) { num6++; } } else if (Sic(activeGoon, val)) { num6++; } _active.Add(activeGoon); } if (num6 > 0) { MelonLogger.Msg($"[Riot] Wave: {num6} Benzies out of the door at {doorPos} → officer hunt ({_active.Count} active)."); } } private static int AssignedCount(PoliceOfficer officer) { int num = 0; for (int i = 0; i < _active.Count; i++) { try { if ((Object)(object)_active[i].Target == (Object)(object)officer) { num++; } } catch { } } return num; } private static void Retarget() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) for (int num = _active.Count - 1; num >= 0; num--) { ActiveGoon activeGoon = _active[num]; Vector3 position; try { position = ((Component)activeGoon.Goon).transform.position; } catch { Despawn(num); continue; } if (ChaosDirector.On) { if (PlayerInvalid(activeGoon.TargetPlayer)) { Player val = ChaosDirector.NearestAlivePlayer(position, 180f); if ((Object)(object)val != (Object)null) { SicPlayer(activeGoon, val); } } continue; } activeGoon.TargetPlayer = null; if (TargetInvalid(activeGoon.Target)) { PoliceOfficer val2 = NearestOfficerTo(position, 90f); if ((Object)(object)val2 == (Object)null) { Despawn(num); } else { Sic(activeGoon, val2); } } } } private static bool SicPlayer(ActiveGoon ag, Player prey) { try { ICombatTargetable val = RiotCompat.CastTargetable<ICombatTargetable>((Il2CppObjectBase)(object)prey); if (val == null) { return false; } bool flag = false; try { flag = !val.IsNull() && val.IsCurrentlyTargetable; } catch { } if (!flag) { return false; } ag.Goon.AttackEntity(val, false); ag.TargetPlayer = prey; ag.Target = null; return true; } catch { return false; } } private static bool PlayerInvalid(Player p) { try { if ((Object)(object)p == (Object)null || (Object)(object)((Component)p).transform == (Object)null) { return true; } PlayerHealth componentInChildren = ((Component)p).GetComponentInChildren<PlayerHealth>(true); return (Object)(object)componentInChildren != (Object)null && !componentInChildren.IsAlive; } catch { return true; } } private static bool TryAnyAlivePlayerPos(out Vector3 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; try { List<Player> playerList = Player.PlayerList; if (playerList == null) { return false; } for (int i = 0; i < playerList.Count; i++) { Player val = playerList[i]; if (!PlayerInvalid(val)) { pos = ((Component)val).transform.position; return true; } } } catch { } return false; } private static void Prune(float now) { for (int num = _active.Count - 1; num >= 0; num--) { ActiveGoon activeGoon = _active[num]; bool flag; try { flag = (Object)(object)activeGoon.Goon == (Object)null || !activeGoon.Goon.IsGoonSpawned; } catch { flag = true; } if (flag) { _active.RemoveAt(num); } else if (now >= activeGoon.DespawnAt) { Despawn(num); } } } private static void Despawn(int idx) { try { CartelGoon goon = _active[idx].Goon; if ((Object)(object)goon != (Object)null && goon.IsGoonSpawned) { goon.Despawn(); } } catch { } _active.RemoveAt(idx); } private static bool Sic(ActiveGoon ag, PoliceOfficer officer) { try { ICombatTargetable val = RiotCompat.CastTargetable<ICombatTargetable>((Il2CppObjectBase)(object)officer); if (val == null) { return false; } bool flag = false; try { flag = !val.IsNull() && val.IsCurrentlyTargetable; } catch { } if (!flag) { return false; } ag.Goon.AttackEntity(val, false); ag.Target = officer; ag.TargetPlayer = null; if (RiotConfig.OfficersFightBack.Value && !ChaosDirector.On) { try { CartelGoon goon = ag.Goon; object obj2; if (goon == null) { obj2 = null; } else { GameObject gameObject = ((Component)goon).gameObject; obj2 = ((gameObject != null) ? gameObject.GetComponent<NetworkObject>() : null); } NetworkObject val2 = (NetworkObject)obj2; object obj3; if (officer == null) { obj3 = null; } else { NPCBehaviour behaviour = ((NPC)officer).Behaviour; obj3 = ((behaviour != null) ? behaviour.CombatBehaviour : null); } CombatBehaviour val3 = (CombatBehaviour)obj3; if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null) { val3.SetTargetAndEnable_Server(val2); if (!_engagedOfficers.Contains(officer)) { _engagedOfficers.Add(officer); } } } catch { } } return true; } catch (Exception ex) { MelonLogger.Warning("[Riot] Sic: " + ex.Message); return false; } } private static void Teardown() { for (int i = 0; i < _engagedOfficers.Count; i++) { try { PoliceOfficer obj = _engagedOfficers[i]; object obj2; if (obj == null) { obj2 = null; } else { NPCBehaviour behaviour = ((NPC)obj).Behaviour; obj2 = ((behaviour != null) ? behaviour.CombatBehaviour : null); } CombatBehaviour val = (CombatBehaviour)obj2; if ((Object)(object)val != (Object)null) { try { ((Behaviour)val).Deactivate(); } catch { } try { ((Behaviour)val).Disable(); } catch { } } } catch { } } _engagedOfficers.Clear(); for (int j = 0; j < _active.Count; j++) { try { CartelGoon goon = _active[j].Goon; if ((Object)(object)goon != (Object)null && goon.IsGoonSpawned) { goon.Despawn(); } } catch { } } _active.Clear(); } private static bool TargetInvalid(PoliceOfficer o) { try { if ((Object)(object)o == (Object)null || (Object)(object)((Component)o).transform == (Object)null) { return true; } NPCHealth health = ((NPC)o).Health; return (Object)(object)health == (Object)null || health.IsDead || health.IsKnockedOut; } catch { return true; } } private static PoliceOfficer NearestOfficerToAnyPlayer(float radius, int perOfficer, out Vector3 officerPos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) officerPos = Vector3.zero; PoliceOfficer result = null; float num = float.MaxValue; try { List<PoliceOfficer> officers = PoliceOfficer.Officers; List<Player> playerList = Player.PlayerList; if (officers == null || playerList == null) { return null; } for (int i = 0; i < officers.Count; i++) { try { PoliceOfficer val = officers[i]; if (TargetInvalid(val) || AssignedCount(val) >= perOfficer) { continue; } Vector3 position = ((Component)val).transform.position; for (int j = 0; j < playerList.Count; j++) { Player val2 = playerList[j]; if (!((Object)(object)val2 == (Object)null)) { float num2 = Vector3.Distance(position, ((Component)val2).transform.position); if (num2 <= radius && num2 < num) { num = num2; result = val; officerPos = position; } } } } catch { } } } catch (Exception ex) { MelonLogger.Warning("[Riot] OfficerScan: " + ex.Message); } return result; } private static PoliceOfficer NearestOfficerTo(Vector3 pos, float radius) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) PoliceOfficer result = null; float num = radius; try { List<PoliceOfficer> officers = PoliceOfficer.Officers; if (officers == null) { return null; } for (int i = 0; i < officers.Count; i++) { try { PoliceOfficer val = officers[i]; if (!TargetInvalid(val)) { float num2 = Vector3.Distance(((Component)val).transform.position, pos); if (num2 < num) { num = num2; result = val; } } } catch { } } } catch { } return result; } private static bool TryNearestDoor(Vector3 from, float maxDistance, out Vector3 doorPos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) doorPos = from; try { Il2CppArrayBase<StaticDoor> val = Object.FindObjectsOfType<StaticDoor>(); if (val == null || val.Length == 0) { return false; } float num = maxDistance * maxDistance; bool result = false; for (int i = 0; i < val.Length; i++) { StaticDoor val2; try { val2 = val[i]; } catch { continue; } if (!((Object)(object)val2 == (Object)null)) { Vector3 val3; try { Transform accessPoint = val2.AccessPoint; val3 = (((Object)(object)accessPoint != (Object)null) ? accessPoint.position : ((Component)val2).transform.position); } catch { continue; } Vector3 val4 = val3 - from; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; doorPos = val3; result = true; } } } return result; } catch { return false; } } private static Vector3 RandomRingDir() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized; if (((Vector2)(ref val)).sqrMagnitude < 0.01f) { val = Vector2.right; } return new Vector3(val.x, 0f, val.y); } private static Vector3 NavPoint(Vector3 p) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) try { NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(p + Vector3.up * 1.5f, ref val, 12f, -1)) { return ((NavMeshHit)(ref val)).position; } } catch { } return p; } } public class RiotMod : MelonMod { private RiotAddon _addon; public override void OnInitializeMelon() { _addon = new RiotAddon(); if (PvpApi.RegisterAddon((IPvpAddon)(object)_addon)) { MelonLogger.Msg("[Riot] registered with MultiplayerPVP."); } else { MelonLogger.Warning("[Riot] registration failed — is MultiplayerPVP loaded?"); } } public override void OnDeinitializeMelon() { try { PvpApi.UnregisterAddon((IPvpAddon)(object)_addon); } catch { } } } }
Riot.MONO.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using FishNet; using FishNet.Managing; using FishNet.Object; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using MultiplayerPVP.Addons; using MultiplayerPVP.Core; using Riot; using ScheduleOne.Cartel; using ScheduleOne.Combat; using ScheduleOne.Doors; using ScheduleOne.NPCs; using ScheduleOne.NPCs.Behaviour; using ScheduleOne.PlayerScripts; using ScheduleOne.PlayerScripts.Health; using ScheduleOne.Police; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonAdditionalDependencies(new string[] { "MultiplayerPVP" })] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: MelonInfo(typeof(RiotMod), "Riot", "1.0.1", "Virtunerd", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Riot { internal static class ChaosDirector { private const float RETARGET_INTERVAL = 1.5f; private const float NPC_GIVE_UP = 200f; private static readonly List<NPC> _engaged = new List<NPC>(); private static readonly List<NPC> _civilians = new List<NPC>(); private static float _cd; internal static bool On { get; private set; } internal static void SetOn(bool on) { if (On != on) { On = on; if (!on) { Teardown(); } else { _cd = 0f; } MelonLogger.Msg("[Riot] CHAOS " + (on ? "ON — the city hunts the players." : "OFF.")); } } internal static void Reset() { _engaged.Clear(); _civilians.Clear(); On = false; } internal static void Tick(float dt) { //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) if (!On) { return; } try { if (!RiotCompat.IsAuthority) { SetOn(on: false); return; } _cd -= dt; if (_cd > 0f) { return; } _cd = 1.5f; float num = Mathf.Clamp(RiotConfig.ChaosRadius.Value, 15f, 200f); try { List<PoliceOfficer> officers = PoliceOfficer.Officers; if (officers != null) { for (int i = 0; i < officers.Count; i++) { try { PoliceOfficer val = officers[i]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null) { continue; } NPCHealth health = ((NPC)val).Health; if (!((Object)(object)health == (Object)null) && !health.IsDead && !health.IsKnockedOut) { Player val2 = NearestAlivePlayer(((Component)val).transform.position, num); if (!((Object)(object)val2 == (Object)null)) { SicNpc((NPC)(object)val, val2, civilian: false); } } } catch { } } } } catch { } if (!RiotConfig.CiviliansJoinChaos.Value) { return; } PruneCivilians(); int num2 = Mathf.Clamp(RiotConfig.MaxChaosCivilians.Value, 1, 16); try { List<NPC> nPCRegistry = NPCManager.NPCRegistry; if (nPCRegistry != null) { for (int j = 0; j < nPCRegistry.Count; j++) { if (_civilians.Count >= num2) { break; } try { NPC val3 = nPCRegistry[j]; if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).transform == (Object)null || (Object)(object)RiotCompat.Cast<PoliceOfficer>((Object)(object)val3) != (Object)null || (Object)(object)RiotCompat.Cast<CartelGoon>((Object)(object)val3) != (Object)null) { continue; } NPCHealth health2 = val3.Health; if (!((Object)(object)health2 == (Object)null) && !health2.IsDead && !health2.IsKnockedOut) { Player val4 = NearestAlivePlayer(((Component)val3).transform.position, num); if (!((Object)(object)val4 == (Object)null) && SicNpc(val3, val4, civilian: true) && !_civilians.Contains(val3)) { _civilians.Add(val3); } } } catch { } } } } catch { } for (int k = 0; k < _civilians.Count; k++) { try { NPC val5 = _civilians[k]; if (!((Object)(object)val5 == (Object)null) && !((Object)(object)((Component)val5).transform == (Object)null)) { Player val6 = NearestAlivePlayer(((Component)val5).transform.position, num * 2f); if ((Object)(object)val6 != (Object)null) { SicNpc(val5, val6, civilian: true); } } } catch { } } } catch (Exception ex) { MelonLogger.Warning("[Riot] Chaos tick: " + ex.Message); } } private static bool SicNpc(NPC npc, Player target, bool civilian) { try { object obj; if (target == null) { obj = null; } else { GameObject gameObject = ((Component)target).gameObject; obj = ((gameObject != null) ? gameObject.GetComponent<NetworkObject>() : null); } NetworkObject val = (NetworkObject)obj; CombatBehaviour val2 = ((npc == null) ? null : npc.Behaviour?.CombatBehaviour); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } try { val2.GiveUpRange = 200f; } catch { } val2.SetTargetAndEnable_Server(val); if (!_engaged.Contains(npc)) { _engaged.Add(npc); } return true; } catch { return false; } } private static void PruneCivilians() { for (int num = _civilians.Count - 1; num >= 0; num--) { try { NPC val = _civilians[num]; NPCHealth val2 = (((Object)(object)val != (Object)null) ? val.Health : null); if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null || (Object)(object)val2 == (Object)null || val2.IsDead || val2.IsKnockedOut) { _civilians.RemoveAt(num); } } catch { _civilians.RemoveAt(num); } } } internal static Player NearestAlivePlayer(Vector3 pos, float radius) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) Player result = null; float num = radius; try { List<Player> playerList = Player.PlayerList; if (playerList == null) { return null; } for (int i = 0; i < playerList.Count; i++) { try { Player val = playerList[i]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null) { continue; } PlayerHealth componentInChildren = ((Component)val).GetComponentInChildren<PlayerHealth>(true); if (!((Object)(object)componentInChildren != (Object)null) || componentInChildren.IsAlive) { float num2 = Vector3.Distance(((Component)val).transform.position, pos); if (num2 < num) { num = num2; result = val; } } } catch { } } } catch { } return result; } private static void Teardown() { for (int i = 0; i < _engaged.Count; i++) { try { NPC obj = _engaged[i]; CombatBehaviour val = ((obj == null) ? null : obj.Behaviour?.CombatBehaviour); if ((Object)(object)val != (Object)null) { try { ((Behaviour)val).Deactivate(); } catch { } try { ((Behaviour)val).Disable(); } catch { } } } catch { } } _engaged.Clear(); _civilians.Clear(); } } internal sealed class RiotAddon : PvpAddonBase { private PvpMatchToggle _riotToggle; private PvpMatchToggle _chaosToggle; private PvpChannel _channel; private int _seq; private readonly Dictionary<ulong, string> _seen = new Dictionary<ulong, string>(); private bool _chaosActiveLocal; private string _lastState = ""; private bool _prevRiotReq; private bool _prevChaosReq; public override string Id => "Riot"; public override void OnRegistered() { RiotConfig.Load(); _channel = PvpApi.Channel("riot"); if (_channel != null) { _channel.OnMessage += OnRiotMsg; } _riotToggle = PvpApi.RegisterMatchToggle("riot", "Riot", "City riot for this round: Benzies storm out of the door nearest each cop and brawl with the police while you play. Mutually exclusive with Chaos."); _chaosToggle = PvpApi.RegisterMatchToggle("chaos", "Chaos", "The city turns on YOU for this round: cops, Benzies and civilians hunt every player on sight until KO. NPC knock-outs confiscate weapons. Mutually exclusive with Riot."); if (_riotToggle != null) { _riotToggle.Activated += OnRiotActivated; _riotToggle.Deactivated += OnRoundDeactivated; } if (_chaosToggle != null) { _chaosToggle.Activated += OnChaosActivated; _chaosToggle.Deactivated += OnRoundDeactivated; } PvpApi.RegisterNpcKoAttributor((Func<bool>)IsKoFromChaos); } private void OnRiotActivated() { if (PvpApi.IsMultiplayer && RiotCompat.IsAuthority) { ChaosDirector.SetOn(on: false); RiotManager.SetOn(on: true); PublishState(); } } private void OnChaosActivated() { if (PvpApi.IsMultiplayer && RiotCompat.IsAuthority) { ChaosDirector.SetOn(on: true); RiotManager.SetOn(on: true); _chaosActiveLocal = true; PublishState(); } } private void OnRoundDeactivated() { bool flag = RiotManager.On || ChaosDirector.On; ChaosDirector.SetOn(on: false); RiotManager.SetOn(on: false); _chaosActiveLocal = false; if (flag) { PublishState(); } } public override void OnUpdate(float dt) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 try { if (_chaosToggle != null && _riotToggle != null) { bool requested = _riotToggle.Requested; bool requested2 = _chaosToggle.Requested; if (requested && requested2) { if (requested2 && !_prevChaosReq) { _riotToggle.Requested = false; } else { _chaosToggle.Requested = false; } } _prevRiotReq = _riotToggle.Requested; _prevChaosReq = _chaosToggle.Requested; } } catch { } bool flag = (int)PvpApi.Phase != 2 || !PvpApi.IsMultiplayer; if (ChaosDirector.On && flag) { ChaosDirector.SetOn(on: false); _chaosActiveLocal = false; } if (RiotManager.On && flag) { RiotManager.SetOn(on: false); } RiotManager.Tick(dt); ChaosDirector.Tick(dt); if (_channel != null) { List<KeyValuePair<ulong, string>> list = _channel.ReadAll(); for (int i = 0; i < list.Count; i++) { OnRiotMsg(list[i].Key, list[i].Value); } } } private void PublishState() { bool flag = RiotManager.On && !ChaosDirector.On; string text = (flag ? "1" : "0") + "~" + (ChaosDirector.On ? "1" : "0"); ShowState(flag, ChaosDirector.On); PvpChannel channel = _channel; if (channel != null) { int num = ++_seq; channel.Publish(num + "~" + text); } } private void OnRiotMsg(ulong fromSteamId, string record) { if (string.IsNullOrEmpty(record) || (_seen.TryGetValue(fromSteamId, out var value) && value == record)) { return; } _seen[fromSteamId] = record; if (!RiotCompat.IsAuthority) { string[] array = record.Split(new char[1] { '~' }); if (array.Length >= 3) { bool riot = array[1] == "1"; ShowState(riot, _chaosActiveLocal = array[2] == "1"); } } } private void ShowState(bool riot, bool chaos) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) string text = (riot ? "r" : "") + (chaos ? "c" : ""); if (!(text == _lastState)) { _lastState = text; if (chaos) { PvpApi.ShowLocalBanner("☠ CHAOS — the whole city is out for YOUR blood!", 5f, new Color(1f, 0.15f, 0.15f)); } else if (riot) { PvpApi.ShowLocalBanner("⚠ RIOT — the Benzies are out!", 5f, new Color(1f, 0.35f, 0.2f)); } else { PvpApi.ShowLocalBanner("The streets calm down.", 4f, Color.white); } } } private bool IsKoFromChaos() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: 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) if (!_chaosActiveLocal) { return false; } try { Player local = Player.Local; if ((Object)(object)local == (Object)null || (Object)(object)((Component)local).transform == (Object)null) { return false; } Vector3 position = ((Component)local).transform.position; float num = float.MaxValue; List<Player> playerList = Player.PlayerList; if (playerList != null) { for (int i = 0; i < playerList.Count; i++) { try { Player val = playerList[i]; if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)local || (Object)(object)((Component)val).transform == (Object)null) { continue; } PlayerHealth componentInChildren = ((Component)val).GetComponentInChildren<PlayerHealth>(true); if (!((Object)(object)componentInChildren != (Object)null) || componentInChildren.IsAlive) { float num2 = Vector3.Distance(position, ((Component)val).transform.position); if (num2 < num) { num = num2; } } } catch { } } } float num3 = float.MaxValue; try { List<PoliceOfficer> officers = PoliceOfficer.Officers; if (officers != null) { for (int j = 0; j < officers.Count; j++) { try { PoliceOfficer val2 = officers[j]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).transform == (Object)null)) { float num4 = Vector3.Distance(position, ((Component)val2).transform.position); if (num4 < num3) { num3 = num4; } } } catch { } } } } catch { } try { CartelGoon[] array = Object.FindObjectsOfType<CartelGoon>(); if (array != null) { for (int k = 0; k < array.Length; k++) { try { CartelGoon val3 = array[k]; if (!((Object)(object)val3 == (Object)null) && val3.IsGoonSpawned && !((Object)(object)((Component)val3).transform == (Object)null)) { float num5 = Vector3.Distance(position, ((Component)val3).transform.position); if (num5 < num3) { num3 = num5; } } } catch { } } } } catch { } return (num3 <= 25f && num3 < num) || num > 60f; } catch { return false; } } public override void OnSceneLoaded(int buildIndex, string sceneName) { RiotManager.Reset(); ChaosDirector.Reset(); _chaosActiveLocal = false; _seen.Clear(); _lastState = ""; } public override void OnDeinit() { ChaosDirector.SetOn(on: false); RiotManager.SetOn(on: false); RiotManager.Reset(); ChaosDirector.Reset(); try { PvpApi.UnregisterNpcKoAttributor((Func<bool>)IsKoFromChaos); } catch { } try { PvpApi.UnregisterMatchToggle(_riotToggle); } catch { } try { PvpApi.UnregisterMatchToggle(_chaosToggle); } catch { } } } internal static class RiotCompat { public static bool IsAuthority { get { try { NetworkManager networkManager = InstanceFinder.NetworkManager; if ((Object)(object)networkManager == (Object)null) { return true; } return networkManager.IsServer; } catch { return true; } } } public static T Cast<T>(Object o) where T : Object { return (T)(object)((o is T) ? o : null); } public static T CastTargetable<T>(object o) where T : class { return o as T; } } internal static class RiotConfig { internal static MelonPreferences_Entry<int> BenziesPerOfficer; internal static MelonPreferences_Entry<int> BenziesMax; internal static MelonPreferences_Entry<float> OfficerScanRadius; internal static MelonPreferences_Entry<float> DoorMaxDistance; internal static MelonPreferences_Entry<float> WaveCooldownSeconds; internal static MelonPreferences_Entry<bool> OfficersFightBack; internal static MelonPreferences_Entry<float> ChaosRadius; internal static MelonPreferences_Entry<bool> CiviliansJoinChaos; internal static MelonPreferences_Entry<int> MaxChaosCivilians; private static bool _loaded; internal static void Load() { if (!_loaded) { _loaded = true; MelonPreferences_Category val = MelonPreferences.CreateCategory("Riot", "Riot"); BenziesPerOfficer = val.CreateEntry<int>("BenziesPerOfficer", 2, "Benzies per officer", "How many Benzies gang up on each targeted officer (1-4).", false, false, (ValueValidator)null, (string)null); BenziesMax = val.CreateEntry<int>("BenziesMax", 8, "Max active Benzies", "Hard cap of simultaneously active riot Benzies (1-16).", false, false, (ValueValidator)null, (string)null); OfficerScanRadius = val.CreateEntry<float>("OfficerScanRadius", 80f, "Officer scan radius (m)", "Waves target the nearest under-staffed officer within this radius of ANY player.", false, false, (ValueValidator)null, (string)null); DoorMaxDistance = val.CreateEntry<float>("DoorMaxDistance", 80f, "Door search radius (m)", "The Benzies spawn at the door nearest to the targeted officer within this radius (ring fallback beyond).", false, false, (ValueValidator)null, (string)null); WaveCooldownSeconds = val.CreateEntry<float>("WaveCooldownSeconds", 20f, "Wave cooldown (s)", "Minimum seconds between spawn waves while the riot runs (min 5).", false, false, (ValueValidator)null, (string)null); OfficersFightBack = val.CreateEntry<bool>("OfficersFightBack", true, "Officers fight back", "Explicitly trigger officer counter-attacks (vanilla cops NEVER retaliate against NPCs on their own).", false, false, (ValueValidator)null, (string)null); ChaosRadius = val.CreateEntry<float>("ChaosRadius", 60f, "Chaos radius (m)", "CHAOS toggle: cops/civilians within this radius of a player join the hunt against the players.", false, false, (ValueValidator)null, (string)null); CiviliansJoinChaos = val.CreateEntry<bool>("CiviliansJoinChaos", true, "Civilians join chaos", "CHAOS toggle: nearby civilian NPCs also attack players (fists). CAUTION: this can pull in other mods' NPCs that stand near a player.", false, false, (ValueValidator)null, (string)null); MaxChaosCivilians = val.CreateEntry<int>("MaxChaosCivilians", 8, "Max chaos civilians", "CHAOS toggle: cap of civilians simultaneously hunting players (1-16).", false, false, (ValueValidator)null, (string)null); } } } internal static class RiotManager { private sealed class ActiveGoon { internal CartelGoon Goon; internal PoliceOfficer Target; internal Player TargetPlayer; internal float DespawnAt; } private const int POOL_RESERVE = 1; private const float GOON_GIVE_UP = 200f; private const float RETARGET_INTERVAL = 1.5f; private const float GOON_LIFETIME = 180f; private const float ORPHAN_RADIUS = 90f; private const float DOOR_FALLBACK_DIST = 18f; private static readonly List<ActiveGoon> _active = new List<ActiveGoon>(); private static readonly List<PoliceOfficer> _engagedOfficers = new List<PoliceOfficer>(); private static float _nextWave; private static float _retargetCd; internal static bool On { get; private set; } internal static int ActiveCount => _active.Count; internal static void SetOn(bool on) { if (On != on) { On = on; if (!on) { Teardown(); } else { _nextWave = 0f; _retargetCd = 0f; } MelonLogger.Msg("[Riot] " + (on ? "ON — Benzies are hunting the badges." : "OFF — streets calm down.")); } } internal static void Reset() { _active.Clear(); _engagedOfficers.Clear(); On = false; } internal static void Tick(float dt) { if (!On) { return; } try { if (!RiotCompat.IsAuthority) { SetOn(on: false); return; } float time = Time.time; Prune(time); _retargetCd -= dt; if (_retargetCd <= 0f) { _retargetCd = 1.5f; Retarget(); } if (time >= _nextWave && _active.Count < Mathf.Clamp(RiotConfig.BenziesMax.Value, 1, 16)) { _nextWave = time + Mathf.Max(5f, RiotConfig.WaveCooldownSeconds.Value); SpawnWave(); } } catch (Exception ex) { MelonLogger.Warning("[Riot] Tick: " + ex.Message); } } private static void SpawnWave() { //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(RiotConfig.BenziesPerOfficer.Value, 1, 4); int num2 = Mathf.Clamp(RiotConfig.BenziesMax.Value, 1, 16); if (_active.Count >= num2) { return; } PoliceOfficer val; Vector3 officerPos; if (ChaosDirector.On) { val = NearestOfficerToAnyPlayer(RiotConfig.OfficerScanRadius.Value, int.MaxValue, out officerPos); if ((Object)(object)val == (Object)null && !TryAnyAlivePlayerPos(out officerPos)) { return; } } else { val = NearestOfficerToAnyPlayer(RiotConfig.OfficerScanRadius.Value, num, out officerPos); if ((Object)(object)val == (Object)null) { return; } } if (!TryNearestDoor(officerPos, RiotConfig.DoorMaxDistance.Value, out var doorPos)) { doorPos = officerPos + RandomRingDir() * 18f; } doorPos = NavPoint(doorPos); GoonPool val2 = Object.FindObjectOfType<GoonPool>(true); if ((Object)(object)val2 == (Object)null) { return; } int num3; try { num3 = val2.UnspawnedGoonCount - 1; } catch { return; } int num4 = (ChaosDirector.On ? num : (num - AssignedCount(val))); int num5 = Mathf.Min(num4, Mathf.Min(num3, num2 - _active.Count)); if (num5 <= 0) { return; } List<CartelGoon> list = val2.SpawnMultipleGoons(doorPos, num5, false); if (list == null) { return; } int num6 = 0; for (int i = 0; i < list.Count; i++) { CartelGoon val3 = list[i]; if ((Object)(object)val3 == (Object)null) { continue; } try { CombatBehaviour val4 = ((NPC)val3).Behaviour?.CombatBehaviour; if ((Object)(object)val4 != (Object)null) { val4.GiveUpRange = 200f; } } catch { } ActiveGoon activeGoon = new ActiveGoon { Goon = val3, DespawnAt = Time.time + 180f }; if (ChaosDirector.On) { Player val5 = ChaosDirector.NearestAlivePlayer(doorPos, 180f); if ((Object)(object)val5 != (Object)null && SicPlayer(activeGoon, val5)) { num6++; } } else if (Sic(activeGoon, val)) { num6++; } _active.Add(activeGoon); } if (num6 > 0) { MelonLogger.Msg($"[Riot] Wave: {num6} Benzies out of the door at {doorPos} → officer hunt ({_active.Count} active)."); } } private static int AssignedCount(PoliceOfficer officer) { int num = 0; for (int i = 0; i < _active.Count; i++) { try { if ((Object)(object)_active[i].Target == (Object)(object)officer) { num++; } } catch { } } return num; } private static void Retarget() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) for (int num = _active.Count - 1; num >= 0; num--) { ActiveGoon activeGoon = _active[num]; Vector3 position; try { position = ((Component)activeGoon.Goon).transform.position; } catch { Despawn(num); continue; } if (ChaosDirector.On) { if (PlayerInvalid(activeGoon.TargetPlayer)) { Player val = ChaosDirector.NearestAlivePlayer(position, 180f); if ((Object)(object)val != (Object)null) { SicPlayer(activeGoon, val); } } continue; } activeGoon.TargetPlayer = null; if (TargetInvalid(activeGoon.Target)) { PoliceOfficer val2 = NearestOfficerTo(position, 90f); if ((Object)(object)val2 == (Object)null) { Despawn(num); } else { Sic(activeGoon, val2); } } } } private static bool SicPlayer(ActiveGoon ag, Player prey) { try { ICombatTargetable val = RiotCompat.CastTargetable<ICombatTargetable>(prey); if (val == null) { return false; } bool flag = false; try { flag = !val.IsNull() && val.IsCurrentlyTargetable; } catch { } if (!flag) { return false; } ag.Goon.AttackEntity(val, false); ag.TargetPlayer = prey; ag.Target = null; return true; } catch { return false; } } private static bool PlayerInvalid(Player p) { try { if ((Object)(object)p == (Object)null || (Object)(object)((Component)p).transform == (Object)null) { return true; } PlayerHealth componentInChildren = ((Component)p).GetComponentInChildren<PlayerHealth>(true); return (Object)(object)componentInChildren != (Object)null && !componentInChildren.IsAlive; } catch { return true; } } private static bool TryAnyAlivePlayerPos(out Vector3 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; try { List<Player> playerList = Player.PlayerList; if (playerList == null) { return false; } for (int i = 0; i < playerList.Count; i++) { Player val = playerList[i]; if (!PlayerInvalid(val)) { pos = ((Component)val).transform.position; return true; } } } catch { } return false; } private static void Prune(float now) { for (int num = _active.Count - 1; num >= 0; num--) { ActiveGoon activeGoon = _active[num]; bool flag; try { flag = (Object)(object)activeGoon.Goon == (Object)null || !activeGoon.Goon.IsGoonSpawned; } catch { flag = true; } if (flag) { _active.RemoveAt(num); } else if (now >= activeGoon.DespawnAt) { Despawn(num); } } } private static void Despawn(int idx) { try { CartelGoon goon = _active[idx].Goon; if ((Object)(object)goon != (Object)null && goon.IsGoonSpawned) { goon.Despawn(); } } catch { } _active.RemoveAt(idx); } private static bool Sic(ActiveGoon ag, PoliceOfficer officer) { try { ICombatTargetable val = RiotCompat.CastTargetable<ICombatTargetable>(officer); if (val == null) { return false; } bool flag = false; try { flag = !val.IsNull() && val.IsCurrentlyTargetable; } catch { } if (!flag) { return false; } ag.Goon.AttackEntity(val, false); ag.Target = officer; ag.TargetPlayer = null; if (RiotConfig.OfficersFightBack.Value && !ChaosDirector.On) { try { CartelGoon goon = ag.Goon; object obj2; if (goon == null) { obj2 = null; } else { GameObject gameObject = ((Component)goon).gameObject; obj2 = ((gameObject != null) ? gameObject.GetComponent<NetworkObject>() : null); } NetworkObject val2 = (NetworkObject)obj2; CombatBehaviour val3 = ((officer == null) ? null : ((NPC)officer).Behaviour?.CombatBehaviour); if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null) { val3.SetTargetAndEnable_Server(val2); if (!_engagedOfficers.Contains(officer)) { _engagedOfficers.Add(officer); } } } catch { } } return true; } catch (Exception ex) { MelonLogger.Warning("[Riot] Sic: " + ex.Message); return false; } } private static void Teardown() { for (int i = 0; i < _engagedOfficers.Count; i++) { try { PoliceOfficer obj = _engagedOfficers[i]; CombatBehaviour val = ((obj == null) ? null : ((NPC)obj).Behaviour?.CombatBehaviour); if ((Object)(object)val != (Object)null) { try { ((Behaviour)val).Deactivate(); } catch { } try { ((Behaviour)val).Disable(); } catch { } } } catch { } } _engagedOfficers.Clear(); for (int j = 0; j < _active.Count; j++) { try { CartelGoon goon = _active[j].Goon; if ((Object)(object)goon != (Object)null && goon.IsGoonSpawned) { goon.Despawn(); } } catch { } } _active.Clear(); } private static bool TargetInvalid(PoliceOfficer o) { try { if ((Object)(object)o == (Object)null || (Object)(object)((Component)o).transform == (Object)null) { return true; } NPCHealth health = ((NPC)o).Health; return (Object)(object)health == (Object)null || health.IsDead || health.IsKnockedOut; } catch { return true; } } private static PoliceOfficer NearestOfficerToAnyPlayer(float radius, int perOfficer, out Vector3 officerPos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) officerPos = Vector3.zero; PoliceOfficer result = null; float num = float.MaxValue; try { List<PoliceOfficer> officers = PoliceOfficer.Officers; List<Player> playerList = Player.PlayerList; if (officers == null || playerList == null) { return null; } for (int i = 0; i < officers.Count; i++) { try { PoliceOfficer val = officers[i]; if (TargetInvalid(val) || AssignedCount(val) >= perOfficer) { continue; } Vector3 position = ((Component)val).transform.position; for (int j = 0; j < playerList.Count; j++) { Player val2 = playerList[j]; if (!((Object)(object)val2 == (Object)null)) { float num2 = Vector3.Distance(position, ((Component)val2).transform.position); if (num2 <= radius && num2 < num) { num = num2; result = val; officerPos = position; } } } } catch { } } } catch (Exception ex) { MelonLogger.Warning("[Riot] OfficerScan: " + ex.Message); } return result; } private static PoliceOfficer NearestOfficerTo(Vector3 pos, float radius) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) PoliceOfficer result = null; float num = radius; try { List<PoliceOfficer> officers = PoliceOfficer.Officers; if (officers == null) { return null; } for (int i = 0; i < officers.Count; i++) { try { PoliceOfficer val = officers[i]; if (!TargetInvalid(val)) { float num2 = Vector3.Distance(((Component)val).transform.position, pos); if (num2 < num) { num = num2; result = val; } } } catch { } } } catch { } return result; } private static bool TryNearestDoor(Vector3 from, float maxDistance, out Vector3 doorPos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) doorPos = from; try { StaticDoor[] array = Object.FindObjectsOfType<StaticDoor>(); if (array == null || array.Length == 0) { return false; } float num = maxDistance * maxDistance; bool result = false; for (int i = 0; i < array.Length; i++) { StaticDoor val; try { val = array[i]; } catch { continue; } if (!((Object)(object)val == (Object)null)) { Vector3 val2; try { Transform accessPoint = val.AccessPoint; val2 = (((Object)(object)accessPoint != (Object)null) ? accessPoint.position : ((Component)val).transform.position); } catch { continue; } Vector3 val3 = val2 - from; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; doorPos = val2; result = true; } } } return result; } catch { return false; } } private static Vector3 RandomRingDir() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Vector2 insideUnitCircle = Random.insideUnitCircle; Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized; if (((Vector2)(ref val)).sqrMagnitude < 0.01f) { val = Vector2.right; } return new Vector3(val.x, 0f, val.y); } private static Vector3 NavPoint(Vector3 p) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) try { NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(p + Vector3.up * 1.5f, ref val, 12f, -1)) { return ((NavMeshHit)(ref val)).position; } } catch { } return p; } } public class RiotMod : MelonMod { private RiotAddon _addon; public override void OnInitializeMelon() { _addon = new RiotAddon(); if (PvpApi.RegisterAddon((IPvpAddon)(object)_addon)) { MelonLogger.Msg("[Riot] registered with MultiplayerPVP."); } else { MelonLogger.Warning("[Riot] registration failed — is MultiplayerPVP loaded?"); } } public override void OnDeinitializeMelon() { try { PvpApi.UnregisterAddon((IPvpAddon)(object)_addon); } catch { } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }