The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of Vasodilation v1.2.2
tony4twentys-Vasodilation.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using ExitGames.Client.Photon; using Microsoft.CodeAnalysis; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using PhotonCustomPropsUtils; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Vasodilation")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Vasodilation")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("15fa7750-965f-4249-837f-3d54157b5401")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace VasodilationMod { [BepInPlugin("tony4twentys.Vasodilation", "Vasodilation", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class VasodilationPlugin : BaseUnityPlugin, IInRoomCallbacks, IMatchmakingCallbacks { [Serializable] public struct HostCfg { public float coldPerSecond; public float tickSeconds; public float gateOn; public float gateOff; } [CompilerGenerated] private sealed class <HostAuthoritativeDriver>d__37 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public VasodilationPlugin <>4__this; private WaitForSeconds <wait>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <HostAuthoritativeDriver>d__37(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(Mathf.Max(0.05f, Synced.tickSeconds)); break; case 1: <>1__state = -1; break; } if (<>4__this._allowVaso) { if (<>4__this._cfgVerbose.Value) { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[Vaso] Tick loop: applying perSec={Synced.coldPerSecond} total={Synced.tickSeconds}"); } <>4__this.ApplyTick(Synced.coldPerSecond, Synced.tickSeconds); } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string ROOM_CFG_KEY = "VASO_CFG_V1"; private ConfigEntry<float> _cfgColdPerSecond; private ConfigEntry<float> _cfgTickSeconds; private ConfigEntry<float> _cfgGateOn; private ConfigEntry<float> _cfgGateOff; private ConfigEntry<bool> _cfgVerbose; public static HostCfg Synced; private Coroutine _hostLoop; private float _runningTickSeconds; private PhotonScopedManager _photonManager; public bool IsHost = false; private bool _allowVaso = false; private void Awake() { _cfgColdPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ColdPerSecond", -0.06f, string.Empty); _cfgTickSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TickSeconds", 1f, string.Empty); _cfgGateOn = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ColdGateOn", 0.025f, string.Empty); _cfgGateOff = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ColdGateOff", 0f, string.Empty); _cfgVerbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogs", false, string.Empty); Synced = BuildFromHostConfig(); _runningTickSeconds = Synced.tickSeconds; if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] Awake: initial cfg built; waiting for scene/Photon events"); } _cfgColdPerSecond.SettingChanged += delegate { OnHostConfigChanged(); }; _cfgTickSeconds.SettingChanged += delegate { OnHostConfigChanged(); }; _cfgGateOn.SettingChanged += delegate { OnHostConfigChanged(); }; _cfgGateOff.SettingChanged += delegate { OnHostConfigChanged(); }; SceneManager.activeSceneChanged += OnSceneChanged; InitializePhotonManager(); } private void OnEnable() { PhotonNetwork.AddCallbackTarget((object)this); } private void OnDisable() { PhotonNetwork.RemoveCallbackTarget((object)this); } private void OnDestroy() { SceneManager.activeSceneChanged -= OnSceneChanged; } private void OnSceneChanged(Scene oldScene, Scene newScene) { if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Vaso] Scene changed: " + ((Scene)(ref oldScene)).name + " -> " + ((Scene)(ref newScene)).name)); } RestartHostLoopIfNeeded(); } public void OnJoinedRoom() { CheckHostStatus(); } public void OnCreatedRoom() { } public void OnCreateRoomFailed(short returnCode, string message) { } public void OnFriendListUpdate(List<FriendInfo> friendList) { } public void OnJoinRandomFailed(short returnCode, string message) { } public void OnJoinRoomFailed(short returnCode, string message) { } void IInRoomCallbacks.OnPlayerEnteredRoom(Player newPlayer) { if (PhotonNetwork.IsMasterClient) { PublishConfig(); } } void IInRoomCallbacks.OnPlayerLeftRoom(Player otherPlayer) { } void IInRoomCallbacks.OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { } void IInRoomCallbacks.OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) { } void IInRoomCallbacks.OnMasterClientSwitched(Player newMasterClient) { if (PhotonNetwork.IsMasterClient) { PublishConfig(); } TryStartOrStopHostLoop(); } private HostCfg BuildFromHostConfig() { HostCfg result = default(HostCfg); result.coldPerSecond = _cfgColdPerSecond.Value; result.tickSeconds = Mathf.Max(0.05f, _cfgTickSeconds.Value); result.gateOn = Mathf.Max(0f, _cfgGateOn.Value); result.gateOff = Mathf.Max(0f, _cfgGateOff.Value); return result; } private static string PackCfg(HostCfg c) { CultureInfo invariantCulture = CultureInfo.InvariantCulture; return c.coldPerSecond.ToString(invariantCulture) + "|" + c.tickSeconds.ToString(invariantCulture) + "|" + c.gateOn.ToString(invariantCulture) + "|" + c.gateOff.ToString(invariantCulture); } private static HostCfg UnpackCfg(string s) { CultureInfo invariantCulture = CultureInfo.InvariantCulture; string[] array = (s ?? string.Empty).Split(new char[1] { '|' }); HostCfg hostCfg = default(HostCfg); hostCfg.coldPerSecond = -0.06f; hostCfg.tickSeconds = 1f; hostCfg.gateOn = 0.025f; hostCfg.gateOff = 0f; HostCfg result = hostCfg; if (array.Length >= 4) { float.TryParse(array[0], NumberStyles.Float, invariantCulture, out result.coldPerSecond); float.TryParse(array[1], NumberStyles.Float, invariantCulture, out result.tickSeconds); float.TryParse(array[2], NumberStyles.Float, invariantCulture, out result.gateOn); float.TryParse(array[3], NumberStyles.Float, invariantCulture, out result.gateOff); } return result; } private void OnHostConfigChanged() { if (PhotonNetwork.IsMasterClient) { if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] Host config changed; publishing to room"); } PublishConfig(); } } private void PublishConfig() { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == null) { return; } Synced = BuildFromHostConfig(); string text = PackCfg(Synced); if (PhotonNetwork.IsMasterClient && _photonManager != null) { if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] Setting room property via PhotonCustomPropsUtils"); } _photonManager.SetRoomProperty("VASO_CFG_V1", (object)text); if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Vaso] Host published config: perSec={Synced.coldPerSecond} tick={Synced.tickSeconds} gates=({Synced.gateOn},{Synced.gateOff})"); } RestartHostLoopIfNeeded(); } else if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] PhotonCustomPropsUtils not ready; skipping direct property set to avoid duplication"); } } private void RestartHostLoopIfNeeded() { if (Math.Abs(_runningTickSeconds - Synced.tickSeconds) > 0.0001f) { StopHostLoop(); TryStartOrStopHostLoop(); } } private void TryStartOrStopHostLoop() { if (_allowVaso) { if (_hostLoop == null) { _runningTickSeconds = Synced.tickSeconds; if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] Starting tick loop"); } _hostLoop = ((MonoBehaviour)this).StartCoroutine(HostAuthoritativeDriver()); } } else { if (_cfgVerbose.Value && _hostLoop != null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] Stopping tick loop (not allowed)"); } StopHostLoop(); } } private void StopHostLoop() { if (_hostLoop != null) { ((MonoBehaviour)this).StopCoroutine(_hostLoop); _hostLoop = null; } } [IteratorStateMachine(typeof(<HostAuthoritativeDriver>d__37))] private IEnumerator HostAuthoritativeDriver() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <HostAuthoritativeDriver>d__37(0) { <>4__this = this }; } private Character FindLocalCharacter() { foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter != (Object)null && (Object)(object)((MonoBehaviourPun)allCharacter).photonView != (Object)null && ((MonoBehaviourPun)allCharacter).photonView.IsMine) { return allCharacter; } } return null; } private void ApplyTick(float perSecond, float totalTime) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown Character val = FindLocalCharacter(); if ((Object)(object)val == (Object)null || val.refs == null || (Object)(object)val.refs.afflictions == (Object)null) { if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] No local character; skip tick"); } return; } bool flag = (Object)(object)val.data != (Object)null && val.data.isSprinting; float currentStatus = val.refs.afflictions.GetCurrentStatus((STATUSTYPE)2); if (!flag || currentStatus <= Synced.gateOff) { if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Vaso] Tick ignored: sprinting={flag} cold={currentStatus}"); } return; } Affliction_AdjustColdOverTime val2 = new Affliction_AdjustColdOverTime { statusPerSecond = perSecond, totalTime = totalTime, character = val }; val.refs.afflictions.AddAffliction((Affliction)(object)val2, false); if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Vaso] Tick applied: per={perSecond} for {totalTime}s; cold={currentStatus}"); } } private void InitializePhotonManager() { if (PhotonCustomPropsUtilsPlugin.IsReady) { SetupPhotonManager(); } else { PhotonCustomPropsUtilsPlugin.OnReady += SetupPhotonManager; } } private void SetupPhotonManager() { _photonManager = PhotonCustomPropsUtilsPlugin.GetManager("tony4twentys.Vasodilation"); _photonManager.RegisterOnJoinedRoom((Action<Player>)delegate { CheckHostStatus(); }); _photonManager.RegisterRoomProperty<string>("VASO_CFG_V1", (RoomEventType)2, (Action<string>)delegate(string configData) { if (!IsHost && !string.IsNullOrEmpty(configData)) { HostCfg synced = Synced; Synced = UnpackCfg(configData); if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Vaso] Config updated from room (PCPU): perSec={Synced.coldPerSecond} tick={Synced.tickSeconds} gates=({Synced.gateOn},{Synced.gateOff}) (was {synced.coldPerSecond}/{synced.tickSeconds})"); } _allowVaso = true; RestartHostLoopIfNeeded(); } }); } private void CheckHostStatus() { if (!PhotonNetwork.InRoom) { return; } if (PhotonNetwork.IsMasterClient) { if (!IsHost) { IsHost = true; _allowVaso = true; if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] Joined room as HOST"); } PublishConfig(); } } else if (IsHost) { IsHost = false; _allowVaso = false; if (_cfgVerbose.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Vaso] Joined room as CLIENT; awaiting config"); } } TryStartOrStopHostLoop(); } public void OnLeftRoom() { IsHost = false; _allowVaso = false; StopHostLoop(); } } }