Decompiled source of SkillsReworked v1.8.2

SkillsReworked.dll

Decompiled 19 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using Groups;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using SkillsReworked.Api;
using SkillsReworked.Bootstrap;
using SkillsReworked.Commands;
using SkillsReworked.Infrastructure.Networking;
using SkillsReworked.Integration.Groups;
using SkillsReworked.Integration.Party;
using SkillsReworked.Integration.SkillManager;
using SkillsReworked.Integration.SocialSystem;
using SkillsReworked.Persistence;
using SkillsReworked.Systems.Common;
using SkillsReworked.Systems.Costs;
using SkillsReworked.Systems.Prestige;
using SkillsReworked.Systems.Progression;
using SkillsReworked.Systems.Rebirth;
using SkillsReworked.Systems.Reset;
using SkillsReworked.Systems.Rewards;
using SkillsReworked.UI.Dialogs;
using SkillsReworked.UI.LevelHud;
using SkillsReworked.UI.SkillPanel;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SkillsReworked")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1bc49e5795a1c1b6d926f4996658c5029ad19805")]
[assembly: AssemblyProduct("SkillsReworked")]
[assembly: AssemblyTitle("SkillsReworked")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 SkillsReworked.UI.SkillPanel
{
	public class BlinkingTextEffect : MonoBehaviour
	{
		public Text Target;

		public Color ColorA = Color.white;

		public Color ColorB = Color.white;

		public float Speed = 2f;

		private void Update()
		{
			//IL_0038: 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)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Target == (Object)null))
			{
				float num = (Mathf.Sin(Time.unscaledTime * Speed) + 1f) * 0.5f;
				((Graphic)Target).color = Color.Lerp(ColorA, ColorB, num);
			}
		}

		public static Color Darken(Color c, float factor)
		{
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return new Color(c.r * factor, c.g * factor, c.b * factor, c.a);
		}

		public static void SetActive(Text target, bool active, Color colorA, Color colorB, Color restColor, float speed = 5f)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			if (!active)
			{
				BlinkingTextEffect component = ((Component)target).GetComponent<BlinkingTextEffect>();
				if ((Object)(object)component != (Object)null)
				{
					((Behaviour)component).enabled = false;
				}
				((Graphic)target).color = restColor;
				return;
			}
			BlinkingTextEffect blinkingTextEffect = ((Component)target).GetComponent<BlinkingTextEffect>();
			if ((Object)(object)blinkingTextEffect == (Object)null)
			{
				blinkingTextEffect = ((Component)target).gameObject.AddComponent<BlinkingTextEffect>();
			}
			blinkingTextEffect.Target = target;
			blinkingTextEffect.ColorA = colorA;
			blinkingTextEffect.ColorB = colorB;
			blinkingTextEffect.Speed = speed;
			((Behaviour)blinkingTextEffect).enabled = true;
		}
	}
	public class SkillRowController : MonoBehaviour
	{
		public static readonly List<SkillRowController> ActiveControllers = new List<SkillRowController>();

		public SkillType SkillType;

		public Text CounterText;

		public InputField CounterInput;

		internal GameObject PlusButtonObj;

		internal GameObject MinusButtonObj;

		internal GameObject CounterTextObj;

		private void Awake()
		{
			ActiveControllers.Add(this);
		}

		private void OnDestroy()
		{
			ActiveControllers.Remove(this);
		}

		public void RefreshCounter()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)CounterText == (Object)null)
			{
				return;
			}
			bool flag = IsSkillMaxed();
			if ((Object)(object)PlusButtonObj != (Object)null)
			{
				PlusButtonObj.SetActive(!flag);
			}
			if ((Object)(object)MinusButtonObj != (Object)null)
			{
				MinusButtonObj.SetActive(!flag);
			}
			if ((Object)(object)CounterTextObj != (Object)null)
			{
				CounterTextObj.SetActive(!flag);
			}
			if (!flag)
			{
				int allocated = SkillUiController.GetAllocated(SkillType);
				if ((Object)(object)CounterInput != (Object)null)
				{
					CounterInput.text = allocated.ToString();
				}
				else
				{
					CounterText.text = allocated.ToString();
				}
				BlinkingTextEffect.SetActive(CounterText, allocated > 0, BlinkingTextEffect.Darken(SkillUiController.PlannedColor, 0.55f), SkillUiController.PlannedColor, Color.white);
			}
		}

		private bool IsSkillMaxed()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Player val = SkillUiController.CurrentPlayer ?? Player.m_localPlayer;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Skills skills = ((Character)val).GetSkills();
			Skill val2 = ((skills != null) ? skills.GetSkill(SkillType) : null);
			if (val2 == null)
			{
				return false;
			}
			float currentSkillCap = SkillCapPolicy.GetCurrentSkillCap(val);
			return val2.m_level >= currentSkillCap;
		}

		public static void DestroyAll()
		{
			List<SkillRowController> list = new List<SkillRowController>(ActiveControllers);
			ActiveControllers.Clear();
			foreach (SkillRowController item in list)
			{
				if (!((Object)(object)item == (Object)null))
				{
					if ((Object)(object)item.PlusButtonObj != (Object)null)
					{
						Object.Destroy((Object)(object)item.PlusButtonObj);
					}
					if ((Object)(object)item.MinusButtonObj != (Object)null)
					{
						Object.Destroy((Object)(object)item.MinusButtonObj);
					}
					if ((Object)(object)item.CounterTextObj != (Object)null)
					{
						Object.Destroy((Object)(object)item.CounterTextObj);
					}
					Object.Destroy((Object)(object)item);
				}
			}
		}
	}
	public static class SkillRowDecorator
	{
		public static void AddButtons(RectTransform row, SkillType skillType)
		{
			//IL_00c1: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Expected O, but got Unknown
			//IL_0039: 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)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			Transform val = Utils.FindChild((Transform)(object)row, "name", (IterativeSearchType)0);
			RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null);
			if (val2 != null)
			{
				Rect rect = val2.rect;
				float width = ((Rect)(ref rect)).width;
				float num = Mathf.Min(width, 100f);
				if (num < width)
				{
					float num2 = val2.anchoredPosition.x - val2.pivot.x * width;
					val2.SetSizeWithCurrentAnchors((Axis)0, num);
					val2.anchoredPosition = new Vector2(num2 + val2.pivot.x * num, val2.anchoredPosition.y);
				}
			}
			SkillRowController skillRowController = ((Component)row).gameObject.AddComponent<SkillRowController>();
			skillRowController.SkillType = skillType;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			GameObject val4 = GUIManager.Instance.CreateButton("+", (Transform)(object)row, val3, val3, new Vector2(-10f, 0f), 24f, 24f);
			GameObject val5 = GUIManager.Instance.CreateButton("-", (Transform)(object)row, val3, val3, new Vector2(-35f, 0f), 24f, 24f);
			GameObject val6 = CreateCounterInputField(row, val3);
			skillRowController.CounterInput = val6.GetComponent<InputField>();
			skillRowController.CounterText = skillRowController.CounterInput.textComponent;
			skillRowController.PlusButtonObj = val4;
			skillRowController.MinusButtonObj = val5;
			skillRowController.CounterTextObj = val6;
			skillRowController.RefreshCounter();
			SkillRowController ctrl = skillRowController;
			((UnityEvent)val4.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				Player val7 = SkillUiController.CurrentPlayer ?? Player.m_localPlayer;
				if (!((Object)(object)val7 == (Object)null) && SkillUiController.GetCurrentUnspent() > 0)
				{
					Skills skills = ((Character)val7).GetSkills();
					Skill val8 = ((skills != null) ? skills.GetSkill(ctrl.SkillType) : null);
					if (val8 != null)
					{
						float num3 = val8.m_level + (float)SkillUiController.GetAllocated(ctrl.SkillType) + 1f;
						if (num3 > SkillCapPolicy.GetCurrentSkillCap(val7))
						{
							return;
						}
					}
					SkillUiController.ChangeAllocated(ctrl.SkillType, 1);
					ctrl.RefreshCounter();
					SkillUiController.RefreshPointsBadge();
				}
			});
			((UnityEvent)val5.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				if (SkillUiController.GetAllocated(ctrl.SkillType) > 0)
				{
					SkillUiController.ChangeAllocated(ctrl.SkillType, -1);
					ctrl.RefreshCounter();
					SkillUiController.RefreshPointsBadge();
				}
			});
			bool suppressCounterInputEvent = false;
			((UnityEvent<string>)(object)skillRowController.CounterInput.onValueChanged).AddListener((UnityAction<string>)delegate(string value)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				if (!suppressCounterInputEvent)
				{
					int.TryParse(value, out var result);
					int maxAllocatable = SkillUiController.GetMaxAllocatable(ctrl.SkillType);
					int num3 = Mathf.Clamp(result, 0, maxAllocatable);
					suppressCounterInputEvent = true;
					try
					{
						SkillUiController.SetAllocated(ctrl.SkillType, num3);
						ctrl.RefreshCounter();
						if (num3 != result)
						{
							ctrl.CounterInput.caretPosition = ctrl.CounterInput.text.Length;
						}
					}
					finally
					{
						suppressCounterInputEvent = false;
					}
					SkillUiController.RefreshPointsBadge();
				}
			});
			((UnityEvent<string>)(object)skillRowController.CounterInput.onEndEdit).AddListener((UnityAction<string>)delegate(string value)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				int.TryParse(value, out var result);
				int maxAllocatable = SkillUiController.GetMaxAllocatable(ctrl.SkillType);
				int value2 = Mathf.Clamp(result, 0, maxAllocatable);
				SkillUiController.SetAllocated(ctrl.SkillType, value2);
				ctrl.RefreshCounter();
				SkillUiController.RefreshPointsBadge();
			});
		}

		private static GameObject CreateCounterInputField(RectTransform row, Vector2 center)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: 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_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Counter", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(InputField)
			});
			val.transform.SetParent((Transform)(object)row, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = center;
			val2.anchorMax = center;
			val2.pivot = center;
			val2.anchoredPosition = new Vector2(19f, 0f);
			val2.sizeDelta = new Vector2(30f, 20f);
			Image component = val.GetComponent<Image>();
			component.sprite = GUIManager.Instance.GetSprite("text_field");
			component.type = (Type)1;
			((Graphic)component).color = new Color(1f, 1f, 1f, 0.15f);
			((Graphic)component).raycastTarget = true;
			InputField component2 = val.GetComponent<InputField>();
			component2.lineType = (LineType)0;
			component2.contentType = (ContentType)2;
			component2.characterLimit = 3;
			GameObject val3 = new GameObject("Text", new Type[2]
			{
				typeof(RectTransform),
				typeof(Text)
			});
			val3.transform.SetParent(val.transform, false);
			RectTransform val4 = (RectTransform)val3.transform;
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = Vector2.zero;
			val4.offsetMax = Vector2.zero;
			Text component3 = val3.GetComponent<Text>();
			component3.text = "0";
			component3.font = GUIManager.Instance.AveriaSerifBold;
			component3.fontSize = 16;
			((Graphic)component3).color = Color.white;
			component3.alignment = (TextAnchor)4;
			component3.supportRichText = false;
			Outline val5 = val3.AddComponent<Outline>();
			((Shadow)val5).effectColor = Color.black;
			component2.textComponent = component3;
			return val;
		}
	}
	public static class SkillUiController
	{
		public enum SkillTab
		{
			Active,
			Passive
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnApplyConfirm;

			public static UnityAction <1>__OnApplyCancel;

			public static UnityAction <2>__OnRebirthConfirm;

			public static UnityAction <3>__OnRebirthCancel;

			public static UnityAction <4>__OnPrestigeConfirm;

			public static UnityAction <5>__OnPrestigeCancel;
		}

		public static Player CurrentPlayer;

		public static int BaseAvailablePoints;

		public static Text PointsText;

		public static Text PrestigeText;

		public static readonly Color PlannedColor = new Color(0.561f, 0.773f, 0.941f, 1f);

		private static readonly Dictionary<SkillType, int> _pendingAllocations = new Dictionary<SkillType, int>();

		public static float LastScrollPos = 1f;

		public static bool SuppressAutoScroll = false;

		public static RectTransform RootPanel;

		public static SkillsDialog CurrentDialog;

		private static GameObject _rebirthDialogRoot;

		private static GameObject _applyDialogRoot;

		private static GameObject _prestigeDialogRoot;

		private static Text _applyDialogLabel;

		private static Text _prestigeDialogLabel;

		public static GameObject PrestigeIconRoot;

		public static GameObject PointsBadgeRoot;

		public static Button PrestigeButton;

		public static SkillTab CurrentTab = SkillTab.Active;

		public static Button TabToggleButton;

		public static Button ApplyButton;

		public static Button RebirthButton;

		public static void Initialize(Player player, Text pointsText)
		{
			CurrentPlayer = player;
			PointsText = pointsText;
			BaseAvailablePoints = ((!((Object)(object)player == (Object)null)) ? SkillPointService.GetAvailablePoints(player) : 0);
			ResetAllocated();
			RefreshPointsBadge();
			RefreshPrestigeLabel();
			RefreshTabButtons();
		}

		public static int GetAllocated(SkillType type)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			int value;
			return _pendingAllocations.TryGetValue(type, out value) ? value : 0;
		}

		public static void ChangeAllocated(SkillType type, int delta)
		{
			//IL_0002: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(0, GetAllocated(type) + delta);
			if (num == 0)
			{
				_pendingAllocations.Remove(type);
			}
			else
			{
				_pendingAllocations[type] = num;
			}
			RefreshRebirthResetButton();
		}

		public static void SetAllocated(SkillType type, int value)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(0, value);
			if (num == 0)
			{
				_pendingAllocations.Remove(type);
			}
			else
			{
				_pendingAllocations[type] = num;
			}
			RefreshRebirthResetButton();
		}

		public static int GetMaxAllocatable(SkillType type)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)CurrentPlayer == (Object)null)
			{
				return 0;
			}
			Skills skills = ((Character)CurrentPlayer).GetSkills();
			Skill val = ((skills != null) ? skills.GetSkill(type) : null);
			if (val == null)
			{
				return 0;
			}
			float currentSkillCap = SkillCapPolicy.GetCurrentSkillCap(CurrentPlayer);
			int num = Mathf.Max(0, Mathf.FloorToInt(currentSkillCap - val.m_level));
			int num2 = GetCurrentUnspent() + GetAllocated(type);
			return Mathf.Min(num, num2);
		}

		public static void ResetAllocated()
		{
			_pendingAllocations.Clear();
			foreach (SkillRowController activeController in SkillRowController.ActiveControllers)
			{
				activeController.RefreshCounter();
			}
			RefreshRebirthResetButton();
		}

		public static int GetTotalAllocated()
		{
			return _pendingAllocations.Values.Sum();
		}

		public static int GetCurrentUnspent()
		{
			int num = BaseAvailablePoints - GetTotalAllocated();
			return Mathf.Max(0, num);
		}

		public static void RefreshPointsBadge()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			if (!((Object)(object)PointsText == (Object)null))
			{
				PointsText.text = GetCurrentUnspent().ToString();
				BlinkingTextEffect.SetActive(PointsText, GetTotalAllocated() > 0, BlinkingTextEffect.Darken(PlannedColor, 0.55f), PlannedColor, Color.white);
			}
		}

		public static void RefreshPrestigeLabel()
		{
			if (!((Object)(object)PrestigeText == (Object)null) && !((Object)(object)CurrentPlayer == (Object)null))
			{
				int num = (ModConfig.PrestigeEnabled ? PlayerProgressionStore.GetPrestigeRank(CurrentPlayer) : 0);
				PrestigeText.text = num.ToString();
			}
		}

		public static void OnTabChanged(SkillTab tab)
		{
			CurrentTab = tab;
			RefreshDialogSoft();
			if ((Object)(object)CurrentDialog != (Object)null)
			{
				ScrollRect skillListScrollRect = CurrentDialog.skillListScrollRect;
				if ((Object)(object)skillListScrollRect != (Object)null)
				{
					skillListScrollRect.verticalNormalizedPosition = 1f;
					LastScrollPos = 1f;
				}
			}
		}

		public static void OnTabToggled()
		{
			OnTabChanged((CurrentTab == SkillTab.Active) ? SkillTab.Passive : SkillTab.Active);
		}

		public static void OnRebirthOrResetClicked()
		{
			if (GetTotalAllocated() > 0)
			{
				OnResetClicked();
			}
			else
			{
				OnRebirthRequested();
			}
		}

		public static void RefreshRebirthResetButton()
		{
			if (!((Object)(object)RebirthButton == (Object)null))
			{
				Text componentInChildren = ((Component)RebirthButton).GetComponentInChildren<Text>();
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					componentInChildren.text = Localization.instance.Localize((GetTotalAllocated() > 0) ? "$m2_sr_btn_reset" : "$m2_sr_btn_rebirth");
				}
			}
		}

		public static void RefreshTabButtons()
		{
			if ((Object)(object)TabToggleButton != (Object)null)
			{
				Text componentInChildren = ((Component)TabToggleButton).GetComponentInChildren<Text>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.text = Localization.instance.Localize((CurrentTab == SkillTab.Active) ? "$m2_sr_tab_active" : "$m2_sr_tab_passive");
				}
			}
			bool flag = CurrentTab == SkillTab.Active;
			if ((Object)(object)ApplyButton != (Object)null)
			{
				((Component)ApplyButton).gameObject.SetActive(flag);
			}
			if ((Object)(object)RebirthButton != (Object)null)
			{
				((Component)RebirthButton).gameObject.SetActive(flag);
			}
			string failureMessage;
			bool active = flag && ModConfig.PrestigeEnabled && (Object)(object)CurrentPlayer != (Object)null && PrestigeFlow.CanStart(CurrentPlayer, out failureMessage);
			if ((Object)(object)PrestigeButton != (Object)null)
			{
				((Component)PrestigeButton).gameObject.SetActive(active);
			}
			if ((Object)(object)PointsBadgeRoot != (Object)null)
			{
				PointsBadgeRoot.SetActive(flag);
			}
		}

		public static void RefreshTabVisibility(int activeCount, int passiveCount)
		{
			bool active = activeCount > 0 && passiveCount > 0;
			if ((Object)(object)TabToggleButton != (Object)null)
			{
				((Component)TabToggleButton).gameObject.SetActive(active);
			}
		}

		public static void RefreshLocalizedButtons()
		{
			RefreshPointsBadge();
			RefreshRebirthResetButton();
			RefreshTabButtons();
			if ((Object)(object)ApplyButton != (Object)null)
			{
				Text componentInChildren = ((Component)ApplyButton).GetComponentInChildren<Text>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.text = Localization.instance.Localize("$m2_sr_btn_apply");
				}
			}
			if ((Object)(object)PrestigeButton != (Object)null)
			{
				Text componentInChildren2 = ((Component)PrestigeButton).GetComponentInChildren<Text>();
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					componentInChildren2.text = Localization.instance.Localize("$m2_sr_btn_prestige");
				}
			}
			GameObject[] array = new GameObject[3];
			Button applyButton = ApplyButton;
			array[0] = ((applyButton != null) ? ((Component)applyButton).gameObject : null);
			Button rebirthButton = RebirthButton;
			array[1] = ((rebirthButton != null) ? ((Component)rebirthButton).gameObject : null);
			Button prestigeButton = PrestigeButton;
			array[2] = ((prestigeButton != null) ? ((Component)prestigeButton).gameObject : null);
			AdjustButtonWidths((GameObject[])(object)array);
		}

		internal static void AdjustButtonWidths(params GameObject[] buttons)
		{
			if (buttons == null || buttons.Length == 0)
			{
				return;
			}
			float num = 20f;
			float num2 = 0f;
			Canvas.ForceUpdateCanvases();
			foreach (GameObject val in buttons)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Text componentInChildren = val.GetComponentInChildren<Text>();
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					float num3 = componentInChildren.preferredWidth + num;
					if (num3 > num2)
					{
						num2 = num3;
					}
				}
			}
			num2 = Mathf.Max(num2, 80f);
			foreach (GameObject val2 in buttons)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					Transform transform = val2.transform;
					RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
					if (!((Object)(object)val3 == (Object)null))
					{
						val3.SetSizeWithCurrentAnchors((Axis)0, num2);
					}
				}
			}
		}

		public static void OnApplyRequested()
		{
			if ((Object)(object)CurrentPlayer == (Object)null)
			{
				return;
			}
			int totalAllocated = GetTotalAllocated();
			if (totalAllocated <= 0)
			{
				string text = Localization.instance.Localize("$m2_sr_no_points_allocated");
				((Character)CurrentPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
				return;
			}
			EnsureApplyDialog();
			if ((Object)(object)_applyDialogLabel != (Object)null)
			{
				string format = Localization.instance.Localize("$m2_sr_apply_dialog_text");
				_applyDialogLabel.text = string.Format(format, totalAllocated, BaseAvailablePoints);
			}
			ShowDialog(_applyDialogRoot);
		}

		public static void OnResetClicked()
		{
			ResetAllocated();
			RefreshPointsBadge();
			RefreshDialogSoft();
		}

		public static void OnRebirthRequested()
		{
			if (!((Object)(object)CurrentPlayer == (Object)null))
			{
				EnsureRebirthDialog();
				ShowDialog(_rebirthDialogRoot);
			}
		}

		public static void OnPrestigeRequested()
		{
			if ((Object)(object)CurrentPlayer == (Object)null)
			{
				return;
			}
			if (!PrestigeFlow.CanStart(CurrentPlayer, out var failureMessage))
			{
				if (!string.IsNullOrEmpty(failureMessage))
				{
					((Character)CurrentPlayer).Message((MessageType)2, failureMessage, 0, (Sprite)null, false);
				}
				return;
			}
			EnsurePrestigeDialog();
			if ((Object)(object)_prestigeDialogLabel != (Object)null)
			{
				int num = PlayerProgressionStore.GetPrestigeRank(CurrentPlayer) + 1;
				int prestigePointsPerRank = ModConfig.PrestigePointsPerRank;
				string format = Localization.instance.Localize("$m2_sr_prestige_confirm_text");
				_prestigeDialogLabel.text = string.Format(format, num, prestigePointsPerRank);
			}
			ShowDialog(_prestigeDialogRoot);
		}

		public static void RefreshDialogSoft()
		{
			if (!((Object)(object)CurrentDialog == (Object)null) && !((Object)(object)CurrentPlayer == (Object)null) && ((Component)CurrentDialog).gameObject.activeInHierarchy)
			{
				ScrollRect skillListScrollRect = CurrentDialog.skillListScrollRect;
				if ((Object)(object)skillListScrollRect != (Object)null)
				{
					LastScrollPos = skillListScrollRect.verticalNormalizedPosition;
				}
				SuppressAutoScroll = true;
				CurrentDialog.Setup(CurrentPlayer);
				SuppressAutoScroll = false;
				if ((Object)(object)skillListScrollRect != (Object)null)
				{
					skillListScrollRect.verticalNormalizedPosition = LastScrollPos;
				}
				RefreshPointsBadge();
				RefreshPrestigeLabel();
			}
		}

		private static void ApplyAllocatedPoints()
		{
			if (!((Object)(object)CurrentPlayer == (Object)null))
			{
				List<SkillAllocationFlow.SkillPointAllocation> pendingAllocations = GetPendingAllocations();
				if (SkillAllocationFlow.Apply(CurrentPlayer, pendingAllocations).Changed)
				{
					RefreshAfterProgressionChange(CurrentPlayer);
				}
			}
		}

		private static List<SkillAllocationFlow.SkillPointAllocation> GetPendingAllocations()
		{
			//IL_0039: 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)
			List<SkillAllocationFlow.SkillPointAllocation> list = new List<SkillAllocationFlow.SkillPointAllocation>();
			foreach (KeyValuePair<SkillType, int> pendingAllocation in _pendingAllocations)
			{
				if (pendingAllocation.Value > 0)
				{
					list.Add(new SkillAllocationFlow.SkillPointAllocation
					{
						SkillType = pendingAllocation.Key,
						Points = pendingAllocation.Value
					});
				}
			}
			return list;
		}

		public static void RefreshAfterProgressionChange(Player player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				CurrentPlayer = player;
				BaseAvailablePoints = SkillPointService.GetAvailablePoints(player);
				ResetAllocated();
				RefreshPointsBadge();
				RefreshPrestigeLabel();
				RefreshDialogSoft();
				if ((Object)(object)player == (Object)(object)Player.m_localPlayer)
				{
					LevelXpHudController.RefreshForLocalPlayer();
				}
			}
		}

		private static void DispatchFlowResult(FlowExecutionResult result)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)CurrentPlayer == (Object)null || result == null)
			{
				return;
			}
			foreach (FlowNotification notification in result.Notifications)
			{
				((Character)CurrentPlayer).Message(notification.MessageType, notification.Message, 0, (Sprite)null, false);
			}
		}

		private static RectTransform GetDialogParent()
		{
			return (RectTransform)(((object)RootPanel) ?? ((object)/*isinst with value type is only supported in some contexts*/));
		}

		private static void ShowDialog(GameObject dialogRoot)
		{
			if ((Object)(object)dialogRoot != (Object)null)
			{
				dialogRoot.SetActive(true);
			}
		}

		private static void HideDialog(GameObject dialogRoot)
		{
			if ((Object)(object)dialogRoot != (Object)null)
			{
				dialogRoot.SetActive(false);
			}
		}

		private static void EnsureApplyDialog()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			if (!((Object)(object)_applyDialogRoot != (Object)null))
			{
				RectTransform dialogParent = GetDialogParent();
				Vector2 size = new Vector2(400f, 150f);
				string initialText = Localization.instance.Localize("$m2_sr_apply_dialog_title");
				object obj = <>O.<0>__OnApplyConfirm;
				if (obj == null)
				{
					UnityAction val = OnApplyConfirm;
					<>O.<0>__OnApplyConfirm = val;
					obj = (object)val;
				}
				object obj2 = <>O.<1>__OnApplyCancel;
				if (obj2 == null)
				{
					UnityAction val2 = OnApplyCancel;
					<>O.<1>__OnApplyCancel = val2;
					obj2 = (object)val2;
				}
				ConfirmationDialogFactory.DialogReferences dialogReferences = ConfirmationDialogFactory.Create("SkillsReworked_ApplyDialog", dialogParent, size, initialText, 320f, 80f, (UnityAction)obj, (UnityAction)obj2);
				_applyDialogRoot = dialogReferences.Root;
				_applyDialogLabel = dialogReferences.Label;
			}
		}

		private static void EnsureRebirthDialog()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			if (!((Object)(object)_rebirthDialogRoot != (Object)null))
			{
				RectTransform dialogParent = GetDialogParent();
				Vector2 size = new Vector2(400f, 150f);
				string initialText = Localization.instance.Localize("$m2_sr_rebirth_confirm_text");
				object obj = <>O.<2>__OnRebirthConfirm;
				if (obj == null)
				{
					UnityAction val = OnRebirthConfirm;
					<>O.<2>__OnRebirthConfirm = val;
					obj = (object)val;
				}
				object obj2 = <>O.<3>__OnRebirthCancel;
				if (obj2 == null)
				{
					UnityAction val2 = OnRebirthCancel;
					<>O.<3>__OnRebirthCancel = val2;
					obj2 = (object)val2;
				}
				_rebirthDialogRoot = ConfirmationDialogFactory.Create("SkillsReworked_RebirthDialog", dialogParent, size, initialText, 280f, 80f, (UnityAction)obj, (UnityAction)obj2).Root;
			}
		}

		private static void EnsurePrestigeDialog()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			if (!((Object)(object)_prestigeDialogRoot != (Object)null))
			{
				RectTransform dialogParent = GetDialogParent();
				Vector2 size = new Vector2(420f, 170f);
				string initialText = Localization.instance.Localize("$m2_sr_prestige_confirm_text");
				object obj = <>O.<4>__OnPrestigeConfirm;
				if (obj == null)
				{
					UnityAction val = OnPrestigeConfirm;
					<>O.<4>__OnPrestigeConfirm = val;
					obj = (object)val;
				}
				object obj2 = <>O.<5>__OnPrestigeCancel;
				if (obj2 == null)
				{
					UnityAction val2 = OnPrestigeCancel;
					<>O.<5>__OnPrestigeCancel = val2;
					obj2 = (object)val2;
				}
				ConfirmationDialogFactory.DialogReferences dialogReferences = ConfirmationDialogFactory.Create("SkillsReworked_PrestigeDialog", dialogParent, size, initialText, 320f, 90f, (UnityAction)obj, (UnityAction)obj2);
				_prestigeDialogRoot = dialogReferences.Root;
				_prestigeDialogLabel = dialogReferences.Label;
			}
		}

		private static void OnApplyConfirm()
		{
			ApplyAllocatedPoints();
			HideDialog(_applyDialogRoot);
		}

		private static void OnApplyCancel()
		{
			HideDialog(_applyDialogRoot);
		}

		private static void OnRebirthConfirm()
		{
			FlowExecutionResult flowExecutionResult = RebirthFlow.Execute(CurrentPlayer);
			HideDialog(_rebirthDialogRoot);
			DispatchFlowResult(flowExecutionResult);
			if (flowExecutionResult.Success)
			{
				RefreshAfterProgressionChange(CurrentPlayer);
			}
		}

		private static void OnRebirthCancel()
		{
			HideDialog(_rebirthDialogRoot);
		}

		private static void OnPrestigeConfirm()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			FlowExecutionResult flowExecutionResult = PrestigeFlow.Execute(CurrentPlayer);
			HideDialog(_prestigeDialogRoot);
			DispatchFlowResult(flowExecutionResult);
			if (flowExecutionResult.Success)
			{
				RefreshAfterProgressionChange(CurrentPlayer);
				CurrentPlayer.StartEmote("roar", true);
				Vector3 centerPoint = ((Character)CurrentPlayer).GetCenterPoint();
				Vector3 position = ((Component)CurrentPlayer).transform.position;
				GameObject prefab = ZNetScene.instance.GetPrefab("vfx_MeadHasty");
				GameObject prefab2 = ZNetScene.instance.GetPrefab("sfx_gdking_scream");
				if ((Object)(object)prefab != (Object)null)
				{
					ZNetScene.instance.SpawnObject(centerPoint, Quaternion.identity, prefab);
				}
				if ((Object)(object)prefab2 != (Object)null)
				{
					ZNetScene.instance.SpawnObject(position, Quaternion.identity, prefab2);
				}
			}
		}

		private static void OnPrestigeCancel()
		{
			HideDialog(_prestigeDialogRoot);
		}
	}
	public static class UiSpriteHelper
	{
		private static bool _cached;

		private static Sprite _workbenchStarSprite;

		private static Type _workbenchStarType;

		private static float _workbenchStarPPU;

		private static bool _workbenchStarPreserveAspect;

		private static Material _workbenchStarMaterial;

		private static Sprite _circleSprite;

		public static Sprite GetCircleSprite()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_circleSprite != (Object)null)
			{
				return _circleSprite;
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)1;
			float num = 63.5f;
			float num2 = num - 1f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num3 = (float)j - num;
					float num4 = (float)i - num;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
					float num6 = Mathf.Clamp01(num2 + 1.5f - num5);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num6));
				}
			}
			val.Apply(false, true);
			_circleSprite = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
			return _circleSprite;
		}

		public static void ApplyWorkbenchLevelStar(Image target)
		{
			//IL_0090: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null))
			{
				CacheWorkbenchStarOnce();
				if ((Object)(object)_workbenchStarSprite != (Object)null)
				{
					target.sprite = _workbenchStarSprite;
					target.type = _workbenchStarType;
					target.pixelsPerUnitMultiplier = _workbenchStarPPU;
					target.preserveAspect = _workbenchStarPreserveAspect;
					((Graphic)target).material = _workbenchStarMaterial;
					((Graphic)target).color = Color.white;
				}
				else
				{
					target.sprite = null;
					target.type = (Type)1;
					target.preserveAspect = false;
					((Graphic)target).color = GUIManager.Instance.ValheimOrange;
				}
			}
		}

		private static void CacheWorkbenchStarOnce()
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (_cached)
			{
				return;
			}
			_cached = true;
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Logger.LogWarning((object)"[SkillsReworked.UI.SkillPanel.UiSpriteHelper] InventoryGui.instance is null");
				return;
			}
			RectTransform crafting = instance.m_crafting;
			if ((Object)(object)crafting == (Object)null)
			{
				Logger.LogWarning((object)"[SkillsReworked.UI.SkillPanel.UiSpriteHelper] InventoryGui.m_crafting is null");
				return;
			}
			Transform val = ((Transform)crafting).Find("Level");
			if ((Object)(object)val == (Object)null)
			{
				Transform[] componentsInChildren = ((Component)crafting).GetComponentsInChildren<Transform>(true);
				foreach (Transform val2 in componentsInChildren)
				{
					if (((Object)val2).name == "Level")
					{
						val = val2;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"[SkillsReworked.UI.SkillPanel.UiSpriteHelper] Could not find 'Level' under InventoryGui.m_crafting");
				return;
			}
			Image component = ((Component)val).GetComponent<Image>();
			if ((Object)(object)component == (Object)null)
			{
				Logger.LogWarning((object)"[SkillsReworked.UI.SkillPanel.UiSpriteHelper] 'Level' does not have an Image component");
				return;
			}
			_workbenchStarSprite = component.sprite;
			_workbenchStarType = component.type;
			_workbenchStarPPU = component.pixelsPerUnitMultiplier;
			_workbenchStarPreserveAspect = component.preserveAspect;
			_workbenchStarMaterial = ((Graphic)component).material;
		}
	}
}
namespace SkillsReworked.UI.LevelHud
{
	public static class LevelXpHudController
	{
		private class HudData
		{
			public RectTransform Root;

			public RectTransform FastFill;

			public RectTransform SlowFill;

			public TMP_Text Label;

			public float LabelBaseFontSize;

			public float MaxWidth;

			public float FastFraction;

			public float SlowFraction;

			public float SlowAnimStart;

			public float SlowAnimTarget;

			public float SlowAnimElapsed;

			public float SlowAnimDuration;

			public float SlowDelayRemaining;

			public bool SlowAnimationActive;

			public int PreviousLevel;

			public bool LevelUpAnimating;

			public float LevelUpFinalTarget;
		}

		private static readonly Dictionary<Hud, HudData> Bars = new Dictionary<Hud, HudData>();

		private const float Margin = 3f;

		private const float SlowStartDelay = 0.18f;

		private const float SlowMinDuration = 0.22f;

		private const float SlowMaxDuration = 1.82f;

		private const float SlowDurationScale = 1.6f;

		public static void Register()
		{
			LevelProgressionService.OnLevelChanged += RefreshForLocalPlayer;
		}

		public static void RefreshForLocalPlayer()
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			Hud instance = Hud.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (!ModConfig.XpBarEnabled)
			{
				if (Bars.TryGetValue(instance, out var value))
				{
					SetActiveSafe(value, active: false);
				}
				return;
			}
			if (!Bars.TryGetValue(instance, out var value2) || (Object)(object)value2.Root == (Object)null)
			{
				CreateBarForHud(instance);
				if (!Bars.TryGetValue(instance, out value2) || (Object)(object)value2.Root == (Object)null)
				{
					return;
				}
			}
			if (!instance.IsVisible())
			{
				SetActiveSafe(value2, active: false);
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				SetActiveSafe(value2, active: false);
				return;
			}
			Skills skills = ((Character)localPlayer).GetSkills();
			Skill val = ((skills != null) ? skills.GetSkill(SkillsReworkedPlugin.LevelSkillType) : null);
			if (val == null)
			{
				SetActiveSafe(value2, active: false);
				return;
			}
			int num = Mathf.FloorToInt(val.m_level);
			float currentLevelFraction = LevelXpCalculator.GetCurrentLevelFraction(val);
			float num2 = Mathf.Clamp01(currentLevelFraction);
			if (num <= 0 && num2 <= 0f)
			{
				value2.FastFraction = 0f;
				SnapSlowTo(value2, 0f);
				if ((Object)(object)value2.FastFill != (Object)null)
				{
					value2.FastFill.sizeDelta = new Vector2(0f, value2.FastFill.sizeDelta.y);
				}
				if ((Object)(object)value2.Label != (Object)null)
				{
					value2.Label.text = string.Empty;
				}
				SetActiveSafe(value2, active: false);
				return;
			}
			bool flag = (Object)(object)value2.Root != (Object)null && ((Component)value2.Root).gameObject.activeSelf;
			float fastFraction = value2.FastFraction;
			int previousLevel = value2.PreviousLevel;
			SetActiveSafe(value2, active: true);
			ApplyLayout(instance, value2);
			value2.PreviousLevel = num;
			if (value2.LevelUpAnimating)
			{
				if ((Object)(object)value2.Label != (Object)null)
				{
					value2.Label.text = $"Level {num}";
				}
				return;
			}
			value2.FastFraction = num2;
			ApplyFillWidth(value2.FastFill, value2.MaxWidth, value2.FastFraction);
			if (!flag)
			{
				SnapSlowTo(value2, num2);
			}
			else if (!Mathf.Approximately(fastFraction, num2))
			{
				bool flag2 = num > previousLevel;
				bool flag3 = num < previousLevel;
				if (flag2)
				{
					value2.FastFraction = 1f;
					ApplyFillWidth(value2.FastFill, value2.MaxWidth, 1f);
					value2.LevelUpFinalTarget = num2;
					value2.LevelUpAnimating = true;
					BeginSlowAnimation(value2, 1f, 0.18f);
				}
				else if (flag3)
				{
					value2.SlowFraction = 1f;
					ApplyFillWidth(value2.SlowFill, value2.MaxWidth, 1f);
					BeginSlowAnimation(value2, num2, 0f);
				}
				else if (num2 < fastFraction || num2 < value2.SlowFraction)
				{
					BeginSlowAnimation(value2, num2, 0f);
				}
				else
				{
					BeginSlowAnimation(value2, num2, 0.18f);
				}
			}
			if ((Object)(object)value2.Label != (Object)null)
			{
				value2.Label.text = $"Level {num}";
			}
		}

		public static void Update(float dt)
		{
			if (Bars.Count == 0)
			{
				return;
			}
			foreach (KeyValuePair<Hud, HudData> bar in Bars)
			{
				HudData value = bar.Value;
				if (value != null && !((Object)(object)value.Root == (Object)null) && ((Component)value.Root).gameObject.activeSelf && !((Object)(object)value.SlowFill == (Object)null) && value.SlowAnimationActive && TickSlowAnimation(value, dt) && value.SlowAnimationActive)
				{
					TickSlowAnimation(value, 0f);
				}
			}
		}

		private static bool TickSlowAnimation(HudData data, float dt)
		{
			if (data.SlowDelayRemaining > 0f)
			{
				data.SlowDelayRemaining = Mathf.Max(0f, data.SlowDelayRemaining - dt);
				if (data.SlowDelayRemaining > 0f)
				{
					return false;
				}
			}
			data.SlowAnimElapsed += dt;
			float num = Mathf.Max(0.0001f, data.SlowAnimDuration);
			float num2 = Mathf.Clamp01(data.SlowAnimElapsed / num);
			float num3 = 1f - Mathf.Pow(1f - num2, 3f);
			ApplyFillWidth(fraction: data.SlowFraction = Mathf.Lerp(data.SlowAnimStart, data.SlowAnimTarget, num3), fill: data.SlowFill, maxWidth: data.MaxWidth);
			if (num2 >= 1f)
			{
				data.SlowFraction = data.SlowAnimTarget;
				ApplyFillWidth(data.SlowFill, data.MaxWidth, data.SlowFraction);
				ClearSlowAnimation(data);
				if (data.LevelUpAnimating)
				{
					data.LevelUpAnimating = false;
					data.FastFraction = data.LevelUpFinalTarget;
					ApplyFillWidth(data.FastFill, data.MaxWidth, data.LevelUpFinalTarget);
					data.SlowFraction = 0f;
					ApplyFillWidth(data.SlowFill, data.MaxWidth, 0f);
					BeginSlowAnimation(data, data.LevelUpFinalTarget, 0f);
					return true;
				}
			}
			return false;
		}

		private static void CreateBarForHud(Hud hud)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Expected O, but got Unknown
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Expected O, but got Unknown
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Expected O, but got Unknown
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hud == (Object)null || Bars.ContainsKey(hud))
			{
				return;
			}
			RectTransform val = (RectTransform)(((Object)(object)hud.m_healthBarRoot != (Object)null) ? /*isinst with value type is only supported in some contexts*/: /*isinst with value type is only supported in some contexts*/);
			if (!((Object)(object)val == (Object)null))
			{
				GameObject val2 = new GameObject("SkillsReworked_LevelXpBar", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				RectTransform component = val2.GetComponent<RectTransform>();
				((Transform)component).SetParent((Transform)(object)val, false);
				if ((Object)(object)hud.m_healthBarRoot != (Object)null)
				{
					component.anchorMin = hud.m_healthBarRoot.anchorMin;
					component.anchorMax = hud.m_healthBarRoot.anchorMax;
					component.pivot = hud.m_healthBarRoot.pivot;
				}
				else
				{
					component.anchorMin = new Vector2(0f, 1f);
					component.anchorMax = new Vector2(0f, 1f);
					component.pivot = new Vector2(0f, 1f);
				}
				Image component2 = val2.GetComponent<Image>();
				((Graphic)component2).color = new Color(0f, 0f, 0f, 0.65f);
				Image val3 = null;
				if ((Object)(object)hud.m_staminaBar2Fast != (Object)null)
				{
					val3 = ((Component)hud.m_staminaBar2Fast).GetComponentInChildren<Image>();
				}
				if ((Object)(object)val3 == (Object)null && (Object)(object)hud.m_healthBarFast != (Object)null)
				{
					val3 = ((Component)hud.m_healthBarFast).GetComponentInChildren<Image>();
				}
				GameObject val4 = new GameObject("FillFast", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				RectTransform component3 = val4.GetComponent<RectTransform>();
				((Transform)component3).SetParent((Transform)(object)component, false);
				component3.anchorMin = new Vector2(0f, 0.5f);
				component3.anchorMax = new Vector2(0f, 0.5f);
				component3.pivot = new Vector2(0f, 0.5f);
				component3.anchoredPosition = new Vector2(3f, 0f);
				Image component4 = val4.GetComponent<Image>();
				((Graphic)component4).color = new Color(1f, 0.86f, 0.25f, 0.95f);
				GameObject val5 = new GameObject("FillSlow", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				RectTransform component5 = val5.GetComponent<RectTransform>();
				((Transform)component5).SetParent((Transform)(object)component, false);
				component5.anchorMin = new Vector2(0f, 0.5f);
				component5.anchorMax = new Vector2(0f, 0.5f);
				component5.pivot = new Vector2(0f, 0.5f);
				component5.anchoredPosition = new Vector2(3f, 0f);
				Image component6 = val5.GetComponent<Image>();
				((Graphic)component6).color = new Color(0.16f, 0.6f, 0.95f, 0.95f);
				if ((Object)(object)val3 != (Object)null && (Object)(object)val3.sprite != (Object)null)
				{
					CopySpriteSettings(val3, component4);
					CopySpriteSettings(val3, component6);
				}
				Shadow val6 = val5.AddComponent<Shadow>();
				val6.effectColor = new Color(0f, 0f, 0f, 0.85f);
				val6.effectDistance = new Vector2(0f, -2f);
				val6.useGraphicAlpha = true;
				TMP_Text val7 = null;
				TMP_Text val8 = hud.m_staminaText ?? hud.m_healthText;
				if ((Object)(object)val8 != (Object)null)
				{
					val7 = Object.Instantiate<TMP_Text>(val8, (Transform)(object)component);
					((Object)val7).name = "LevelXpLabel";
					val7.alignment = (TextAlignmentOptions)514;
					RectTransform val9 = (RectTransform)val7.transform;
					val9.anchorMin = new Vector2(0f, 0f);
					val9.anchorMax = new Vector2(1f, 1f);
					val9.offsetMin = Vector2.zero;
					val9.offsetMax = Vector2.zero;
					val7.enableAutoSizing = false;
					val7.fontSize = val8.fontSize;
					val7.text = string.Empty;
				}
				Bars[hud] = new HudData
				{
					Root = component,
					FastFill = component3,
					SlowFill = component5,
					Label = val7,
					LabelBaseFontSize = (((Object)(object)val8 != (Object)null) ? val8.fontSize : 0f),
					FastFraction = 0f,
					SlowFraction = 0f,
					SlowAnimStart = 0f,
					SlowAnimTarget = 0f,
					SlowAnimElapsed = 0f,
					SlowAnimDuration = 0f,
					SlowDelayRemaining = 0f,
					SlowAnimationActive = false
				};
				((Component)component).gameObject.SetActive(false);
			}
		}

		public static void OnHudDestroy(Hud hud)
		{
			if (!((Object)(object)hud == (Object)null) && Bars.TryGetValue(hud, out var value))
			{
				if ((Object)(object)value.Root != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)value.Root).gameObject);
				}
				Bars.Remove(hud);
			}
		}

		private static void ApplyLayout(Hud hud, HudData data)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)data?.Root == (Object)null))
			{
				float xpBarWidth = ModConfig.XpBarWidth;
				float xpBarHeight = ModConfig.XpBarHeight;
				data.MaxWidth = xpBarWidth;
				data.Root.sizeDelta = new Vector2(xpBarWidth + 6f, xpBarHeight + 6f);
				data.Root.anchoredPosition = (Vector2)(((Object)(object)hud.m_healthBarRoot != (Object)null) ? (hud.m_healthBarRoot.anchoredPosition + new Vector2(ModConfig.XpBarOffsetX, ModConfig.XpBarOffsetY)) : new Vector2(0f, -80f));
				if ((Object)(object)data.FastFill != (Object)null)
				{
					data.FastFill.sizeDelta = new Vector2(data.FastFill.sizeDelta.x, xpBarHeight);
				}
				if ((Object)(object)data.SlowFill != (Object)null)
				{
					data.SlowFill.sizeDelta = new Vector2(data.SlowFill.sizeDelta.x, xpBarHeight);
				}
				ApplyFillWidth(data.FastFill, data.MaxWidth, data.FastFraction);
				ApplyFillWidth(data.SlowFill, data.MaxWidth, data.SlowFraction);
				if ((Object)(object)data.Label != (Object)null && data.LabelBaseFontSize > 0f)
				{
					data.Label.fontSize = data.LabelBaseFontSize * (xpBarHeight / 25f);
				}
			}
		}

		private static void SetActiveSafe(HudData data, bool active)
		{
			if (!((Object)(object)data?.Root == (Object)null))
			{
				GameObject gameObject = ((Component)data.Root).gameObject;
				if (gameObject.activeSelf != active)
				{
					gameObject.SetActive(active);
				}
			}
		}

		private static void BeginSlowAnimation(HudData data, float targetFraction, float delay)
		{
			if (data != null)
			{
				float num = Mathf.Clamp01(targetFraction);
				float num2 = Mathf.Clamp01(data.SlowFraction);
				if (Mathf.Approximately(num2, num))
				{
					SnapSlowTo(data, num);
					return;
				}
				float num3 = Mathf.Abs(num - num2);
				data.SlowAnimStart = num2;
				data.SlowAnimTarget = num;
				data.SlowAnimElapsed = 0f;
				data.SlowAnimDuration = Mathf.Clamp(0.22f + num3 * 1.6f, 0.22f, 1.82f);
				data.SlowDelayRemaining = Mathf.Max(0f, delay);
				data.SlowAnimationActive = true;
			}
		}

		private static void SnapSlowTo(HudData data, float fraction)
		{
			if (data != null)
			{
				ApplyFillWidth(fraction: data.SlowFraction = Mathf.Clamp01(fraction), fill: data.SlowFill, maxWidth: data.MaxWidth);
				ClearSlowAnimation(data);
			}
		}

		private static void ClearSlowAnimation(HudData data)
		{
			if (data != null)
			{
				data.SlowAnimStart = data.SlowFraction;
				data.SlowAnimTarget = data.SlowFraction;
				data.SlowAnimElapsed = 0f;
				data.SlowAnimDuration = 0f;
				data.SlowDelayRemaining = 0f;
				data.SlowAnimationActive = false;
			}
		}

		private static void ApplyFillWidth(RectTransform fill, float maxWidth, float fraction)
		{
			//IL_001b: 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)
			if (!((Object)(object)fill == (Object)null))
			{
				float num = Mathf.Clamp01(fraction);
				fill.sizeDelta = new Vector2(maxWidth * num, fill.sizeDelta.y);
			}
		}

		private static void CopySpriteSettings(Image from, Image to)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			to.sprite = from.sprite;
			to.type = from.type;
			to.pixelsPerUnitMultiplier = from.pixelsPerUnitMultiplier;
			to.preserveAspect = from.preserveAspect;
		}
	}
}
namespace SkillsReworked.UI.Dialogs
{
	public static class ConfirmationDialogFactory
	{
		public struct DialogReferences
		{
			public GameObject Root;

			public Text Label;
		}

		public static DialogReferences Create(string name, RectTransform parent, Vector2 size, string initialText, float textWidth, float textHeight, UnityAction onConfirm, UnityAction onCancel)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_003b: 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)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			val.transform.SetParent((Transform)(object)parent, false);
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = Vector2.zero;
			component.sizeDelta = size;
			Image val2 = val.AddComponent<Image>();
			GUIManager.Instance.ApplyWoodpanelStyle(((Component)val2).transform);
			GameObject val3 = GUIManager.Instance.CreateText(initialText, (Transform)(object)component, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -40f), GUIManager.Instance.AveriaSerifBold, 16, Color.white, true, Color.black, textWidth, textHeight, false);
			Text component2 = val3.GetComponent<Text>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.alignment = (TextAnchor)4;
			}
			string text = Localization.instance.Localize("$menu_yes");
			string text2 = Localization.instance.Localize("$menu_no");
			GameObject val4 = GUIManager.Instance.CreateButton(text, (Transform)(object)component, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(60f, 30f), 100f, 30f);
			((UnityEvent)val4.GetComponent<Button>().onClick).AddListener(onConfirm);
			GameObject val5 = GUIManager.Instance.CreateButton(text2, (Transform)(object)component, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(-60f, 30f), 100f, 30f);
			((UnityEvent)val5.GetComponent<Button>().onClick).AddListener(onCancel);
			return new DialogReferences
			{
				Root = val,
				Label = component2
			};
		}
	}
}
namespace SkillsReworked.Systems.Rewards
{
	internal static class KillCreditResolver
	{
		internal const float CreditMaxAgeSeconds = 30f;

		internal static bool TryResolveKillerPlayer(HitData hit, out Player killer)
		{
			killer = null;
			if (hit == null)
			{
				return false;
			}
			Character attacker = hit.GetAttacker();
			if ((Object)(object)attacker == (Object)null)
			{
				return false;
			}
			Player val = (Player)(object)((attacker is Player) ? attacker : null);
			if (val != null)
			{
				killer = val;
				return true;
			}
			MonsterAI val2 = default(MonsterAI);
			if (((Component)attacker).TryGetComponent<MonsterAI>(ref val2) && (Object)(object)val2 != (Object)null)
			{
				GameObject followTarget = val2.GetFollowTarget();
				if (Object.op_Implicit((Object)(object)followTarget))
				{
					killer = followTarget.GetComponent<Player>();
					return (Object)(object)killer != (Object)null;
				}
			}
			return false;
		}

		internal static bool TryResolveAttackerPeerId(HitData hit, out long attackerPeerId)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			attackerPeerId = ZNetView.Everybody;
			if (hit == null)
			{
				return false;
			}
			if (TryResolveKillerPlayer(hit, out var killer) && (Object)(object)killer != (Object)null)
			{
				ZNetView nview = ((Character)killer).m_nview;
				ZDO val = ((nview != null) ? nview.GetZDO() : null);
				if (val != null)
				{
					attackerPeerId = val.GetOwner();
					return attackerPeerId != ZNetView.Everybody;
				}
			}
			if (((ZDOID)(ref hit.m_attacker)).IsNone())
			{
				return false;
			}
			ZDOMan instance = ZDOMan.instance;
			ZDO val2 = ((instance != null) ? instance.GetZDO(hit.m_attacker) : null);
			if (val2 == null)
			{
				return false;
			}
			if (val2.GetLong(ZDOVars.s_playerID, 0L) == 0)
			{
				return false;
			}
			attackerPeerId = val2.GetOwner();
			return attackerPeerId != ZNetView.Everybody;
		}

		public static bool TryResolveKillerPeerId(Character victim, HitData lastHit, out long killerPeerId)
		{
			killerPeerId = ZNetView.Everybody;
			if ((Object)(object)victim == (Object)null)
			{
				return false;
			}
			if (TryResolveAttackerPeerId(lastHit, out killerPeerId))
			{
				return true;
			}
			return KillCreditStore.TryGet(victim, 30f, out killerPeerId);
		}
	}
	internal static class KillCreditStore
	{
		private static readonly int LastAttackerKey = StringExtensionMethods.GetStableHashCode("SkillsReworked_lastAttacker");

		private static readonly int LastAttackerAtKey = StringExtensionMethods.GetStableHashCode("SkillsReworked_lastAttackerAt");

		public static void Store(Character victim, long attackerPeerId)
		{
			if (attackerPeerId != ZNetView.Everybody)
			{
				object obj;
				if (victim == null)
				{
					obj = null;
				}
				else
				{
					ZNetView nview = victim.m_nview;
					obj = ((nview != null) ? nview.GetZDO() : null);
				}
				ZDO val = (ZDO)obj;
				if (val != null)
				{
					val.Set(LastAttackerKey, attackerPeerId);
					val.Set(LastAttackerAtKey, CurrentTime());
				}
			}
		}

		public static bool TryGet(Character victim, float maxAgeSeconds, out long attackerPeerId)
		{
			attackerPeerId = ZNetView.Everybody;
			object obj;
			if (victim == null)
			{
				obj = null;
			}
			else
			{
				ZNetView nview = victim.m_nview;
				obj = ((nview != null) ? nview.GetZDO() : null);
			}
			ZDO val = (ZDO)obj;
			if (val == null)
			{
				return false;
			}
			long num = val.GetLong(LastAttackerKey, 0L);
			if (num == ZNetView.Everybody)
			{
				return false;
			}
			long num2 = val.GetLong(LastAttackerAtKey, 0L);
			if (CurrentTime() - num2 > (long)maxAgeSeconds)
			{
				return false;
			}
			attackerPeerId = num;
			return true;
		}

		private static long CurrentTime()
		{
			return ((Object)(object)ZNet.instance != (Object)null) ? ((long)ZNet.instance.GetTimeSeconds()) : 0;
		}
	}
	internal static class KillRewardFlow
	{
		internal const string CharacterDiedRpcName = "SkillsReworked_RPC_CharacterDied";

		private const float BossKeyMaxDistance = 300f;

		public static void AnnounceDeath(Character victim, long killerPeerId, float baseXp, Biome biome, string defeatKey, bool isBoss)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected I4, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (ZRoutedRpc.instance != null)
			{
				bool flag = !string.IsNullOrEmpty(defeatKey);
				bool flag2 = killerPeerId != ZNetView.Everybody && baseXp > 0f;
				if (flag || flag2)
				{
					bool flag3 = flag2 && ModConfig.PartyShareRadius > 0f && ModConfig.PartyShareFactor > 0f;
					long num = ((flag || flag3) ? 0 : killerPeerId);
					ZRoutedRpc.instance.InvokeRoutedRPC(num, "SkillsReworked_RPC_CharacterDied", new object[6]
					{
						killerPeerId,
						baseXp,
						(int)biome,
						defeatKey ?? string.Empty,
						isBoss,
						((Object)(object)victim != (Object)null) ? ((Component)victim).transform.position : Vector3.zero
					});
				}
			}
		}

		internal static void RPC_OnCharacterDied(long sender, long killerPeerId, float baseXp, int biomeInt, string defeatKey, bool isBoss, Vector3 victimPos)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer))
			{
				return;
			}
			bool flag = killerPeerId != ZNetView.Everybody && ZNet.GetUID() == killerPeerId;
			bool flag2 = false;
			if (!string.IsNullOrEmpty(defeatKey) && (flag || RpcRangeUtil.IsLocalPlayerWithinRange(victimPos, 300f)))
			{
				flag2 = !((Humanoid)localPlayer).HaveUniqueKey(defeatKey);
				if (flag2)
				{
					((Humanoid)localPlayer).AddUniqueKey(defeatKey);
				}
			}
			if (!(baseXp <= 0f))
			{
				float xp = baseXp;
				if (isBoss && (!ModConfig.BossXpMultiplierFirstKillOnly || flag2))
				{
					xp = KillXpCalculator.ApplyBossMultiplier(xp);
				}
				Biome biome = (Biome)biomeInt;
				if (flag)
				{
					AwardXp(localPlayer, biome, xp);
				}
				else
				{
					PartyXpIntegration.TryAwardPartyShare(localPlayer, killerPeerId, biome, xp);
				}
			}
		}

		internal static void AwardXp(Player player, Biome biome, float xp)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			float num = LevelXpCalculator.ApplyLevelScaling(player, biome, xp);
			if (!(num <= 0f))
			{
				((Character)player).RaiseSkill(SkillsReworkedPlugin.LevelSkillType, num);
			}
		}
	}
	internal static class KillXpCalculator
	{
		public static float CalculateRawXp(float victimMaxHealth)
		{
			if (victimMaxHealth <= 0f)
			{
				return 0f;
			}
			float num = victimMaxHealth * 0.1f;
			float xpMultiplier = ModConfig.XpMultiplier;
			float num2 = num * xpMultiplier + 5f;
			return Mathf.Max(0f, num2);
		}

		public static float ApplyBossMultiplier(float xp)
		{
			return Mathf.Max(0f, xp * ModConfig.BossXpMultiplier);
		}
	}
	public class MobBiomeTracker : MonoBehaviour
	{
		public Biome SpawnBiome;
	}
}
namespace SkillsReworked.Systems.Reset
{
	public static class ProgressionResetService
	{
		public static void ResetActiveSkills(Skills skills)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			//IL_006a: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)skills == (Object)null)
			{
				return;
			}
			List<Skill> skillList = skills.GetSkillList();
			foreach (Skill item in skillList)
			{
				if (item?.m_info != null)
				{
					SkillType skill = item.m_info.m_skill;
					if ((int)skill != 0 && (int)skill != 999 && skill != SkillsReworkedPlugin.LevelSkillType && SkillCategoryService.IsActiveSkill(skill))
					{
						skills.ResetSkill(skill);
					}
				}
			}
		}

		public static void ResetLevelSkill(Skills skills)
		{
			LevelProgressionService.Reset(skills);
		}

		public static void ResetSpentPoints(Player player)
		{
			PlayerProgressionStore.ResetSpentSkillPoints(player);
		}

		public static void ResyncSpentPointsFromSkillLevels(Player player, Skills skills)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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)
			if ((Object)(object)player == (Object)null || (Object)(object)skills == (Object)null)
			{
				return;
			}
			int num = 0;
			foreach (Skill skill2 in skills.GetSkillList())
			{
				if (skill2?.m_info != null)
				{
					SkillType skill = skill2.m_info.m_skill;
					if ((int)skill != 0 && (int)skill != 999 && skill != SkillsReworkedPlugin.LevelSkillType && SkillCategoryService.IsActiveSkill(skill))
					{
						num += Mathf.RoundToInt(skill2.m_level);
					}
				}
			}
			PlayerProgressionStore.SetSpentSkillPoints(player, num);
		}
	}
}
namespace SkillsReworked.Systems.Rebirth
{
	public enum RebirthCostMode
	{
		None,
		LevelOnly,
		ItemOnly,
		Both
	}
	public static class RebirthFlow
	{
		public static event Action<Player> OnExecuted;

		public static FlowExecutionResult Execute(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return FlowExecutionResult.Failed();
			}
			Skills skills = ((Character)player).GetSkills();
			if ((Object)(object)skills == (Object)null)
			{
				return FlowExecutionResult.Failed();
			}
			bool rebirthCostEnabled = ModConfig.RebirthCostEnabled;
			RebirthCostMode rebirthCostModeSetting = ModConfig.RebirthCostModeSetting;
			bool flag = rebirthCostEnabled && (rebirthCostModeSetting == RebirthCostMode.LevelOnly || rebirthCostModeSetting == RebirthCostMode.Both);
			bool flag2 = rebirthCostEnabled && (rebirthCostModeSetting == RebirthCostMode.ItemOnly || rebirthCostModeSetting == RebirthCostMode.Both);
			int rebirthLevelLoss = ModConfig.RebirthLevelLoss;
			string rebirthItemName = ModConfig.RebirthItemName;
			int rebirthItemAmount = ModConfig.RebirthItemAmount;
			if (flag && rebirthLevelLoss > 0)
			{
				int level = LevelSkillService.GetLevel(skills);
				if (level < rebirthLevelLoss)
				{
					string format = Localization.instance.Localize("$m2_sr_rebirth_need_levels");
					return FlowExecutionResult.Failed().AddNotification((MessageType)2, string.Format(format, rebirthLevelLoss));
				}
			}
			if (flag2 && rebirthItemAmount > 0 && !string.IsNullOrEmpty(rebirthItemName) && !ItemCostService.HasRequiredItems(player, rebirthItemName, rebirthItemAmount))
			{
				string format2 = Localization.instance.Localize("$m2_sr_rebirth_need_items");
				string itemDisplayName = ItemCostService.GetItemDisplayName(rebirthItemName);
				return FlowExecutionResult.Failed().AddNotification((MessageType)2, string.Format(format2, rebirthItemAmount, itemDisplayName));
			}
			FlowExecutionResult flowExecutionResult = FlowExecutionResult.Succeeded();
			if (flag && rebirthLevelLoss > 0)
			{
				if (LevelProgressionService.TryConsumeWholeLevels(skills, rebirthLevelLoss))
				{
					string format3 = Localization.instance.Localize("$m2_sr_rebirth_cost_levels");
					flowExecutionResult.AddNotification((MessageType)1, string.Format(format3, rebirthLevelLoss));
				}
				else
				{
					Logger.LogWarning((object)"[SkillsReworked] Rebirth level cost could not be applied because the Level skill was missing.");
				}
			}
			if (flag2 && rebirthItemAmount > 0 && !string.IsNullOrEmpty(rebirthItemName) && ItemCostService.TryConsumeItems(player, rebirthItemName, rebirthItemAmount))
			{
				string format4 = Localization.instance.Localize("$m2_sr_rebirth_cost_items");
				string itemDisplayName2 = ItemCostService.GetItemDisplayName(rebirthItemName);
				flowExecutionResult.AddNotification((MessageType)1, string.Format(format4, rebirthItemAmount, itemDisplayName2));
			}
			ProgressionResetService.ResetActiveSkills(skills);
			ProgressionResetService.ResetSpentPoints(player);
			string message = Localization.instance.Localize("$m2_sr_rebirth_done");
			Logger.LogInfo((object)"[SkillsReworked] Rebirth executed: non-level skills reset and spent points cleared.");
			RebirthFlow.OnExecuted?.Invoke(player);
			return flowExecutionResult.AddNotification((MessageType)1, message);
		}
	}
}
namespace SkillsReworked.Systems.Progression
{
	public static class BossProgressionService
	{
		public static readonly string[] DefeatKeys = new string[7] { "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader" };

		public static bool HasDefeated(Player player, string defeatKey)
		{
			if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(defeatKey))
			{
				return false;
			}
			if (ModConfig.UseGlobalBossKeys)
			{
				return (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey(defeatKey);
			}
			return ((Humanoid)player).HaveUniqueKey(defeatKey);
		}

		public static int GetDefeatedCount(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			int num = 0;
			string[] defeatKeys = DefeatKeys;
			foreach (string defeatKey in defeatKeys)
			{
				if (HasDefeated(player, defeatKey))
				{
					num++;
				}
			}
			return num;
		}
	}
	public static class LevelProgressionService
	{
		public static event Action OnLevelChanged;

		public static void Reset(Skills skills)
		{
			Skill skill = LevelSkillService.GetSkill(skills);
			if (skill != null)
			{
				SetLevelAndAccumulator(skill, 0f, 0f);
			}
		}

		public static bool TryConsumeWholeLevels(Skills skills, int levelLoss)
		{
			if ((Object)(object)skills == (Object)null || levelLoss <= 0)
			{
				return false;
			}
			Skill skill = LevelSkillService.GetSkill(skills);
			if (skill == null)
			{
				return false;
			}
			SetLevelAndAccumulator(skill, Mathf.Max(0f, skill.m_level - (float)levelLoss), 0f);
			return true;
		}

		public static bool ApplyDeathFractionLoss(Skills skills, float fraction)
		{
			if ((Object)(object)skills == (Object)null)
			{
				return false;
			}
			Skill skill = LevelSkillService.GetSkill(skills);
			if (skill == null)
			{
				return false;
			}
			fraction = Mathf.Clamp01(fraction);
			if (fraction <= 0f)
			{
				return true;
			}
			int num = Mathf.FloorToInt(skill.m_level);
			float requirementForLevel = LevelXpCalculator.GetRequirementForLevel(num);
			if (requirementForLevel <= 0f)
			{
				return true;
			}
			float num2 = Mathf.Clamp01(skill.m_accumulator / requirementForLevel);
			if (num2 >= fraction)
			{
				float num3 = num2 - fraction;
				SetLevelAndAccumulator(skill, skill.m_level, num3 * requirementForLevel);
				return true;
			}
			float num4 = fraction - num2;
			if (num > 0)
			{
				int num5 = num - 1;
				float requirementForLevel2 = LevelXpCalculator.GetRequirementForLevel(num5);
				float num6 = 1f - num4;
				if (num6 <= 0f)
				{
					SetLevelAndAccumulator(skill, num5, 0f);
				}
				else
				{
					SetLevelAndAccumulator(skill, num5, num6 * requirementForLevel2);
				}
			}
			else
			{
				SetLevelAndAccumulator(skill, 0f, 0f);
			}
			return true;
		}

		public static int AddXp(Skills skills, float factor)
		{
			if ((Object)(object)skills == (Object)null || factor <= 0f)
			{
				return 0;
			}
			Skill skill = LevelSkillService.GetSkill(skills);
			if (skill == null || skill.m_info == null)
			{
				return 0;
			}
			if (skill.m_level >= 100f)
			{
				SetLevelAndAccumulator(skill, 100f, 0f);
				return 0;
			}
			float num = skill.m_info.m_increseStep * factor * Game.m_skillGainRate;
			if (num <= 0f)
			{
				return 0;
			}
			float num2 = Mathf.Max(0f, skill.m_accumulator) + num;
			float num3 = skill.m_level;
			int num4 = 0;
			while (num3 < 100f)
			{
				int levelIndex = Mathf.FloorToInt(num3);
				float requirementForLevel = LevelXpCalculator.GetRequirementForLevel(levelIndex);
				if (requirementForLevel <= 0f || num2 + 0.0001f < requirementForLevel)
				{
					break;
				}
				num2 -= requirementForLevel;
				num3 = Mathf.Min(num3 + 1f, 100f);
				num4++;
				if (num3 >= 100f)
				{
					num2 = 0f;
					break;
				}
			}
			SetLevelAndAccumulator(skill, num3, num2);
			return num4;
		}

		private static void SetLevelAndAccumulator(Skill levelSkill, float level, float accumulator)
		{
			if (levelSkill != null)
			{
				levelSkill.m_level = Mathf.Clamp(level, 0f, 100f);
				levelSkill.m_accumulator = Mathf.Max(0f, accumulator);
				LevelProgressionService.OnLevelChanged?.Invoke();
			}
		}
	}
	public static class LevelSkillService
	{
		public static Skill GetSkill(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			return GetSkill(((Character)player).GetSkills());
		}

		public static Skill GetSkill(Skills skills)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)skills == (Object)null)
			{
				return null;
			}
			return skills.GetSkill(SkillsReworkedPlugin.LevelSkillType);
		}

		public static int GetLevel(Player player)
		{
			return GetLevel((player != null) ? ((Character)player).GetSkills() : null);
		}

		public static int GetLevel(Skills skills)
		{
			Skill skill = GetSkill(skills);
			return (skill != null) ? Mathf.FloorToInt(skill.m_level) : 0;
		}

		public static float GetCurrentLevelFraction(Player player)
		{
			return GetCurrentLevelFraction(GetSkill(player));
		}

		public static float GetCurrentLevelFraction(Skills skills)
		{
			return GetCurrentLevelFraction(GetSkill(skills));
		}

		public static float GetCurrentLevelFraction(Skill levelSkill)
		{
			return LevelXpCalculator.GetCurrentLevelFraction(levelSkill);
		}
	}
	public static class LevelXpCalculator
	{
		public static float GetRequirementForLevel(int levelIndex)
		{
			float num = Mathf.Floor((float)levelIndex + 1f);
			return Mathf.Pow(num, 1.5f) * 0.5f + 0.5f;
		}

		public static float GetCurrentLevelFraction(Skill levelSkill)
		{
			if (levelSkill == null)
			{
				return 0f;
			}
			int levelIndex = Mathf.FloorToInt(levelSkill.m_level);
			float requirementForLevel = GetRequirementForLevel(levelIndex);
			if (requirementForLevel <= 0f)
			{
				return 0f;
			}
			return Mathf.Clamp01(levelSkill.m_accumulator / requirementForLevel);
		}

		public static int GetPlayerLevel(Player player)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			Skills skills = ((Character)player).GetSkills();
			if ((Object)(object)skills == (Object)null)
			{
				return 0;
			}
			Skill skill = skills.GetSkill(SkillsReworkedPlugin.LevelSkillType);
			if (skill == null)
			{
				return 0;
			}
			return Mathf.FloorToInt(skill.m_level);
		}

		private static int GetOptimalLevelForBiome(Biome biome)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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_0008: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_000a: 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_0022: Expected I4, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			if ((int)biome <= 16)
			{
				switch (biome - 1)
				{
				default:
					if ((int)biome != 8)
					{
						if ((int)biome != 16)
						{
							break;
						}
						return ModConfig.PlainsOptimalLevel;
					}
					return ModConfig.BlackForestOptimalLevel;
				case 0:
					return ModConfig.MeadowsOptimalLevel;
				case 1:
					return ModConfig.SwampOptimalLevel;
				case 3:
					return ModConfig.MountainOptimalLevel;
				case 2:
					break;
				}
			}
			else
			{
				if ((int)biome == 32)
				{
					return ModConfig.AshlandsOptimalLevel;
				}
				if ((int)biome == 64)
				{
					return ModConfig.DeepNorthOptimalLevel;
				}
				if ((int)biome == 512)
				{
					return ModConfig.MistlandsOptimalLevel;
				}
			}
			return ModConfig.MeadowsOptimalLevel;
		}

		public static Biome GetMobBiome(Character mob)
		{
			//IL_000d: 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_0027: Invalid comparison between Unknown and I4
			//IL_004d: 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)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mob == (Object)null)
			{
				return (Biome)1;
			}
			MobBiomeTracker component = ((Component)mob).GetComponent<MobBiomeTracker>();
			if ((Object)(object)component != (Object)null && (int)component.SpawnBiome > 0)
			{
				return component.SpawnBiome;
			}
			return Heightmap.FindBiome(((Component)mob).transform.position);
		}

		public static float GetLevelBasedXpFactor(Player player, Character mob)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)mob == (Object)null)
			{
				return 1f;
			}
			return GetLevelBasedXpFactor(player, GetMobBiome(mob));
		}

		public static float GetLevelBasedXpFactor(Player player, Biome biome)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return 1f;
			}
			int playerLevel = GetPlayerLevel(player);
			int optimalLevelForBiome = GetOptimalLevelForBiome(biome);
			if (optimalLevelForBiome <= 0)
			{
				return 1f;
			}
			if (playerLevel <= optimalLevelForBiome)
			{
				return 1f;
			}
			int num = playerLevel - optimalLevelForBiome;
			int num2 = ModConfig.XpMaxOverLevel;
			if (num2 <= 0)
			{
				num2 = 1;
			}
			float xpMinFactor = ModConfig.XpMinFactor;
			xpMinFactor = Mathf.Clamp(xpMinFactor, 0.01f, 1f);
			float num3 = Mathf.Clamp01((float)num / (float)num2);
			float num4 = Mathf.Lerp(1f, xpMinFactor, num3);
			return Mathf.Clamp(num4, xpMinFactor, 1f);
		}

		public static float ApplyLevelScaling(Player player, Character mob, float xp)
		{
			if (xp <= 0f)
			{
				return 0f;
			}
			float levelBasedXpFactor = GetLevelBasedXpFactor(player, mob);
			return xp * levelBasedXpFactor;
		}

		public static float ApplyLevelScaling(Player player, Biome biome, float xp)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (xp <= 0f)
			{
				return 0f;
			}
			float levelBasedXpFactor = GetLevelBasedXpFactor(player, biome);
			return xp * levelBasedXpFactor;
		}
	}
	public static class ProgressionZdoSync
	{
		private static readonly int LevelHash = StringExtensionMethods.GetStableHashCode("SkillsReworked_Level");

		private static readonly int PrestigeHash = StringExtensionMethods.GetStableHashCode("SkillsReworked_Prestige");

		public static void Register()
		{
			LevelProgressionService.OnLevelChanged += SyncLocalPlayer;
			PlayerProgressionStore.OnPrestigeChanged += Sync;
		}

		public static void SyncLocalPlayer()
		{
			Sync(Player.m_localPlayer);
		}

		public static void Sync(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || (Object)(object)((Character)player).m_nview == (Object)null)
			{
				return;
			}
			ZDO zDO = ((Character)player).m_nview.GetZDO();
			if (zDO != null && zDO.IsOwner())
			{
				zDO.Set(LevelHash, SkillsReworkedApi.GetLevel(player), false);
				int prestigeLevel = SkillsReworkedApi.GetPrestigeLevel(player);
				int num = default(int);
				if (prestigeLevel > 0)
				{
					zDO.Set(PrestigeHash, prestigeLevel, false);
				}
				else if (zDO.GetInt(PrestigeHash, ref num) && num != 0)
				{
					zDO.Set(PrestigeHash, 0, false);
				}
			}
		}
	}
	public static class SkillAllocationFlow
	{
		public struct SkillPointAllocation
		{
			public SkillType SkillType;

			public int Points;
		}

		public struct SkillAllocationResult
		{
			public int AvailableBefore;

			public int EffectiveSpent;

			public bool Changed => EffectiveSpent > 0;
		}

		private struct PlannedAllocation
		{
			public Skill Skill;

			public int Points;
		}

		public static SkillAllocationResult Apply(Player player, IList<SkillPointAllocation> allocations)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			SkillAllocationResult result = default(SkillAllocationResult);
			if ((Object)(object)player == (Object)null || allocations == null || allocations.Count == 0)
			{
				return result;
			}
			Skills skills = ((Character)player).GetSkills();
			if ((Object)(object)skills == (Object)null)
			{
				return result;
			}
			int num = (result.AvailableBefore = SkillPointService.GetAvailablePoints(player));
			if (num <= 0)
			{
				return result;
			}
			float currentSkillCap = SkillCapPolicy.GetCurrentSkillCap(player);
			int num2 = num;
			int num3 = 0;
			List<PlannedAllocation> list = new List<PlannedAllocation>();
			foreach (SkillPointAllocation allocation in allocations)
			{
				if (allocation.Points <= 0 || num2 <= 0)
				{
					continue;
				}
				Skill skill = skills.GetSkill(allocation.SkillType);
				if (skill != null && !(skill.m_level >= currentSkillCap))
				{
					int num4 = Mathf.Max(0, Mathf.CeilToInt(currentSkillCap - skill.m_level));
					int num5 = Mathf.Min(allocation.Points, Mathf.Min(num2, num4));
					if (num5 > 0)
					{
						list.Add(new PlannedAllocation
						{
							Skill = skill,
							Points = num5
						});
						num2 -= num5;
						num3 += num5;
					}
				}
			}
			if (num3 <= 0)
			{
				return result;
			}
			if (!SkillPointService.TrySpendPoints(player, num3))
			{
				Logger.LogWarning((object)$"[SkillsReworked] TrySpendPoints({num3}) failed before applying queued allocations.");
				return result;
			}
			foreach (PlannedAllocation item in list)
			{
				Skill skill2 = item.Skill;
				skill2.m_level += (float)item.Points;
				item.Skill.m_accumulator = 0f;
			}
			result.EffectiveSpent = num3;
			return result;
		}
	}
	public static class SkillCapPolicy
	{
		public static float GetCurrentSkillCap(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 100f;
			}
			if (!ModConfig.SkillCapsEnabled)
			{
				return 100f;
			}
			int capBeforeEikthyr = ModConfig.CapBeforeEikthyr;
			int capAfterEikthyr = ModConfig.CapAfterEikthyr;
			int capAfterElder = ModConfig.CapAfterElder;
			int capAfterBonemass = ModConfig.CapAfterBonemass;
			int capAfterModer = ModConfig.CapAfterModer;
			int capAfterYagluth = ModConfig.CapAfterYagluth;
			int capAfterQueen = ModConfig.CapAfterQueen;
			int capAfterFader = ModConfig.CapAfterFader;
			if (Defeated("defeated_fader"))
			{
				return ClampCap(capAfterFader);
			}
			if (Defeated("defeated_queen"))
			{
				return ClampCap(capAfterQueen);
			}
			if (Defeated("defeated_goblinking"))
			{
				return ClampCap(capAfterYagluth);
			}
			if (Defeated("defeated_dragon"))
			{
				return ClampCap(capAfterModer);
			}
			if (Defeated("defeated_bonemass"))
			{
				return ClampCap(capAfterBonemass);
			}
			if (Defeated("defeated_gdking"))
			{
				return ClampCap(capAfterElder);
			}
			if (Defeated("defeated_eikthyr"))
			{
				return ClampCap(capAfterEikthyr);
			}
			return ClampCap(capBeforeEikthyr);
			bool Defeated(string key)
			{
				return BossProgressionService.HasDefeated(player, key);
			}
		}

		private static float ClampCap(int cap)
		{
			return Mathf.Clamp((float)cap, 0f, 100f);
		}
	}
	public static class SkillCategoryService
	{
		private static HashSet<SkillType> _activeCache;

		private static HashSet<SkillType> _passiveXpCache;

		private static Dictionary<string, SkillType> _nameLookupMap;

		public static void InvalidateCache()
		{
			_activeCache = null;
			_passiveXpCache = null;
		}

		public unsafe static void BuildNameLookup(Skills skillsInstance)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (_nameLookupMap != null || skillsInstance?.m_skills == null)
			{
				return;
			}
			_nameLookupMap = new Dictionary<string, SkillType>(StringComparer.OrdinalIgnoreCase);
			foreach (SkillDef skill2 in skillsInstance.m_skills)
			{
				SkillType skill = skill2.m_skill;
				if ((int)skill != 0 && (int)skill != 999)
				{
					_nameLookupMap[((object)(*(SkillType*)(&skill))/*cast due to .constrained prefix*/).ToString()] = skill;
					string text = "$skill_" + ((object)(*(SkillType*)(&skill))/*cast due to .constrained prefix*/).ToString().ToLower();
					Localization instance = Localization.instance;
					string text2 = ((instance != null) ? instance.Localize(text) : null);
					if (!string.IsNullOrWhiteSpace(text2) && !text2.StartsWith("$"))
					{
						_nameLookupMap[text2] = skill;
					}
				}
			}
			_activeCache = null;
		}

		public static bool IsActiveSkill(SkillType skillType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (skillType == SkillsReworkedPlugin.LevelSkillType)
			{
				return false;
			}
			if ((int)skillType == 0 || (int)skillType == 999)
			{
				return false;
			}
			if (GetActiveSet().Contains(skillType))
			{
				return true;
			}
			if (Enum.IsDefined(typeof(SkillType), skillType))
			{
				return false;
			}
			return ModConfig.UnknownSkillsDefaultActive;
		}

		public static bool IsPassiveXpSkill(SkillType skillType)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return GetPassiveXpSet().Contains(skillType);
		}

		private static HashSet<SkillType> GetActiveSet()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (_activeCache != null)
			{
				return _activeCache;
			}
			_activeCache = new HashSet<SkillType>();
			string activeSkillNames = ModConfig.ActiveSkillNames;
			if (string.IsNullOrWhiteSpace(activeSkillNames))
			{
				return _activeCache;
			}
			string[] array = activeSkillNames.Split(new char[1] { ',' });
			foreach (string text in array)
			{
				string text2 = text.Trim();
				if (!string.IsNullOrEmpty(text2))
				{
					SkillType? val = TryResolveSkillName(text2);
					if (val.HasValue)
					{
						_activeCache.Add(val.Value);
					}
					else
					{
						Logger.LogWarning((object)("[SkillCategoryService] Could not resolve skill name: '" + text2 + "'"));
					}
				}
			}
			return _activeCache;
		}

		private static HashSet<SkillType> GetPassiveXpSet()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (_passiveXpCache != null)
			{
				return _passiveXpCache;
			}
			_passiveXpCache = new HashSet<SkillType>();
			string passiveXpSkillNames = ModConfig.PassiveXpSkillNames;
			if (string.IsNullOrWhiteSpace(passiveXpSkillNames))
			{
				return _passiveXpCache;
			}
			string[] array = passiveXpSkillNames.Split(new char[1] { ',' });
			foreach (string text in array)
			{
				string text2 = text.Trim();
				if (!string.IsNullOrEmpty(text2))
				{
					SkillType? val = TryResolveSkillName(text2);
					if (val.HasValue)
					{
						_passiveXpCache.Add(val.Value);
					}
				}
			}
			return _passiveXpCache;
		}

		private static SkillType? TryResolveSkillName(string name)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (Enum.TryParse<SkillType>(name, ignoreCase: true, out SkillType result))
			{
				return result;
			}
			if (int.TryParse(name, out var result2))
			{
				return (SkillType)result2;
			}
			if (_nameLookupMap != null && _nameLookupMap.TryGetValue(name, out var value))
			{
				return value;
			}
			return null;
		}
	}
	public static class SkillPointService
	{
		private static int BasePoints => ModConfig.BasePoints;

		private static int PointsPerLevel => ModConfig.PointsPerLevel;

		public static int GetTotalPoints(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return 0;
			}
			int num = Mathf.Max(0, LevelSkillService.GetLevel(player));
			int basePoints = BasePoints;
			int pointsPerLevel = PointsPerLevel;
			int num2 = (ModConfig.PrestigeEnabled ? PlayerProgressionStore.GetPrestigeRank(player) : 0);
			int prestigePointsPerRank = ModConfig.PrestigePointsPerRank;
			int num3 = Mathf.Max(0, pointsPerLevel + num2 * prestigePointsPerRank);
			int num4 = basePoints + num * num3;
			return Mathf.Max(0, num4);
		}

		public static int GetAvailablePoints(Player player)
		{
			int totalPoints = GetTotalPoints(player);
			int spentSkillPoints = PlayerProgressionStore.GetSpentSkillPoints(player);
			return Mathf.Max(0, totalPoints - spentSkillPoints);
		}

		public static bool TrySpendPoints(Player player, int amount)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (amount <= 0)
			{
				return true;
			}
			int availablePoints = GetAvailablePoints(player);
			if (availablePoints < amount)
			{
				return false;
			}
			int spentSkillPoints = PlayerProgressionStore.GetSpentSkillPoints(player);
			PlayerProgressionStore.SetSpentSkillPoints(player, spentSkillPoints + amount);
			return true;
		}
	}
}
namespace SkillsReworked.Systems.Prestige
{
	public static class PrestigeFlow
	{
		public static event Action<Player> OnExecuted;

		public static bool CanStart(Player player, out string failureMessage)
		{
			failureMessage = null;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!ModConfig.PrestigeEnabled)
			{
				return false;
			}
			Skills skills = ((Character)player).GetSkills();
			if ((Object)(object)skills == (Object)null)