Decompiled source of SkillPoints v1.1.0

SkillPoints.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using Candide;
using Candide.CandideUI;
using Candide.GameModels;
using Candide.GameModels.Managers;
using Candide.GameModels.Services;
using Candide.Sound;
using Candide.Terminal;
using CandideServer.MessageModels.Skills;
using CandideServer.ServerControllers;
using HarmonyLib;
using Shared.Models.Player;
using Shared.Models.Skill;
using SkillPoints.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace SkillPoints
{
	public enum SkillProgressionMode
	{
		Hybrid,
		MilestonesOnly,
		SoftenedCurveOnly,
		Vanilla
	}
	[BepInPlugin("com.atomiz.romestead.skillpoints", "Skill Points Overhaul", "1.1.0")]
	public class SkillPointsPlugin : BasePlugin
	{
		public const string PluginGuid = "com.atomiz.romestead.skillpoints";

		public const string PluginName = "Skill Points Overhaul";

		public const string PluginVersion = "1.1.0";

		public static ConfigEntry<bool> OverhaulEnabled;

		public static ConfigEntry<SkillProgressionMode> ModeConfig;

		public static ConfigEntry<float> CurveGrowthFactor;

		public static ConfigEntry<float> CurveBaseXp;

		public static ConfigEntry<string> MilestonesConfig;

		public static ConfigEntry<int> MilestoneBonusPoints;

		public static ConfigEntry<bool> AutoReconcileOnLoad;

		private static bool _terminalCommandRegistered;

		private static readonly HashSet<string> _reconciledCharacters = new HashSet<string>();

		[field: CompilerGenerated]
		public static SkillPointsPlugin Instance
		{
			[CompilerGenerated]
			get;
			[CompilerGenerated]
			private set;
		}

		public override void Load()
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			Instance = this;
			OverhaulEnabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Whether the Skill Points progression overhaul is enabled.");
			ModeConfig = ((BasePlugin)this).Config.Bind<SkillProgressionMode>("General", "Mode", SkillProgressionMode.Hybrid, "Progression mode: Hybrid (softened curve + milestone bonuses), MilestonesOnly, SoftenedCurveOnly, or Vanilla.");
			CurveGrowthFactor = ((BasePlugin)this).Config.Bind<float>("Curve", "GrowthFactor", 1.05f, "Exponential growth rate per point in the curve (default 1.05 vs vanilla 1.20). Prevents mid/late-game grind walls.");
			CurveBaseXp = ((BasePlugin)this).Config.Bind<float>("Curve", "BaseXp", 1500f, "Base XP required for the first favor point (default 1500).");
			MilestonesConfig = ((BasePlugin)this).Config.Bind<string>("Milestones", "Levels", "25,50,75,100", "Comma-separated skill levels that award bonus Skill Points upon reaching them.");
			MilestoneBonusPoints = ((BasePlugin)this).Config.Bind<int>("Milestones", "PointsPerMilestone", 1, "Number of bonus SP awarded when a skill crosses each milestone level (default 1).");
			AutoReconcileOnLoad = ((BasePlugin)this).Config.Bind<bool>("SaveCompatibility", "AutoReconcileOnLoad", true, "Automatically check and grant missing SP for existing / already upgraded save files upon loading.");
			Harmony val = new Harmony("com.atomiz.romestead.skillpoints");
			val.PatchAll(typeof(SkillPointsPatches));
			val.PatchAll(typeof(SkillPointsPlugin));
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Skill Points Overhaul");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("] loaded successfully! Version: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.1.0");
			}
			log.LogInfo(val2);
		}

		public static int[] GetMilestones()
		{
			try
			{
				string value = MilestonesConfig.Value;
				char[] array = new char[3];
				RuntimeHelpers.InitializeArray((global::System.Array)array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
				string[] array2 = value.Split(array, (StringSplitOptions)1);
				List<int> val = new List<int>();
				string[] array3 = array2;
				int num = default(int);
				for (int i = 0; i < array3.Length; i++)
				{
					if (int.TryParse(array3[i].Trim(), ref num) && num > 0)
					{
						val.Add(num);
					}
				}
				if (val.Count > 0)
				{
					val.Sort();
					return val.ToArray();
				}
			}
			catch
			{
			}
			int[] array4 = new int[4];
			RuntimeHelpers.InitializeArray((global::System.Array)array4, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			return array4;
		}

		public static void ReconcilePlayerSP(PlayerCharacterModel player, bool notifyUser = true)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			if (player == null || !OverhaulEnabled.Value)
			{
				return;
			}
			int num = 0;
			if (player.Skills.Favours != null)
			{
				Enumerator<string, int> enumerator = player.Skills.Favours.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						num += enumerator.Current.Value;
					}
				}
				finally
				{
					((global::System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			int currentFavourPoints = player.Skills.CurrentFavourPoints;
			int num2 = num + currentFavourPoints;
			int[] milestones = GetMilestones();
			int value = MilestoneBonusPoints.Value;
			int num3 = 0;
			if (player.Skills.CharacterSkills != null)
			{
				Enumerator<string, CharacterSkill> enumerator2 = player.Skills.CharacterSkills.Values.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						CharacterSkill current = enumerator2.Current;
						int[] array = milestones;
						foreach (int num4 in array)
						{
							if (current.Level >= num4)
							{
								num3++;
							}
						}
					}
				}
				finally
				{
					((global::System.IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			int num5 = ((ModeConfig.Value == SkillProgressionMode.Hybrid || ModeConfig.Value == SkillProgressionMode.MilestonesOnly) ? (num3 * value) : 0);
			double num6 = 0.0;
			if (player.Skills.CharacterSkills != null)
			{
				Enumerator<string, CharacterSkill> enumerator2 = player.Skills.CharacterSkills.Values.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						CharacterSkill current2 = enumerator2.Current;
						for (int j = 1; j < current2.Level; j++)
						{
							num6 += Math.Round(100.0 * Math.Pow(1.1, (double)j));
						}
						num6 += (double)current2.CurrentExperience;
					}
				}
				finally
				{
					((global::System.IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
			int num7 = 0;
			double num8 = num6;
			if (ModeConfig.Value == SkillProgressionMode.Hybrid || ModeConfig.Value == SkillProgressionMode.SoftenedCurveOnly)
			{
				double num9 = CurveBaseXp.Value;
				double num10 = CurveGrowthFactor.Value;
				while (true)
				{
					double num11 = Math.Round(num9 * Math.Pow(num10, (double)(num7 + 1)));
					if (!(num8 >= num11))
					{
						break;
					}
					num8 -= num11;
					num7++;
				}
			}
			else if (ModeConfig.Value == SkillProgressionMode.Vanilla)
			{
				while (true)
				{
					double num12 = Math.Round(1500.0 * Math.Pow(1.2, (double)(num7 + 1)));
					if (!(num8 >= num12))
					{
						break;
					}
					num8 -= num12;
					num7++;
				}
			}
			int num13 = num7 + num5;
			int num14 = num13 - num2;
			if (num14 > 0)
			{
				player.Skills.CurrentFavourPoints += num14;
				player.Skills.FavourLevel = Math.Max(player.Skills.FavourLevel, num13);
				player.Skills.TotalExperience = (float)num8;
				SkillsManager.OnFavourChanged(player, num14, true);
				SoundPlayer.PlayEventOneShot("event:/player/player_gain_favourpoint", 1f, 1f);
				string text = $"[SkillPoints] Reconciled SP for existing character: +{num14} bonus SP granted! (Total: {num13} | Spent: {num} | Available: {player.Skills.CurrentFavourPoints} | Milestones: {num5} | Curve: {num7})";
				SkillPointsPlugin instance = Instance;
				if (instance != null)
				{
					ManualLogSource log = ((BasePlugin)instance).Log;
					if (log != null)
					{
						log.LogInfo((object)text);
					}
				}
				if (!notifyUser)
				{
					return;
				}
				try
				{
					CandideEngine game = Globals.Game;
					if (game != null)
					{
						GameTerminal terminal = game.Terminal;
						if (terminal != null)
						{
							terminal.AddLine(text);
						}
					}
					return;
				}
				catch
				{
					return;
				}
			}
			string text2 = $"[SkillPoints] Character verified: Current SP {num2} (Spent: {num}, Available: {currentFavourPoints}) >= Expected {num13} (Curve: {num7}, Milestones: {num5}). No missing points.";
			SkillPointsPlugin instance2 = Instance;
			if (instance2 != null)
			{
				ManualLogSource log2 = ((BasePlugin)instance2).Log;
				if (log2 != null)
				{
					log2.LogInfo((object)text2);
				}
			}
			if (!notifyUser)
			{
				return;
			}
			try
			{
				CandideEngine game2 = Globals.Game;
				if (game2 != null)
				{
					GameTerminal terminal2 = game2.Terminal;
					if (terminal2 != null)
					{
						terminal2.AddLine(text2);
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(CandideEngine), "Update")]
		[HarmonyPostfix]
		public static void CandideEngine_Update_Postfix()
		{
			if (!OverhaulEnabled.Value || !AutoReconcileOnLoad.Value)
			{
				return;
			}
			try
			{
				PlayerCharacterModel val = GameState.LocalPlayer?.Character?.Character;
				if (val != null && val.Skills.CharacterSkills != null && val.Skills.CharacterSkills.Count > 0)
				{
					string text = ((!string.IsNullOrEmpty(val.Name)) ? val.Name : ((object)global::System.Runtime.CompilerServices.Unsafe.As<Guid, Guid>(ref val.EntityId)/*cast due to .constrained prefix*/).ToString());
					if (!_reconciledCharacters.Contains(text))
					{
						_reconciledCharacters.Add(text);
						ReconcilePlayerSP(val);
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(PlayerUi), "ShowSkillsAndFavoursWindow")]
		[HarmonyPrefix]
		public static void ShowSkillsAndFavoursWindow_Prefix()
		{
			if (!OverhaulEnabled.Value)
			{
				return;
			}
			try
			{
				PlayerCharacterModel val = GameState.LocalPlayer?.Character?.Character;
				if (val != null && val.Skills.CharacterSkills != null && val.Skills.CharacterSkills.Count > 0)
				{
					ReconcilePlayerSP(val, notifyUser: false);
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(CandideEngine), "AddTerminalCommands")]
		[HarmonyPostfix]
		public static void CandideEngine_AddTerminalCommands_Postfix(CandideEngine __instance)
		{
			RegisterTerminalCommands(__instance?.Terminal);
		}

		public static void RegisterTerminalCommands(GameTerminal terminal)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			if (terminal == null || _terminalCommandRegistered)
			{
				return;
			}
			try
			{
				terminal.AddCommand("skillpoints", new TerminalCommandAction(HandleSkillPointsStatusCommand));
				terminal.AddCommand("reconcilesp", new TerminalCommandAction(HandleReconcileCommand));
				terminal.AddCommand("addpoints", new TerminalCommandAction(HandleAddPointsCommand));
				terminal.AddCommand("giveskillpoints", new TerminalCommandAction(HandleAddPointsCommand));
				terminal.AddCommand("skillpointmode", new TerminalCommandAction(HandleSkillPointModeCommand));
				_terminalCommandRegistered = true;
				SkillPointsPlugin instance = Instance;
				if (instance != null)
				{
					ManualLogSource log = ((BasePlugin)instance).Log;
					if (log != null)
					{
						log.LogInfo((object)"[SkillPoints] In-game terminal commands registered.");
					}
				}
			}
			catch (global::System.Exception ex)
			{
				SkillPointsPlugin instance2 = Instance;
				if (instance2 == null)
				{
					return;
				}
				ManualLogSource log2 = ((BasePlugin)instance2).Log;
				if (log2 != null)
				{
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(51, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SkillPoints] Failed to register terminal command: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					log2.LogWarning(val);
				}
			}
		}

		public static object HandleSkillPointsStatusCommand(string[] parameters)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			PlayerCharacterModel val = GameState.LocalPlayer?.Character?.Character;
			if (val == null)
			{
				return "[SkillPoints] No active player character found.";
			}
			int num = 0;
			if (val.Skills.Favours != null)
			{
				Enumerator<string, int> enumerator = val.Skills.Favours.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						num += enumerator.Current.Value;
					}
				}
				finally
				{
					((global::System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}
			int currentFavourPoints = val.Skills.CurrentFavourPoints;
			int num2 = num + currentFavourPoints;
			return $"[SkillPoints] Mode: {ModeConfig.Value} | Spent SP: {num} | Available SP: {currentFavourPoints} | Total SP: {num2} | Next Favour XP: {val.Skills.TotalExperience:F0}/{((Skills)(ref val.Skills)).ExperienceRequiredForNextFavour:F0}";
		}

		public static object HandleReconcileCommand(string[] parameters)
		{
			PlayerCharacterModel val = GameState.LocalPlayer?.Character?.Character;
			if (val == null)
			{
				return "[SkillPoints] No active player character found.";
			}
			ReconcilePlayerSP(val);
			return "[SkillPoints] Reconciliation complete.";
		}

		public static object HandleAddPointsCommand(string[] parameters)
		{
			int num = 1;
			int num2 = default(int);
			if (parameters.Length > 1 && int.TryParse(parameters[1], ref num2))
			{
				num = num2;
			}
			PlayerCharacterModel val = GameState.LocalPlayer?.Character?.Character;
			if (val != null)
			{
				val.Skills.CurrentFavourPoints += num;
				val.Skills.FavourLevel += num;
				SkillsManager.OnFavourChanged(val, num, true);
				SoundPlayer.PlayEventOneShot("event:/player/player_gain_favourpoint", 1f, 1f);
				return $"[SkillPoints] Granted {num} Skill Point(s)! Total available: {val.Skills.CurrentFavourPoints}";
			}
			return "[SkillPoints] Player character not found in active session.";
		}

		public static object HandleSkillPointModeCommand(string[] parameters)
		{
			if (parameters.Length > 1)
			{
				string text = parameters[1].ToLowerInvariant();
				if (text.Contains("hyb") || text == "0")
				{
					ModeConfig.Value = SkillProgressionMode.Hybrid;
				}
				else if (text.Contains("mile") || text == "1")
				{
					ModeConfig.Value = SkillProgressionMode.MilestonesOnly;
				}
				else if (text.Contains("curve") || text == "2")
				{
					ModeConfig.Value = SkillProgressionMode.SoftenedCurveOnly;
				}
				else if (text.Contains("vanilla") || text == "3")
				{
					ModeConfig.Value = SkillProgressionMode.Vanilla;
				}
				return $"[SkillPoints] Mode set to {ModeConfig.Value}.";
			}
			return $"[SkillPoints] Current mode: {ModeConfig.Value}. Options: hybrid, milestones, curve, vanilla. Usage: skillpointmode [mode]";
		}
	}
}
namespace SkillPoints.Patches
{
	public static class SkillPointsPatches
	{
		private static readonly MethodInfo OnLevelUpMethod = AccessTools.Method(typeof(SkillsManager), "OnLevelUp", (global::System.Type[])null, (global::System.Type[])null);

		private static void TriggerOnLevelUp(CharacterSkill skill, int levelsGained)
		{
			try
			{
				MethodInfo onLevelUpMethod = OnLevelUpMethod;
				if (onLevelUpMethod != null)
				{
					((MethodBase)onLevelUpMethod).Invoke((object)null, new object[2] { skill, levelsGained });
				}
			}
			catch
			{
			}
		}

		private static void ProcessSkillProgression(PlayerCharacterModel player, CharacterSkill skill, int oldLvl, int newLvl)
		{
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			int[] milestones = SkillPointsPlugin.GetMilestones();
			int value = SkillPointsPlugin.MilestoneBonusPoints.Value;
			if (SkillPointsPlugin.ModeConfig.Value == SkillProgressionMode.Hybrid || SkillPointsPlugin.ModeConfig.Value == SkillProgressionMode.MilestonesOnly)
			{
				int[] array = milestones;
				foreach (int num in array)
				{
					if (oldLvl >= num || newLvl < num)
					{
						continue;
					}
					player.Skills.CurrentFavourPoints += value;
					player.Skills.FavourLevel += value;
					string text = $"[SkillPoints] Milestone reached! {skill.Name ?? skill.SkillId} reached Level {newLvl}! (+{value} SP)";
					SkillPointsPlugin instance = SkillPointsPlugin.Instance;
					if (instance != null)
					{
						ManualLogSource log = ((BasePlugin)instance).Log;
						if (log != null)
						{
							log.LogInfo((object)text);
						}
					}
					try
					{
						CandideEngine game = Globals.Game;
						if (game != null)
						{
							GameTerminal terminal = game.Terminal;
							if (terminal != null)
							{
								terminal.AddLine(text);
							}
						}
					}
					catch
					{
					}
				}
			}
			if (SkillPointsPlugin.ModeConfig.Value == SkillProgressionMode.Hybrid || SkillPointsPlugin.ModeConfig.Value == SkillProgressionMode.SoftenedCurveOnly)
			{
				player.Skills.TotalExperience += skill.ExperienceRequiredToLevelUp;
				double num2 = SkillPointsPlugin.CurveBaseXp.Value;
				double num3 = SkillPointsPlugin.CurveGrowthFactor.Value;
				int num4 = 0;
				if (player.Skills.CharacterSkills != null)
				{
					Enumerator<string, CharacterSkill> enumerator = player.Skills.CharacterSkills.Values.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							CharacterSkill current = enumerator.Current;
							int[] array = milestones;
							foreach (int num5 in array)
							{
								if (current.Level >= num5)
								{
									num4 += value;
								}
							}
						}
					}
					finally
					{
						((global::System.IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
					}
				}
				int num6 = Math.Max(0, player.Skills.FavourLevel - num4);
				float num7 = (float)Math.Round(num2 * Math.Pow(num3, (double)(num6 + 1)));
				while (player.Skills.TotalExperience >= num7)
				{
					player.Skills.CurrentFavourPoints++;
					player.Skills.FavourLevel++;
					player.Skills.TotalExperience -= num7;
					num6++;
					num7 = (float)Math.Round(num2 * Math.Pow(num3, (double)(num6 + 1)));
				}
			}
			else if (SkillPointsPlugin.ModeConfig.Value == SkillProgressionMode.Vanilla)
			{
				player.Skills.TotalExperience += skill.ExperienceRequiredToLevelUp;
				float experienceRequiredForNextFavour = ((Skills)(ref player.Skills)).ExperienceRequiredForNextFavour;
				if (player.Skills.TotalExperience >= experienceRequiredForNextFavour)
				{
					player.Skills.CurrentFavourPoints++;
					player.Skills.FavourLevel++;
					player.Skills.TotalExperience -= experienceRequiredForNextFavour;
				}
			}
		}

		[HarmonyPatch(typeof(SkillsManager), "LevelUpSkill")]
		[HarmonyPrefix]
		public static bool LevelUpSkill_Prefix(PlayerCharacterModel playerCharacter, CharacterSkill skill, int amountOfLevels, ref int __result)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			if (!SkillPointsPlugin.OverhaulEnabled.Value)
			{
				return true;
			}
			try
			{
				int num = amountOfLevels;
				int currentFavourPoints = playerCharacter.Skills.CurrentFavourPoints;
				while (num > 0 && skill.Level < 100)
				{
					int level = skill.Level;
					skill.Level++;
					int level2 = skill.Level;
					num--;
					ProcessSkillProgression(playerCharacter, skill, level, level2);
				}
				int num2 = playerCharacter.Skills.CurrentFavourPoints - currentFavourPoints;
				int num3 = amountOfLevels - num;
				if (num3 > 0)
				{
					TriggerOnLevelUp(skill, num3);
					SkillsService.Send_PlayerSkillsChanged(new PlayerSkillsChangedMessage
					{
						CurrentSkillLevel = skill.Level,
						SkillId = skill.SkillId
					});
				}
				if (num2 > 0)
				{
					SkillsManager.OnFavourChanged(playerCharacter, num2, true);
					SoundPlayer.PlayEventOneShot("event:/player/player_gain_favourpoint", 1f, 1f);
				}
				__result = num;
				return false;
			}
			catch (global::System.Exception ex)
			{
				SkillPointsPlugin instance = SkillPointsPlugin.Instance;
				if (instance != null)
				{
					ManualLogSource log = ((BasePlugin)instance).Log;
					if (log != null)
					{
						bool flag = default(bool);
						BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(44, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SkillPoints] Error in LevelUpSkill prefix: ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<global::System.Exception>(ex);
						}
						log.LogError(val);
					}
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(SkillsSController), "IncreaseSkillLevel")]
		[HarmonyPrefix]
		public static bool IncreaseSkillLevel_Prefix(PlayerCharacterModel characterModel, string skillId, int newLevel, ref bool __result)
		{
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			if (!SkillPointsPlugin.OverhaulEnabled.Value)
			{
				return true;
			}
			try
			{
				CharacterSkill val = default(CharacterSkill);
				if (!characterModel.Skills.CharacterSkills.TryGetValue(skillId, ref val))
				{
					__result = false;
					return false;
				}
				if (newLevel < 0 || newLevel > 100)
				{
					__result = false;
					return false;
				}
				if (newLevel < val.Level)
				{
					__result = false;
					return false;
				}
				int currentFavourPoints = characterModel.Skills.CurrentFavourPoints;
				int num = newLevel - val.Level;
				while (num > 0 && val.Level < 100)
				{
					int level = val.Level;
					CharacterSkill obj = val;
					obj.Level++;
					int level2 = val.Level;
					num--;
					ProcessSkillProgression(characterModel, val, level, level2);
				}
				int num2 = characterModel.Skills.CurrentFavourPoints - currentFavourPoints;
				if (num2 > 0)
				{
					SkillsManager.OnFavourChanged(characterModel, num2, true);
					SoundPlayer.PlayEventOneShot("event:/player/player_gain_favourpoint", 1f, 1f);
				}
				__result = true;
				return false;
			}
			catch (global::System.Exception ex)
			{
				SkillPointsPlugin instance = SkillPointsPlugin.Instance;
				if (instance != null)
				{
					ManualLogSource log = ((BasePlugin)instance).Log;
					if (log != null)
					{
						bool flag = default(bool);
						BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(50, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SkillPoints] Error in IncreaseSkillLevel prefix: ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<global::System.Exception>(ex);
						}
						log.LogError(val2);
					}
				}
				return true;
			}
		}
	}
}