Please disclose if any significant portion of your mod was created 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 Carturs Safe Stamina v1.0.14
plugins/CarturSafeStamina.dll
Decompiled 2 weeks agousing 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 HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("CarturSafeStamina")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.6.0")] [assembly: AssemblyInformationalVersion("1.0.6+3a70b3f439fa23adb6989e56d68a305369dfd079")] [assembly: AssemblyProduct("CarturSafeStamina")] [assembly: AssemblyTitle("CarturSafeStamina")] [assembly: AssemblyVersion("1.0.6.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 CarturSafeStamina { [BepInPlugin("com.jekkle.valheim.cartursafestamina", "Cartur's Safe Stamina", "1.0.13")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.jekkle.valheim.cartursafestamina"; public const string PluginName = "Cartur's Safe Stamina"; public const string PluginVersion = "1.0.13"; public static ConfigEntry<float> SafeRadius; public static ConfigEntry<bool> AffectSprint; public static ConfigEntry<bool> AffectJump; public static ConfigEntry<bool> AffectBuild; public static ConfigEntry<bool> AffectSwim; public static ConfigEntry<bool> AffectAttacks; public static ConfigEntry<bool> AffectSneak; public static ConfigEntry<bool> AffectEncumbered; public static ConfigEntry<string> IgnoredCreatures; private static float _lastCheckTime = -999f; private static bool _lastResult = true; private const float CheckInterval = 0.25f; private static string _ignoredRaw; private static readonly HashSet<string> Ignored = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private void Awake() { SafeRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SafeRadius", 25f, "No stamina cost for sprint/jump/build/swim/attacks/sneak when no enemy is within this many meters."); AffectSprint = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectSprint", true, "Free sprint stamina when safe."); AffectJump = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectJump", true, "Free jump stamina when safe."); AffectBuild = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectBuild", true, "Free build/repair/remove stamina when safe. Covers every build tool, so planting with the cultivator and levelling with the hoe are free too."); AffectSwim = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectSwim", true, "Free swim stamina when safe. Note this also removes the drowning risk while safe, since drowning only starts once stamina is empty."); AffectAttacks = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectAttacks", true, "Free attack stamina when safe - chopping wood, mining, and weapon swings all pay through the same cost."); AffectSneak = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectSneak", true, "Free sneak/crouch stamina when safe."); AffectEncumbered = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectEncumbered", false, "Over the weight limit and safe: walking costs no stamina and stamina refills. Off by default, so being over-loaded costs you as in vanilla."); IgnoredCreatures = ((BaseUnityPlugin)this).Config.Bind<string>("General", "IgnoredCreatures", "", "Comma-separated creatures that never count as an enemy nearby, by prefab name or by the name shown in game (e.g. T.W.I.G). For modded creatures that are hostile by faction but never fight."); Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "com.jekkle.valheim.cartursafestamina"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Cartur's Safe Stamina 1.0.13 loaded."); } public static bool IsLocalAndSafe(Character c) { Player val = (Player)(object)((c is Player) ? c : null); if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer) { return IsSafe(val); } return false; } public static bool IsSafe(Player player) { //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) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return true; } if (Time.time - _lastCheckTime < 0.25f) { return _lastResult; } _lastCheckTime = Time.time; _lastResult = true; float value = SafeRadius.Value; float num = value * value; Vector3 position = ((Component)player).transform.position; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)player) && !allCharacter.IsDead() && BaseAI.IsEnemy((Character)(object)player, allCharacter)) { Vector3 val = ((Component)allCharacter).transform.position - position; if (((Vector3)(ref val)).sqrMagnitude <= num && !IsIgnored(allCharacter)) { _lastResult = false; break; } } } return _lastResult; } private static bool IsIgnored(Character c) { string text = IgnoredCreatures.Value ?? ""; if (text != _ignoredRaw) { _ignoredRaw = text; Ignored.Clear(); string[] array = text.Split(new char[1] { ',' }); foreach (string text2 in array) { if (text2.Trim().Length > 0) { Ignored.Add(text2.Trim()); } } } if (Ignored.Count == 0) { return false; } if (!Ignored.Contains(Utils.GetPrefabName(((Component)c).gameObject))) { if (Localization.instance != null) { return Ignored.Contains(Localization.instance.Localize(c.m_name)); } return false; } return true; } } [HarmonyPatch(typeof(SEMan), "ModifyRunStaminaDrain")] public static class Patch_RunStaminaDrain { private static void Postfix(ref float drain, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectSprint.Value && Plugin.IsLocalAndSafe(___m_character)) { drain = 0f; } } } [HarmonyPatch(typeof(SEMan), "ModifyJumpStaminaUsage")] public static class Patch_JumpStamina { private static void Postfix(ref float staminaUse, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectJump.Value && Plugin.IsLocalAndSafe(___m_character)) { staminaUse = 0f; } } } [HarmonyPatch(typeof(Player), "GetBuildStamina")] public static class Patch_GetBuildStamina { private static void Postfix(Player __instance, ref float __result) { if (Plugin.AffectBuild.Value && Plugin.IsSafe(__instance)) { __result = 0f; } } } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] public static class Patch_GetAttackStamina { private static void Postfix(ref float __result, Humanoid ___m_character) { if (Plugin.AffectAttacks.Value && !(__result <= 0f)) { Player val = (Player)(object)((___m_character is Player) ? ___m_character : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && Plugin.IsSafe(val)) { __result = 0f; } } } } [HarmonyPatch(typeof(SEMan), "ModifySwimStaminaUsage")] public static class Patch_SwimStamina { private static void Postfix(ref float staminaUse, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectSwim.Value && Plugin.IsLocalAndSafe(___m_character)) { staminaUse = 0f; } } } [HarmonyPatch(typeof(SEMan), "ModifySneakStaminaUsage")] public static class Patch_SneakStamina { private static void Postfix(ref float staminaUse, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectSneak.Value && Plugin.IsLocalAndSafe(___m_character)) { staminaUse = 0f; } } } [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] public static class Patch_UpdateStats { private static void Postfix(Player __instance, float dt, ref float ___m_stamina, float ___m_staminaRegenTimer) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !(___m_staminaRegenTimer > 0f) && BlockedAndAllowed(__instance) && Plugin.IsSafe(__instance)) { float maxStamina = ((Character)__instance).GetMaxStamina(); if (!(___m_stamina >= maxStamina)) { float num = __instance.m_staminaRegen + (1f - ___m_stamina / maxStamina) * __instance.m_staminaRegen * __instance.m_staminaRegenTimeMultiplier; float num2 = 1f; ((Character)__instance).GetSEMan().ModifyStaminaRegen(ref num2); ___m_stamina = Mathf.Min(maxStamina, ___m_stamina + num * num2 * dt * Game.m_staminaRegenRate); } } } private static bool BlockedAndAllowed(Player p) { if (((Character)p).IsEncumbered()) { return Plugin.AffectEncumbered.Value; } if (((Character)p).IsSwimming() && !((Character)p).IsOnGround()) { return Plugin.AffectSwim.Value; } if (((Character)p).InAttack() || ((Character)p).InDodge()) { return Plugin.AffectAttacks.Value; } return ((Character)p).IsWallRunning(); } } [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] public static class Patch_EncumberedBracket { internal static bool Skip; private static void Prefix(Player __instance) { Skip = Plugin.AffectEncumbered.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && ((Character)__instance).IsEncumbered() && Plugin.IsSafe(__instance); } private static void Finalizer() { Skip = false; } } [HarmonyPatch(typeof(Player), "UseStamina")] public static class Patch_EncumberedDrain { private static bool Prefix() { return !Patch_EncumberedBracket.Skip; } } }