using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SkillFloors")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SkillFloors")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.1.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.0")]
[module: UnverifiableCode]
namespace SkillFloors;
[BepInPlugin("Armikur.mod.Valheim.SkillFloors", "SkillFloors", "1.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class SkillFloors : BaseUnityPlugin
{
public const string PluginName = "SkillFloors";
internal const string PluginAuthor = "Armikur";
public const string PluginGUID = "Armikur.mod.Valheim.SkillFloors";
public const string PluginVersion = "1.1.2";
private readonly Harmony HarmonyInstance = new Harmony("Armikur.mod.Valheim.SkillFloors");
internal static ConfigEntry<float> Config_SkillFloors_FloorXPGainRate;
internal static ConfigEntry<bool> Config_SkillFloors_EnableDebugLogging;
public static Dictionary<SkillType, SkillFloors_SkillFloorData> SkillFloors_SkillFloorDictionary = new Dictionary<SkillType, SkillFloors_SkillFloorData>();
private void Awake()
{
CreateConfigValues();
Logger.LogInfo((object)"Armikur's SkillFloors mod 1.1.2 has loaded!");
Assembly executingAssembly = Assembly.GetExecutingAssembly();
HarmonyInstance.PatchAll(executingAssembly);
}
private void CreateConfigValues()
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
Config_SkillFloors_FloorXPGainRate = ((BaseUnityPlugin)this).Config.Bind<float>("Server Config", "Floor XP Gain Rate", 0.15f, new ConfigDescription("Multiplier for how much XP floor skills gain relative to regular skills (e.g., 0.15 = 15%). Values over 1 will give more XP than normal; helpful for catching up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.5f), new object[1] { (object)new ConfigurationManagerAttributes
{
IsAdminOnly = true
} }));
Config_SkillFloors_EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Client Config", "Enable Debug Logging", false, new ConfigDescription("Shows each skill floor increase in the BepInEx window.", (AcceptableValueBase)null, Array.Empty<object>()));
}
public static void SkillFloors_GainFloorXP(Skill skill, float xpGained)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
SkillType skill2 = skill.m_info.m_skill;
if (!SkillFloors_SkillFloorDictionary.TryGetValue(skill2, out var value))
{
value = new SkillFloors_SkillFloorData();
SkillFloors_SkillFloorDictionary[skill2] = value;
}
float value2 = Config_SkillFloors_FloorXPGainRate.Value;
float num = xpGained * value2;
value.SkillFloors_Floor_XPProgress += num;
float num2 = SkillFloors_CalculateRequiredFloorXP(value.SkillFloors_Floor_Level);
if (value.SkillFloors_Floor_XPProgress >= num2)
{
value.SkillFloors_Floor_Level += 1f;
value.SkillFloors_Floor_XPProgress = 0f;
Logger.LogInfo((object)$"[SkillFloor] ---- {skill2} floor level increased to {value.SkillFloors_Floor_Level} ----");
}
float level = skill.m_level;
float accumulator = skill.m_accumulator;
float nextLevelRequirement = skill.GetNextLevelRequirement();
if (Config_SkillFloors_EnableDebugLogging.Value)
{
Logger.LogInfo((object)$"[SkillFloor] {skill2} Floor: {value.SkillFloors_Floor_Level} ({value.SkillFloors_Floor_XPProgress}/{num2} | Skill: {level} ({accumulator}/{nextLevelRequirement})");
}
}
public static float SkillFloors_GetSkillFloor(SkillType type)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
if (!SkillFloors_SkillFloorDictionary.TryGetValue(type, out var value))
{
return 0f;
}
return value.SkillFloors_Floor_Level;
}
public static float SkillFloors_CalculateRequiredFloorXP(float currentFloorLevel)
{
return Mathf.Pow(Mathf.Floor(currentFloorLevel + 1f), 1.5f) * 0.5f + 0.5f;
}
}
public class SkillFloors_SkillFloorData
{
public float SkillFloors_Floor_Level;
public float SkillFloors_Floor_XPProgress;
}
[HarmonyPatch(typeof(Skill), "Raise")]
public class SkillFloors_Patch_SkillFloor_Raise
{
private static void Postfix(Skill __instance, float factor)
{
float increseStep = __instance.m_info.m_increseStep;
float skillGainRate = Game.m_skillGainRate;
float xpGained = increseStep * factor * skillGainRate;
SkillFloors.SkillFloors_GainFloorXP(__instance, xpGained);
}
}
[HarmonyPatch(typeof(Player), "OnDeath")]
public class SkillFloors_Patch_Player_OnDeath
{
private static void Postfix(Player __instance)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: 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_003c: Unknown result type (might be due to invalid IL or missing references)
foreach (Skill skill2 in ((Character)__instance).GetSkills().GetSkillList())
{
SkillType skill = skill2.m_info.m_skill;
float num = SkillFloors.SkillFloors_GetSkillFloor(skill);
if (skill2.m_level < num)
{
Debug.Log((object)$"[SkillFloors] Preventing {skill} from dropping below floor level {num}");
skill2.m_level = num;
}
}
}
}
[HarmonyPatch(typeof(SkillsDialog), "Setup")]
public class SkillFloors_Patch_SkillsDialog
{
private static void Postfix(SkillsDialog __instance, Player player)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
List<Skill> skillList = ((Character)player).GetSkills().GetSkillList();
for (int i = 0; i < skillList.Count && i < __instance.m_elements.Count; i++)
{
SkillType skill = skillList[i].m_info.m_skill;
float num = SkillFloors.SkillFloors_GetSkillFloor(skill);
GameObject val = __instance.m_elements[i];
TMP_Text component = ((Component)Utils.FindChild(val.transform, "name", (IterativeSearchType)0)).GetComponent<TMP_Text>();
if ((Object)(object)component != (Object)null && num > 0f)
{
string arg = Localization.instance.Localize("$skill_" + ((object)(SkillType)(ref skill)).ToString().ToLower());
component.text = $"{arg} <color=#7D9FB8><size=85%>{Mathf.FloorToInt(num)}</size></color>";
}
if (!SkillFloors.SkillFloors_SkillFloorDictionary.TryGetValue(skill, out var value))
{
continue;
}
GuiBar component2 = ((Component)Utils.FindChild(val.transform, "currentlevel", (IterativeSearchType)0)).GetComponent<GuiBar>();
if ((Object)(object)component2 != (Object)null)
{
Transform obj = Utils.FindChild(val.transform, "floorlevel", (IterativeSearchType)0);
GuiBar val2 = ((obj != null) ? ((Component)obj).GetComponent<GuiBar>() : null);
GuiBar val3;
if ((Object)(object)val2 != (Object)null)
{
val3 = val2;
}
else
{
GameObject obj2 = Object.Instantiate<GameObject>(((Component)component2).gameObject, ((Component)component2).transform.parent);
((Object)obj2).name = "floorlevel";
val3 = obj2.GetComponent<GuiBar>();
RectTransform component3 = obj2.GetComponent<RectTransform>();
component3.anchoredPosition -= new Vector2(0f, 2f);
component3.SetSizeWithCurrentAnchors((Axis)1, 2f);
}
float num2 = SkillFloors.SkillFloors_CalculateRequiredFloorXP(value.SkillFloors_Floor_Level);
float value2 = Mathf.Clamp01(value.SkillFloors_Floor_XPProgress / num2);
val3.SetValue(value2);
val3.SetColor(new Color(0.66f, 0.76f, 0.84f, 1f));
}
}
}
}
public static class SkillFloors_SaveLoad_JSDN
{
private const string SkillFloors_SaveKey = "SkillFloors_SkillFloorData_JSON";
public static void SkillFloors_Save(Player player)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
JsonSerializerSettings val = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { (JsonConverter)new StringEnumConverter() },
Formatting = (Formatting)0
};
string value = JsonConvert.SerializeObject((object)SkillFloors.SkillFloors_SkillFloorDictionary, val);
player.m_customData["SkillFloors_SkillFloorData_JSON"] = value;
}
public static void SkillFloors_Load(Player player)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_0031: Expected O, but got Unknown
if (player.m_customData.TryGetValue("SkillFloors_SkillFloorData_JSON", out var value))
{
JsonSerializerSettings val = new JsonSerializerSettings
{
Converters = new List<JsonConverter> { (JsonConverter)new StringEnumConverter() }
};
Dictionary<SkillType, SkillFloors_SkillFloorData> dictionary = JsonConvert.DeserializeObject<Dictionary<SkillType, SkillFloors_SkillFloorData>>(value, val);
if (dictionary != null)
{
SkillFloors.SkillFloors_SkillFloorDictionary = dictionary;
}
}
}
}
[HarmonyPatch(typeof(Player), "Save")]
public class SkillFloors_Patch_Player_Save
{
private static void Prefix(Player __instance)
{
SkillFloors_SaveLoad_JSDN.SkillFloors_Save(__instance);
}
}
[HarmonyPatch(typeof(Player), "Load")]
public class SkillFloors_Patch_Player_Load
{
private static void Postfix(Player __instance)
{
SkillFloors_SaveLoad_JSDN.SkillFloors_Load(__instance);
}
}