using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Character_Stats; using HarmonyLib; using Microsoft.CodeAnalysis; 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: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("headclef")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.2.0")] [assembly: AssemblyInformationalVersion("1.1.2+2994e678935afde3216a3c7544df3f03a7755155")] [assembly: AssemblyProduct("Constitution")] [assembly: AssemblyTitle("Constitution")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.2.0")] [module: UnverifiableCode] [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 Constitution { [BepInPlugin("headclef.Constitution", "Constitution", "1.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Constitution : BaseUnityPlugin { private const string PluginGuid = "headclef.Constitution"; private const string PluginName = "Constitution"; private const string PluginVersion = "1.1.2"; internal static ConfigEntry EnableHealthRegen; internal static ConfigEntry RegenPerHealthLevel; internal static ConfigEntry MaxRegenPerSecond; internal static ConfigEntry RegenDelay; internal static Constitution Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { //IL_0043: 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_004a: Expected O, but got Unknown //IL_004f: Expected O, but got Unknown Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; BindConfiguration(); if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } private void OnDestroy() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void BindConfiguration() { //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 EnableHealthRegen = ((BaseUnityPlugin)this).Config.Bind("Health Regeneration", "Enable", true, "Enable passive health regeneration based on Health stat level."); RegenPerHealthLevel = ((BaseUnityPlugin)this).Config.Bind("Health Regeneration", "Regen Per Health Level", 0.05f, new ConfigDescription("Health regeneration per second for each Health upgrade level. Intentionally slow — designed for long-run sustain.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 1f), Array.Empty())); MaxRegenPerSecond = ((BaseUnityPlugin)this).Config.Bind("Health Regeneration", "Max Regen Per Second", 0f, new ConfigDescription("Maximum health regeneration per second. 0 = no cap.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 5f), Array.Empty())); RegenDelay = ((BaseUnityPlugin)this).Config.Bind("Health Regeneration", "Regen Delay", 10f, new ConfigDescription("Seconds after taking damage before health regeneration starts again.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 60f), Array.Empty())); } } } namespace Constitution.Patches { [HarmonyPatch] internal static class HealthRegenPatch { private static float _lastDamageTime; private static float _lastLogTime; private static int _lastKnownHealth = -1; private static float _hpAccumulator; [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeath")] [HarmonyPrefix] private static void PlayerDeath_Prefix() { _lastDamageTime = float.MaxValue; } [HarmonyPatch(typeof(PlayerAvatar), "Revive")] [HarmonyPostfix] private static void Revive_Postfix() { _lastDamageTime = Time.time; _lastKnownHealth = -1; } [HarmonyPatch(typeof(PlayerController), "Update")] [HarmonyPostfix] private static void PlayerController_Update_Postfix(PlayerController __instance) { if (!Constitution.EnableHealthRegen.Value || !Character_Stats.AreStatsReady) { return; } try { if ((Object)(object)__instance != (Object)(object)PlayerController.instance) { return; } string localSteamId = Character_Stats.GetLocalSteamId(); if (localSteamId == null) { return; } int upgradeLevel = Character_Stats.GetUpgradeLevel(localSteamId, "Health"); if (upgradeLevel <= 0) { return; } PlayerAvatar playerAvatarScript = __instance.playerAvatarScript; if ((Object)(object)playerAvatarScript == (Object)null || (Object)(object)playerAvatarScript.playerHealth == (Object)null) { return; } int health = playerAvatarScript.playerHealth.health; int maxHealth = playerAvatarScript.playerHealth.maxHealth; if (_lastKnownHealth >= 0 && health < _lastKnownHealth) { _lastDamageTime = Time.time; } _lastKnownHealth = health; if (health <= 0 || health >= maxHealth) { return; } float value = Constitution.RegenDelay.Value; if (Time.time - _lastDamageTime < value) { return; } float num = Constitution.RegenPerHealthLevel.Value * (float)upgradeLevel; float value2 = Constitution.MaxRegenPerSecond.Value; if (value2 > 0f) { num = Math.Min(num, value2); } if (!(num <= 0f)) { float num2 = num * Time.deltaTime; _hpAccumulator += num2; if (_hpAccumulator >= 1f) { int num3 = (int)_hpAccumulator; _hpAccumulator -= num3; int num4 = Math.Min(health + num3, maxHealth); playerAvatarScript.playerHealth.health = num4; Constitution.Logger.LogDebug((object)$"Health regen: +{num3} HP ({health} -> {num4}/{maxHealth})"); } if (Time.time - _lastLogTime > 30f) { _lastLogTime = Time.time; Constitution.Logger.LogDebug((object)$"Health regen active: {num:F2}/sec (Health level: {upgradeLevel})"); } } } catch (Exception ex) { Constitution.Logger.LogError((object)("HealthRegen exception: " + ex.Message)); } } } }