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 Odins Free Refills v1.0.8
plugins/OdinsFreeRefills.dll
Decompiled 19 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; 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("OdinsFreeRefills")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.8.0")] [assembly: AssemblyInformationalVersion("1.0.8+f8984ab2d6529ccc7311f8189e16fe631100b357")] [assembly: AssemblyProduct("OdinsFreeRefills")] [assembly: AssemblyTitle("OdinsFreeRefills")] [assembly: AssemblyVersion("1.0.8.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 OdinsFreeRefills { [BepInPlugin("hevyh2o.valheim.odinsfreerefills", "Odin's Free Refills", "1.0.8")] public class Plugin : BaseUnityPlugin { public const string Guid = "hevyh2o.valheim.odinsfreerefills"; public const string Name = "Odin's Free Refills"; public const string Version = "1.0.8"; private const string LegacyConfigName = "com.jekkle.valheim.cartursafestamina.cfg"; internal static ConfigEntry<float> SafeRadius; internal static ConfigEntry<bool> AffectSprint; internal static ConfigEntry<bool> AffectJump; internal static ConfigEntry<bool> AffectBuild; internal static ConfigEntry<bool> AffectSwim; internal static ConfigEntry<bool> AffectAttacks; internal static ConfigEntry<bool> AffectSneak; internal static ConfigEntry<string> IgnoredCreatures; private Harmony _harmony; private void Awake() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown bool num = !File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath); SafeRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SafeRadius", 25f, new ConfigDescription("How close (in metres) a hostile creature must be before Odin closes the tab and stamina costs return.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>())); AffectSprint = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectSprint", true, "Odin covers running. Also keeps the bar topping up while you wall-run."); AffectJump = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectJump", true, "Odin covers jumping."); AffectBuild = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectBuild", true, "Odin covers hammer work: placing, repairing and removing pieces."); AffectSwim = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectSwim", true, "Odin covers swimming, and the bar refills while you're in the water. Heads-up: with an empty bar never reached, you also can't drown when no threat is near."); AffectAttacks = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectAttacks", true, "Odin covers tool and weapon swings (woodcutting and mining included), and the bar refills mid-swing and mid-dodge."); AffectSneak = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AffectSneak", true, "Odin covers crouch-walking."); IgnoredCreatures = ((BaseUnityPlugin)this).Config.Bind<string>("General", "IgnoredCreatures", "", "Creatures that should never close the tab, separated by commas. Use the prefab name or the name shown in game. Handy for modded critters flagged hostile that never actually attack."); if (num) { ImportLegacyConfig(); } _harmony = new Harmony("hevyh2o.valheim.odinsfreerefills"); _harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Odin's Free Refills 1.0.8 loaded. The mead is on Odin."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void ImportLegacyConfig() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007e: Expected O, but got Unknown string text = Path.Combine(Paths.ConfigPath, "com.jekkle.valheim.cartursafestamina.cfg"); if (File.Exists(text)) { ConfigFile val = new ConfigFile(text, false) { SaveOnConfigSet = false }; CopyFrom<float>(val, SafeRadius); CopyFrom<bool>(val, AffectSprint); CopyFrom<bool>(val, AffectJump); CopyFrom<bool>(val, AffectBuild); CopyFrom<bool>(val, AffectSwim); CopyFrom<bool>(val, AffectAttacks); CopyFrom<bool>(val, AffectSneak); CopyFrom<string>(val, IgnoredCreatures); ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Imported settings from Cartur's Safe Stamina."); } } private static void CopyFrom<T>(ConfigFile legacy, ConfigEntry<T> target) { ConfigDefinition definition = ((ConfigEntryBase)target).Definition; target.Value = legacy.Bind<T>(definition.Section, definition.Key, (T)((ConfigEntryBase)target).DefaultValue, (ConfigDescription)null).Value; } } [HarmonyPatch(typeof(SEMan), "ModifyRunStaminaDrain")] internal static class RunDrainPatch { private static void Postfix(ref float drain, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectSprint.Value && ThreatRadar.LocalPlayerSafe(___m_character)) { drain = 0f; } } } [HarmonyPatch(typeof(SEMan), "ModifyJumpStaminaUsage")] internal static class JumpCostPatch { private static void Postfix(ref float staminaUse, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectJump.Value && ThreatRadar.LocalPlayerSafe(___m_character)) { staminaUse = 0f; } } } [HarmonyPatch(typeof(SEMan), "ModifySwimStaminaUsage")] internal static class SwimCostPatch { private static void Postfix(ref float staminaUse, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectSwim.Value && ThreatRadar.LocalPlayerSafe(___m_character)) { staminaUse = 0f; } } } [HarmonyPatch(typeof(SEMan), "ModifySneakStaminaUsage")] internal static class SneakCostPatch { private static void Postfix(ref float staminaUse, bool minZero, Character ___m_character) { if (minZero && Plugin.AffectSneak.Value && ThreatRadar.LocalPlayerSafe(___m_character)) { staminaUse = 0f; } } } [HarmonyPatch(typeof(Player), "GetBuildStamina")] internal static class BuildCostPatch { private static void Postfix(Player __instance, ref float __result) { if (Plugin.AffectBuild.Value && ThreatRadar.LocalPlayerSafe((Character)(object)__instance)) { __result = 0f; } } } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] internal static class AttackCostPatch { private static void Postfix(ref float __result, Humanoid ___m_character) { if (__result > 0f && Plugin.AffectAttacks.Value && ThreatRadar.LocalPlayerSafe((Character)(object)___m_character)) { __result = 0f; } } } [HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })] internal static class RegenPatch { private static void Postfix(Player __instance, float dt, ref float ___m_stamina, float ___m_staminaRegenTimer) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Character)__instance).InIntro() && !((Character)__instance).IsTeleporting() && !(___m_staminaRegenTimer > 0f) && VanillaBlockedRegenWeCover(__instance) && ThreatRadar.AllClear(__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 VanillaBlockedRegenWeCover(Player p) { if (((Character)p).IsEncumbered()) { return false; } if (((Character)p).IsSwimming() && !((Character)p).IsOnGround()) { return Plugin.AffectSwim.Value; } if (((Character)p).InAttack() || ((Character)p).InDodge()) { return Plugin.AffectAttacks.Value; } if (((Character)p).IsWallRunning()) { return Plugin.AffectSprint.Value; } return false; } } internal static class ThreatRadar { private const float ScanInterval = 0.25f; private static float _nextScanTime; private static bool _allClear; private static string _ignoredSource; private static readonly HashSet<string> IgnoredNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); internal static bool LocalPlayerSafe(Character c) { Player val = (Player)(object)((c is Player) ? c : null); if (val != null && (Object)(object)val == (Object)(object)Player.m_localPlayer) { return AllClear(val); } return false; } internal static bool AllClear(Player player) { if ((Object)(object)player == (Object)null) { return false; } float time = Time.time; if (time < _nextScanTime) { return _allClear; } _nextScanTime = time + 0.25f; _allClear = !AnyThreatWithin(player, Plugin.SafeRadius.Value); return _allClear; } private static bool AnyThreatWithin(Player player, float radius) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0050: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; 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()) { Vector3 val = ((Component)allCharacter).transform.position - position; if (!(((Vector3)(ref val)).sqrMagnitude > num) && BaseAI.IsEnemy((Character)(object)player, allCharacter) && !IsIgnored(allCharacter)) { return true; } } } return false; } private static bool IsIgnored(Character c) { RefreshIgnoredNames(); if (IgnoredNames.Count == 0) { return false; } if (IgnoredNames.Contains(Utils.GetPrefabName(((Component)c).gameObject))) { return true; } if (Localization.instance != null) { return IgnoredNames.Contains(Localization.instance.Localize(c.m_name)); } return false; } private static void RefreshIgnoredNames() { string text = Plugin.IgnoredCreatures.Value ?? string.Empty; if (text == _ignoredSource) { return; } _ignoredSource = text; IgnoredNames.Clear(); string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length > 0) { IgnoredNames.Add(text2); } } } } internal static class BuildInfo { public const string Version = "1.0.8"; } }