Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RealHeartAttack v1.2.4
HeartAttack.dll
Decompiled 3 months agousing 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.4")] public class Plugin : BaseUnityPlugin { private const string modGUID = "Turkeysteaks.HeartAttackMod"; private const string modName = "Real Heart Attack"; private const string modVersion = "1.2.4"; 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; } } }