using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Coroner;
using GameNetcodeStuff;
using HarmonyLib;
using HeartAttack.Patches;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("HeartAttack")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HeartAttack")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f58e7f15-ddcf-41ab-a659-59dc598c291f")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[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 HeartAttack
{
[BepInPlugin("Turkeysteaks.HeartAttackMod", "Real Heart Attack", "1.2.3")]
public class Plugin : BaseUnityPlugin
{
private const string modGUID = "Turkeysteaks.HeartAttackMod";
private const string modName = "Real Heart Attack";
private const string modVersion = "1.2.3";
private readonly Harmony harmony = new Harmony("Turkeysteaks.HeartAttackMod");
private static Plugin Instance;
internal static ManualLogSource Logger;
internal static HeartAttackConfig BoundConfig { get; private set; }
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
BoundConfig = new HeartAttackConfig(((BaseUnityPlugin)this).Config);
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"OH MY LORD!");
harmony.PatchAll(typeof(Plugin));
harmony.PatchAll(typeof(PlayerControllerBPatch));
if (CoronerCompatibility.enabled)
{
CoronerCompatibility.CoronerRegister();
}
}
}
}
namespace HeartAttack.Patches
{
public class CoronerCompatibility
{
private static bool? _enabled;
private static string HEART_ATTACK_LANGUAGE_KEY = "DeathHeartAttack";
private static AdvancedCauseOfDeath HEART_ATTACK;
public static bool enabled
{
get
{
if (!_enabled.HasValue)
{
_enabled = Chainloader.PluginInfos.ContainsKey("com.elitemastereric.coroner");
}
return _enabled.Value;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void CoronerRegister()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
if (!API.IsRegistered(HEART_ATTACK_LANGUAGE_KEY))
{
HEART_ATTACK = API.Register(HEART_ATTACK_LANGUAGE_KEY);
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static void CoronerSetCauseOfDeathHeartAttack(PlayerControllerB player)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
API.SetCauseOfDeath(player, (AdvancedCauseOfDeath?)HEART_ATTACK);
}
}
public class HeartAttackConfig
{
public readonly ConfigEntry<float> heartAttackChance;
public readonly ConfigEntry<float> trembleChance;
public readonly ConfigEntry<float> adrenalineChance;
public readonly ConfigEntry<float> minFearToTrigger;
public readonly ConfigEntry<float> maxFearToReset;
public readonly ConfigEntry<bool> heartAttackWhenAlone;
public readonly ConfigEntry<bool> trembleAfterAdrenaline;
public readonly ConfigEntry<bool> trembleInstant;
public readonly ConfigEntry<float> playerTrembleMoveSpeed;
public readonly ConfigEntry<float> playerTrembleClimbSpeed;
public readonly ConfigEntry<float> playerTrembleTime;
public readonly ConfigEntry<bool> trembleDrainsStamina;
public readonly ConfigEntry<bool> adrenalineInstant;
public readonly ConfigEntry<float> adrenalineMoveSpeed;
public readonly ConfigEntry<float> adrenalineClimbSpeed;
public readonly ConfigEntry<float> adrenalineTime;
public readonly ConfigEntry<float> adrenalineFOV;
public readonly ConfigEntry<float> adrenalineDrunkness;
public HeartAttackConfig(ConfigFile cfg)
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Expected O, but got Unknown
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Expected O, but got Unknown
cfg.SaveOnConfigSet = false;
heartAttackChance = cfg.Bind<float>("General", "HeartAttackChance", 5f, new ConfigDescription("Percentage chance to have a heart attack on fear. Set to 0 for no chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
trembleChance = cfg.Bind<float>("General", "TrembleChance", 13f, new ConfigDescription("Percentage chance to tremble on fear. Set to 0 for no chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
adrenalineChance = cfg.Bind<float>("General", "AdrenalineChance", 15f, new ConfigDescription("Percentage chance to gain an adrenaline rush on fear. Set to 0 for no chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
minFearToTrigger = cfg.Bind<float>("General", "FearToTrigger", 0.5f, "Minimum fear required to trigger any of the effects. Value should be between 0 and 1, and must be higher than FearToReset.");
maxFearToReset = cfg.Bind<float>("General", "FearToReset", 0.25f, "Maximum fear required to reset the chance to have an effect. Once fear is below this number, getting scared again can trigger another effect. Value should be between 0 and 1, and must be lower than FearToTrigger.");
heartAttackWhenAlone = cfg.Bind<bool>("General", "HeartAttackWhenAlone", false, "Whether it's possible to have a heart attack when on your own. Note that in singleplayer, this value is ignored and you can always have a heart attack.");
trembleAfterAdrenaline = cfg.Bind<bool>("Adrenaline", "TrembleAfterAdrenaline", false, "Whether to always force a tremble (slowdown) after an adrenaline rush.");
trembleInstant = cfg.Bind<bool>("Tremble", "TrembleIsInstant", true, "Whether tremble's effects happen instantly or are gradually started and ended.");
trembleDrainsStamina = cfg.Bind<bool>("Tremble", "TrembleDrainsStamina", true, "Whether tremble drains stamina.");
playerTrembleMoveSpeed = cfg.Bind<float>("Tremble", "TrembleMoveSpeed", 0.5f, "Speed the player walks while trembling.");
playerTrembleClimbSpeed = cfg.Bind<float>("Tremble", "TrembleClimbSpeed", 2f, "Speed the player climbs while trembling");
playerTrembleTime = cfg.Bind<float>("Tremble", "TrembleTime", 2.5f, "Time (in seconds) the player trembles for.");
adrenalineInstant = cfg.Bind<bool>("Adrenaline", "AdrenalineIsInstant", false, "Whether adrenaline's effects happen instantly or are gradually started and ended.");
adrenalineMoveSpeed = cfg.Bind<float>("Adrenaline", "AdrenalineMoveSpeed", 7f, "Speed the player walks with adrenaline.");
adrenalineClimbSpeed = cfg.Bind<float>("Adrenaline", "AdrenalineClimbSpeed", 4f, "Speed the player climbs with adrenaline.");
adrenalineTime = cfg.Bind<float>("Adrenaline", "AdrenalineTime", 3f, "Time (in seconds) the player is affected by the adrenaline rush.");
adrenalineFOV = cfg.Bind<float>("Adrenaline", "AdrenalineFOV", 72f, "(Currently not used) Field of View to use while affected by the adrenaline rush.");
adrenalineDrunkness = cfg.Bind<float>("Adrenaline", "AdrenalineExtraDrunkness", 0.6f, "How much 'drunkness' to add to the player when hit with adrenaline.");
ClearOrphanedEntries(cfg);
cfg.Save();
cfg.SaveOnConfigSet = true;
}
private static void ClearOrphanedEntries(ConfigFile cfg)
{
PropertyInfo propertyInfo = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries");
Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)propertyInfo.GetValue(cfg);
dictionary.Clear();
}
}
[HarmonyPatch(typeof(PlayerControllerB))]
internal class PlayerControllerBPatch
{
private static bool hasHeartAttackOccurred = false;
private static bool hasFearAttackOccurred = false;
private static bool hasAdrenalineOccurred = false;
private static bool trembling = false;
private static bool adrenaline = false;
private static float minFearToTrigger = 0.5f;
private static float maxFearToReset = 0.25f;
private static bool heartAttackWhenAlone = false;
private static float heartAttackChance = 10f;
private static float trembleChance = 13f;
private static bool trembleInstant = true;
private static float trembleMoveSpeed = 0.35f;
private static float trembleClimbSpeed = 2f;
private static float trembleTime = 2.5f;
private static bool trembleDrainsStamina = true;
private static float adrenalineChance = 10f;
private static bool adrenalineInstant = false;
private static float adrenalineMoveSpeed = 1.5f;
private static float adrenalineClimbSpeed = 4f;
private static float adrenalineTime = 2.5f;
private static float adrenalineFOV = 72f;
private static float adrenalineDrunkness = 5f;
private static bool trembleAfterAdrenaline = false;
private static bool hasSetVals = false;
[HarmonyPatch("Update")]
[HarmonyPostfix]
private static void HeartAttack(PlayerControllerB __instance)
{
if (!((Object)(object)__instance == (Object)(object)GameNetworkManager.Instance.localPlayerController))
{
return;
}
if (!hasSetVals)
{
heartAttackChance = Plugin.BoundConfig.heartAttackChance.Value;
trembleChance = Plugin.BoundConfig.trembleChance.Value;
adrenalineChance = Plugin.BoundConfig.adrenalineChance.Value;
minFearToTrigger = Plugin.BoundConfig.minFearToTrigger.Value;
maxFearToReset = Plugin.BoundConfig.maxFearToReset.Value;
heartAttackWhenAlone = Plugin.BoundConfig.heartAttackWhenAlone.Value;
trembleInstant = Plugin.BoundConfig.trembleInstant.Value;
trembleMoveSpeed = Plugin.BoundConfig.playerTrembleMoveSpeed.Value;
trembleClimbSpeed = Plugin.BoundConfig.playerTrembleClimbSpeed.Value;
trembleTime = Plugin.BoundConfig.playerTrembleTime.Value;
trembleDrainsStamina = Plugin.BoundConfig.trembleDrainsStamina.Value;
adrenalineInstant = Plugin.BoundConfig.adrenalineInstant.Value;
adrenalineMoveSpeed = Plugin.BoundConfig.adrenalineMoveSpeed.Value;
adrenalineClimbSpeed = Plugin.BoundConfig.adrenalineClimbSpeed.Value;
adrenalineTime = Plugin.BoundConfig.adrenalineTime.Value;
adrenalineFOV = Plugin.BoundConfig.adrenalineFOV.Value;
adrenalineDrunkness = Plugin.BoundConfig.adrenalineDrunkness.Value;
trembleAfterAdrenaline = Plugin.BoundConfig.trembleAfterAdrenaline.Value;
hasSetVals = true;
}
int num = StartOfRound.Instance.allPlayerScripts.Count((PlayerControllerB x) => x.isPlayerControlled);
if (StartOfRound.Instance.fearLevel >= minFearToTrigger)
{
if (!hasHeartAttackOccurred && (num <= 1 || !__instance.isPlayerAlone || heartAttackWhenAlone))
{
TriggerHeartAttack(__instance);
}
else if (!hasFearAttackOccurred)
{
TriggerTremblingFear(__instance);
}
else if (!hasAdrenalineOccurred)
{
TriggerAdrenaline(__instance);
}
}
else if (StartOfRound.Instance.fearLevel < maxFearToReset)
{
hasHeartAttackOccurred = false;
hasFearAttackOccurred = false;
hasAdrenalineOccurred = false;
}
}
private static void TriggerHeartAttack(PlayerControllerB player)
{
//IL_003f: 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)
float num = Random.Range(0f, 100f);
float num2 = heartAttackChance;
Plugin.Logger.LogDebug((object)$"Heart Attack Trigger Value: {num}");
if (num <= num2)
{
player.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, Vector3.zero);
if (CoronerCompatibility.enabled)
{
CoronerCompatibility.CoronerRegister();
CoronerCompatibility.CoronerSetCauseOfDeathHeartAttack(player);
}
Plugin.Logger.LogDebug((object)"HEART ATTACK");
}
hasHeartAttackOccurred = true;
}
private static void TriggerTremblingFear(PlayerControllerB player, bool force = false)
{
float num = Random.Range(0f, 100f);
float num2 = trembleChance;
Plugin.Logger.LogDebug((object)$"Tremble Trigger Value: {num}");
if ((!trembling && !adrenaline && num <= num2) || force)
{
Plugin.Logger.LogDebug((object)"FEAR!");
((MonoBehaviour)player).StartCoroutine(ApplyTheFear(player));
}
hasFearAttackOccurred = true;
}
private static void TriggerAdrenaline(PlayerControllerB player)
{
float num = Random.Range(0f, 100f);
float num2 = adrenalineChance;
Plugin.Logger.LogDebug((object)$"Adrenaline Trigger Value: {num}");
if (!adrenaline && !trembling && num <= num2)
{
Plugin.Logger.LogDebug((object)"ADRENALINE!");
((MonoBehaviour)player).StartCoroutine(ApplyTheAdrenaline(player));
}
hasAdrenalineOccurred = true;
}
private static IEnumerator ApplyTheFear(PlayerControllerB player)
{
trembling = true;
float originalMovementSpeed = player.movementSpeed;
float originalClimbSpeed = player.climbSpeed;
HUDManager.Instance.ShakeCamera((ScreenShakeType)1);
if (trembleInstant)
{
player.movementSpeed = trembleMoveSpeed;
player.climbSpeed = trembleClimbSpeed;
if (trembleDrainsStamina)
{
player.sprintMeter = 0f;
}
yield return (object)new WaitForSeconds(trembleTime);
}
else
{
float trembleTimeInc = trembleTime / 20f;
float trembleSprintDrainMod = 0.5f;
for (int j = 0; j < 15; j++)
{
player.movementSpeed = Mathf.Lerp(originalMovementSpeed, trembleMoveSpeed, (float)j / 15f);
player.climbSpeed = Mathf.Lerp(originalClimbSpeed, trembleClimbSpeed, (float)j / 15f);
yield return (object)new WaitForSeconds(trembleTimeInc);
if (trembleDrainsStamina)
{
player.sprintMeter -= trembleTimeInc * trembleSprintDrainMod;
}
}
for (int i = 0; i < 5; i++)
{
player.movementSpeed = Mathf.Lerp(trembleMoveSpeed, originalMovementSpeed, (float)i / 5f);
player.climbSpeed = Mathf.Lerp(trembleClimbSpeed, originalClimbSpeed, (float)i / 5f);
yield return (object)new WaitForSeconds(trembleTimeInc);
if (trembleDrainsStamina)
{
player.sprintMeter -= trembleTimeInc * trembleSprintDrainMod * 0.5f;
}
}
}
player.movementSpeed = originalMovementSpeed;
player.climbSpeed = originalClimbSpeed;
trembling = false;
}
private static IEnumerator ApplyTheAdrenaline(PlayerControllerB player)
{
adrenaline = true;
float originalMovementSpeed = player.movementSpeed;
float originalClimbSpeed = player.climbSpeed;
float originalFOV = player.targetFOV;
float originalDrunkness = player.drunkness;
if (adrenalineInstant)
{
player.movementSpeed = adrenalineMoveSpeed;
player.climbSpeed = adrenalineClimbSpeed;
player.drunkness = adrenalineDrunkness;
yield return (object)new WaitForSeconds(adrenalineTime);
}
else
{
float adrenalineTimeInc = adrenalineTime / 20f;
for (int j = 0; j < 15; j++)
{
player.movementSpeed = Mathf.Lerp(originalMovementSpeed, adrenalineMoveSpeed, (float)j / 15f);
player.climbSpeed = Mathf.Lerp(originalClimbSpeed, adrenalineClimbSpeed, (float)j / 15f);
player.drunkness = Mathf.Lerp(originalDrunkness, adrenalineDrunkness, (float)j / 15f);
yield return (object)new WaitForSeconds(adrenalineTimeInc);
}
for (int i = 0; i < 5; i++)
{
player.movementSpeed = Mathf.Lerp(adrenalineMoveSpeed, originalMovementSpeed, (float)i / 5f);
player.climbSpeed = Mathf.Lerp(adrenalineClimbSpeed, originalClimbSpeed, (float)i / 5f);
player.drunkness = Mathf.Lerp(adrenalineDrunkness, originalDrunkness, (float)i / 5f);
yield return (object)new WaitForSeconds(adrenalineTimeInc);
}
}
player.movementSpeed = originalMovementSpeed;
player.climbSpeed = originalClimbSpeed;
player.targetFOV = originalFOV;
player.drunkness = originalDrunkness;
if (trembleAfterAdrenaline)
{
TriggerTremblingFear(player, force: true);
}
adrenaline = false;
}
}
}