Decompiled source of Uncap player level v2.0.2

plugins/UncapPlayerLevel/UncapPlayerLevel.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using On.RoR2;
using On.RoR2.Items;
using ProperSave;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Items;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UncapPlayerLevel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fe14cb3162fc1415b7b32c843dc0cb8e92475b2e")]
[assembly: AssemblyProduct("UncapPlayerLevel")]
[assembly: AssemblyTitle("UncapPlayerLevel")]
[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 UncapPlayerLevel
{
	internal static class DebugKeys
	{
		public static void Update()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (UncapPlayerLevel.debugKeys.Value)
			{
				KeyboardShortcut value = UncapPlayerLevel.spawnPrayerBeadsKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Spawn(Items.ExtraStatsOnLevelUp);
				}
				value = UncapPlayerLevel.spawnSolitudeKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Spawn(Items.OnLevelUpFreeUnlock);
				}
				value = UncapPlayerLevel.spawnBrittleCrownKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Spawn(Items.GoldOnHit);
				}
			}
		}

		private static void Spawn(ItemDef item)
		{
			//IL_0062: 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_0067: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)Run.instance))
			{
				return;
			}
			if (!NetworkServer.active)
			{
				Log.Warning("The debug keys only work for the host");
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				Vector3 val2 = (Object.op_Implicit((Object)(object)val.inputBank) ? val.inputBank.aimDirection : val.transform.forward);
				val2.y = 0f;
				PickupDropletController.CreatePickupDroplet(new UniquePickup(PickupCatalog.FindPickupIndex(item.itemIndex)), val.corePosition, Vector3.up * 20f + ((Vector3)(ref val2)).normalized * 5f, false);
				Log.Info("Debug key pressed, spawned " + ((Object)item).name);
			}
		}
	}
	internal static class KillExperienceHooks
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_OnKilledServer <0>__OnKilledServer;

			public static hook_AwardExperience <1>__AwardExperience;
		}

		private const double EXPERIENCE_PER_LEVEL = 0.3;

		private const double VANILLA_LIMIT = 4290000000.0;

		private const double STUCK_LEVEL = 2147483648.0;

		private static BigInteger killExperience;

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: 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_003b: Expected O, but got Unknown
			object obj = <>O.<0>__OnKilledServer;
			if (obj == null)
			{
				hook_OnKilledServer val = OnKilledServer;
				<>O.<0>__OnKilledServer = val;
				obj = (object)val;
			}
			DeathRewards.OnKilledServer += (hook_OnKilledServer)obj;
			object obj2 = <>O.<1>__AwardExperience;
			if (obj2 == null)
			{
				hook_AwardExperience val2 = AwardExperience;
				<>O.<1>__AwardExperience = val2;
				obj2 = (object)val2;
			}
			ExperienceManager.AwardExperience += (hook_AwardExperience)obj2;
		}

		private static void OnKilledServer(orig_OnKilledServer orig, DeathRewards self, DamageReport damageReport)
		{
			killExperience = GetExperience(self);
			try
			{
				orig.Invoke(self, damageReport);
			}
			finally
			{
				killExperience = BigInteger.Zero;
			}
		}

		private static BigInteger GetExperience(DeathRewards rewards)
		{
			CharacterBody characterBody = rewards.characterBody;
			Run instance = Run.instance;
			if (!Object.op_Implicit((Object)(object)characterBody) || !Object.op_Implicit((Object)(object)instance))
			{
				return BigInteger.Zero;
			}
			double num = rewards.expReward;
			double num2 = (double)rewards.spawnValue * (double)instance.compensatedDifficultyCoefficient;
			if (num2 > 4294967295.0)
			{
				num = num2;
			}
			double num3 = num * (1.0 + (GetLevel(characterBody, instance) - 1.0) * 0.3);
			if (double.IsNaN(num3) || num3 <= 4290000000.0)
			{
				return BigInteger.Zero;
			}
			return new BigInteger(Math.Min(num3, double.MaxValue));
		}

		private static double GetLevel(CharacterBody body, Run run)
		{
			double num = body.level;
			if (!(num >= 2147483648.0))
			{
				return num;
			}
			return Math.Max(num, run.ambientLevel);
		}

		private static void AwardExperience(orig_AwardExperience orig, ExperienceManager self, Vector3 origin, CharacterBody body, ulong amount)
		{
			//IL_0037: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			BigInteger bigInteger = killExperience;
			killExperience = BigInteger.Zero;
			if (bigInteger.IsZero || SuppressExperience.suppressExperience || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.master))
			{
				orig.Invoke(self, origin, body, amount);
				return;
			}
			BigInteger bigInteger2 = BigInteger.Min(bigInteger, CharacterMaster.maxXPDisplay);
			orig.Invoke(self, origin, body, (ulong)bigInteger2);
			TeamManagerHooks.GiveExperience(body.master.teamIndex, bigInteger - bigInteger2);
		}
	}
	internal readonly struct LevelSettings
	{
		public const int GROWTH_SCALE = 1000;

		public readonly int InitialCost;

		public readonly uint MaxLevel;

		public readonly uint LevelsPerLevelUp;

		public readonly int Growth;

		public bool IsFlat => Growth == 1000;

		public LevelSettings(int initialCost, int maxLevel, int levelsPerLevelUp, float growthPercent)
		{
			InitialCost = Math.Max(1, initialCost);
			MaxLevel = (uint)Math.Max(1, maxLevel);
			LevelsPerLevelUp = (uint)Math.Max(1, levelsPerLevelUp);
			double num = Math.Round((double)growthPercent * 10.0);
			Growth = ((num > 1000.0) ? ((int)Math.Min(num, 2147483647.0)) : 1000);
		}
	}
	internal sealed class LevelProgress
	{
		private const int COST_FRACTION_BITS = 16;

		private const double MAX_COST_BITS = 16777216.0;

		private const int MAX_FIELD_BITS = 62;

		private const int BULK_LEVEL_UPS = 64;

		private const int BULK_MARGIN = 2;

		private const int BULK_MIN_COST_BITS = 20;

		private BigInteger scaledCost;

		private BigInteger cost;

		private BigInteger experience;

		private ulong pending;

		private ulong room;

		private int progressShift;

		private ulong progressCost;

		private ulong progressExperience;

		private int packShift;

		private ulong packCost;

		private ulong packExperience;

		public uint Level { get; private set; }

		public BigInteger Experience
		{
			get
			{
				if (pending != 0L)
				{
					return experience + pending;
				}
				return experience;
			}
		}

		public BigInteger NextLevelCost => cost;

		public LevelProgress(in LevelSettings settings)
		{
			Reset(in settings);
		}

		public void Reset(in LevelSettings settings)
		{
			Level = 1u;
			experience = BigInteger.Zero;
			pending = 0uL;
			SetScaledCost((BigInteger)settings.InitialCost << 16);
			Refresh();
		}

		public void Restore(uint level, BigInteger experience, BigInteger nextLevelCost, in LevelSettings settings)
		{
			Level = Math.Max(1u, level);
			this.experience = BigInteger.Max(BigInteger.Zero, experience);
			pending = 0uL;
			SetScaledCost(BigInteger.Max(BigInteger.One, nextLevelCost) << 16);
			SettleLevelUps(in settings);
		}

		public void AddExperience(ulong amount, in LevelSettings settings)
		{
			if (Level >= settings.MaxLevel)
			{
				ClearAtCap();
				return;
			}
			if (amount < room - pending)
			{
				pending += amount;
				return;
			}
			experience += (BigInteger)pending;
			experience += (BigInteger)amount;
			pending = 0uL;
			SettleLevelUps(in settings);
		}

		public void AddExperience(BigInteger amount, in LevelSettings settings)
		{
			if (Level >= settings.MaxLevel)
			{
				ClearAtCap();
				return;
			}
			if (amount.Sign > 0 && amount.CompareTo(room - pending) < 0)
			{
				pending += (ulong)amount;
				return;
			}
			experience += (BigInteger)pending;
			if (amount.Sign > 0)
			{
				experience += amount;
			}
			pending = 0uL;
			SettleLevelUps(in settings);
		}

		public void SetLevel(uint level, in LevelSettings settings)
		{
			Level = Math.Min(Math.Max(1u, level), settings.MaxLevel);
			experience = BigInteger.Zero;
			pending = 0uL;
			ulong levelUps = (ulong)((long)Level - 1L + settings.LevelsPerLevelUp - 1) / (ulong)settings.LevelsPerLevelUp;
			SetScaledCost(ScaledCostAfter(levelUps, in settings));
			Refresh();
		}

		public void GetProgress(out ulong experience, out ulong nextLevelExperience)
		{
			nextLevelExperience = progressCost;
			experience = Math.Min(progressExperience + ShiftRight(pending, progressShift), progressCost);
		}

		public int Pack(out ulong experience, out ulong nextLevelCost)
		{
			ulong num = ((packShift >= 16) ? ShiftRight(pending, packShift - 16) : (pending << 16 - packShift));
			nextLevelCost = packCost;
			experience = Math.Min(packExperience + num, packCost);
			return packShift;
		}

		public void Unpack(uint level, ulong experience, ulong nextLevelCost, int shift, in LevelSettings settings)
		{
			shift = Math.Max(0, shift);
			Level = Math.Max(1u, level);
			this.experience = (BigInteger)experience << shift >> 16;
			pending = 0uL;
			SetScaledCost(BigInteger.Max(BigInteger.One << 16, (BigInteger)nextLevelCost << shift));
			SettleLevelUps(in settings);
		}

		private void SetScaledCost(BigInteger value)
		{
			scaledCost = value;
			cost = BigInteger.Max(BigInteger.One, scaledCost >> 16);
		}

		private void ClearAtCap()
		{
			if (!experience.IsZero || pending != 0L)
			{
				experience = BigInteger.Zero;
				pending = 0uL;
				Refresh();
			}
		}

		private void SettleLevelUps(in LevelSettings settings)
		{
			while (Level < settings.MaxLevel && experience >= cost)
			{
				if (settings.IsFlat)
				{
					ulong num = (ulong)((long)settings.MaxLevel - (long)Level + settings.LevelsPerLevelUp - 1) / (ulong)settings.LevelsPerLevelUp;
					BigInteger bigInteger = BigInteger.Min(experience / cost, num);
					experience -= bigInteger * cost;
					Level = (uint)BigInteger.Min(Level + bigInteger * settings.LevelsPerLevelUp, settings.MaxLevel);
				}
				else if (!TryBulkLevelUps(in settings))
				{
					experience -= cost;
					Level = (uint)Math.Min((ulong)Level + (ulong)settings.LevelsPerLevelUp, settings.MaxLevel);
					SetScaledCost(scaledCost * settings.Growth / 1000);
				}
			}
			if (Level >= settings.MaxLevel)
			{
				experience = BigInteger.Zero;
			}
			Refresh();
		}

		private bool TryBulkLevelUps(in LevelSettings settings)
		{
			if (cost < BigInteger.One << 20)
			{
				return false;
			}
			double num = (double)settings.Growth / 1000.0;
			double num2 = Math.Log(num, 2.0);
			double num3 = Math.Log(num - 1.0, 2.0);
			double num4 = BigInteger.Log(experience, 2.0) - BigInteger.Log(cost, 2.0) + num3;
			double num5 = Math.Floor(((num4 > 50.0) ? num4 : Math.Log(1.0 + Math.Pow(2.0, num4), 2.0)) / num2) - 2.0;
			if (double.IsNaN(num5) || num5 < 64.0)
			{
				return false;
			}
			ulong num6 = (ulong)((long)settings.MaxLevel - (long)Level + settings.LevelsPerLevelUp - 1) / (ulong)settings.LevelsPerLevelUp;
			ulong num7 = ((num5 >= (double)num6) ? num6 : ((ulong)num5));
			double num8 = (double)num7 * num2;
			double num9 = ((num8 > 50.0) ? num8 : Math.Log(Math.Pow(2.0, num8) - 1.0, 2.0));
			BigInteger bigInteger = BigMath.MultiplyByPowerOfTwo(scaledCost, num9 - num3) >> 16;
			if (bigInteger.Sign <= 0 || bigInteger > experience)
			{
				return false;
			}
			experience -= bigInteger;
			Level = (uint)Math.Min(Level + num7 * settings.LevelsPerLevelUp, settings.MaxLevel);
			SetScaledCost(BigMath.MultiplyByPowerOfTwo(scaledCost, num8));
			return true;
		}

		private void Refresh()
		{
			BigInteger bigInteger = cost - experience;
			room = ((bigInteger.Sign <= 0) ? 0 : ((bigInteger.CompareTo(ulong.MaxValue) >= 0) ? ulong.MaxValue : ((ulong)bigInteger)));
			progressShift = ((!(cost <= long.MaxValue)) ? (BigMath.ApproximateBitLength(cost) - 62) : 0);
			progressCost = (ulong)(cost >> progressShift);
			progressExperience = (ulong)BigInteger.Min(experience >> progressShift, progressCost);
			packShift = ((!(scaledCost <= long.MaxValue)) ? (BigMath.ApproximateBitLength(scaledCost) - 62) : 0);
			packCost = (ulong)(scaledCost >> packShift);
			packExperience = (ulong)BigInteger.Min(experience << 16 >> packShift, packCost);
		}

		private static ulong ShiftRight(ulong value, int bits)
		{
			if (bits < 64)
			{
				return value >> bits;
			}
			return 0uL;
		}

		private static BigInteger ScaledCostAfter(ulong levelUps, in LevelSettings settings)
		{
			BigInteger bigInteger = (BigInteger)settings.InitialCost << 16;
			if (levelUps == 0L || settings.IsFlat)
			{
				return bigInteger;
			}
			double bits = Math.Min((double)levelUps * Math.Log((double)settings.Growth / 1000.0, 2.0), 16777216.0);
			return BigMath.MultiplyByPowerOfTwo(bigInteger, bits);
		}
	}
	internal static class BigMath
	{
		public static BigInteger Multiply(BigInteger value, double factor)
		{
			if (double.IsNaN(factor) || double.IsInfinity(factor) || factor <= 0.0)
			{
				return BigInteger.Zero;
			}
			long num = BitConverter.DoubleToInt64Bits(factor);
			int num2 = (int)((num >> 52) & 0x7FF);
			long num3 = num & 0xFFFFFFFFFFFFFL;
			if (num2 == 0)
			{
				num2 = 1;
			}
			else
			{
				num3 |= 0x10000000000000L;
			}
			num2 -= 1075;
			BigInteger bigInteger = value * num3;
			if (num2 < 0)
			{
				return bigInteger >> -num2;
			}
			return bigInteger << num2;
		}

		public static BigInteger MultiplyByPowerOfTwo(BigInteger value, double bits)
		{
			double num = Math.Floor(bits);
			BigInteger bigInteger = Multiply(value, Math.Pow(2.0, bits - num));
			int num2 = (int)Math.Max(-2147483648.0, Math.Min(2147483647.0, num));
			if (num2 < 0)
			{
				return bigInteger >> -num2;
			}
			return bigInteger << num2;
		}

		public static double Divide(BigInteger numerator, BigInteger denominator)
		{
			if (numerator.Sign <= 0 || denominator.Sign <= 0)
			{
				return 0.0;
			}
			int num = Math.Max(ApproximateBitLength(numerator), ApproximateBitLength(denominator)) - 1000;
			if (num > 0)
			{
				numerator >>= num;
				denominator >>= num;
				if (denominator.IsZero)
				{
					return double.PositiveInfinity;
				}
			}
			return (double)numerator / (double)denominator;
		}

		public static int ApproximateBitLength(BigInteger value)
		{
			if (value.Sign > 0)
			{
				return (int)Math.Ceiling(BigInteger.Log(value, 2.0));
			}
			return 0;
		}
	}
	internal static class LevelUpEffectHooks
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_OnCharacterLevelUp <0>__OnCharacterLevelUp;

			public static hook_OnTeamLevelUp <1>__OnTeamLevelUp;
		}

		private static readonly Dictionary<CharacterBody, float> lastRing = new Dictionary<CharacterBody, float>();

		private static readonly Dictionary<CharacterBody, float> lastBeadFlash = new Dictionary<CharacterBody, float>();

		private static float lastSound = float.NegativeInfinity;

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: 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_003b: Expected O, but got Unknown
			object obj = <>O.<0>__OnCharacterLevelUp;
			if (obj == null)
			{
				hook_OnCharacterLevelUp val = OnCharacterLevelUp;
				<>O.<0>__OnCharacterLevelUp = val;
				obj = (object)val;
			}
			LevelUpEffectManager.OnCharacterLevelUp += (hook_OnCharacterLevelUp)obj;
			object obj2 = <>O.<1>__OnTeamLevelUp;
			if (obj2 == null)
			{
				hook_OnTeamLevelUp val2 = OnTeamLevelUp;
				<>O.<1>__OnTeamLevelUp = val2;
				obj2 = (object)val2;
			}
			LevelUpEffectManager.OnTeamLevelUp += (hook_OnTeamLevelUp)obj2;
			CharacterBody.onBodyDestroyGlobal += delegate(CharacterBody body)
			{
				lastRing.Remove(body);
				lastBeadFlash.Remove(body);
			};
			Run.onRunStartGlobal += delegate
			{
				lastRing.Clear();
				lastBeadFlash.Clear();
				lastSound = float.NegativeInfinity;
			};
		}

		public static bool CanShowBeadFlash(CharacterBody body)
		{
			if (UncapPlayerLevel.beadEffect.Value)
			{
				return IsDue(lastBeadFlash, body, UncapPlayerLevel.beadEffectInterval);
			}
			return false;
		}

		private static void OnCharacterLevelUp(orig_OnCharacterLevelUp orig, CharacterBody characterBody)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			if (!Object.op_Implicit((Object)(object)characterBody) || !Object.op_Implicit((Object)(object)characterBody.teamComponent) || (int)characterBody.teamComponent.teamIndex != 1 || (UncapPlayerLevel.levelUpEffect.Value && IsDue(lastRing, characterBody, UncapPlayerLevel.levelUpEffectInterval)))
			{
				orig.Invoke(characterBody);
			}
		}

		private static void OnTeamLevelUp(orig_OnTeamLevelUp orig, TeamIndex teamIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if ((int)teamIndex == 1)
			{
				if (!UncapPlayerLevel.levelUpSound.Value)
				{
					return;
				}
				int value = UncapPlayerLevel.levelUpSoundInterval.Value;
				if (value > 0)
				{
					if (Time.unscaledTime - lastSound < (float)value)
					{
						return;
					}
					lastSound = Time.unscaledTime;
				}
			}
			orig.Invoke(teamIndex);
		}

		private static bool IsDue(Dictionary<CharacterBody, float> lastShown, CharacterBody body, ConfigEntry<int> intervalSetting)
		{
			int value = intervalSetting.Value;
			if (value <= 0 || !Object.op_Implicit((Object)(object)body))
			{
				return true;
			}
			if (lastShown.TryGetValue(body, out var value2) && Time.unscaledTime - value2 < (float)value)
			{
				return false;
			}
			lastShown[body] = Time.unscaledTime;
			return true;
		}
	}
	internal static class Log
	{
		private static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void Debug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void Error(object data)
		{
			_logSource.LogError(data);
		}

		internal static void Fatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	internal static class PrayerBeadHooks
	{
		private sealed class WrittenBeads
		{
			public LevelProgress beads;

			public uint level;

			public ulong experience;

			public ulong nextLevelCost;

			public uint storage;

			public bool IsStillIn(CharacterMaster master)
			{
				if (master.oldBeadLevel == level && master.beadExperience == experience && master.beadXPNeededForCurrentLevel == nextLevelCost)
				{
					return master.newBeadLevel == storage;
				}
				return false;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static hook_TrackBeadExperience <0>__TrackBeadExperience;

			public static hook_OnBeadReset <1>__OnBeadReset;

			public static hook_OnBodyStart <2>__OnBodyStart;
		}

		private const uint UNCAPPED_FLAG = 2147483648u;

		private const int MAX_SHIFT = 16777216;

		private static readonly Dictionary<CharacterMaster, WrittenBeads> written = new Dictionary<CharacterMaster, WrittenBeads>();

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: 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_003b: Expected O, but got Unknown
			//IL_0050: 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_005b: Expected O, but got Unknown
			object obj = <>O.<0>__TrackBeadExperience;
			if (obj == null)
			{
				hook_TrackBeadExperience val = TrackBeadExperience;
				<>O.<0>__TrackBeadExperience = val;
				obj = (object)val;
			}
			CharacterMaster.TrackBeadExperience += (hook_TrackBeadExperience)obj;
			object obj2 = <>O.<1>__OnBeadReset;
			if (obj2 == null)
			{
				hook_OnBeadReset val2 = OnBeadReset;
				<>O.<1>__OnBeadReset = val2;
				obj2 = (object)val2;
			}
			CharacterMaster.OnBeadReset += (hook_OnBeadReset)obj2;
			object obj3 = <>O.<2>__OnBodyStart;
			if (obj3 == null)
			{
				hook_OnBodyStart val3 = OnBodyStart;
				<>O.<2>__OnBodyStart = val3;
				obj3 = (object)val3;
			}
			CharacterMaster.OnBodyStart += (hook_OnBodyStart)obj3;
			Run.onRunStartGlobal += delegate
			{
				written.Clear();
			};
		}

		public static void GiveTeamExperience(TeamIndex teamIndex, BigInteger amount)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if ((int)teamIndex != 1)
			{
				return;
			}
			ReadOnlyCollection<TeamComponent> teamMembers = TeamComponent.GetTeamMembers(teamIndex);
			for (int i = 0; i < teamMembers.Count; i++)
			{
				CharacterBody component = ((Component)teamMembers[i]).GetComponent<CharacterBody>();
				if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.master))
				{
					GiveExperience(component.master, amount);
				}
			}
		}

		private static bool TryGetFactors(CharacterMaster master, out ulong bonusFactor, out ulong penaltyFactor)
		{
			int num = (Object.op_Implicit((Object)(object)master.inventory) ? master.inventory.GetItemCountEffective(Items.ExtraStatsOnLevelUp) : 0);
			bonusFactor = (ulong)(0.25f * (float)(num - 1));
			penaltyFactor = (ulong)(0.025f * (float)Math.Max(0, master.numberOfBeadStatsGained_XPGainNerf));
			return num > 0;
		}

		private static void GiveExperience(CharacterMaster master, ulong amount)
		{
			if (!TryGetFactors(master, out var bonusFactor, out var penaltyFactor))
			{
				return;
			}
			if (amount > ulong.MaxValue / (bonusFactor + 1) || (penaltyFactor != 0 && amount > ulong.MaxValue / penaltyFactor))
			{
				GiveExperience(master, (BigInteger)amount);
				return;
			}
			ulong num = amount + amount * bonusFactor;
			ulong num2 = amount * penaltyFactor;
			if (num2 >= num)
			{
				num2 = num - (ulong)((long)(num / 5) + (long)((num % 5 != 0) ? 1 : 0));
			}
			LevelSettings settings = UncapPlayerLevel.BeadSettings;
			LevelProgress levelProgress = Read(master, in settings);
			uint level = levelProgress.Level;
			levelProgress.AddExperience(num - num2, in settings);
			OnExperienceAdded(master, levelProgress, level);
		}

		private static void GiveExperience(CharacterMaster master, BigInteger amount)
		{
			if (TryGetFactors(master, out var bonusFactor, out var penaltyFactor))
			{
				BigInteger bigInteger = amount * bonusFactor;
				BigInteger bigInteger2 = amount * penaltyFactor;
				if (bigInteger2 >= amount + bigInteger)
				{
					bigInteger2 = (amount + bigInteger) * 4 / 5;
				}
				LevelSettings settings = UncapPlayerLevel.BeadSettings;
				LevelProgress levelProgress = Read(master, in settings);
				uint level = levelProgress.Level;
				levelProgress.AddExperience(amount + bigInteger - bigInteger2, in settings);
				OnExperienceAdded(master, levelProgress, level);
			}
		}

		private static void OnExperienceAdded(CharacterMaster master, LevelProgress beads, uint oldLevel)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Write(master, beads);
			if (beads.Level <= oldLevel)
			{
				return;
			}
			CharacterBody body = master.GetBody();
			if (Object.op_Implicit((Object)(object)body))
			{
				body.SetBuffCount(Buffs.ExtraStatsOnLevelUpBuff.buffIndex, GetBuffCount(beads));
				if (LevelUpEffectHooks.CanShowBeadFlash(body))
				{
					SpawnLevelUpEffect(body);
				}
			}
		}

		private static int GetBuffCount(LevelProgress beads)
		{
			return (int)Math.Min(beads.Level - 1, 2147483647u);
		}

		private static LevelProgress Read(CharacterMaster master, in LevelSettings settings)
		{
			if (written.TryGetValue(master, out var value) && value.IsStillIn(master))
			{
				return value.beads;
			}
			LevelProgress levelProgress = new LevelProgress(in settings);
			if ((master.newBeadLevel & 0x80000000u) != 0)
			{
				int shift = (int)Math.Min(master.newBeadLevel & 0x7FFFFFFF, 16777216u);
				levelProgress.Unpack(master.oldBeadLevel, master.beadExperience, master.beadXPNeededForCurrentLevel, shift, in settings);
			}
			else
			{
				levelProgress.AddExperience(master.beadExperience, in settings);
			}
			return levelProgress;
		}

		private static void Write(CharacterMaster master, LevelProgress beads)
		{
			ulong experience;
			ulong nextLevelCost;
			int num = beads.Pack(out experience, out nextLevelCost);
			master.oldBeadLevel = beads.Level;
			master.beadExperience = experience;
			master.beadXPNeededForCurrentLevel = nextLevelCost;
			master.newBeadLevel = (uint)(int.MinValue | num);
			if (!written.TryGetValue(master, out var value))
			{
				value = new WrittenBeads();
				written[master] = value;
			}
			value.beads = beads;
			value.level = master.oldBeadLevel;
			value.experience = master.beadExperience;
			value.nextLevelCost = master.beadXPNeededForCurrentLevel;
			value.storage = master.newBeadLevel;
		}

		private static void SpawnLevelUpEffect(CharacterBody body)
		{
			//IL_0007: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0067: Expected O, but got Unknown
			float num = 1f;
			HullClassification hullClassification = body.hullClassification;
			if ((int)hullClassification != 1)
			{
				if ((int)hullClassification == 2)
				{
					num = 2.5f;
				}
			}
			else
			{
				num = 1.5f;
			}
			num += Util.ConvertAmplificationPercentageIntoReductionNormalized((float)body.GetBuffCount(Buffs.ExtraStatsOnLevelUpBuff) * 0.1f);
			EffectManager.SpawnEffect(LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/ExtraStatsOnLevelUpEffect"), new EffectData
			{
				origin = body.footPosition,
				scale = num
			}, true);
		}

		private static void TrackBeadExperience(orig_TrackBeadExperience orig, CharacterMaster self, ulong amount)
		{
			GiveExperience(self, amount);
		}

		private static void OnBeadReset(orig_OnBeadReset orig, CharacterMaster self, bool gainedStats)
		{
			uint val = (uint)(int.MaxValue - Math.Max(0, self.numberOfBeadStatsGained_XPGainNerf));
			self.oldBeadLevel = Math.Min(self.oldBeadLevel, val);
			orig.Invoke(self, gainedStats);
			if (NetworkServer.active)
			{
				Write(self, new LevelProgress(UncapPlayerLevel.BeadSettings));
			}
		}

		private static void OnBodyStart(orig_OnBodyStart orig, CharacterMaster self, CharacterBody body)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self, body);
			if (NetworkServer.active && Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)self.inventory) && self.inventory.GetItemCountEffective(Items.ExtraStatsOnLevelUp) > 0)
			{
				body.SetBuffCount(Buffs.ExtraStatsOnLevelUpBuff.buffIndex, GetBuffCount(Read(self, UncapPlayerLevel.BeadSettings)));
			}
		}
	}
	internal static class ProperSaveCompat
	{
		public const string GUID = "com.KingEnderBrine.ProperSave";

		public static bool Enabled => Chainloader.PluginInfos.ContainsKey("com.KingEnderBrine.ProperSave");

		public static bool IsLoading
		{
			[MethodImpl(MethodImplOptions.NoInlining)]
			get
			{
				return Loading.IsLoading;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Init()
		{
			SaveFile.OnGatherSaveData += GatherSaveData;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool TryLoad(LevelProgress[] teams, in LevelSettings settings)
		{
			if (!Loading.IsLoading || Loading.CurrentSave == null)
			{
				return false;
			}
			try
			{
				ProperSaveModel properSaveModel = Loading.CurrentSave.TryGetModdedData<ProperSaveModel>("UncapPlayerLevel.DATA");
				if (properSaveModel != null && properSaveModel.TryApplyTo(teams, in settings))
				{
					Log.Info("Loaded the team levels from the save file");
					return true;
				}
			}
			catch (Exception arg)
			{
				Log.Error($"Couldn't read the team levels from the save file: {arg}");
			}
			Log.Warning("The save file has no team levels in it, they will be worked out from the XP the game saved instead");
			return false;
		}

		private static void GatherSaveData(Dictionary<string, object> dictionary)
		{
			if (TeamManagerHooks.TryCreateSaveData(out var model))
			{
				dictionary["UncapPlayerLevel.DATA"] = model;
			}
		}
	}
	internal class ProperSaveModel
	{
		public const string SAVE_KEY = "UncapPlayerLevel.DATA";

		public string[] TeamExperience { get; set; }

		public string[] TeamNextLevelExperience { get; set; }

		public uint[] TeamLevel { get; set; }

		public static ProperSaveModel From(LevelProgress[] teams)
		{
			return new ProperSaveModel
			{
				TeamExperience = teams.Select((LevelProgress team) => team.Experience.ToString()).ToArray(),
				TeamNextLevelExperience = teams.Select((LevelProgress team) => team.NextLevelCost.ToString()).ToArray(),
				TeamLevel = teams.Select((LevelProgress team) => team.Level).ToArray()
			};
		}

		public bool TryApplyTo(LevelProgress[] teams, in LevelSettings settings)
		{
			if (TeamExperience == null || TeamNextLevelExperience == null || TeamLevel == null)
			{
				return false;
			}
			int num = Math.Min(teams.Length, Math.Min(TeamLevel.Length, Math.Min(TeamExperience.Length, TeamNextLevelExperience.Length)));
			BigInteger[] array = new BigInteger[num];
			BigInteger[] array2 = new BigInteger[num];
			for (int i = 0; i < num; i++)
			{
				if (!BigInteger.TryParse(TeamExperience[i], out array[i]) || !BigInteger.TryParse(TeamNextLevelExperience[i], out array2[i]))
				{
					return false;
				}
			}
			for (int j = 0; j < num; j++)
			{
				teams[j].Restore(TeamLevel[j], array[j], array2[j], in settings);
			}
			return true;
		}
	}
	internal static class RiskOfOptionsCompat
	{
		public const string GUID = "com.rune580.riskofoptions";

		private const string ICON_FILE = "icon.png";

		public static bool Enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Init(string pluginLocation)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//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_005a: 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_0075: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_0090: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00ab: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00b5: 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)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_0121: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_013c: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			//IL_0157: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Expected O, but got Unknown
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Expected O, but got Unknown
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("Removes the level cap of 94 and lets you change how much XP a level costs. Only the host's settings count.");
			Sprite val = LoadIcon(pluginLocation);
			if (Object.op_Implicit((Object)(object)val))
			{
				ModSettingsManager.SetModIcon(val);
			}
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(UncapPlayerLevel.initialPlayerLevelCost, new IntSliderConfig
			{
				min = 1,
				max = 1024
			}));
			ModSettingsManager.AddOption((BaseOption)new SliderOption(UncapPlayerLevel.playerXpMultiplier, new SliderConfig
			{
				min = 100f,
				max = 1000f,
				FormatString = "{0:0.#}%"
			}));
			ConfigEntry<int> maxPlayerLevel = UncapPlayerLevel.maxPlayerLevel;
			IntFieldConfig val2 = new IntFieldConfig();
			((NumericFieldConfig<int>)val2).Min = 1;
			ModSettingsManager.AddOption((BaseOption)new IntFieldOption(maxPlayerLevel, val2));
			ConfigEntry<int> playerLevelPerLevelUps = UncapPlayerLevel.playerLevelPerLevelUps;
			IntFieldConfig val3 = new IntFieldConfig();
			((NumericFieldConfig<int>)val3).Min = 1;
			ModSettingsManager.AddOption((BaseOption)new IntFieldOption(playerLevelPerLevelUps, val3));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(UncapPlayerLevel.initialBeadLevelCost, new IntSliderConfig
			{
				min = 1,
				max = 1024
			}));
			ModSettingsManager.AddOption((BaseOption)new SliderOption(UncapPlayerLevel.beadXpMultiplier, new SliderConfig
			{
				min = 100f,
				max = 1000f,
				FormatString = "{0:0.#}%"
			}));
			ConfigEntry<int> maxBeadLevel = UncapPlayerLevel.maxBeadLevel;
			IntFieldConfig val4 = new IntFieldConfig();
			((NumericFieldConfig<int>)val4).Min = 1;
			ModSettingsManager.AddOption((BaseOption)new IntFieldOption(maxBeadLevel, val4));
			ConfigEntry<int> beadLevelPerLevelUps = UncapPlayerLevel.beadLevelPerLevelUps;
			IntFieldConfig val5 = new IntFieldConfig();
			((NumericFieldConfig<int>)val5).Min = 1;
			ModSettingsManager.AddOption((BaseOption)new IntFieldOption(beadLevelPerLevelUps, val5));
			ConfigEntry<int> solitudePearlLevel = UncapPlayerLevel.solitudePearlLevel;
			IntFieldConfig val6 = new IntFieldConfig();
			((NumericFieldConfig<int>)val6).Min = 1;
			ModSettingsManager.AddOption((BaseOption)new IntFieldOption(solitudePearlLevel, val6));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(UncapPlayerLevel.levelUpEffect));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(UncapPlayerLevel.levelUpEffectInterval, new IntSliderConfig
			{
				min = 0,
				max = 60
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(UncapPlayerLevel.levelUpSound));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(UncapPlayerLevel.levelUpSoundInterval, new IntSliderConfig
			{
				min = 0,
				max = 60
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(UncapPlayerLevel.beadEffect));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(UncapPlayerLevel.beadEffectInterval, new IntSliderConfig
			{
				min = 0,
				max = 60
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(UncapPlayerLevel.debugKeys));
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(UncapPlayerLevel.spawnPrayerBeadsKey));
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(UncapPlayerLevel.spawnSolitudeKey));
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(UncapPlayerLevel.spawnBrittleCrownKey));
		}

		private static Sprite LoadIcon(string pluginLocation)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0067: 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)
			string directoryName = Path.GetDirectoryName(pluginLocation);
			string path = Path.Combine(directoryName, "icon.png");
			if (!File.Exists(path))
			{
				path = Path.Combine(Path.GetDirectoryName(directoryName), "icon.png");
			}
			if (!File.Exists(path))
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2);
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path)))
			{
				return null;
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
	}
	internal static class SolitudeHooks
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_GiveMoneyWithOnLevelUpFreeUnlock <0>__GiveMoneyWithOnLevelUpFreeUnlock;

			public static hook_OnCalculatedLevelChanged <1>__OnCalculatedLevelChanged;

			public static hook_LevelThresholdCheck <2>__LevelThresholdCheck;
		}

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: 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_003b: Expected O, but got Unknown
			//IL_0050: 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_005b: Expected O, but got Unknown
			object obj = <>O.<0>__GiveMoneyWithOnLevelUpFreeUnlock;
			if (obj == null)
			{
				hook_GiveMoneyWithOnLevelUpFreeUnlock val = GiveMoneyWithOnLevelUpFreeUnlock;
				<>O.<0>__GiveMoneyWithOnLevelUpFreeUnlock = val;
				obj = (object)val;
			}
			CharacterMaster.GiveMoneyWithOnLevelUpFreeUnlock += (hook_GiveMoneyWithOnLevelUpFreeUnlock)obj;
			object obj2 = <>O.<1>__OnCalculatedLevelChanged;
			if (obj2 == null)
			{
				hook_OnCalculatedLevelChanged val2 = OnCalculatedLevelChanged;
				<>O.<1>__OnCalculatedLevelChanged = val2;
				obj2 = (object)val2;
			}
			CharacterBody.OnCalculatedLevelChanged += (hook_OnCalculatedLevelChanged)obj2;
			object obj3 = <>O.<2>__LevelThresholdCheck;
			if (obj3 == null)
			{
				hook_LevelThresholdCheck val3 = LevelThresholdCheck;
				<>O.<2>__LevelThresholdCheck = val3;
				obj3 = (object)val3;
			}
			OnLevelUpFreeUnlockBehavior.LevelThresholdCheck += (hook_LevelThresholdCheck)obj3;
		}

		private static void OnCalculatedLevelChanged(orig_OnCalculatedLevelChanged orig, CharacterBody self, float oldLevel, float newLevel)
		{
			//IL_0067: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self, oldLevel, newLevel);
			double num = Math.Floor(newLevel) - Math.Floor(oldLevel) - 1.0;
			if (!NetworkServer.active || oldLevel < 1f || num < 1.0 || !Object.op_Implicit((Object)(object)self.inventory))
			{
				return;
			}
			int itemCountEffective = self.inventory.GetItemCountEffective(Items.OnLevelUpFreeUnlock);
			if (itemCountEffective > 0)
			{
				BuffIndex buffIndex = Buffs.FreeUnlocks.buffIndex;
				int buffCount = self.GetBuffCount(buffIndex);
				int num2 = (int)Math.Min(num * (double)itemCountEffective, int.MaxValue - buffCount);
				self.SetBuffCount(buffIndex, buffCount + num2);
				if (Object.op_Implicit((Object)(object)self.master))
				{
					self.master.trackedFreeUnlocks = (uint)Math.Min((ulong)self.master.trackedFreeUnlocks + (ulong)(uint)num2, 2147483647uL);
				}
			}
		}

		private static void LevelThresholdCheck(orig_LevelThresholdCheck orig, OnLevelUpFreeUnlockBehavior self)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0054: 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)
			if (!(((BaseItemBodyBehavior)self).body.level < (float)UncapPlayerLevel.SolitudePearlLevel))
			{
				ItemTransformation val = default(ItemTransformation);
				((ItemTransformation)(ref val)).originalItemIndex = Items.OnLevelUpFreeUnlock.itemIndex;
				((ItemTransformation)(ref val)).newItemIndex = Items.Pearl.itemIndex;
				((ItemTransformation)(ref val)).maxToTransform = ((BaseItemBodyBehavior)self).stack;
				val.transformationType = (ItemTransformationTypeIndex)0;
				ItemTransformation val2 = val;
				TryTransformResult val3 = default(TryTransformResult);
				((ItemTransformation)(ref val2)).TryTransform(((BaseItemBodyBehavior)self).body.inventory, ref val3);
			}
		}

		private static void GiveMoneyWithOnLevelUpFreeUnlock(orig_GiveMoneyWithOnLevelUpFreeUnlock orig, CharacterMaster self, uint amount)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			if (!TeamManagerHooks.TryGetNextLevelCost(self.teamIndex, out var cost))
			{
				orig.Invoke(self, amount);
				return;
			}
			self.moneyEarnedSoFar += (float)amount;
			CharacterBody body = self.GetBody();
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory) || CharacterMaster.costOfSmallChest == 0)
			{
				return;
			}
			int num = Math.Max(1, Math.Min(body.inventory.GetItemCountEffective(Items.OnLevelUpFreeUnlock), (int)CharacterMaster.maxStacks));
			double num2 = (double)(CharacterMaster.chestPerLevelFactor + (float)(num - 1) * CharacterMaster.stackingBonus) / (double)CharacterMaster.costOfSmallChest;
			BigInteger bigInteger = BigMath.Multiply(cost, num2 * (double)self.moneyEarnedSoFar);
			if (bigInteger.Sign > 0)
			{
				double num3 = Math.Ceiling(BigMath.Divide(bigInteger, cost) / num2);
				self.moneyEarnedSoFar = (float)Math.Max(0.0, (double)self.moneyEarnedSoFar - num3);
				BigInteger bigInteger2 = BigInteger.Zero;
				if (Object.op_Implicit((Object)(object)ExperienceManager.instance))
				{
					bigInteger2 = BigInteger.Min(bigInteger, CharacterMaster.maxXPDisplay);
					Vector3 val = body.transform.position + CharacterMaster.RandomPointOnUnitSphere() * CharacterMaster.orbSpawnDistance;
					ExperienceManager.instance.AwardExperience(val, body, (ulong)bigInteger2);
				}
				TeamManagerHooks.GiveExperience(self.teamIndex, bigInteger - bigInteger2);
			}
		}
	}
	internal static class TeamManagerHooks
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_Start <0>__Start;

			public static hook_GiveTeamExperience <1>__GiveTeamExperience;

			public static hook_SetTeamExperience <2>__SetTeamExperience;

			public static hook_SetTeamLevel <3>__SetTeamLevel;

			public static hook_OnSerialize <4>__OnSerialize;

			public static hook_OnDeserialize <5>__OnDeserialize;
		}

		private static LevelProgress[] teams = Array.Empty<LevelProgress>();

		private static bool ignoreSaveReplay;

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: 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_003b: Expected O, but got Unknown
			//IL_0050: 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_005b: 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
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			object obj = <>O.<0>__Start;
			if (obj == null)
			{
				hook_Start val = Start;
				<>O.<0>__Start = val;
				obj = (object)val;
			}
			TeamManager.Start += (hook_Start)obj;
			object obj2 = <>O.<1>__GiveTeamExperience;
			if (obj2 == null)
			{
				hook_GiveTeamExperience val2 = GiveTeamExperience;
				<>O.<1>__GiveTeamExperience = val2;
				obj2 = (object)val2;
			}
			TeamManager.GiveTeamExperience += (hook_GiveTeamExperience)obj2;
			object obj3 = <>O.<2>__SetTeamExperience;
			if (obj3 == null)
			{
				hook_SetTeamExperience val3 = SetTeamExperience;
				<>O.<2>__SetTeamExperience = val3;
				obj3 = (object)val3;
			}
			TeamManager.SetTeamExperience += (hook_SetTeamExperience)obj3;
			object obj4 = <>O.<3>__SetTeamLevel;
			if (obj4 == null)
			{
				hook_SetTeamLevel val4 = SetTeamLevel;
				<>O.<3>__SetTeamLevel = val4;
				obj4 = (object)val4;
			}
			TeamManager.SetTeamLevel += (hook_SetTeamLevel)obj4;
			object obj5 = <>O.<4>__OnSerialize;
			if (obj5 == null)
			{
				hook_OnSerialize val5 = OnSerialize;
				<>O.<4>__OnSerialize = val5;
				obj5 = (object)val5;
			}
			TeamManager.OnSerialize += (hook_OnSerialize)obj5;
			object obj6 = <>O.<5>__OnDeserialize;
			if (obj6 == null)
			{
				hook_OnDeserialize val6 = OnDeserialize;
				<>O.<5>__OnDeserialize = val6;
				obj6 = (object)val6;
			}
			TeamManager.OnDeserialize += (hook_OnDeserialize)obj6;
		}

		public static bool TryGetNextLevelCost(TeamIndex teamIndex, out BigInteger cost)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			LevelProgress team;
			bool flag = TryGetTeam(teamIndex, out team);
			cost = (flag ? team.NextLevelCost : BigInteger.Zero);
			return flag;
		}

		public static void GiveExperience(TeamIndex teamIndex, BigInteger amount)
		{
			//IL_0052: 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)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			TeamManager instance = TeamManager.instance;
			if (Object.op_Implicit((Object)(object)instance) && amount.Sign > 0)
			{
				if (amount > ulong.MaxValue && TryGetTeam(teamIndex, out var team))
				{
					BigInteger amount2 = amount - ulong.MaxValue;
					team.AddExperience(amount2, UncapPlayerLevel.Settings);
					PrayerBeadHooks.GiveTeamExperience(teamIndex, amount2);
				}
				instance.GiveTeamExperience(teamIndex, (ulong)BigInteger.Min(amount, ulong.MaxValue));
			}
		}

		public static bool TryCreateSaveData(out ProperSaveModel model)
		{
			model = ((NetworkServer.active && teams.Length != 0) ? ProperSaveModel.From(teams) : null);
			return model != null;
		}

		private static bool TryGetTeam(TeamIndex teamIndex, out LevelProgress team)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			int num = (int)teamIndex;
			team = ((NetworkServer.active && num >= 0 && num < teams.Length) ? teams[num] : null);
			return team != null;
		}

		private static void Start(orig_Start orig, TeamManager self)
		{
			if (NetworkServer.active)
			{
				LevelSettings settings = UncapPlayerLevel.Settings;
				teams = new LevelProgress[self.teamLevels.Length];
				for (int i = 0; i < teams.Length; i++)
				{
					teams[i] = new LevelProgress(in settings);
				}
				ignoreSaveReplay = ProperSaveCompat.Enabled && ProperSaveCompat.TryLoad(teams, in settings);
			}
			orig.Invoke(self);
		}

		private static void GiveTeamExperience(orig_GiveTeamExperience orig, TeamManager self, TeamIndex teamIndex, ulong experience)
		{
			//IL_0000: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			if (TryGetTeam(teamIndex, out var team))
			{
				if (ignoreSaveReplay && (int)teamIndex == 1 && ProperSaveCompat.IsLoading)
				{
					ignoreSaveReplay = false;
				}
				else
				{
					team.AddExperience(experience, UncapPlayerLevel.Settings);
				}
			}
			orig.Invoke(self, teamIndex, experience);
		}

		private static void SetTeamExperience(orig_SetTeamExperience orig, TeamManager self, TeamIndex teamIndex, ulong newExperience)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetTeam(teamIndex, out var team))
			{
				Publish(self, teamIndex, team);
			}
		}

		private static void SetTeamLevel(orig_SetTeamLevel orig, TeamManager self, TeamIndex teamIndex, uint newLevel)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetTeam(teamIndex, out var team) && team.Level != newLevel)
			{
				team.SetLevel(newLevel, UncapPlayerLevel.Settings);
				Publish(self, teamIndex, team);
			}
		}

		private static bool OnSerialize(orig_OnSerialize orig, TeamManager self, NetworkWriter writer, bool initialState)
		{
			int num = self.teamLevels.Length;
			uint num2 = (initialState ? ((uint)((1 << num) - 1)) : ((NetworkBehaviour)self).syncVarDirtyBits);
			writer.WritePackedUInt32(num2);
			if (num2 == 0)
			{
				return false;
			}
			for (int i = 0; i < num; i++)
			{
				if ((num2 & (uint)(1 << i)) != 0)
				{
					writer.WritePackedUInt32(self.teamLevels[i]);
					writer.WritePackedUInt64(self.teamExperience[i]);
					writer.WritePackedUInt64(self.teamNextLevelExperience[i]);
				}
			}
			return true;
		}

		private static void OnDeserialize(orig_OnDeserialize orig, TeamManager self, NetworkReader reader, bool initialState)
		{
			int num = self.teamLevels.Length;
			uint num2 = reader.ReadPackedUInt32();
			for (int i = 0; i < num; i++)
			{
				if ((num2 & (uint)(1 << i)) != 0)
				{
					uint level = reader.ReadPackedUInt32();
					ulong experience = reader.ReadPackedUInt64();
					ulong nextLevelExperience = reader.ReadPackedUInt64();
					Apply(self, (TeamIndex)(sbyte)i, level, experience, nextLevelExperience);
				}
			}
		}

		private static void Publish(TeamManager teamManager, TeamIndex teamIndex, LevelProgress team)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			team.GetProgress(out var experience, out var nextLevelExperience);
			Apply(teamManager, teamIndex, team.Level, experience, nextLevelExperience);
			((NetworkBehaviour)teamManager).SetDirtyBit((uint)(1 << (int)teamIndex));
		}

		private static void Apply(TeamManager teamManager, TeamIndex teamIndex, uint level, ulong experience, ulong nextLevelExperience)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			//IL_002d: 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)
			int num = (int)teamIndex;
			teamManager.teamExperience[num] = experience;
			teamManager.teamCurrentLevelExperience[num] = 0uL;
			teamManager.teamNextLevelExperience[num] = nextLevelExperience;
			uint num2 = teamManager.teamLevels[num];
			if (num2 == level)
			{
				return;
			}
			ReadOnlyCollection<TeamComponent> teamMembers = TeamComponent.GetTeamMembers(teamIndex);
			for (int i = 0; i < teamMembers.Count; i++)
			{
				CharacterBody component = ((Component)teamMembers[i]).GetComponent<CharacterBody>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.OnTeamLevelChanged();
				}
			}
			teamManager.teamLevels[num] = level;
			if (num2 < level)
			{
				GlobalEventManager.OnTeamLevelUp(teamIndex);
			}
		}
	}
	[BepInPlugin("360gaggi.UncapPlayerLevel", "UncapPlayerLevel", "2.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class UncapPlayerLevel : BaseUnityPlugin
	{
		public const string PLUGIN_GUID = "360gaggi.UncapPlayerLevel";

		public const string PLUGIN_AUTHOR = "360gaggi";

		public const string PLUGIN_NAME = "UncapPlayerLevel";

		public const string PLUGIN_VERSION = "2.0.2";

		private const string OLD_CONFIG_FILE = "HeroYT.UncapPlayerLevel.cfg";

		public const int MIN_INITIAL_LEVEL_COST = 1;

		public const int MAX_INITIAL_LEVEL_COST = 1024;

		public const float MIN_XP_MULTIPLICATOR = 100f;

		public const float MAX_XP_MULTIPLICATOR = 1000f;

		public const int MAX_LEVEL_UP_EFFECT_INTERVAL = 60;

		public static ConfigEntry<int> initialPlayerLevelCost;

		public static ConfigEntry<int> maxPlayerLevel;

		public static ConfigEntry<int> playerLevelPerLevelUps;

		public static ConfigEntry<float> playerXpMultiplier;

		public static ConfigEntry<int> initialBeadLevelCost;

		public static ConfigEntry<int> maxBeadLevel;

		public static ConfigEntry<int> beadLevelPerLevelUps;

		public static ConfigEntry<float> beadXpMultiplier;

		public static ConfigEntry<int> solitudePearlLevel;

		public static ConfigEntry<bool> levelUpEffect;

		public static ConfigEntry<int> levelUpEffectInterval;

		public static ConfigEntry<bool> levelUpSound;

		public static ConfigEntry<int> levelUpSoundInterval;

		public static ConfigEntry<bool> beadEffect;

		public static ConfigEntry<int> beadEffectInterval;

		public static ConfigEntry<bool> debugKeys;

		public static ConfigEntry<KeyboardShortcut> spawnPrayerBeadsKey;

		public static ConfigEntry<KeyboardShortcut> spawnSolitudeKey;

		public static ConfigEntry<KeyboardShortcut> spawnBrittleCrownKey;

		internal static LevelSettings Settings => new LevelSettings(initialPlayerLevelCost.Value, maxPlayerLevel.Value, playerLevelPerLevelUps.Value, playerXpMultiplier.Value);

		internal static LevelSettings BeadSettings => new LevelSettings(initialBeadLevelCost.Value, maxBeadLevel.Value, beadLevelPerLevelUps.Value, beadXpMultiplier.Value);

		internal static uint SolitudePearlLevel => Math.Min((uint)Math.Max(1, solitudePearlLevel.Value), Settings.MaxLevel);

		public void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Expected O, but got Unknown
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Expected O, but got Unknown
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Expected O, but got Unknown
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Expected O, but got Unknown
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			Log.Init(((BaseUnityPlugin)this).Logger);
			KeepOldConfig();
			initialPlayerLevelCost = ((BaseUnityPlugin)this).Config.Bind<int>("Player", "Initial level cost", 20, new ConfigDescription("How much XP the first level up costs (vanilla is 20)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1024), Array.Empty<object>()));
			maxPlayerLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Player", "Max level", int.MaxValue, new ConfigDescription("The highest level that can be reached (vanilla stops at 94)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
			playerLevelPerLevelUps = ((BaseUnityPlugin)this).Config.Bind<int>("Player", "How many levels per level up", 1, new ConfigDescription("How many levels you get per level up (vanilla is 1)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
			playerXpMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Player", "XP multiplicator", 155f, new ConfigDescription("How much XP a level up costs compared to the one before it, in percent (vanilla is 155%). 100% means every level costs the same", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 1000f), Array.Empty<object>()));
			initialBeadLevelCost = ((BaseUnityPlugin)this).Config.Bind<int>("Beads", "Initial level cost", 20, new ConfigDescription("How much XP the first level of the Prayer Beads costs (vanilla is 20)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1024), Array.Empty<object>()));
			maxBeadLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Beads", "Max level", int.MaxValue, new ConfigDescription("The highest level the Prayer Beads can reach (vanilla stops at 94)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
			beadLevelPerLevelUps = ((BaseUnityPlugin)this).Config.Bind<int>("Beads", "How many levels per level up", 1, new ConfigDescription("How many levels the Prayer Beads get per level up (vanilla is 1)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
			beadXpMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Beads", "XP multiplicator", 155f, new ConfigDescription("How much XP a level of the Prayer Beads costs compared to the one before it, in percent (vanilla is 155%). 100% means every level costs the same", (AcceptableValueBase)(object)new AcceptableValueRange<float>(100f, 1000f), Array.Empty<object>()));
			solitudePearlLevel = ((BaseUnityPlugin)this).Config.Bind<int>("Solitude", "Pearl level", int.MaxValue, new ConfigDescription("The level at which Longstanding Solitude turns into a Pearl (vanilla is 91). It always does so when the max level of the player is reached, even if this is set higher", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, int.MaxValue), Array.Empty<object>()));
			levelUpEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "Level up effect", true, "Shows the ring of light a player (or one of their allies) gets when they level up. Turn it off to never see it");
			levelUpEffectInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Effects", "Level up effect interval", 1, new ConfigDescription("The least time between two rings of light on the same character, in seconds. Past 94 you can level many times a second. 0 shows every single one like vanilla", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>()));
			levelUpSound = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "Level up sound", true, "Plays the sound when the players level up. Turn it off to never hear it");
			levelUpSoundInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Effects", "Level up sound interval", 1, new ConfigDescription("The least time between two level up sounds, in seconds. 0 plays every single one like vanilla", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>()));
			beadEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("Effects", "Prayer Beads effect", true, "Shows the golden flash when the Prayer Beads level up. Turn it off to never see it");
			beadEffectInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Effects", "Prayer Beads effect interval", 1, new ConfigDescription("The least time between two flashes of the Prayer Beads on the same player, in seconds. 0 shows every single one like vanilla", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>()));
			debugKeys = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Debug keys", false, "Turns on the keys below, for trying things out. They only work for the host");
			spawnPrayerBeadsKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Debug", "Spawn Prayer Beads", new KeyboardShortcut((KeyCode)283, Array.Empty<KeyCode>()), "Drops Prayer Beads in front of you");
			spawnSolitudeKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Debug", "Spawn Longstanding Solitude", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Drops a Longstanding Solitude in front of you");
			spawnBrittleCrownKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Debug", "Spawn Brittle Crown", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), "Drops a Brittle Crown in front of you. With a Longstanding Solitude all gold turns into XP, so this is a quick way to a lot of levels");
			NetworkModCompatibilityHelper.networkModList = NetworkModCompatibilityHelper.networkModList.Append("360gaggi.UncapPlayerLevel;2.0.2");
			TeamManagerHooks.Init();
			SolitudeHooks.Init();
			PrayerBeadHooks.Init();
			KillExperienceHooks.Init();
			LevelUpEffectHooks.Init();
			if (ProperSaveCompat.Enabled)
			{
				ProperSaveCompat.Init();
			}
			if (RiskOfOptionsCompat.Enabled)
			{
				RiskOfOptionsCompat.Init(((BaseUnityPlugin)this).Info.Location);
			}
		}

		public void Update()
		{
			DebugKeys.Update();
		}

		private void KeepOldConfig()
		{
			string text = Path.Combine(Paths.ConfigPath, "HeroYT.UncapPlayerLevel.cfg");
			if (!File.Exists(text) || File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
			{
				return;
			}
			try
			{
				File.Move(text, ((BaseUnityPlugin)this).Config.ConfigFilePath);
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch (Exception ex)
			{
				Log.Warning("Could not take over the old config file: " + ex.Message);
			}
		}
	}
}