using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PassTheCurse")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.4.0")] [assembly: AssemblyInformationalVersion("0.1.4")] [assembly: AssemblyProduct("PassTheCurse")] [assembly: AssemblyTitle("PassTheCurse")] [assembly: AssemblyVersion("0.1.4.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } [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 PassTheCurse { internal enum CurseEffect { None, RandomSlip, BadStaminaRegen, InvoluntaryJump, CameraWobble, FakeUi, BackpackLeakage, TripSneeze, InvertedControls, GripHiccup } internal sealed class CurseManager { private const string CursedActorKey = "PassTheCurse.CursedActor"; private const string CurseEffectKey = "PassTheCurse.CurseEffect"; private const string LastTransferKey = "PassTheCurse.LastTransferTime"; private static readonly MethodInfo? DropItemFromSlotMethod = AccessTools.Method(typeof(CharacterItems), "DropItemFromSlotRPC", (Type[])null, (Type[])null); private readonly string[] fakeWarnings = new string[6] { "LOW STAMINA", "BACKPACK LEAK DETECTED", "GRIP FAILURE IMMINENT", "YOU DROPPED AN ITEM", "WRONG WAY", "CURSE LEVEL RISING" }; private int cachedCursedActor = -1; private CurseEffect cachedCurseEffect; private int previousLocalCursedActor = -1; private CurseEffect previousLocalCurseEffect; private int lastCharacterCount; private float charactersAppearedAt = -1f; private bool shouldAssignAtRunStart = true; private float localLastTransferTime = -9999f; private float nextSlipAt; private float nextJumpAt; private float nextFakeUiAt; private float nextLeakAt; private float nextTripSneezeAt; private float nextGripHiccupAt; private float nextCurseStatusAt; private float cueUntil; private string cueTitle = string.Empty; private string cueSubtitle = string.Empty; internal int CursedActor => cachedCursedActor; internal CurseEffect ActiveEffect => cachedCurseEffect; internal bool LocalPlayerIsCursed { get { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter != (Object)null && TryGetActorNumber(localCharacter, out var actorNumber)) { return actorNumber == cachedCursedActor; } return false; } } internal void Update() { if (!Plugin.ModEnabled.Value || !PhotonNetwork.InRoom) { ResetLocalState(); return; } RefreshCachedCursedActor(); HandleHostAssignmentAndTransfers(); HandleLocalCurseEffects(); } internal void FixedUpdate() { } internal void OnGUI() { //IL_0033: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00b0: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) if (!(Time.time >= cueUntil) && !string.IsNullOrEmpty(cueTitle)) { float num = Mathf.Clamp01((cueUntil - Time.time) / 0.8f); Color color = GUI.color; GUI.color = new Color(1f, 1f, 1f, num); Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width * 0.1f, (float)Screen.height * 0.18f, (float)Screen.width * 0.8f, 70f); GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 34, fontStyle = (FontStyle)1, wordWrap = true }; val2.normal.textColor = new Color(1f, 0.24f, 0.2f, num); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor((float)Screen.width * 0.1f, ((Rect)(ref val)).yMax - 6f, (float)Screen.width * 0.8f, 52f); GUIStyle val4 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 19, fontStyle = (FontStyle)1, wordWrap = true }; val4.normal.textColor = new Color(1f, 1f, 1f, num); GUI.Label(val, cueTitle, val2); GUI.Label(val3, cueSubtitle, val4); GUI.color = color; } } internal static bool IsCursed(Character character) { if (Plugin.Instance.Curse.TryGetActorNumber(character, out var actorNumber)) { return actorNumber == Plugin.Instance.Curse.CursedActor; } return false; } internal static bool HasActiveEffect(Character character, CurseEffect effect) { if (IsCursed(character)) { return Plugin.Instance.Curse.ActiveEffect == effect; } return false; } internal bool LocalPlayerHasEffect(CurseEffect effect) { if (LocalPlayerIsCursed) { return cachedCurseEffect == effect; } return false; } internal static bool TryGetCharacterActor(Character character, out int actorNumber) { return Plugin.Instance.Curse.TryGetActorNumber(character, out actorNumber); } private void RefreshCachedCursedActor() { Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties; if (((Dictionary)(object)customProperties).ContainsKey((object)"PassTheCurse.CursedActor") && customProperties[(object)"PassTheCurse.CursedActor"] is int num) { cachedCursedActor = num; } if (((Dictionary)(object)customProperties).ContainsKey((object)"PassTheCurse.CurseEffect") && customProperties[(object)"PassTheCurse.CurseEffect"] is int num2 && Enum.IsDefined(typeof(CurseEffect), num2)) { cachedCurseEffect = (CurseEffect)num2; } if (((Dictionary)(object)customProperties).ContainsKey((object)"PassTheCurse.LastTransferTime") && customProperties[(object)"PassTheCurse.LastTransferTime"] is float num3) { localLastTransferTime = num3; } } private void HandleHostAssignmentAndTransfers() { //IL_0100: 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_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } List validCharacters = GetValidCharacters(); int count = validCharacters.Count; if (count == 0) { lastCharacterCount = 0; charactersAppearedAt = -1f; shouldAssignAtRunStart = true; return; } if (lastCharacterCount == 0) { charactersAppearedAt = Time.time; shouldAssignAtRunStart = true; } lastCharacterCount = count; if (charactersAppearedAt >= 0f && Time.time - charactersAppearedAt < Plugin.StartDelay.Value) { return; } if (shouldAssignAtRunStart || cachedCursedActor < 0 || (Object)(object)FindCharacterByActor(cachedCursedActor, validCharacters) == (Object)null) { Character character = validCharacters[Random.Range(0, validCharacters.Count)]; if (TryGetActorNumber(character, out var actorNumber)) { SetCursedActor(actorNumber, "initial"); } } else { if (Time.time - localLastTransferTime < Plugin.TransferCooldown.Value) { return; } Character val = FindCharacterByActor(cachedCursedActor, validCharacters); if ((Object)(object)val == (Object)null) { return; } Vector3 val2 = SafeHipPosition(val); float value = Plugin.TouchDistance.Value; foreach (Character item in validCharacters) { if (item != val && TryGetActorNumber(item, out var actorNumber2) && Vector3.Distance(val2, SafeHipPosition(item)) <= value) { SetCursedActor(actorNumber2, "touch"); break; } } } } private void HandleLocalCurseEffects() { Character localCharacter = Character.localCharacter; if (!LocalPlayerIsCursed) { if (previousLocalCursedActor == PhotonNetwork.LocalPlayer.ActorNumber && (Object)(object)localCharacter?.refs.afflictions != (Object)null) { localCharacter.refs.afflictions.SetStatus((STATUSTYPE)5, 0f, false); } previousLocalCursedActor = cachedCursedActor; return; } if (previousLocalCursedActor != cachedCursedActor || previousLocalCurseEffect != cachedCurseEffect) { ResetEffectTimers(); ShowCurseCue(cachedCurseEffect); ApplyImmediateEffectCue(localCharacter, cachedCurseEffect); } previousLocalCursedActor = cachedCursedActor; previousLocalCurseEffect = cachedCurseEffect; if (!((Object)(object)localCharacter == (Object)null)) { if (Plugin.ShowCurseOnStaminaBar.Value && Time.time >= nextCurseStatusAt && (Object)(object)localCharacter.refs.afflictions != (Object)null) { localCharacter.refs.afflictions.AddStatus((STATUSTYPE)5, 0.025f, false, true, false); nextCurseStatusAt = Time.time + 6f; } else if (!Plugin.ShowCurseOnStaminaBar.Value && (Object)(object)localCharacter.refs.afflictions != (Object)null) { localCharacter.refs.afflictions.SetStatus((STATUSTYPE)5, 0f, false); } if (cachedCurseEffect == CurseEffect.RandomSlip && Plugin.EnableRandomSlip.Value && Time.time >= nextSlipAt) { ApplyRandomSlip(localCharacter); nextSlipAt = Time.time + RandomRange(Plugin.SlipIntervalMin.Value, Plugin.SlipIntervalMax.Value); } if (cachedCurseEffect == CurseEffect.InvoluntaryJump && Plugin.EnableInvoluntaryJump.Value && Time.time >= nextJumpAt) { ApplyInvoluntaryJump(localCharacter); nextJumpAt = Time.time + RandomRange(Plugin.JumpIntervalMin.Value, Plugin.JumpIntervalMax.Value); } if (cachedCurseEffect == CurseEffect.FakeUi && Plugin.EnableFakeUi.Value && Time.time >= nextFakeUiAt) { Notify(fakeWarnings[Random.Range(0, fakeWarnings.Length)]); nextFakeUiAt = Time.time + RandomRange(Plugin.FakeUiIntervalMin.Value, Plugin.FakeUiIntervalMax.Value); } if (cachedCurseEffect == CurseEffect.BackpackLeakage && Plugin.EnableBackpackLeakage.Value && Time.time >= nextLeakAt) { TryLeakItem(localCharacter); nextLeakAt = Time.time + RandomRange(Plugin.LeakIntervalMin.Value, Plugin.LeakIntervalMax.Value); } if (cachedCurseEffect == CurseEffect.TripSneeze && Plugin.EnableTripSneeze.Value && Time.time >= nextTripSneezeAt) { ApplyTripSneeze(localCharacter); nextTripSneezeAt = Time.time + RandomRange(Plugin.TripSneezeIntervalMin.Value, Plugin.TripSneezeIntervalMax.Value); } if (cachedCurseEffect == CurseEffect.GripHiccup && Plugin.EnableGripHiccup.Value && Time.time >= nextGripHiccupAt) { ApplyGripHiccup(localCharacter); nextGripHiccupAt = Time.time + RandomRange(Plugin.GripHiccupIntervalMin.Value, Plugin.GripHiccupIntervalMax.Value); } } } private void ApplyRandomSlip(Character local) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //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) if ((Object)(object)local.refs.climbing != (Object)null) { float num = ((Random.value < 0.5f) ? (-1f) : 1f); CharacterClimbing climbing = local.refs.climbing; climbing.playerSlide += new Vector2(num * Plugin.SlipStrength.Value, 0f - Plugin.SlipStrength.Value); } Notify("Grip slipped."); } private void ApplyInvoluntaryJump(Character local) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0021: 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_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_0047: 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_00a8: Unknown result type (might be due to invalid IL or missing references) Vector3 insideUnitSphere = Random.insideUnitSphere; insideUnitSphere.y = 0f; Vector3 val = Vector3.up * Plugin.JumpForce.Value + ((Vector3)(ref insideUnitSphere)).normalized * (Plugin.JumpForce.Value * 0.18f); if ((Object)(object)local.refs.hip != (Object)null) { local.refs.hip.AddForce(val, (ForceMode)1); } if ((Object)(object)local.refs.hip != (Object)null && (Object)(object)local.refs.hip.Rig != (Object)null) { local.refs.hip.Rig.AddForce(val, (ForceMode)1); } Notify("The curse jumped."); } private void TryLeakItem(Character local) { //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_0098: 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_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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) if (DropItemFromSlotMethod == null || (Object)(object)Player.localPlayer == (Object)null || (Object)(object)local.refs.items == (Object)null) { return; } List list = new List(); ItemSlot[] itemSlots = Player.localPlayer.itemSlots; foreach (ItemSlot val in itemSlots) { if (val != null && !val.IsEmpty()) { list.Add(val); } } if (list.Count == 0) { return; } ItemSlot val2 = list[Random.Range(0, list.Count)]; Vector3 val3 = SafeHipPosition(local) + Vector3.up * 0.75f + Random.insideUnitSphere * 0.2f; try { DropItemFromSlotMethod.Invoke(local.refs.items, new object[2] { val2.itemSlotID, val3 }); Notify("Something leaked from your pack."); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Backpack leakage failed: " + ex.Message)); } } private void ApplyTripSneeze(Character local) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //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_0052: 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_0070: 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_0026: 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_0094: 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_00bf: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Random.insideUnitSphere; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = local.data.lookDirection_Right; } ((Vector3)(ref val)).Normalize(); Vector3 val2 = (val * 0.55f + Vector3.down * 0.25f + Vector3.up * 0.15f) * Plugin.TripSneezeForce.Value; if ((Object)(object)local.refs.hip != (Object)null) { local.refs.hip.AddForce(val2, (ForceMode)1); } if ((Object)(object)local.refs.climbing != (Object)null) { CharacterClimbing climbing = local.refs.climbing; climbing.playerSlide += new Vector2(val.x, -1f) * (Plugin.TripSneezeForce.Value / 220f); } local.data.slippy = Mathf.Max(local.data.slippy, Plugin.SlippyAmount.Value * 0.75f); Notify("Trip sneeze."); } private void ApplyGripHiccup(Character local) { //IL_002d: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)local.refs.climbing == (Object)null) && local.data.isClimbing) { CharacterClimbing climbing = local.refs.climbing; climbing.playerSlide += Vector2.down * Plugin.GripHiccupSlideStrength.Value; local.refs.climbing.StopClimbing(); Notify("Grip hiccup."); } } private void ResetEffectTimers() { float time = Time.time; nextSlipAt = time + 2f; nextJumpAt = time + 2.5f; nextFakeUiAt = time + 2f; nextLeakAt = time + 4f; nextTripSneezeAt = time + 2.5f; nextGripHiccupAt = time + 3f; nextCurseStatusAt = time + 1f; } private void ApplyImmediateEffectCue(Character? local, CurseEffect effect) { Plugin.Log.LogInfo((object)$"Local player is cursed with {effect}."); if (!((Object)(object)local == (Object)null)) { switch (effect) { case CurseEffect.FakeUi: Notify(fakeWarnings[Random.Range(0, fakeWarnings.Length)]); break; case CurseEffect.BackpackLeakage: Notify("Your pack feels loose."); break; case CurseEffect.InvoluntaryJump: Notify("Your legs twitch."); break; case CurseEffect.TripSneeze: Notify("You feel a sneeze building."); break; case CurseEffect.InvertedControls: Notify("Your controls feel backwards."); break; case CurseEffect.GripHiccup: Notify("Your grip feels unreliable."); break; case CurseEffect.CameraWobble: break; } } } private void ResetLocalState() { cachedCursedActor = -1; cachedCurseEffect = CurseEffect.None; previousLocalCursedActor = -1; previousLocalCurseEffect = CurseEffect.None; lastCharacterCount = 0; charactersAppearedAt = -1f; shouldAssignAtRunStart = true; localLastTransferTime = -9999f; cueUntil = 0f; cueTitle = string.Empty; cueSubtitle = string.Empty; } private void SetCursedActor(int actorNumber, string reason) { //IL_0006: 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) //IL_0024: 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_004b: Expected O, but got Unknown CurseEffect curseEffect = RollRandomEffect(); Hashtable val = new Hashtable { [(object)"PassTheCurse.CursedActor"] = actorNumber, [(object)"PassTheCurse.CurseEffect"] = (int)curseEffect, [(object)"PassTheCurse.LastTransferTime"] = Time.time }; cachedCursedActor = actorNumber; cachedCurseEffect = curseEffect; shouldAssignAtRunStart = false; localLastTransferTime = Time.time; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); Plugin.Log.LogInfo((object)$"Curse assigned to actor {actorNumber} ({reason}, {curseEffect})."); } private static CurseEffect RollRandomEffect() { List list = new List(); if (Plugin.EnableRandomSlip.Value) { list.Add(CurseEffect.RandomSlip); } if (Plugin.EnableBadStaminaRegen.Value) { list.Add(CurseEffect.BadStaminaRegen); } if (Plugin.EnableInvoluntaryJump.Value) { list.Add(CurseEffect.InvoluntaryJump); } if (Plugin.EnableCameraWobble.Value) { list.Add(CurseEffect.CameraWobble); } if (Plugin.EnableFakeUi.Value) { list.Add(CurseEffect.FakeUi); } if (Plugin.EnableBackpackLeakage.Value) { list.Add(CurseEffect.BackpackLeakage); } if (Plugin.EnableTripSneeze.Value) { list.Add(CurseEffect.TripSneeze); } if (Plugin.EnableInvertedControls.Value) { list.Add(CurseEffect.InvertedControls); } if (Plugin.EnableGripHiccup.Value) { list.Add(CurseEffect.GripHiccup); } if (list.Count != 0) { return list[Random.Range(0, list.Count)]; } return CurseEffect.None; } private List GetValidCharacters() { List list = new List(); foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter != (Object)null && !allCharacter.isBot && !allCharacter.data.dead && !allCharacter.data.passedOut && !allCharacter.data.fullyPassedOut && TryGetActorNumber(allCharacter, out var _)) { list.Add(allCharacter); } } return list; } private Character? FindCharacterByActor(int actorNumber, List candidates) { foreach (Character candidate in candidates) { if (TryGetActorNumber(candidate, out var actorNumber2) && actorNumber2 == actorNumber) { return candidate; } } return null; } private bool TryGetActorNumber(Character character, out int actorNumber) { actorNumber = -1; PhotonView view = character.refs.view; if ((Object)(object)view == (Object)null || view.Owner == null) { return false; } actorNumber = view.Owner.ActorNumber; return actorNumber > 0; } private static Vector3 SafeHipPosition(Character character) { //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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) try { return character.Center; } catch (Exception) { return ((Component)character).transform.position; } } private static float RandomRange(float min, float max) { if (max < min) { float num = max; max = min; min = num; } return Random.Range(min, max); } private static void Notify(string text) { try { UI_Notifications val = Object.FindObjectOfType(); if (val != null) { val.AddNotification(text); } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Failed to show curse notification: " + ex.Message)); } } private static void ShowCurseCue(CurseEffect effect) { string text = FormatEffectName(effect); string text2 = "YOU ARE CURSED\n" + text.ToUpperInvariant(); string text3 = "You are cursed: " + text + ". Touch someone."; Plugin.Instance.Curse.cueTitle = "YOU ARE CURSED"; Plugin.Instance.Curse.cueSubtitle = text + " - touch another player"; Plugin.Instance.Curse.cueUntil = Time.time + 4.5f; try { if ((Object)(object)GUIManager.instance != (Object)null) { GUIManager.instance.SetHeroTitle(text2, (AudioClip)null); return; } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Failed to show big curse cue: " + ex.Message)); } Notify(text3); } private static string FormatEffectName(CurseEffect effect) { return effect switch { CurseEffect.RandomSlip => "Random Slip", CurseEffect.BadStaminaRegen => "Bad Stamina Regen", CurseEffect.InvoluntaryJump => "Involuntary Jump", CurseEffect.CameraWobble => "Camera Wobble", CurseEffect.FakeUi => "Fake UI", CurseEffect.BackpackLeakage => "Backpack Leakage", CurseEffect.TripSneeze => "Trip Sneeze", CurseEffect.InvertedControls => "Inverted Controls", CurseEffect.GripHiccup => "Grip Hiccup", _ => "Unknown", }; } } [HarmonyPatch(typeof(CharacterInput))] internal static class CharacterInputPatches { [HarmonyPostfix] [HarmonyPatch("Sample")] private static void SamplePostfix(CharacterInput __instance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //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) if (ShouldInvertControls()) { __instance.movementInput *= -1f; } } [HarmonyPostfix] [HarmonyPatch("GetMovementInput")] private static void GetMovementInputPostfix(ref Vector2 __result) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //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) if (ShouldInvertControls()) { __result *= -1f; } } private static bool ShouldInvertControls() { if (Plugin.ModEnabled.Value && Plugin.EnableInvertedControls.Value) { return Plugin.Instance.Curse.LocalPlayerHasEffect(CurseEffect.InvertedControls); } return false; } } [HarmonyPatch(typeof(Character))] internal static class CharacterPatches { [HarmonyPrefix] [HarmonyPatch("AddStamina")] private static void AddStaminaPrefix(Character __instance, ref float add) { if (Plugin.ModEnabled.Value && Plugin.EnableBadStaminaRegen.Value && add > 0f && CurseManager.HasActiveEffect(__instance, CurseEffect.BadStaminaRegen)) { add *= Plugin.StaminaRegenMultiplier.Value; } } } [HarmonyPatch(typeof(MainCameraMovement))] internal static class MainCameraMovementPatches { [HarmonyPostfix] [HarmonyPatch("LateUpdate")] private static void LateUpdatePostfix(MainCameraMovement __instance) { //IL_007b: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ModEnabled.Value && Plugin.EnableCameraWobble.Value && Plugin.Instance.Curse.LocalPlayerHasEffect(CurseEffect.CameraWobble)) { float value = Plugin.CameraWobbleDegrees.Value; if (!(value <= 0f)) { float value2 = Plugin.CameraWobbleSpeed.Value; float num = Mathf.Sin(Time.time * value2 * 1.17f) * value * 0.45f; float num2 = Mathf.Sin(Time.time * value2) * value; Transform transform = ((Component)__instance).transform; transform.localRotation *= Quaternion.Euler(num, 0f, num2); } } } } [BepInPlugin("edwar.peak.passthecurse", "Pass The Curse", "0.1.4")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "edwar.peak.passthecurse"; public const string PluginName = "Pass The Curse"; public const string PluginVersion = "0.1.4"; private Harmony? harmony; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static ConfigEntry ModEnabled { get; private set; } internal static ConfigEntry TouchDistance { get; private set; } internal static ConfigEntry TransferCooldown { get; private set; } internal static ConfigEntry StartDelay { get; private set; } internal static ConfigEntry EnableRandomSlip { get; private set; } internal static ConfigEntry SlipIntervalMin { get; private set; } internal static ConfigEntry SlipIntervalMax { get; private set; } internal static ConfigEntry SlipStrength { get; private set; } internal static ConfigEntry SlippyAmount { get; private set; } internal static ConfigEntry EnableBadStaminaRegen { get; private set; } internal static ConfigEntry StaminaRegenMultiplier { get; private set; } internal static ConfigEntry EnableInvoluntaryJump { get; private set; } internal static ConfigEntry JumpIntervalMin { get; private set; } internal static ConfigEntry JumpIntervalMax { get; private set; } internal static ConfigEntry JumpForce { get; private set; } internal static ConfigEntry EnableCameraWobble { get; private set; } internal static ConfigEntry CameraWobbleDegrees { get; private set; } internal static ConfigEntry CameraWobbleSpeed { get; private set; } internal static ConfigEntry EnableFakeUi { get; private set; } internal static ConfigEntry FakeUiIntervalMin { get; private set; } internal static ConfigEntry FakeUiIntervalMax { get; private set; } internal static ConfigEntry EnableBackpackLeakage { get; private set; } internal static ConfigEntry LeakIntervalMin { get; private set; } internal static ConfigEntry LeakIntervalMax { get; private set; } internal static ConfigEntry ShowCurseOnStaminaBar { get; private set; } internal static ConfigEntry EnableTripSneeze { get; private set; } internal static ConfigEntry TripSneezeIntervalMin { get; private set; } internal static ConfigEntry TripSneezeIntervalMax { get; private set; } internal static ConfigEntry TripSneezeForce { get; private set; } internal static ConfigEntry EnableInvertedControls { get; private set; } internal static ConfigEntry EnableGripHiccup { get; private set; } internal static ConfigEntry GripHiccupIntervalMin { get; private set; } internal static ConfigEntry GripHiccupIntervalMax { get; private set; } internal static ConfigEntry GripHiccupSlideStrength { get; private set; } internal CurseManager Curse { get; private set; } private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfig(); Curse = new CurseManager(); harmony = new Harmony("edwar.peak.passthecurse"); harmony.PatchAll(); Log.LogInfo((object)"Pass The Curse 0.1.4 loaded."); } private void Update() { Curse.Update(); } private void FixedUpdate() { Curse.FixedUpdate(); } private void OnGUI() { Curse.OnGUI(); } private void OnDestroy() { Harmony? obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private void BindConfig() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Expected O, but got Unknown //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Expected O, but got Unknown //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Expected O, but got Unknown //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Expected O, but got Unknown //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Expected O, but got Unknown //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Expected O, but got Unknown //IL_0464: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Expected O, but got Unknown //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Expected O, but got Unknown //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Expected O, but got Unknown //IL_055b: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Expected O, but got Unknown //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Expected O, but got Unknown //IL_05d5: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Expected O, but got Unknown //IL_0652: Unknown result type (might be due to invalid IL or missing references) //IL_065c: Expected O, but got Unknown //IL_068f: Unknown result type (might be due to invalid IL or missing references) //IL_0699: Expected O, but got Unknown //IL_06cc: Unknown result type (might be due to invalid IL or missing references) //IL_06d6: Expected O, but got Unknown ModEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enables cursed tag."); TouchDistance = ((BaseUnityPlugin)this).Config.Bind("General", "TouchDistance", 1.65f, new ConfigDescription("Distance between player hips that counts as touching.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 5f), Array.Empty())); TransferCooldown = ((BaseUnityPlugin)this).Config.Bind("General", "TransferCooldown", 4f, new ConfigDescription("Seconds before the curse can transfer again.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 30f), Array.Empty())); StartDelay = ((BaseUnityPlugin)this).Config.Bind("General", "StartDelay", 5f, new ConfigDescription("Seconds after characters appear before the host assigns the first curse.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 60f), Array.Empty())); ShowCurseOnStaminaBar = ((BaseUnityPlugin)this).Config.Bind("General", "ShowCurseOnStaminaBar", false, "When true, also adds PEAK's built-in Curse status so it appears on the stamina bar."); EnableRandomSlip = ((BaseUnityPlugin)this).Config.Bind("Effects.RandomSlip", "Enabled", true, "Makes the cursed player randomly slip while climbing."); SlipIntervalMin = ((BaseUnityPlugin)this).Config.Bind("Effects.RandomSlip", "IntervalMin", 8f, new ConfigDescription("Minimum seconds between random slips.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); SlipIntervalMax = ((BaseUnityPlugin)this).Config.Bind("Effects.RandomSlip", "IntervalMax", 18f, new ConfigDescription("Maximum seconds between random slips.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); SlipStrength = ((BaseUnityPlugin)this).Config.Bind("Effects.RandomSlip", "SlideStrength", 1.6f, new ConfigDescription("How hard the climbing slide impulse is.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); SlippyAmount = ((BaseUnityPlugin)this).Config.Bind("Effects.RandomSlip", "SlippyAmount", 0.8f, new ConfigDescription("Temporary PEAK slippy value to apply.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); EnableBadStaminaRegen = ((BaseUnityPlugin)this).Config.Bind("Effects.BadStaminaRegen", "Enabled", true, "Slows stamina regeneration for the cursed player."); StaminaRegenMultiplier = ((BaseUnityPlugin)this).Config.Bind("Effects.BadStaminaRegen", "Multiplier", 0.45f, new ConfigDescription("Positive stamina gains are multiplied by this while cursed.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); EnableInvoluntaryJump = ((BaseUnityPlugin)this).Config.Bind("Effects.InvoluntaryJump", "Enabled", true, "Occasionally launches the cursed player upward."); JumpIntervalMin = ((BaseUnityPlugin)this).Config.Bind("Effects.InvoluntaryJump", "IntervalMin", 12f, new ConfigDescription("Minimum seconds between involuntary jumps.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); JumpIntervalMax = ((BaseUnityPlugin)this).Config.Bind("Effects.InvoluntaryJump", "IntervalMax", 28f, new ConfigDescription("Maximum seconds between involuntary jumps.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); JumpForce = ((BaseUnityPlugin)this).Config.Bind("Effects.InvoluntaryJump", "Force", 420f, new ConfigDescription("Impulse force used for involuntary jumps.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1500f), Array.Empty())); EnableCameraWobble = ((BaseUnityPlugin)this).Config.Bind("Effects.CameraWobble", "Enabled", true, "Adds mild camera wobble while cursed."); CameraWobbleDegrees = ((BaseUnityPlugin)this).Config.Bind("Effects.CameraWobble", "Degrees", 1.8f, new ConfigDescription("Camera wobble strength in degrees.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); CameraWobbleSpeed = ((BaseUnityPlugin)this).Config.Bind("Effects.CameraWobble", "Speed", 2.5f, new ConfigDescription("Camera wobble speed.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 20f), Array.Empty())); EnableFakeUi = ((BaseUnityPlugin)this).Config.Bind("Effects.FakeUI", "Enabled", true, "Shows fake warning notifications to the cursed player."); FakeUiIntervalMin = ((BaseUnityPlugin)this).Config.Bind("Effects.FakeUI", "IntervalMin", 6f, new ConfigDescription("Minimum seconds between fake warnings.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 180f), Array.Empty())); FakeUiIntervalMax = ((BaseUnityPlugin)this).Config.Bind("Effects.FakeUI", "IntervalMax", 14f, new ConfigDescription("Maximum seconds between fake warnings.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 180f), Array.Empty())); EnableBackpackLeakage = ((BaseUnityPlugin)this).Config.Bind("Effects.BackpackLeakage", "Enabled", true, "Occasionally drops an item from the cursed player's inventory."); LeakIntervalMin = ((BaseUnityPlugin)this).Config.Bind("Effects.BackpackLeakage", "IntervalMin", 25f, new ConfigDescription("Minimum seconds between item leaks.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 240f), Array.Empty())); LeakIntervalMax = ((BaseUnityPlugin)this).Config.Bind("Effects.BackpackLeakage", "IntervalMax", 55f, new ConfigDescription("Maximum seconds between item leaks.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 240f), Array.Empty())); EnableTripSneeze = ((BaseUnityPlugin)this).Config.Bind("Effects.TripSneeze", "Enabled", true, "Occasionally makes the cursed player stumble with a sudden sneeze."); TripSneezeIntervalMin = ((BaseUnityPlugin)this).Config.Bind("Effects.TripSneeze", "IntervalMin", 7f, new ConfigDescription("Minimum seconds between trip sneezes.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); TripSneezeIntervalMax = ((BaseUnityPlugin)this).Config.Bind("Effects.TripSneeze", "IntervalMax", 16f, new ConfigDescription("Maximum seconds between trip sneezes.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); TripSneezeForce = ((BaseUnityPlugin)this).Config.Bind("Effects.TripSneeze", "Force", 280f, new ConfigDescription("Impulse force used for trip sneezes.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1200f), Array.Empty())); EnableInvertedControls = ((BaseUnityPlugin)this).Config.Bind("Effects.InvertedControls", "Enabled", true, "Inverts movement controls while this curse is active."); EnableGripHiccup = ((BaseUnityPlugin)this).Config.Bind("Effects.GripHiccup", "Enabled", true, "Occasionally interrupts the cursed player's climbing grip."); GripHiccupIntervalMin = ((BaseUnityPlugin)this).Config.Bind("Effects.GripHiccup", "IntervalMin", 8f, new ConfigDescription("Minimum seconds between grip hiccups.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); GripHiccupIntervalMax = ((BaseUnityPlugin)this).Config.Bind("Effects.GripHiccup", "IntervalMax", 18f, new ConfigDescription("Maximum seconds between grip hiccups.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 120f), Array.Empty())); GripHiccupSlideStrength = ((BaseUnityPlugin)this).Config.Bind("Effects.GripHiccup", "SlideStrength", 1.2f, new ConfigDescription("Downward slide impulse when grip hiccup triggers.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); } } }