using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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 BepInEx.Logging;
using Configs;
using HarmonyLib;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Logging;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FortifySkillsRedux")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FortifySkillsRedux")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b17a1148-6db3-4f0b-9e79-d760d18acf4d")]
[assembly: AssemblyFileVersion("1.5.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 Logging
{
internal static class Log
{
internal enum InfoLevel
{
Low,
Medium,
High
}
private static ManualLogSource logSource;
internal static ConfigEntry<InfoLevel> Verbosity { get; set; }
internal static InfoLevel VerbosityLevel => Verbosity.Value;
internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low;
internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium;
internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High;
internal static void Init(ManualLogSource logSource)
{
Log.logSource = logSource;
}
internal static void LogDebug(object data)
{
logSource.LogDebug(data);
}
internal static void LogError(object data)
{
logSource.LogError(data);
}
internal static void LogFatal(object data)
{
logSource.LogFatal(data);
}
internal static void LogMessage(object data)
{
logSource.LogMessage(data);
}
internal static void LogWarning(object data)
{
logSource.LogWarning(data);
}
internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low)
{
if (Verbosity == null || VerbosityLevel >= level)
{
logSource.LogInfo(data);
}
}
internal static void LogGameObject(GameObject prefab, bool includeChildren = false)
{
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
LogInfo("***** " + ((Object)prefab).name + " *****");
Component[] components = prefab.GetComponents<Component>();
for (int i = 0; i < components.Length; i++)
{
LogComponent(components[i]);
}
if (!includeChildren)
{
return;
}
LogInfo("***** " + ((Object)prefab).name + " (children) *****");
foreach (Transform item in prefab.transform)
{
Transform val = item;
if (Object.op_Implicit((Object)(object)val))
{
LogInfo(" - " + ((Object)val).name);
components = ((Component)val).GetComponents<Component>();
for (int i = 0; i < components.Length; i++)
{
LogComponent(components[i]);
}
}
}
}
internal static void LogComponent(Component compo)
{
if (!Object.op_Implicit((Object)(object)compo))
{
return;
}
try
{
LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
}
catch (Exception ex)
{
LogError(ex.ToString());
LogWarning("Could not get type name for component!");
return;
}
try
{
foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType()))
{
try
{
LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}");
}
catch (Exception ex2)
{
LogError(ex2.ToString());
LogWarning("Could not get property: " + declaredProperty.Name + " for component!");
}
}
}
catch (Exception ex3)
{
LogError(ex3.ToString());
LogWarning("Could not get properties for component!");
}
try
{
foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType()))
{
try
{
LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}");
}
catch (Exception ex4)
{
LogError(ex4.ToString());
LogWarning("Could not get field: " + declaredField.Name + " for component!");
}
}
}
catch (Exception ex5)
{
LogError(ex5.ToString());
LogWarning("Could not get fields for component!");
}
}
}
}
namespace FortifySkillsRedux
{
internal sealed class FortifySkillData
{
public static Dictionary<SkillType, FortifySkillData> s_FortifySkills = new Dictionary<SkillType, FortifySkillData>();
public static Player s_AssociatedPlayer;
public float FortifyLevel;
public float FortifyAccumulator;
public SkillDef Info;
public string SkillName => GetLocalizedSkillName(this);
public static bool IsSkillValid(SkillType skillType)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: 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: Invalid comparison between Unknown and I4
if (Skills.IsSkillValid(skillType) && (int)skillType != 0)
{
return (int)skillType != 999;
}
return false;
}
public FortifySkillData(SkillDef skillDef)
{
FortifyAccumulator = 0f;
FortifyLevel = 0f;
Info = skillDef;
}
public FortifySkillData(SkillDef skillDef, float newLevel, float newAccumulator)
{
FortifyAccumulator = newAccumulator;
FortifyLevel = newLevel;
Info = skillDef;
}
public static void ResetFortifySkill(SkillType skillType)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: 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)
if (s_FortifySkills.ContainsKey(skillType))
{
s_FortifySkills[skillType].FortifyLevel = 0f;
s_FortifySkills[skillType].FortifyAccumulator = 0f;
}
}
public static SkillType MapDummySkill(SkillType skillType)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
return (SkillType)(int.MaxValue - skillType);
}
public static string GetLocalizedSkillName(Skill skill)
{
return "$skill_" + ((object)(SkillType)(ref skill.m_info.m_skill)).ToString().ToLower();
}
public static string GetLocalizedSkillName(FortifySkillData fortSkill)
{
return "$skill_" + ((object)(SkillType)(ref fortSkill.Info.m_skill)).ToString().ToLower();
}
public static string LocalizeSkillName(SkillType skillType)
{
return "$skill_" + ((object)(SkillType)(ref skillType)).ToString().ToLower();
}
}
[BepInPlugin("Searica.Valheim.FortifySkillsRedux", "FortifySkillsRedux", "1.5.3")]
[BepInDependency("com.jotunn.jotunn", "2.23.0")]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[SynchronizationMode(/*Could not decode attribute arguments.*/)]
internal sealed class FortifySkillsRedux : BaseUnityPlugin
{
internal class SkillConfig
{
public ConfigEntry<float> ActiveSkillXPMult;
public ConfigEntry<float> FortifySkillMaxXPRate;
public ConfigEntry<float> FortifySkillXPPerLevel;
}
public const string PluginName = "FortifySkillsRedux";
internal const string Author = "Searica";
public const string PluginGUID = "Searica.Valheim.FortifySkillsRedux";
public const string PluginVersion = "1.5.3";
private const string MainSection = "Global";
private const string Mechanics = "Mechanics";
private const string ModdedSkills = "Modded Skill Settings";
public static FortifySkillsRedux Instance;
internal static ConfigFileWatcher ConfigFileWatcher;
internal Dictionary<SkillType, SkillConfig> SkillConfigsMap = new Dictionary<SkillType, SkillConfig>();
private bool ShouldSave;
internal SkillConfig GlobalSkillConfig { get; private set; }
internal ConfigEntry<bool> EnableIndividualSettings { get; private set; }
internal ConfigEntry<bool> KeepAllItemsOnDeath { get; private set; }
internal ConfigEntry<bool> KeepEquippedItemsOnDeath { get; private set; }
internal SkillConfig ModdedSkillConfig { get; private set; }
public void Awake()
{
Instance = this;
Log.Init(((BaseUnityPlugin)this).Logger);
((BaseUnityPlugin)this).Config.DisableSaveOnConfigSet();
SetUpConfigEntries();
((BaseUnityPlugin)this).Config.Save();
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.FortifySkillsRedux");
Game.isModded = true;
ConfigFileWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config);
SynchronizationManager.OnConfigurationWindowClosed += delegate
{
if (ShouldSave)
{
((BaseUnityPlugin)this).Config.Save();
ShouldSave = false;
}
};
}
public void OnDestroy()
{
((BaseUnityPlugin)this).Config.Save();
}
internal void SetUpConfigEntries()
{
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Invalid comparison between Unknown and I4
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
Log.Verbosity = ConfigFileExtensions.BindConfigInOrder<Log.InfoLevel>(((BaseUnityPlugin)this).Config, "Global", "Verbosity", Log.InfoLevel.Low, "Low will log basic information about the mod. Medium will log information that is useful for troubleshooting. High will log a lot of information, do not set it to this without good reason as it will slow down your game.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
Log.Verbosity.SettingChanged += delegate
{
if (!ShouldSave)
{
ShouldSave = true;
}
};
KeepAllItemsOnDeath = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Global", "Keep All Items on Death", false, "Whether to keep all items on death.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
KeepEquippedItemsOnDeath = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Global", "Keep Equipped Items on Death", false, "Whether to keep your equiped items when you die.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
EnableIndividualSettings = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Global", "Use Individual Settings", false, "If enabled, use the config settings for each individual Vanilla skill and the Modded skill config settings for all skills added by mods. If disabled use the config setting from the Mechanics section for all skills.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
EnableIndividualSettings.SettingChanged += delegate
{
if (!ShouldSave)
{
ShouldSave = true;
}
};
GlobalSkillConfig = BindSkillConfig("Mechanics", order: true);
Log.LogInfo($"{Skills.s_allSkills.Count()} SkillTypes are defined in base game.", Log.InfoLevel.Medium);
SkillType[] s_allSkills = Skills.s_allSkills;
for (int i = 0; i < s_allSkills.Length; i++)
{
SkillType val = s_allSkills[i];
if ((int)val != 0 && (int)val != 999)
{
string text = ((object)(SkillType)(ref val)).ToString();
if (text != null)
{
Log.LogInfo("Adding " + text + " to config.", Log.InfoLevel.Medium);
SkillConfig value = BindSkillConfig(text);
SkillConfigsMap.Add(val, value);
}
}
}
ModdedSkillConfig = BindSkillConfig("Modded Skill Settings");
}
internal SkillConfig BindSkillConfig(string section, bool order = false)
{
SkillConfig skillConfig = new SkillConfig();
skillConfig.ActiveSkillXPMult = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, section, "Active Skill XP Multiplier", 1.5f, "Controls XP gained for the active skill level. 1 = base game XP, 1.5 = 50% bonus XP, 0.8 = 20% less XP.", true, order, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
skillConfig.FortifySkillMaxXPRate = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, section, "Max Fortify Skill XP Rate", 0.8f, "Controls maximum rate of XP earned for the fortified skill as a percentage of vanilla XP rates.Values below 1 mean that fortified skills will always increase slower than vanilla skills.Values above 1 mean that fortified skills can increase faster than vanilla skills if your active skill level is high enough.", true, order, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
skillConfig.FortifySkillXPPerLevel = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, section, "Fortify Skill XP Per Level", 0.1f, "Controls XP gained for the fortified skill. For every level the active skill is above the fortified skill increasethe percentage of XP gained for the fortified skill by this amount up to Max Fortify Skill XP Rate.", true, order, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
skillConfig.ActiveSkillXPMult.SettingChanged += delegate
{
if (!ShouldSave)
{
ShouldSave = true;
}
};
skillConfig.FortifySkillXPPerLevel.SettingChanged += delegate
{
if (!ShouldSave)
{
ShouldSave = true;
}
};
skillConfig.FortifySkillMaxXPRate.SettingChanged += delegate
{
if (!ShouldSave)
{
ShouldSave = true;
}
};
return skillConfig;
}
internal float GetActiveSkillXPMult(Skill skill)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
if (!EnableIndividualSettings.Value)
{
return GlobalSkillConfig.ActiveSkillXPMult.Value;
}
SkillType skill2 = skill.m_info.m_skill;
if (SkillConfigsMap.ContainsKey(skill2))
{
return SkillConfigsMap[skill2].ActiveSkillXPMult.Value;
}
return ModdedSkillConfig.ActiveSkillXPMult.Value;
}
internal float GetFortifyXPPerLevel(Skill skill)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
if (!EnableIndividualSettings.Value)
{
return GlobalSkillConfig.FortifySkillXPPerLevel.Value;
}
SkillType skill2 = skill.m_info.m_skill;
if (SkillConfigsMap.ContainsKey(skill2))
{
return SkillConfigsMap[skill2].FortifySkillXPPerLevel.Value;
}
return ModdedSkillConfig.FortifySkillXPPerLevel.Value;
}
internal float GetFortityMaxXPRate(Skill skill)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
if (!EnableIndividualSettings.Value)
{
return GlobalSkillConfig.FortifySkillMaxXPRate.Value;
}
SkillType skill2 = skill.m_info.m_skill;
if (SkillConfigsMap.ContainsKey(skill2))
{
return SkillConfigsMap[skill2].FortifySkillMaxXPRate.Value;
}
return ModdedSkillConfig.FortifySkillMaxXPRate.Value;
}
}
}
namespace FortifySkillsRedux.Patches
{
[HarmonyPatch]
internal static class ItemLossPatches
{
[HarmonyPrefix]
[HarmonyPriority(50)]
[HarmonyPatch(typeof(Player), "CreateTombStone")]
private static void StoreItems(Player __instance, out Dictionary<ItemData, bool> __state)
{
__state = new Dictionary<ItemData, bool>();
if (!Object.op_Implicit((Object)(object)__instance))
{
return;
}
bool value = FortifySkillsRedux.Instance.KeepAllItemsOnDeath.Value;
bool value2 = FortifySkillsRedux.Instance.KeepEquippedItemsOnDeath.Value;
if (!value && !value2)
{
return;
}
List<ItemData> list = new List<ItemData>();
string text = (value ? "KeepAllItems setting" : "KeepEquippedItems setting");
foreach (ItemData item in ((Humanoid)__instance).m_inventory.m_inventory)
{
string prefabName = Utils.GetPrefabName(item.m_dropPrefab);
string text2 = ((item.m_gridPos.y == 0) ? "hotbar" : "inventory");
if (value || (value2 && item.m_equipped))
{
__state.Add(item, item.m_equipped);
Log.LogDebug("Keeping " + prefabName + " in " + text2 + " due to the " + text + ".");
}
else
{
list.Add(item);
Log.LogDebug("Dropping " + prefabName + " from " + text2 + ".");
}
}
((Humanoid)__instance).m_inventory.m_inventory = list;
}
[HarmonyPostfix]
[HarmonyPriority(750)]
[HarmonyPatch(typeof(Player), "CreateTombStone")]
private static void RestoreItems(Player __instance, Dictionary<ItemData, bool> __state)
{
if (!Object.op_Implicit((Object)(object)__instance) || __state.Count == 0)
{
return;
}
foreach (KeyValuePair<ItemData, bool> item in __state)
{
Log.LogDebug("Adding " + ((Object)item.Key.m_dropPrefab).name + " back to inventory.");
((Humanoid)__instance).m_inventory.m_inventory.Add(item.Key);
Log.LogDebug($"Item {((Object)item.Key.m_dropPrefab).name} was equipped: {item.Value}");
if (item.Value && (!((Object)item.Key.m_dropPrefab).name.StartsWith("BBH") || !((Object)item.Key.m_dropPrefab).name.EndsWith("Quiver")))
{
((Humanoid)__instance).EquipItem(item.Key, false);
}
}
((Humanoid)__instance).m_inventory.Changed();
}
}
[HarmonyPatch(typeof(Player))]
internal static class OnDeathPatches
{
[HarmonyPrefix]
[HarmonyPriority(0)]
[HarmonyPatch("OnDeath")]
private static void OnDeath()
{
if (ZoneSystem.instance.GetGlobalKey((GlobalKeys)17))
{
ZoneSystem.instance.m_globalKeysEnums.Remove((GlobalKeys)17);
}
}
[HarmonyFinalizer]
[HarmonyPriority(100)]
[HarmonyPatch("OnDeath")]
private static void OnDeathFinalizer(Player __instance)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
Log.LogInfo("Finalizing skills on death", Log.InfoLevel.Medium);
if (!Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)__instance.m_skills))
{
return;
}
foreach (KeyValuePair<SkillType, Skill> skillDatum in __instance.m_skills.m_skillData)
{
if (FortifySkillData.s_FortifySkills.ContainsKey(skillDatum.Key))
{
FortifySkillData fortifySkillData = FortifySkillData.s_FortifySkills[skillDatum.Key];
Log.LogInfo($"Setting {fortifySkillData.SkillName} to fortify level: {fortifySkillData.FortifyLevel}", Log.InfoLevel.Medium);
skillDatum.Value.m_level = fortifySkillData.FortifyLevel;
skillDatum.Value.m_accumulator = 0f;
}
}
}
}
[HarmonyPatch]
internal static class ResetCmdPatches
{
[HarmonyPrefix]
[HarmonyPatch(typeof(Player), "ResetCharacter")]
internal static void ResetFortifySkills(Player __instance)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
foreach (SkillDef skill in __instance.m_skills.m_skills)
{
if (FortifySkillData.s_FortifySkills.ContainsKey(skill.m_skill))
{
FortifySkillData.ResetFortifySkill(skill.m_skill);
}
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Skills), "ResetSkill")]
private static void SkillResetSkill(SkillType skillType)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
FortifySkillData.ResetFortifySkill(skillType);
}
}
[HarmonyPatch(typeof(Skills))]
public static class SaveLoadPatches
{
[HarmonyPrefix]
[HarmonyPatch("Load")]
private static void LoadPrefix(Skills __instance, ZPackage pkg)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
Log.LogInfo("Skills.Load.Prefix()", Log.InfoLevel.Medium);
int pos = pkg.GetPos();
FortifySkillData.s_FortifySkills.Clear();
FortifySkillData.s_AssociatedPlayer = __instance.m_player;
int num = pkg.ReadInt();
int num2 = pkg.ReadInt();
for (int i = 0; i < num2; i++)
{
SkillType val = (SkillType)pkg.ReadInt();
float num3 = pkg.ReadSingle();
float newAccumulator = ((num >= 2) ? pkg.ReadSingle() : 0f);
if (FortifySkillData.IsSkillValid(val))
{
Skill skill = __instance.GetSkill(val);
if (skill?.m_info != null && !FortifySkillData.s_FortifySkills.ContainsKey(val))
{
Log.LogInfo("Fortify Skill initialized for: " + FortifySkillData.LocalizeSkillName(val) + " a.k.a " + skill.m_info?.m_description, Log.InfoLevel.Medium);
FortifySkillData.s_FortifySkills[val] = new FortifySkillData(skill.m_info, num3 * 0.95f, 0f);
}
continue;
}
SkillType val2 = FortifySkillData.MapDummySkill(val);
if (!FortifySkillData.IsSkillValid(val2))
{
Log.LogInfo("Unrecognized Fortify skill!", Log.InfoLevel.Medium);
continue;
}
Skill skill2 = __instance.GetSkill(val2);
if (skill2?.m_info != null)
{
if (Log.VerbosityLevel >= Log.InfoLevel.Medium)
{
string arg = FortifySkillData.LocalizeSkillName(val2);
Log.LogInfo($"Fortify Skill mapped to: {arg} a.k.a {skill2.m_info?.m_description} @: {num3}");
}
FortifySkillData.s_FortifySkills[val2] = new FortifySkillData(skill2.m_info, num3, newAccumulator);
}
}
pkg.SetPos(pos);
}
[HarmonyPrefix]
[HarmonyPriority(700)]
[HarmonyPatch("Save")]
private static void SavePrefix(Skills __instance, out Dictionary<SkillType, Skill> __state)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: 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_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Expected O, but got Unknown
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Expected O, but got Unknown
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
Log.LogInfo("Skills.Save.Prefix()", Log.InfoLevel.Medium);
if ((Object)(object)FortifySkillData.s_AssociatedPlayer != (Object)(object)__instance.m_player)
{
__state = null;
Log.LogInfo("New character: skip saving Fortified Skill data", Log.InfoLevel.Medium);
return;
}
__state = new Dictionary<SkillType, Skill>();
foreach (KeyValuePair<SkillType, Skill> skillDatum in __instance.m_skillData)
{
if (skillDatum.Value?.m_info != null)
{
Log.LogInfo("Copying " + FortifySkillData.LocalizeSkillName(skillDatum.Key) + " a.k.a " + skillDatum.Value.m_info.m_description, Log.InfoLevel.High);
__state[skillDatum.Key] = skillDatum.Value;
}
}
foreach (KeyValuePair<SkillType, FortifySkillData> s_FortifySkill in FortifySkillData.s_FortifySkills)
{
FortifySkillData value = s_FortifySkill.Value;
if (value == null)
{
continue;
}
SkillDef info = value.Info;
if (info != null)
{
_ = info.m_skill;
if (0 == 0)
{
Log.LogInfo("Making dummy skill for " + FortifySkillData.LocalizeSkillName(s_FortifySkill.Key) + " a.k.a " + s_FortifySkill.Value.Info.m_description, Log.InfoLevel.High);
SkillDef val = new SkillDef
{
m_skill = FortifySkillData.MapDummySkill(s_FortifySkill.Value.Info.m_skill),
m_description = s_FortifySkill.Value.Info?.m_description
};
Skill value2 = new Skill(val)
{
m_accumulator = s_FortifySkill.Value.FortifyAccumulator,
m_level = s_FortifySkill.Value.FortifyLevel
};
__instance.m_skillData[val.m_skill] = value2;
}
}
}
}
[HarmonyPostfix]
[HarmonyPatch("Save")]
private static void SavePostfix(Skills __instance, Dictionary<SkillType, Skill> __state)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
if (__state == null)
{
Log.LogInfo("No fortified skill data, skip removing dummy skills.", Log.InfoLevel.Medium);
return;
}
Log.LogInfo("Reseting m_skillData to remove dummy skills.", Log.InfoLevel.Medium);
__instance.m_skillData.Clear();
foreach (KeyValuePair<SkillType, Skill> item in __state)
{
if (Log.VerbosityLevel >= Log.InfoLevel.High)
{
string text = FortifySkillData.LocalizeSkillName(item.Key);
Log.LogInfo("Copying " + text + " a.k.a " + item.Value.m_info.m_description);
}
__instance.m_skillData[item.Key] = item.Value;
}
}
}
[HarmonyPatch(typeof(Skill))]
public static class SkillPatch
{
[HarmonyPrefix]
[HarmonyPriority(700)]
[HarmonyPatch("Raise")]
private static void RaiseFortifySkill(Skill __instance, ref float factor)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: 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)
Log.LogInfo("Raising XP for Fortified skill", Log.InfoLevel.Medium);
float num = __instance.m_info.m_increseStep * factor;
FortifySkillData fortifySkillData;
if (FortifySkillData.s_FortifySkills.ContainsKey(__instance.m_info.m_skill))
{
fortifySkillData = FortifySkillData.s_FortifySkills[__instance.m_info.m_skill];
}
else
{
fortifySkillData = new FortifySkillData(__instance.m_info, __instance.m_level, 0f);
FortifySkillData.s_FortifySkills[__instance.m_info.m_skill] = fortifySkillData;
}
if (!(fortifySkillData.FortifyLevel >= 100f))
{
float fortifyXPPerLevel = FortifySkillsRedux.Instance.GetFortifyXPPerLevel(__instance);
float fortityMaxXPRate = FortifySkillsRedux.Instance.GetFortityMaxXPRate(__instance);
fortifySkillData.FortifyAccumulator += num * Mathf.Clamp((__instance.m_level - fortifySkillData.FortifyLevel) * fortifyXPPerLevel, 0f, fortityMaxXPRate);
Log.LogInfo("Fortify XP:" + fortifySkillData.FortifyAccumulator, Log.InfoLevel.Medium);
if (fortifySkillData.FortifyAccumulator >= GetLevelUpXpRequirement(fortifySkillData.FortifyLevel))
{
LevelUpFortifySkill(fortifySkillData);
}
}
}
private static void LevelUpFortifySkill(FortifySkillData fortifySkill)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: 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)
MessageType val = (MessageType)(((int)fortifySkill.FortifyLevel != 0) ? 1 : 2);
fortifySkill.FortifyLevel = Mathf.Clamp(fortifySkill.FortifyLevel + 1f, 0f, 100f);
fortifySkill.FortifyAccumulator = 0f;
Log.LogInfo("Fortify level:" + fortifySkill.FortifyLevel, Log.InfoLevel.Medium);
Player localPlayer = Player.m_localPlayer;
GameObject prefab = ZNetScene.instance.GetPrefab("vfx_ColdBall_launch");
GameObject prefab2 = localPlayer.m_skillLevelupEffects.m_effectPrefabs[1].m_prefab;
Object.Instantiate<GameObject>(prefab, ((Character)localPlayer).GetHeadPoint(), Quaternion.Euler(-90f, 0f, 0f));
Object.Instantiate<GameObject>(prefab2, ((Character)localPlayer).GetHeadPoint(), Quaternion.identity);
((Character)localPlayer).Message(val, $"Fortified skill improved {fortifySkill.SkillName}: {(int)fortifySkill.FortifyLevel}", 0, fortifySkill.Info.m_icon);
}
private static float GetLevelUpXpRequirement(float level)
{
return Mathf.Pow(level + 1f, 1.5f) * 0.5f + 0.5f;
}
[HarmonyPrefix]
[HarmonyPriority(0)]
[HarmonyPatch("Raise")]
private static void ActiveSkillXpMultiplier(Skill __instance, ref float factor)
{
Log.LogInfo("Applying active skill XP multiplier", Log.InfoLevel.Medium);
factor *= FortifySkillsRedux.Instance.GetActiveSkillXPMult(__instance);
}
}
[HarmonyPatch(typeof(SkillsDialog))]
public static class SkillsUIPatches
{
[HarmonyPostfix]
[HarmonyPatch("Setup")]
private static void SkillsDialogSetupPostfix(SkillsDialog __instance, Player player)
{
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
Log.LogInfo("SkillsDialog.Setup.Postfix()", Log.InfoLevel.Medium);
List<Skill> skillList = ((Character)player).GetSkills().GetSkillList();
foreach (GameObject element in __instance.m_elements)
{
string text = element.GetComponentInChildren<UITooltip>().m_text;
foreach (Skill item in skillList)
{
if (item.m_info.m_description == text)
{
if (FortifySkillData.s_FortifySkills.TryGetValue(item.m_info.m_skill, out var value))
{
string text2 = $" ({(int)value.FortifyLevel})";
TMP_Text component = ((Component)Utils.FindChild(element.transform, "leveltext", (IterativeSearchType)0)).GetComponent<TMP_Text>();
component.text += text2;
}
else
{
Log.LogInfo($"No Fortified skill for: {item.m_info.m_skill}", Log.InfoLevel.Medium);
}
break;
}
}
}
}
}
}
namespace Configs
{
public static class ConfigFileExtensions
{
public static bool DisableSaveOnConfigSet(this ConfigFile configFile)
{
bool saveOnConfigSet = configFile.SaveOnConfigSet;
configFile.SaveOnConfigSet = false;
return saveOnConfigSet;
}
}
internal sealed class ConfigFileWatcher
{
private const long RELOAD_DELAY = 10000000L;
private DateTime lastReadTime = DateTime.MinValue;
private readonly ConfigFile configFile;
private readonly string ConfigFileDir;
private readonly string ConfigFileName;
internal event Action OnConfigFileReloaded;
internal ConfigFileWatcher(ConfigFile configFile)
{
this.configFile = configFile;
ConfigFileDir = Directory.GetParent(configFile.ConfigFilePath).FullName;
ConfigFileName = Path.GetFileName(configFile.ConfigFilePath);
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(ConfigFileDir, ConfigFileName);
fileSystemWatcher.Changed += ReloadConfigFile;
fileSystemWatcher.Created += ReloadConfigFile;
fileSystemWatcher.Renamed += ReloadConfigFile;
fileSystemWatcher.IncludeSubdirectories = true;
fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher.EnableRaisingEvents = true;
}
private void InvokeOnConfigFileReloaded()
{
this.OnConfigFileReloaded?.SafeInvoke();
}
internal void ReloadConfigFile(object sender, FileSystemEventArgs eventArgs)
{
DateTime now = DateTime.Now;
long num = now.Ticks - lastReadTime.Ticks;
if (!File.Exists(configFile.ConfigFilePath) || num < 10000000)
{
return;
}
try
{
Log.LogInfo("Reloading " + configFile.ConfigFilePath);
bool saveOnConfigSet = configFile.DisableSaveOnConfigSet();
configFile.Reload();
configFile.SaveOnConfigSet = saveOnConfigSet;
lastReadTime = now;
InvokeOnConfigFileReloaded();
}
catch
{
Log.LogError("There was an issue loading " + configFile.ConfigFilePath);
Log.LogError("Please check your config entries for spelling and format!");
}
}
}
internal static class SafeInvokeEvent
{
internal static void SafeInvoke(this Action events)
{
if (events == null)
{
return;
}
Delegate[] invocationList = events.GetInvocationList();
for (int i = 0; i < invocationList.Length; i++)
{
Action action = (Action)invocationList[i];
try
{
action();
}
catch (Exception arg)
{
Log.LogWarning("Exception thrown at event " + new StackFrame(1).GetMethod().Name + $" in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{arg}");
}
}
}
}
}