using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DioCompany.Networking; using GameNetcodeStuff; using HarmonyLib; using LethalNetworkAPI; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.VFX; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.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 DioCompany { public static class DamageQueue { private class Entry { public EnemyAI Enemy; public int Force; public Vector3 HitDirection; public PlayerControllerB PlayerWhoHit; public bool PlayHitSFX; public int HitId; } private static readonly List Pending = new List(); public static void Enqueue(EnemyAI enemy, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitId) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Pending.Add(new Entry { Enemy = enemy, Force = force, HitDirection = hitDirection, PlayerWhoHit = playerWhoHit, PlayHitSFX = playHitSFX, HitId = hitId }); } public static void ReplayAndClear() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (Pending.Count == 0) { return; } List list = new List(Pending); Pending.Clear(); foreach (Entry item in list) { if (!((Object)(object)item.Enemy == (Object)null)) { item.Enemy.HitEnemyOnLocalClient(item.Force, item.HitDirection, item.PlayerWhoHit, item.PlayHitSFX, item.HitId); } } } } public static class ElevatorFreeze { public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { MineshaftElevatorController val = RoundManager.Instance?.currentMineshaftElevator; if (!((Object)(object)val == (Object)null)) { if ((Object)(object)val.elevatorAnimator != (Object)null) { val.elevatorAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } public static class EnemyFreeze { public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { List list = RoundManager.Instance?.SpawnedEnemies; if (list == null) { return; } foreach (EnemyAI item in list) { if ((Object)(object)item == (Object)null) { continue; } if ((Object)(object)item.agent != (Object)null) { item.agent.isStopped = frozen; } if ((Object)(object)item.creatureAnimator != (Object)null) { item.creatureAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } VisualEffect[] componentsInChildren2 = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].pause = frozen; } ParticleSystem[] componentsInChildren3 = ((Component)item).GetComponentsInChildren(true); foreach (ParticleSystem val in componentsInChildren3) { if (frozen) { val.Pause(true); } else { val.Play(true); } } } } } public static class HostPermissions { public static readonly HashSet AllowedClientIds = new HashSet(); public static bool IsAllowed(ulong clientId) { if ((Object)(object)NetworkManager.Singleton != (Object)null && clientId == 0L) { return true; } return AllowedClientIds.Contains(clientId); } } public static class MineFreeze { public static readonly List Active = new List(); public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { foreach (Landmine item in Active) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)item.mineAnimator != (Object)null) { item.mineAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } } public static class MineQueue { private static readonly MethodInfo TriggerMethod = AccessTools.Method(typeof(Landmine), "TriggerMineOnLocalClientByExiting", (Type[])null, (Type[])null); private static readonly List Pending = new List(); public static void Enqueue(Landmine mine) { Pending.Add(mine); } public static void ReplayAndClear() { if (Pending.Count == 0) { return; } List list = new List(Pending); Pending.Clear(); foreach (Landmine item in list) { if (!((Object)(object)item == (Object)null)) { TriggerMethod?.Invoke(item, null); } } } } public static class ModTick { public static void Tick() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current != null && ((ButtonControl)current[Plugin.PauseKey.Value]).wasPressedThisFrame) { PauseController.LocalKeyPressed(); } if (PauseState.IsPaused && (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsHost && Time.realtimeSinceStartup >= PauseState.PauseEndsAtRealtime) { PauseController.ResumeFromHost(); } PauseEffects.Tick(); PauseAudio.Tick(); ScanPulse.Tick(); } } public static class PauseAudio { private class PendingLoad { public UnityWebRequest Request; public UnityWebRequestAsyncOperation Operation; public Action OnLoaded; } private static readonly List Pending = new List(); private static AudioClip _pauseClip; private static AudioClip _resumeClip; private static bool _loadStarted; public static void LoadClips() { if (!_loadStarted) { _loadStarted = true; StartLoad("DioCompany.Resources.pause_sfx.mp3", delegate(AudioClip clip) { _pauseClip = clip; }); StartLoad("DioCompany.Resources.resume_sfx.mp3", delegate(AudioClip clip) { _resumeClip = clip; }); } } public static void Tick() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 if (Pending.Count == 0) { return; } for (int num = Pending.Count - 1; num >= 0; num--) { PendingLoad pendingLoad = Pending[num]; if (((AsyncOperation)pendingLoad.Operation).isDone) { if ((int)pendingLoad.Request.result == 1) { pendingLoad.OnLoaded(DownloadHandlerAudioClip.GetContent(pendingLoad.Request)); } pendingLoad.Request.Dispose(); Pending.RemoveAt(num); } } } public static void PlayPause() { PlayOneShot(_pauseClip); } public static void PlayResume() { PlayOneShot(_resumeClip); } private static void PlayOneShot(AudioClip clip) { if (!((Object)(object)clip == (Object)null)) { AudioSource val = (((Object)(object)HUDManager.Instance != (Object)null) ? HUDManager.Instance.UIAudio : null); if ((Object)(object)val != (Object)null) { val.PlayOneShot(clip); } } } private static void StartLoad(string resourceName, Action onLoaded) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream != null) { string text = Path.Combine(Path.GetTempPath(), Path.GetFileName(resourceName)); using (FileStream destination = File.Create(text)) { stream.CopyTo(destination); } UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file://" + text, (AudioType)13); UnityWebRequestAsyncOperation operation = audioClip.SendWebRequest(); Pending.Add(new PendingLoad { Request = audioClip, Operation = operation, OnLoaded = onLoaded }); } } } public static class PauseController { public static void LocalKeyPressed() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return; } if (PauseState.IsPaused) { if (PauseState.CasterClientId == val.playerClientId) { PauseNetworking.RequestToggle(); } } else { PauseNetworking.RequestToggle(); } } public static void HostHandleToggleRequest(ulong senderClientId) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array != null) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append($"[DioDiag] HostHandleToggleRequest senderClientId={senderClientId}, IsPaused={PauseState.IsPaused}. Roster: "); for (int i = 0; i < array.Length; i++) { PlayerControllerB val = array[i]; if (!((Object)(object)val == (Object)null)) { stringBuilder.Append($"[idx={i} name={val.playerUsername} playerClientId={val.playerClientId} isPlayerControlled={val.isPlayerControlled} isOwner={((NetworkBehaviour)val).IsOwner}] "); } } Plugin.Log.LogInfo((object)stringBuilder.ToString()); } if (!PauseState.IsPaused) { if (HostPermissions.IsAllowed(senderClientId) && (!PauseState.CooldownEndsAtRealtime.TryGetValue(senderClientId, out var value) || !(Time.realtimeSinceStartup < value))) { PlayerControllerB val2 = FindPlayerByClientId(senderClientId); if (!((Object)(object)val2 == (Object)null)) { PauseStateData data = PauseStateData.Paused(senderClientId, ((Component)val2).transform.position, Plugin.PauseTimeLimitSeconds.Value); PauseState.PauseEndsAtRealtime = Time.realtimeSinceStartup + data.TimeLimit; PauseNetworking.BroadcastState(data); ApplyStateChange(data); } } } else if (senderClientId == PauseState.CasterClientId) { ResumeFromHost(); } } public static void ResumeFromHost() { PauseStateData data = PauseStateData.Resumed(); PauseState.CooldownEndsAtRealtime[PauseState.CasterClientId] = Time.realtimeSinceStartup + Plugin.PauseCooldownSeconds.Value; PauseNetworking.BroadcastState(data); ApplyStateChange(data); } public static void ApplyStateChange(PauseStateData data) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) PauseState.IsPaused = data.IsPaused; PauseState.CasterClientId = data.CasterClientId; if (data.IsPaused) { PlayerFreeze.ApplyIfNotExempt(data.CasterClientId); EnemyFreeze.Freeze(); TurretFreeze.Freeze(); SpikeTrapFreeze.Freeze(); ElevatorFreeze.Freeze(); MineFreeze.Freeze(); PauseEffects.StartPauseEffect(data.CasterPosition); ScanPulse.PlayAt(data.CasterPosition); } else { PlayerFreeze.RemoveFreeze(); EnemyFreeze.Unfreeze(); TurretFreeze.Unfreeze(); SpikeTrapFreeze.Unfreeze(); ElevatorFreeze.Unfreeze(); MineFreeze.Unfreeze(); PauseEffects.EndPauseEffect(); DamageQueue.ReplayAndClear(); MineQueue.ReplayAndClear(); PlayerDamageQueue.ReplayAndClear(); } } private static PlayerControllerB FindPlayerByClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } PlayerControllerB[] array2 = array; foreach (PlayerControllerB val in array2) { if ((Object)(object)val != (Object)null && val.playerClientId == clientId) { return val; } } return null; } } public static class PauseEffects { private const float TransitionDuration = 0.6f; private static Volume _volume; private static ChromaticAberration _chromaticAberration; private static ColorAdjustments _colorAdjustments; private static bool _transitioning; private static float _transitionStart; private static float _startSaturation; private static float _endSaturation; private static float _startAberration; private static float _endAberration; public static void StartPauseEffect(Vector3 casterWorldPosition) { PauseAudio.PlayPause(); EnsureVolume(); BeginTransition(toGrey: true); } public static void EndPauseEffect() { PauseAudio.PlayResume(); EnsureVolume(); BeginTransition(toGrey: false); } public static void Tick() { if (_transitioning) { float num = Mathf.Clamp01((Time.unscaledTime - _transitionStart) / 0.6f); ((VolumeParameter)(object)_colorAdjustments.saturation).value = Mathf.Lerp(_startSaturation, _endSaturation, num); ((VolumeParameter)(object)_chromaticAberration.intensity).value = Mathf.Lerp(_startAberration, _endAberration, num); if (num >= 1f) { _transitioning = false; } } } private static void BeginTransition(bool toGrey) { _transitionStart = Time.unscaledTime; _startSaturation = ((VolumeParameter)(object)_colorAdjustments.saturation).value; _endSaturation = (toGrey ? (-100f) : 0f); _startAberration = ((VolumeParameter)(object)_chromaticAberration.intensity).value; _endAberration = (toGrey ? 1f : 0f); _transitioning = true; } private static void EnsureVolume() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_volume != (Object)null)) { GameObject val = new GameObject("DioCompany_TimeStopVolume"); Object.DontDestroyOnLoad((Object)val); _volume = val.AddComponent(); _volume.isGlobal = true; _volume.priority = 1000f; _volume.weight = 1f; VolumeProfile val2 = ScriptableObject.CreateInstance(); _chromaticAberration = val2.Add(false); ((VolumeParameter)(object)_chromaticAberration.intensity).value = 0f; ((VolumeParameter)_chromaticAberration.intensity).overrideState = true; _colorAdjustments = val2.Add(false); ((VolumeParameter)(object)_colorAdjustments.saturation).value = 0f; ((VolumeParameter)_colorAdjustments.saturation).overrideState = true; _volume.profile = val2; Plugin.Log.LogInfo((object)"[PauseEffects] Created dedicated time-stop Volume."); } } } public static class PauseState { public static bool IsPaused; public static ulong CasterClientId; public static float PauseEndsAtRealtime; public static readonly Dictionary CooldownEndsAtRealtime = new Dictionary(); } public static class PlayerDamageQueue { private class Entry { public PlayerControllerB Target; public int Force; public Vector3 HitDirection; public PlayerControllerB PlayerWhoHit; public bool PlayHitSFX; public int HitId; } private static readonly MethodInfo HitMethod = ResolveHitMethod(); private static readonly List Pending = new List(); private static MethodInfo ResolveHitMethod() { InterfaceMapping interfaceMap = typeof(PlayerControllerB).GetInterfaceMap(typeof(IHittable)); int num = Array.IndexOf(interfaceMap.InterfaceMethods, typeof(IHittable).GetMethod("Hit")); if (num < 0) { return null; } return interfaceMap.TargetMethods[num]; } public static void Enqueue(PlayerControllerB target, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitId) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Pending.Add(new Entry { Target = target, Force = force, HitDirection = hitDirection, PlayerWhoHit = playerWhoHit, PlayHitSFX = playHitSFX, HitId = hitId }); } public static void ReplayAndClear() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (Pending.Count == 0 || HitMethod == null) { return; } List list = new List(Pending); Pending.Clear(); foreach (Entry item in list) { if (!((Object)(object)item.Target == (Object)null)) { HitMethod.Invoke(item.Target, new object[5] { item.Force, item.HitDirection, item.PlayerWhoHit, item.PlayHitSFX, item.HitId }); } } } } public static class PlayerFreeze { public static void ApplyIfNotExempt(ulong casterClientId) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && val.playerClientId != casterClientId) { val.disableMoveInput = true; val.disableLookInput = true; } } public static void RemoveFreeze() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { val.disableMoveInput = false; val.disableLookInput = false; } } } [BepInPlugin("com.paul.diocompany.timestop", "Dio Company - Time Stop", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.paul.diocompany.timestop"; public const string Name = "Dio Company - Time Stop"; public const string Version = "1.0.0"; public static ConfigEntry PauseKey; public static ConfigEntry PauseTimeLimitSeconds; public static ConfigEntry PauseCooldownSeconds; public static ConfigEntry ScanPulseColorHex; private Harmony _harmony; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PauseKey = ((BaseUnityPlugin)this).Config.Bind("Keybinds", "PauseKey", (Key)24, "Requests a time-stop. Usable by the host, or by anyone the host has granted permission to (host types '/allow PlayerName' or '/deny PlayerName' in chat). Pressing it again while your own time-stop is active resumes it early."); PauseTimeLimitSeconds = ((BaseUnityPlugin)this).Config.Bind("General", "PauseTimeLimitSeconds", 30f, "Maximum duration, in seconds, a time-stop lasts before automatically resuming."); PauseCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind("General", "PauseCooldownSeconds", 5f, "How long, in seconds, a given player must wait after ending their own time-stop before starting another. Per-player -- doesn't affect anyone else's cooldown."); ScanPulseColorHex = ((BaseUnityPlugin)this).Config.Bind("Effects", "ScanPulseColorHex", "#FF33D9", "Hex color (e.g. #FF33D9) for the scan-pulse flash on time-stop cast. This is purely a local display preference -- it only changes what YOU see, regardless of who casts it."); _harmony = new Harmony("com.paul.diocompany.timestop"); _harmony.PatchAll(); PauseNetworking.Init(); PauseAudio.LoadClips(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Dio Company - Time Stop v1.0.0 loaded."); } } public static class ScanPulse { private const float PulseLifetime = 1.5f; private static readonly Color DefaultPulseColor = new Color(1f, 0.2f, 0.85f, 1f); private static readonly int[] ColorPropertyIds = new int[4] { Shader.PropertyToID("_Color"), Shader.PropertyToID("_BaseColor"), Shader.PropertyToID("_TintColor"), Shader.PropertyToID("_EmissionColor") }; private static Renderer[] _renderers; private static bool _tinted; private static float _untintAtRealtime; public static void PlayAt(Vector3 worldPosition) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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) Animator val = (((Object)(object)HUDManager.Instance != (Object)null) ? HUDManager.Instance.scanEffectAnimator : null); if (!((Object)(object)val == (Object)null)) { if (_renderers == null) { _renderers = ((Component)val).GetComponentsInChildren(true); } MaterialPropertyBlock val2 = new MaterialPropertyBlock(); Color configuredColor = GetConfiguredColor(); int[] colorPropertyIds = ColorPropertyIds; foreach (int num in colorPropertyIds) { val2.SetColor(num, configuredColor); } Renderer[] renderers = _renderers; for (int i = 0; i < renderers.Length; i++) { renderers[i].SetPropertyBlock(val2); } ((Component)val).transform.position = worldPosition; val.SetTrigger("scan"); _tinted = true; _untintAtRealtime = Time.realtimeSinceStartup + 1.5f; } } public static void Tick() { if (_tinted && !(Time.realtimeSinceStartup < _untintAtRealtime)) { Renderer[] renderers = _renderers; for (int i = 0; i < renderers.Length; i++) { renderers[i].SetPropertyBlock((MaterialPropertyBlock)null); } _tinted = false; } } private static Color GetConfiguredColor() { //IL_001f: 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) string value = Plugin.ScanPulseColorHex.Value; Color result = default(Color); if (!string.IsNullOrEmpty(value) && ColorUtility.TryParseHtmlString(value, ref result)) { return result; } return DefaultPulseColor; } } public static class SpikeTrapFreeze { public static readonly List Active = new List(); public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { foreach (SpikeRoofTrap item in Active) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)item.spikeTrapAnimator != (Object)null) { item.spikeTrapAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } } public static class TurretFreeze { public static readonly List Active = new List(); public static void Freeze() { SetFrozen(frozen: true); } public static void Unfreeze() { SetFrozen(frozen: false); } private static void SetFrozen(bool frozen) { foreach (Turret item in Active) { if (!((Object)(object)item == (Object)null)) { if ((Object)(object)item.turretAnimator != (Object)null) { item.turretAnimator.speed = (frozen ? 0f : 1f); } AudioSource[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].mute = frozen; } } } } } } namespace DioCompany.Patches { [HarmonyPatch(typeof(HUDManager), "AddTextToChatOnServer")] public static class ChatCommandPatch { private const string AllowPrefix = "/allow "; private const string DenyPrefix = "/deny "; [HarmonyPrefix] private static bool Prefix(string chatMessage) { if (chatMessage == null) { return true; } bool allow; string targetName; if (chatMessage.StartsWith("/allow ", StringComparison.OrdinalIgnoreCase)) { allow = true; targetName = chatMessage.Substring("/allow ".Length).Trim(); } else { if (!chatMessage.StartsWith("/deny ", StringComparison.OrdinalIgnoreCase)) { return true; } allow = false; targetName = chatMessage.Substring("/deny ".Length).Trim(); } HandleCommand(allow, targetName); return false; } private static void HandleCommand(bool allow, string targetName) { if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsHost) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("Time Stop", "Only the host can grant time-stop permission.", true, false, "LC_Tip1"); } return; } PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return; } PlayerControllerB[] array2 = array; foreach (PlayerControllerB val in array2) { if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && string.Equals(val.playerUsername, targetName, StringComparison.OrdinalIgnoreCase)) { if (allow) { HostPermissions.AllowedClientIds.Add(val.playerClientId); } else { HostPermissions.AllowedClientIds.Remove(val.playerClientId); } HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.DisplayTip("Time Stop", allow ? (val.playerUsername + " can now use time-stop.") : (val.playerUsername + "'s time-stop permission was revoked."), false, false, "LC_Tip1"); } return; } } HUDManager instance3 = HUDManager.Instance; if (instance3 != null) { instance3.DisplayTip("Time Stop", "No connected player found named '" + targetName + "'.", true, false, "LC_Tip1"); } } } [HarmonyPatch(typeof(MineshaftElevatorController))] public static class ElevatorFreezePatch { [HarmonyPatch("Update")] [HarmonyPrefix] private static bool UpdatePrefix() { return !PauseState.IsPaused; } [HarmonyPatch("LateUpdate")] [HarmonyPrefix] private static bool LateUpdatePrefix() { return !PauseState.IsPaused; } } [HarmonyPatch] public static class EnemyContactPatch { private static IEnumerable TargetMethods() { Type[] types = typeof(EnemyAI).Assembly.GetTypes(); foreach (Type type in types) { if (typeof(EnemyAI).IsAssignableFrom(type)) { MethodInfo method = type.GetMethod("OnCollideWithPlayer", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { yield return method; } } } } [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(EnemyAI), "HitEnemyOnLocalClient")] public static class EnemyDamagePatch { [HarmonyPrefix] private static bool Prefix(EnemyAI __instance, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!PauseState.IsPaused) { return true; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || val.playerClientId != PauseState.CasterClientId) { return true; } DamageQueue.Enqueue(__instance, force, hitDirection, playerWhoHit, playHitSFX, hitID); return false; } } [HarmonyPatch] public static class EnemyLogicFreezePatch { private static readonly string[] MethodNames = new string[3] { "Update", "FixedUpdate", "LateUpdate" }; private static IEnumerable TargetMethods() { Type[] types = typeof(EnemyAI).Assembly.GetTypes(); foreach (Type type in types) { if (!typeof(EnemyAI).IsAssignableFrom(type)) { continue; } string[] methodNames = MethodNames; foreach (string name in methodNames) { MethodInfo method = type.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { yield return method; } } } } [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(Landmine), "TriggerMineOnLocalClientByExiting")] public static class MinePatch { [HarmonyPrefix] private static bool Prefix(Landmine __instance) { if (!PauseState.IsPaused) { return true; } MineQueue.Enqueue(__instance); return false; } } [HarmonyPatch(typeof(Landmine), "Start")] public static class MineRegistrationPatch { [HarmonyPostfix] private static void Postfix(Landmine __instance) { if (!MineFreeze.Active.Contains(__instance)) { MineFreeze.Active.Add(__instance); } } } [HarmonyPatch] public static class PlayerHitPatch { private static MethodBase TargetMethod() { InterfaceMapping interfaceMap = typeof(PlayerControllerB).GetInterfaceMap(typeof(IHittable)); int num = Array.IndexOf(interfaceMap.InterfaceMethods, typeof(IHittable).GetMethod("Hit")); if (num < 0) { return null; } return interfaceMap.TargetMethods[num]; } [HarmonyPrefix] private static bool Prefix(PlayerControllerB __instance, int force, Vector3 hitDirection, PlayerControllerB playerWhoHit, bool playHitSFX, int hitID, ref bool __result) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!PauseState.IsPaused) { return true; } PlayerDamageQueue.Enqueue(__instance, force, hitDirection, playerWhoHit, playHitSFX, hitID); __result = true; return false; } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] public static class PlayerTickPatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !((Object)(object)__instance != (Object)(object)val)) { ModTick.Tick(); } } } [HarmonyPatch(typeof(SpikeRoofTrap))] public static class SpikeTrapFreezePatch { [HarmonyPatch("Update")] [HarmonyPrefix] private static bool UpdatePrefix() { return !PauseState.IsPaused; } [HarmonyPatch("OnTriggerStay")] [HarmonyPrefix] private static bool OnTriggerStayPrefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(SpikeRoofTrap), "Start")] public static class SpikeTrapRegistrationPatch { [HarmonyPostfix] private static void Postfix(SpikeRoofTrap __instance) { if (!SpikeTrapFreeze.Active.Contains(__instance)) { SpikeTrapFreeze.Active.Add(__instance); } } } [HarmonyPatch(typeof(TimeOfDay), "MoveTimeOfDay")] public static class TimeOfDayPatch { [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(Turret), "Update")] public static class TurretFreezePatch { [HarmonyPrefix] private static bool Prefix() { return !PauseState.IsPaused; } } [HarmonyPatch(typeof(Turret), "Start")] public static class TurretRegistrationPatch { [HarmonyPostfix] private static void Postfix(Turret __instance) { if (!TurretFreeze.Active.Contains(__instance)) { TurretFreeze.Active.Add(__instance); } } } } namespace DioCompany.Networking { [Serializable] public struct PauseStateData { public bool IsPaused; public ulong CasterClientId; public float CasterPosX; public float CasterPosY; public float CasterPosZ; public float TimeLimit; public Vector3 CasterPosition => new Vector3(CasterPosX, CasterPosY, CasterPosZ); public static PauseStateData Paused(ulong casterClientId, Vector3 casterPosition, float timeLimit) { //IL_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references) return new PauseStateData { IsPaused = true, CasterClientId = casterClientId, CasterPosX = casterPosition.x, CasterPosY = casterPosition.y, CasterPosZ = casterPosition.z, TimeLimit = timeLimit }; } public static PauseStateData Resumed() { return new PauseStateData { IsPaused = false }; } } public static class PauseNetworking { private static LNetworkMessage _toggleRequest; private static LNetworkMessage _stateChanged; private static bool _initialized; public static void Init() { if (!_initialized) { _initialized = true; _toggleRequest = LNetworkMessage.Connect("ToggleRequest", (Action)delegate(bool _, ulong senderClientId) { PauseController.HostHandleToggleRequest(senderClientId); }, (Action)null, (Action)null); _stateChanged = LNetworkMessage.Connect("PauseStateChanged", (Action)null, (Action)PauseController.ApplyStateChange, (Action)null); } } public static void RequestToggle() { _toggleRequest.SendServer(true); } public static void BroadcastState(PauseStateData data) { _stateChanged.SendClients(data); } } }