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 Magical v1.2.3
Magical.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using ConditionalConfigSync; using HarmonyLib; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Magical")] [assembly: AssemblyDescription("Magical")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Crystal")] [assembly: AssemblyProduct("Magical")] [assembly: AssemblyCopyright("Copyright © 2026 Crystal Ferrai")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1414a5c1-1a42-448f-8f27-000b965fcb46")] [assembly: AssemblyFileVersion("1.2.3.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.2.3.0")] namespace Magical; [BepInPlugin("dev.crystal.magical", "Magical", "1.2.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] public class MagicalPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player))] private static class Player_Tracking_Patches { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void Awake_Prefix(Player __instance) { SetPlayerValues(__instance); sPlayers.Add(__instance); } [HarmonyPatch("OnDestroy")] [HarmonyPrefix] private static void OnDestroy_Prefix(Player __instance) { sPlayers.Remove(__instance); } } [HarmonyPatch(typeof(Player))] private static class Player_Patches { private enum TranspilerState { Searching, Checking, Replacing, Searching2, Checking2, Replacing2, Finishing } [HarmonyPatch("UpdateFood")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> UpdateFood_Transpiler(IEnumerable<CodeInstruction> instructions) { TranspilerState state = TranspilerState.Searching; CodeInstruction previousInstruction = null; foreach (CodeInstruction instruction in instructions) { switch (state) { case TranspilerState.Searching: if (instruction.opcode == OpCodes.Ldfld && ((FieldInfo)instruction.operand).Name.Equals("m_foodRegenTimer")) { state = TranspilerState.Checking; } yield return instruction; break; case TranspilerState.Checking: if (instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 10f) { state = TranspilerState.Replacing; break; } yield return instruction; state = TranspilerState.Searching; break; case TranspilerState.Replacing: yield return new CodeInstruction(OpCodes.Ldc_R4, (object)HealthRegenTickRate.Value); yield return instruction; state = TranspilerState.Searching2; break; case TranspilerState.Searching2: if (instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 0f) { previousInstruction = instruction; state = TranspilerState.Checking2; } else { yield return instruction; } break; case TranspilerState.Checking2: if (instruction.opcode == OpCodes.Stloc_S) { previousInstruction = instruction; state = TranspilerState.Replacing2; } else { yield return previousInstruction; yield return instruction; state = TranspilerState.Searching2; } break; case TranspilerState.Replacing2: yield return new CodeInstruction(OpCodes.Ldc_R4, (object)BaseHealthRegen.Value); yield return previousInstruction; yield return instruction; state = TranspilerState.Finishing; break; case TranspilerState.Finishing: yield return instruction; break; } } } [HarmonyPatch("GetTotalFoodValue")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GetTotalFoodValue_Transpiler(IEnumerable<CodeInstruction> instructions) { TranspilerState state = TranspilerState.Searching; foreach (CodeInstruction instruction in instructions) { switch (state) { case TranspilerState.Searching: if (instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 0f) { state = TranspilerState.Replacing; } else { yield return instruction; } break; case TranspilerState.Replacing: yield return new CodeInstruction(OpCodes.Ldc_R4, (object)BaseEitr.Value); yield return instruction; state = TranspilerState.Finishing; break; case TranspilerState.Finishing: yield return instruction; break; } } } } [HarmonyPatch(typeof(Attack))] private static class Attack_Patches { private enum TranspilerState { Searching, Replacing, Finishing } [HarmonyPatch("GetAttackStamina")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GetAttackStamina_Transpiler(IEnumerable<CodeInstruction> instructions) { return ReplaceSkillModifier(instructions, SkillStaminaReduction.Value); } [HarmonyPatch("GetAttackEitr", new Type[] { typeof(Character), typeof(ItemData) })] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GetAttackEitr_Transpiler(IEnumerable<CodeInstruction> instructions) { return ReplaceSkillModifier(instructions, SkillEitrReduction.Value); } [HarmonyPatch("GetAttackHealth")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GetAttackHealth_Transpiler(IEnumerable<CodeInstruction> instructions) { return ReplaceSkillModifier(instructions, SkillHealthReduction.Value); } private static IEnumerable<CodeInstruction> ReplaceSkillModifier(IEnumerable<CodeInstruction> instructions, float newModifier) { TranspilerState state = TranspilerState.Searching; foreach (CodeInstruction instruction in instructions) { switch (state) { case TranspilerState.Searching: if (instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 0.33f) { state = TranspilerState.Replacing; } else { yield return instruction; } break; case TranspilerState.Replacing: yield return new CodeInstruction(OpCodes.Ldc_R4, (object)newModifier); yield return instruction; state = TranspilerState.Finishing; break; case TranspilerState.Finishing: yield return instruction; break; } } } } public const string ModId = "dev.crystal.magical"; public const string ModName = "Magical"; public const string ModVersion = "1.2.3.0"; internal static readonly ConfigSync ConfigSync; public static ConfigEntry<float> BaseStamina; public static ConfigEntry<float> BaseEitr; public static ConfigEntry<float> BaseHealth; public static ConfigEntry<float> BaseStaminaRegen; public static ConfigEntry<float> BaseEitrRegen; public static ConfigEntry<float> BaseHealthRegen; public static ConfigEntry<float> StaminaRegenDelay; public static ConfigEntry<float> EitrRegenDelay; public static ConfigEntry<float> HealthRegenTickRate; public static ConfigEntry<float> SkillStaminaReduction; public static ConfigEntry<float> SkillEitrReduction; public static ConfigEntry<float> SkillHealthReduction; private static Harmony sPlayerTrackingHarmony; private static Harmony sPlayerHarmony; private static Harmony sAttackHarmony; private static List<Player> sPlayers; static MagicalPlugin() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown ConfigSync = new ConfigSync("dev.crystal.magical") { DisplayName = "Magical", CurrentVersion = "1.2.3.0", MinimumRequiredVersion = "1.2.3.0", ModRequired = true, ModRequirementMode = (ModRequirementMode)1 }; sPlayers = new List<Player>(); } private void Awake() { //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Expected O, but got Unknown //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Expected O, but got Unknown //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Expected O, but got Unknown BaseStamina = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "BaseStamina", 50f, "Maximum stamina before any food modifiers are applied. Game default 50. [The value will be enforced on a server.]"); BaseStamina.SettingChanged += PlayerVariable_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(BaseStamina, (ConfigSyncMode)0); BaseEitr = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "BaseEitr", 0f, "Maximum eitr before any food modifiers are applied. Game default 0. [The value will be enforced on a server.]"); BaseEitr.SettingChanged += PlayerConstant_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(BaseEitr, (ConfigSyncMode)0); BaseHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "BaseHealth", 25f, "Maximum health before any food modifiers are applied. Game default 25. [The value will be enforced on a server.]"); BaseHealth.SettingChanged += PlayerVariable_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(BaseHealth, (ConfigSyncMode)0); BaseStaminaRegen = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "BaseStaminaRegen", 6f, "The base rate of stamina regen per second, before any modifiers are applied. Game default 6. [The value will be enforced on a server.]"); BaseStaminaRegen.SettingChanged += PlayerVariable_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(BaseStaminaRegen, (ConfigSyncMode)0); BaseEitrRegen = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "BaseEitrRegen", 2f, "The base rate of eitr regen per second, before any modifiers are applied. Game default 2. [The value will be enforced on a server.]"); BaseEitrRegen.SettingChanged += PlayerVariable_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(BaseEitrRegen, (ConfigSyncMode)0); BaseHealthRegen = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "BaseHealthRegen", 0f, "The base rate of health regen per health regen tick, before any modifiers are applied. Game default 0. [The value will be enforced on a server.]"); BaseHealthRegen.SettingChanged += PlayerConstant_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(BaseHealthRegen, (ConfigSyncMode)0); StaminaRegenDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "StaminaRegenDelay", 1f, "The number of seconds after using stamina before it starts to regenerate. Game default 1. [The value will be enforced on a server.]"); StaminaRegenDelay.SettingChanged += PlayerVariable_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(StaminaRegenDelay, (ConfigSyncMode)0); EitrRegenDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "EitrRegenDelay", 1f, "The number of seconds after using eitr before it starts to regenerate. Game default 1. [The value will be enforced on a server.]"); EitrRegenDelay.SettingChanged += PlayerVariable_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(EitrRegenDelay, (ConfigSyncMode)0); HealthRegenTickRate = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "HealthRegenTickRate", 10f, "The number of seconds between ticks of health regeneration. Game default 10. [The value will be enforced on a server.]"); HealthRegenTickRate.SettingChanged += PlayerConstant_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(HealthRegenTickRate, (ConfigSyncMode)0); SkillStaminaReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillStaminaReduction", 0.33f, "Stamina cost reduction multiplier for actions based on player skill. Value represents reduction with 100 skill and will scale down at lower skill levels. Game default 0.33. [The value will be enforced on a server.]"); SkillStaminaReduction.SettingChanged += Attack_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(SkillStaminaReduction, (ConfigSyncMode)0); SkillEitrReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillEitrReduction", 0.33f, "Eitr cost reduction multiplier for actions based on player skill. Value represents reduction with 100 skill and will scale down at lower skill levels. Game default 0.33. [The value will be enforced on a server.]"); SkillEitrReduction.SettingChanged += Attack_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(SkillEitrReduction, (ConfigSyncMode)0); SkillHealthReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Skill", "SkillHealthReduction", 0.33f, "Health cost reduction multiplier for actions based on player skill. Value represents reduction with 100 skill and will scale down at lower skill levels. Game default 0.33. [The value will be enforced on a server.]"); SkillHealthReduction.SettingChanged += Attack_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(SkillHealthReduction, (ConfigSyncMode)0); sPlayerTrackingHarmony = new Harmony("dev.crystal.magical_Player_Tracking"); sPlayerHarmony = new Harmony("dev.crystal.magical_Player"); sAttackHarmony = new Harmony("dev.crystal.magical_Attack"); ClampConfig(); sPlayerTrackingHarmony.PatchAll(typeof(Player_Tracking_Patches)); sPlayerHarmony.PatchAll(typeof(Player_Patches)); sAttackHarmony.PatchAll(typeof(Attack_Patches)); } private void OnDestroy() { sPlayerTrackingHarmony.UnpatchSelf(); sPlayerHarmony.UnpatchSelf(); sAttackHarmony.UnpatchSelf(); sPlayers.Clear(); } private static void ClampConfig() { if (BaseStamina.Value < 0f) { BaseStamina.Value = 0f; } if (BaseStamina.Value > 1000f) { BaseStamina.Value = 1000f; } if (BaseEitr.Value < 0f) { BaseEitr.Value = 0f; } if (BaseEitr.Value > 1000f) { BaseEitr.Value = 1000f; } if (BaseHealth.Value < 0f) { BaseHealth.Value = 0f; } if (BaseHealth.Value > 1000f) { BaseHealth.Value = 1000f; } if (BaseStaminaRegen.Value < 0.1f) { BaseStaminaRegen.Value = 0.1f; } if (BaseStaminaRegen.Value > 1000f) { BaseStaminaRegen.Value = 1000f; } if (BaseEitrRegen.Value < 0.1f) { BaseEitrRegen.Value = 0.1f; } if (BaseEitrRegen.Value > 1000f) { BaseEitrRegen.Value = 1000f; } if (BaseHealthRegen.Value < 0f) { BaseHealthRegen.Value = 0f; } if (BaseHealthRegen.Value > 1000f) { BaseHealthRegen.Value = 1000f; } if (StaminaRegenDelay.Value < 0.1f) { StaminaRegenDelay.Value = 0.1f; } if (StaminaRegenDelay.Value > 3600f) { StaminaRegenDelay.Value = 3600f; } if (EitrRegenDelay.Value < 0.1f) { EitrRegenDelay.Value = 0.1f; } if (EitrRegenDelay.Value > 3600f) { EitrRegenDelay.Value = 3600f; } if (HealthRegenTickRate.Value < 0.1f) { HealthRegenTickRate.Value = 0.1f; } if (HealthRegenTickRate.Value > 3600f) { HealthRegenTickRate.Value = 3600f; } if (SkillStaminaReduction.Value < 0f) { SkillStaminaReduction.Value = 0f; } if (SkillStaminaReduction.Value > 1f) { SkillStaminaReduction.Value = 1f; } if (SkillEitrReduction.Value < 0f) { SkillEitrReduction.Value = 0f; } if (SkillEitrReduction.Value > 1f) { SkillEitrReduction.Value = 1f; } if (SkillHealthReduction.Value < 0f) { SkillHealthReduction.Value = 0f; } if (SkillHealthReduction.Value > 1f) { SkillHealthReduction.Value = 1f; } } private void PlayerVariable_SettingChanged(object sender, EventArgs e) { ClampConfig(); foreach (Player sPlayer in sPlayers) { SetPlayerValues(sPlayer); } } private void Attack_SettingChanged(object sender, EventArgs e) { ClampConfig(); sAttackHarmony.UnpatchSelf(); sAttackHarmony.PatchAll(typeof(Attack_Patches)); } private void PlayerConstant_SettingChanged(object sender, EventArgs e) { ClampConfig(); sPlayerHarmony.UnpatchSelf(); sPlayerHarmony.PatchAll(typeof(Player_Patches)); } private static void SetPlayerValues(Player player) { player.m_baseStamina = BaseStamina.Value; player.m_baseHP = BaseHealth.Value; player.m_staminaRegen = BaseStaminaRegen.Value; player.m_eiterRegen = BaseEitrRegen.Value; player.m_staminaRegenDelay = StaminaRegenDelay.Value; player.m_eitrRegenDelay = EitrRegenDelay.Value; } }