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 InstantLvlUpSkills v1.0.0
BepInEx/plugins/InstantLvlUpSkills/InstantLvlUpSkills.dll
Decompiled 2 weeks agousing System; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace InstantLvlUpSkills; [BepInPlugin("InstantLvlUpSkills.Valheim", "InstantLvlUpSkills", "1.0.0")] public sealed class InstantLvlUpSkillsPlugin : BaseUnityPlugin { private sealed class RaiseState { public object Skill; public float BeforeLevel; public bool Valid; } public const string PluginGuid = "InstantLvlUpSkills.Valheim"; public const string PluginName = "InstantLvlUpSkills"; public const string PluginVersion = "1.0.0"; internal static ConfigEntry<bool> EnabledConfig; internal static ConfigEntry<bool> RemoveDeathSkillPenaltyConfig; internal static ManualLogSource ModLog; private static bool _handlingDeath = false; private static MethodInfo _getSkillMethod; private static MethodInfo _getNextLevelRequirementMethod; private static FieldInfo _skillLevelField; private static FieldInfo _skillAccumulatorField; private Harmony _harmony; private static bool _loggedWarning = false; private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0148: Expected O, but got Unknown ModLog = ((BaseUnityPlugin)this).Logger; EnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, new ConfigDescription("When enabled, every normal skill-gain event immediately grants exactly one full skill level, up to level 100.", (AcceptableValueBase)null, new object[0])); RemoveDeathSkillPenaltyConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Death Penalty", "Remove Skill Penalty", true, new ConfigDescription("When enabled, dying does not reduce skill levels or erase partial progress toward the next skill level.", (AcceptableValueBase)null, new object[0])); _getSkillMethod = AccessTools.Method(typeof(Skills), "GetSkill", new Type[1] { typeof(SkillType) }, (Type[])null); if (_getSkillMethod == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Skills.GetSkill(SkillType) was not found. Runtime fallback discovery will be used."); } _harmony = new Harmony("InstantLvlUpSkills.Valheim"); MethodInfo methodInfo = AccessTools.Method(typeof(InstantLvlUpSkillsPlugin), "RaiseSkillPrefix", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(InstantLvlUpSkillsPlugin), "RaiseSkillPostfix", (Type[])null, (Type[])null); MethodInfo[] methods = typeof(Skills).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); int num = 0; foreach (MethodInfo methodInfo3 in methods) { if (!(methodInfo3 == null) && !(methodInfo3.Name != "RaiseSkill")) { try { _harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo), new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not patch a Skills.RaiseSkill overload: " + ex.Message)); } } } PatchDeathPenalty(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("InstantLvlUpSkills 1.0.0 loaded. Patched " + num + " Skills.RaiseSkill method(s).")); } private void PatchDeathPenalty() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00cf: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(Skills), "OnDeath", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Skills), "LowerAllSkills", (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Skills.OnDeath() was not found. Death penalty removal will be unavailable."); return; } if (methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Skills.LowerAllSkills(...) was not found. Death penalty removal will be unavailable."); return; } MethodInfo methodInfo3 = AccessTools.Method(typeof(InstantLvlUpSkillsPlugin), "SkillsOnDeathPrefix", (Type[])null, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(typeof(InstantLvlUpSkillsPlugin), "SkillsOnDeathPostfix", (Type[])null, (Type[])null); MethodInfo methodInfo5 = AccessTools.Method(typeof(InstantLvlUpSkillsPlugin), "LowerAllSkillsPrefix", (Type[])null, (Type[])null); _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo3), new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(methodInfo5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Death skill penalty protection initialized."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not initialize death skill penalty protection: " + ex.Message)); } } private static void SkillsOnDeathPrefix() { _handlingDeath = true; } private static void SkillsOnDeathPostfix() { _handlingDeath = false; } private static bool LowerAllSkillsPrefix() { if (!_handlingDeath) { return true; } if (EnabledConfig == null || !EnabledConfig.Value || RemoveDeathSkillPenaltyConfig == null || !RemoveDeathSkillPenaltyConfig.Value) { return true; } return false; } private void OnDestroy() { try { if (_harmony != null) { _harmony.UnpatchSelf(); } } catch { } } private static void RaiseSkillPrefix(Skills __instance, object[] __args, ref RaiseState __state) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) __state = new RaiseState(); if (EnabledConfig == null || !EnabledConfig.Value || (Object)(object)__instance == (Object)null) { return; } try { if (!TryGetSkillType(__args, out var skillType)) { return; } object skillObject = GetSkillObject(__instance, skillType); if (skillObject == null) { return; } CacheSkillMembers(skillObject); if (_skillLevelField == null) { return; } float num = Convert.ToSingle(_skillLevelField.GetValue(skillObject)); __state.Skill = skillObject; __state.BeforeLevel = num; __state.Valid = true; if (num >= 100f) { _skillLevelField.SetValue(skillObject, 100f); if (_skillAccumulatorField != null) { _skillAccumulatorField.SetValue(skillObject, 0f); } } else if (_skillAccumulatorField != null) { float nextLevelRequirement = GetNextLevelRequirement(skillObject); if (nextLevelRequirement > 0f) { _skillAccumulatorField.SetValue(skillObject, nextLevelRequirement); } } } catch (Exception ex) { LogWarningOnce("RaiseSkill prefix failed: " + ex.Message); } } private static void RaiseSkillPostfix(ref RaiseState __state) { if (EnabledConfig == null || !EnabledConfig.Value || __state == null || !__state.Valid || __state.Skill == null || _skillLevelField == null) { return; } try { float beforeLevel = __state.BeforeLevel; if (beforeLevel >= 100f) { _skillLevelField.SetValue(__state.Skill, 100f); if (_skillAccumulatorField != null) { _skillAccumulatorField.SetValue(__state.Skill, 0f); } return; } float num = Mathf.Min(100f, Mathf.Floor(beforeLevel) + 1f); float num2 = Convert.ToSingle(_skillLevelField.GetValue(__state.Skill)); if (Mathf.Abs(num2 - num) > 0.001f) { _skillLevelField.SetValue(__state.Skill, num); } if (_skillAccumulatorField != null) { _skillAccumulatorField.SetValue(__state.Skill, 0f); } } catch (Exception ex) { LogWarningOnce("RaiseSkill postfix failed: " + ex.Message); } } private static bool TryGetSkillType(object[] args, out SkillType skillType) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected I4, but got Unknown skillType = (SkillType)0; if (args == null) { return false; } foreach (object obj in args) { if (obj is SkillType) { skillType = (SkillType)(int)(SkillType)obj; return true; } } return false; } private static object GetSkillObject(Skills skills, SkillType skillType) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)skills == (Object)null) { return null; } try { if (_getSkillMethod == null) { MethodInfo[] methods = typeof(Skills).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo == null) && !(methodInfo.Name != "GetSkill")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(SkillType)) { _getSkillMethod = methodInfo; break; } } } } if (_getSkillMethod == null) { return null; } return _getSkillMethod.Invoke(skills, new object[1] { skillType }); } catch { return null; } } private static void CacheSkillMembers(object skill) { if (skill != null) { Type type = skill.GetType(); if (_skillLevelField == null || _skillLevelField.DeclaringType != type) { _skillLevelField = AccessTools.Field(type, "m_level"); _skillAccumulatorField = AccessTools.Field(type, "m_accumulator"); _getNextLevelRequirementMethod = AccessTools.Method(type, "GetNextLevelRequirement", Type.EmptyTypes, (Type[])null); } } } private static float GetNextLevelRequirement(object skill) { if (skill == null || _getNextLevelRequirementMethod == null) { return 0f; } try { object obj = _getNextLevelRequirementMethod.Invoke(skill, null); if (obj == null) { return 0f; } return Convert.ToSingle(obj); } catch { return 0f; } } private static void LogWarningOnce(string message) { if (!_loggedWarning) { _loggedWarning = true; if (ModLog != null) { ModLog.LogWarning((object)message); } } } }