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, object>)(object)customProperties).ContainsKey((object)"PassTheCurse.CursedActor") && customProperties[(object)"PassTheCurse.CursedActor"] is int num)
{
cachedCursedActor = num;
}
if (((Dictionary<object, object>)(object)customProperties).ContainsKey((object)"PassTheCurse.CurseEffect") && customProperties[(object)"PassTheCurse.CurseEffect"] is int num2 && Enum.IsDefined(typeof(CurseEffect), num2))
{
cachedCurseEffect = (CurseEffect)num2;
}
if (((Dictionary<object, object>)(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<Character> 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<ItemSlot> list = new List<ItemSlot>();
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<CurseEffect> list = new List<CurseEffect>();
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<Character> GetValidCharacters()
{
List<Character> list = new List<Character>();
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<Character> 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<UI_Notifications>();
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<bool> ModEnabled { get; private set; }
internal static ConfigEntry<float> TouchDistance { get; private set; }
internal static ConfigEntry<float> TransferCooldown { get; private set; }
internal static ConfigEntry<float> StartDelay { get; private set; }
internal static ConfigEntry<bool> EnableRandomSlip { get; private set; }
internal static ConfigEntry<float> SlipIntervalMin { get; private set; }
internal static ConfigEntry<float> SlipIntervalMax { get; private set; }
internal static ConfigEntry<float> SlipStrength { get; private set; }
internal static ConfigEntry<float> SlippyAmount { get; private set; }
internal static ConfigEntry<bool> EnableBadStaminaRegen { get; private set; }
internal static ConfigEntry<float> StaminaRegenMultiplier { get; private set; }
internal static ConfigEntry<bool> EnableInvoluntaryJump { get; private set; }
internal static ConfigEntry<float> JumpIntervalMin { get; private set; }
internal static ConfigEntry<float> JumpIntervalMax { get; private set; }
internal static ConfigEntry<float> JumpForce { get; private set; }
internal static ConfigEntry<bool> EnableCameraWobble { get; private set; }
internal static ConfigEntry<float> CameraWobbleDegrees { get; private set; }
internal static ConfigEntry<float> CameraWobbleSpeed { get; private set; }
internal static ConfigEntry<bool> EnableFakeUi { get; private set; }
internal static ConfigEntry<float> FakeUiIntervalMin { get; private set; }
internal static ConfigEntry<float> FakeUiIntervalMax { get; private set; }
internal static ConfigEntry<bool> EnableBackpackLeakage { get; private set; }
internal static ConfigEntry<float> LeakIntervalMin { get; private set; }
internal static ConfigEntry<float> LeakIntervalMax { get; private set; }
internal static ConfigEntry<bool> ShowCurseOnStaminaBar { get; private set; }
internal static ConfigEntry<bool> EnableTripSneeze { get; private set; }
internal static ConfigEntry<float> TripSneezeIntervalMin { get; private set; }
internal static ConfigEntry<float> TripSneezeIntervalMax { get; private set; }
internal static ConfigEntry<float> TripSneezeForce { get; private set; }
internal static ConfigEntry<bool> EnableInvertedControls { get; private set; }
internal static ConfigEntry<bool> EnableGripHiccup { get; private set; }
internal static ConfigEntry<float> GripHiccupIntervalMin { get; private set; }
internal static ConfigEntry<float> GripHiccupIntervalMax { get; private set; }
internal static ConfigEntry<float> 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<bool>("General", "Enabled", true, "Enables cursed tag.");
TouchDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TouchDistance", 1.65f, new ConfigDescription("Distance between player hips that counts as touching.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
TransferCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TransferCooldown", 4f, new ConfigDescription("Seconds before the curse can transfer again.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 30f), Array.Empty<object>()));
StartDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "StartDelay", 5f, new ConfigDescription("Seconds after characters appear before the host assigns the first curse.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
ShowCurseOnStaminaBar = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("Effects.RandomSlip", "Enabled", true, "Makes the cursed player randomly slip while climbing.");
SlipIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.RandomSlip", "IntervalMin", 8f, new ConfigDescription("Minimum seconds between random slips.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
SlipIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.RandomSlip", "IntervalMax", 18f, new ConfigDescription("Maximum seconds between random slips.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
SlipStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.RandomSlip", "SlideStrength", 1.6f, new ConfigDescription("How hard the climbing slide impulse is.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
SlippyAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.RandomSlip", "SlippyAmount", 0.8f, new ConfigDescription("Temporary PEAK slippy value to apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
EnableBadStaminaRegen = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.BadStaminaRegen", "Enabled", true, "Slows stamina regeneration for the cursed player.");
StaminaRegenMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.BadStaminaRegen", "Multiplier", 0.45f, new ConfigDescription("Positive stamina gains are multiplied by this while cursed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
EnableInvoluntaryJump = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.InvoluntaryJump", "Enabled", true, "Occasionally launches the cursed player upward.");
JumpIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.InvoluntaryJump", "IntervalMin", 12f, new ConfigDescription("Minimum seconds between involuntary jumps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
JumpIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.InvoluntaryJump", "IntervalMax", 28f, new ConfigDescription("Maximum seconds between involuntary jumps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
JumpForce = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.InvoluntaryJump", "Force", 420f, new ConfigDescription("Impulse force used for involuntary jumps.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1500f), Array.Empty<object>()));
EnableCameraWobble = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.CameraWobble", "Enabled", true, "Adds mild camera wobble while cursed.");
CameraWobbleDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.CameraWobble", "Degrees", 1.8f, new ConfigDescription("Camera wobble strength in degrees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
CameraWobbleSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.CameraWobble", "Speed", 2.5f, new ConfigDescription("Camera wobble speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
EnableFakeUi = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.FakeUI", "Enabled", true, "Shows fake warning notifications to the cursed player.");
FakeUiIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.FakeUI", "IntervalMin", 6f, new ConfigDescription("Minimum seconds between fake warnings.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 180f), Array.Empty<object>()));
FakeUiIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.FakeUI", "IntervalMax", 14f, new ConfigDescription("Maximum seconds between fake warnings.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 180f), Array.Empty<object>()));
EnableBackpackLeakage = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.BackpackLeakage", "Enabled", true, "Occasionally drops an item from the cursed player's inventory.");
LeakIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.BackpackLeakage", "IntervalMin", 25f, new ConfigDescription("Minimum seconds between item leaks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 240f), Array.Empty<object>()));
LeakIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.BackpackLeakage", "IntervalMax", 55f, new ConfigDescription("Maximum seconds between item leaks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 240f), Array.Empty<object>()));
EnableTripSneeze = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.TripSneeze", "Enabled", true, "Occasionally makes the cursed player stumble with a sudden sneeze.");
TripSneezeIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.TripSneeze", "IntervalMin", 7f, new ConfigDescription("Minimum seconds between trip sneezes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
TripSneezeIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.TripSneeze", "IntervalMax", 16f, new ConfigDescription("Maximum seconds between trip sneezes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
TripSneezeForce = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.TripSneeze", "Force", 280f, new ConfigDescription("Impulse force used for trip sneezes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1200f), Array.Empty<object>()));
EnableInvertedControls = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.InvertedControls", "Enabled", true, "Inverts movement controls while this curse is active.");
EnableGripHiccup = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects.GripHiccup", "Enabled", true, "Occasionally interrupts the cursed player's climbing grip.");
GripHiccupIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.GripHiccup", "IntervalMin", 8f, new ConfigDescription("Minimum seconds between grip hiccups.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
GripHiccupIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.GripHiccup", "IntervalMax", 18f, new ConfigDescription("Maximum seconds between grip hiccups.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
GripHiccupSlideStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Effects.GripHiccup", "SlideStrength", 1.2f, new ConfigDescription("Downward slide impulse when grip hiccup triggers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
}
}
}