Decompiled source of GTFuckingXP v2.0.0

Expansions.dll

Decompiled 8 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using AIGraph;
using Agents;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using DoubleJump;
using EndskApi.Api;
using Enemies;
using GTFuckingXP.Communication;
using GTFuckingXP.Extensions;
using GTFuckingXP.Information.Level;
using GTFuckingXP.Managers;
using GameData;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using UnityEngine;
using XpExpansions.Extensions;
using XpExpansions.Information;
using XpExpansions.Information.BioTrackerLocal;
using XpExpansions.Information.DoubleJump;
using XpExpansions.Information.StartingXp;
using XpExpansions.Manager;
using XpExpansions.Scripts;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Expansions")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+gitc03396b-dirty-master")]
[assembly: AssemblyProduct("Expansions")]
[assembly: AssemblyTitle("Expansions")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Expansions
{
	[GeneratedCode("VersionInfoGenerator", "2.0.0+git50a4b1a-master")]
	[CompilerGenerated]
	internal static class VersionInfo
	{
		public const string RootNamespace = "Expansions";

		public const string Version = "1.0.0";

		public const string VersionPrerelease = null;

		public const string VersionMetadata = "gitc03396b-dirty-master";

		public const string SemVer = "1.0.0+gitc03396b-dirty-master";

		public const string GitRevShort = "c03396b-dirty";

		public const string GitRevLong = "c03396b43dd7f0dd7f6be64a74260c9045444f6f-dirty";

		public const string GitBranch = "master";

		public const string GitTag = null;

		public const bool GitIsDirty = true;
	}
}
namespace XpExpansions
{
	[BepInPlugin("Endskill.XpExpansions", "XpExpansions", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BepinExLoader : BasePlugin
	{
		public const string MODNAME = "XpExpansions";

		public const string AUTHOR = "Endskill";

		public const string GUID = "Endskill.XpExpansions";

		public const string VERSION = "1.0.0";

		public override void Load()
		{
			LogManager.SetLogger(((BasePlugin)this).Log);
			LogManager._debugMessagesActive = ((BasePlugin)this).Config.Bind<bool>("Dev Settings", "DebugMessages", false, "This settings activates/deactivates debug messages in the console for this specific plugin.").Value;
			ClassInjector.RegisterTypeInIl2Cpp<ClientSidedBioTrackerAbility>();
			CacheApi.SaveInstance<ExpansionManager>(new ExpansionManager(), CacheApiWrapper.ExtensionCacheName);
		}
	}
}
namespace XpExpansions.Scripts
{
	public class ClientSidedBioTrackerAbility : MonoBehaviour
	{
		private float _nextUpdate = 0f;

		public ClientSidedBioTrackerAbility(IntPtr intPtr)
			: base(intPtr)
		{
		}

		public void Update()
		{
			if (!(Time.time > _nextUpdate))
			{
				return;
			}
			if (GameStateManager.IsInExpedition)
			{
				PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
				Enumerator<EnemyAgent> enumerator = AIG_CourseGraph.GetReachableEnemiesInNodes(((Agent)PlayerManager.GetLocalPlayerAgent()).CourseNode, 1).GetEnumerator();
				while (enumerator.MoveNext())
				{
					EnemyAgent current = enumerator.Current;
					ToolSyncManager.WantToTagEnemy(current);
				}
			}
			_nextUpdate = Time.time + 10f;
		}
	}
}
namespace XpExpansions.Patches
{
	[HarmonyBefore(new string[] { "Endskill.XpExpansions", "Endskill.GTFuckingXP" })]
	[HarmonyPatch(typeof(Dam_EnemyDamageBase))]
	public class EnemyDamageBasePatches
	{
		[HarmonyPatch("MeleeDamage")]
		[HarmonyPrefix]
		public static bool MeleePrefix(Dam_EnemyDamageBase __instance, ref float dam, Agent sourceAgent)
		{
			return true;
		}
	}
}
namespace XpExpansions.Manager
{
	public abstract class BaseManager
	{
		private static string? _folderPath;

		protected string FolderPath
		{
			get
			{
				if (string.IsNullOrEmpty(_folderPath))
				{
					_folderPath = CacheApiWrapper.GetFolderPath();
				}
				return _folderPath;
			}
		}

		public abstract void LevelReached(Level level);

		public virtual void LevelInitialized(Level level)
		{
		}

		public virtual void Initialize()
		{
		}

		public virtual void LevelCleanup()
		{
		}
	}
	public class ClientSidedBioTrackerManager : BaseManager
	{
		private const string _expansionFileName = "BioTracker.json";

		public ClientSidedBioTrackerManager()
		{
			LevelApi.AddEndLevelCallback((Action)DestroyBioTrackerAbility);
		}

		public override void Initialize()
		{
			WriteDefaultJsonBlocks();
			UpdateEverything();
		}

		public override void LevelReached(Level level)
		{
			LevelLayout levelLayout = CacheApiWrapper.GetCurrentLevelLayout();
			List<LocalBioTrackerData> instance = CacheApi.GetInstance<List<LocalBioTrackerData>>(CacheApiWrapper.ExtensionCacheName);
			LocalBioTrackerData localBioTrackerData = instance.FirstOrDefault((LocalBioTrackerData it) => it.LevelLayoutPersistentId == levelLayout.PersistentId);
			if (localBioTrackerData != null)
			{
				if (localBioTrackerData.UnlockAtLevel <= level.LevelNumber)
				{
					CacheApiWrapper.DestroyOldCreateRegisterAndReturnComponent<ClientSidedBioTrackerAbility>();
				}
				else
				{
					DestroyBioTrackerAbility();
				}
			}
		}

		public void DestroyBioTrackerAbility()
		{
			CacheApiWrapper.KillScript<ClientSidedBioTrackerAbility>();
		}

		private void WriteDefaultJsonBlocks()
		{
			if (!Directory.Exists(base.FolderPath))
			{
				Directory.CreateDirectory(base.FolderPath);
			}
			string path = Path.Combine(base.FolderPath, "BioTracker.json");
			if (!File.Exists(path))
			{
				JsonSerializerOptions options = new JsonSerializerOptions
				{
					IncludeFields = false,
					ReadCommentHandling = JsonCommentHandling.Skip,
					PropertyNameCaseInsensitive = true,
					WriteIndented = true
				};
				File.WriteAllText(path, JsonSerializer.Serialize(GetDefaultData(), options));
			}
		}

		private void UpdateEverything()
		{
			CacheApi.SaveInstance<List<LocalBioTrackerData>>(JsonSerializer.Deserialize<List<LocalBioTrackerData>>(File.ReadAllText(Path.Combine(base.FolderPath, "BioTracker.json"))), CacheApiWrapper.ExtensionCacheName);
		}

		private List<LocalBioTrackerData> GetDefaultData()
		{
			List<LocalBioTrackerData> list = new List<LocalBioTrackerData>();
			for (int i = 0; i < 20; i++)
			{
				list.Add(new LocalBioTrackerData(i, 3));
			}
			return list;
		}
	}
	public class DeactivateManager : BaseManager
	{
		private const string _expansionFileName = "DeactivateOnMissions.json";

		private const string _expansionClassFileName = "DeactivateClassLayout.json";

		public override void Initialize()
		{
		}

		public override void LevelReached(Level level)
		{
		}

		private void WriteDefaultJsonBlocks()
		{
			if (base.FolderPath.Contains("BepInEx"))
			{
				if (!Directory.Exists(base.FolderPath))
				{
					Directory.CreateDirectory(base.FolderPath);
				}
				JsonSerializerOptions options = new JsonSerializerOptions
				{
					IncludeFields = false,
					ReadCommentHandling = JsonCommentHandling.Skip,
					PropertyNameCaseInsensitive = true,
					WriteIndented = true
				};
				string path = Path.Combine(base.FolderPath, "DeactivateOnMissions.json");
				if (!File.Exists(path))
				{
					File.WriteAllText(path, JsonSerializer.Serialize(new List<int> { 69420, 42069 }, options));
				}
			}
		}
	}
	public class DoubleJumpManager : BaseManager
	{
		public const string DoubleJumpXpExpansionId = "Endskill.DoubleJumpExpansion";

		private const string _expansionFileName = "DoubleJumpExpansion.json";

		private bool _harmonyState;

		public Harmony DoubleJumpHarmonyAbility { get; private set; }

		public DoubleJumpManager()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			DoubleJumpHarmonyAbility = new Harmony("Endskill.DoubleJumpExpansion");
			Harmony.UnpatchID("com.mccad00.DoubleJump");
			_harmonyState = false;
		}

		public override void Initialize()
		{
			WriteDefaultJsonBlocks();
			UpdateEverything();
		}

		public override void LevelCleanup()
		{
			if (_harmonyState)
			{
				DoubleJumpHarmonyAbility.UnpatchSelf();
				_harmonyState = false;
			}
		}

		public override void LevelReached(Level level)
		{
			LogManager.Message("LevelReached, DoubleJump " + ((object)level).ToString());
			LevelLayout levelLayout = CacheApiWrapper.GetCurrentLevelLayout();
			List<DoubleJumpData> instance = CacheApi.GetInstance<List<DoubleJumpData>>(CacheApiWrapper.ExtensionCacheName);
			DoubleJumpData doubleJumpData = instance.FirstOrDefault((DoubleJumpData it) => it.LevelLayoutPersistentId == levelLayout.PersistentId);
			if (doubleJumpData != null)
			{
				if (doubleJumpData.UnlockAtLevel <= level.LevelNumber)
				{
					if (!_harmonyState)
					{
						Assembly assembly = Assembly.GetAssembly(typeof(EntryPoint));
						DoubleJumpHarmonyAbility.PatchAll(assembly);
						_harmonyState = true;
					}
				}
				else if (_harmonyState)
				{
					DoubleJumpHarmonyAbility.UnpatchSelf();
					_harmonyState = false;
				}
			}
			else if (_harmonyState)
			{
				DoubleJumpHarmonyAbility.UnpatchSelf();
				_harmonyState = false;
			}
		}

		private void WriteDefaultJsonBlocks()
		{
			if (!Directory.Exists(base.FolderPath))
			{
				Directory.CreateDirectory(base.FolderPath);
			}
			string path = Path.Combine(base.FolderPath, "DoubleJumpExpansion.json");
			if (!File.Exists(path))
			{
				File.WriteAllText(path, "[\r\n  {\r\n    \"LevelLayoutPersistentId\": 13,\r\n    \"UnlockAtLevel\": 10\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 14,\r\n    \"UnlockAtLevel\": 6\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 7,\r\n    \"UnlockAtLevel\": 5\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 8,\r\n    \"UnlockAtLevel\": 5\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 15,\r\n    \"UnlockAtLevel\": 5\r\n  }\r\n]");
			}
		}

		private void UpdateEverything()
		{
			CacheApi.SaveInstance<List<DoubleJumpData>>(JsonSerializer.Deserialize<List<DoubleJumpData>>(File.ReadAllText(Path.Combine(base.FolderPath, "DoubleJumpExpansion.json"))), CacheApiWrapper.ExtensionCacheName);
		}

		private List<DoubleJumpData> GetDefaultData()
		{
			List<DoubleJumpData> list = new List<DoubleJumpData>();
			for (int i = 0; i < 20; i++)
			{
				list.Add(new DoubleJumpData(i, 3));
			}
			return list;
		}
	}
	public class ExpansionManager : BaseManager
	{
		public const string ExpansionActivePath = "ExpansionsActive.json";

		public ExpansionManager()
		{
			LogManager.Message("ExpansionManager constructor.");
			InitApi.AddInitCallback((Action)Initialize);
			LevelApi.AddEndLevelCallback((Action)LevelCleanup);
			XpApi.AddOnLevelUpCallback((Action<Level>)LevelReached);
			XpApi.AddScriptsLoaded((Action<Level>)LevelInitialized);
		}

		public override void Initialize()
		{
			CacheApiWrapper.SetFolderPath(Path.Combine(ScriptManager.Instance.GetFolderPath(), "Expansions"));
			WriteDefaultData();
			List<BaseManager> list = CreateManagers();
			CacheApi.SaveInstance<List<BaseManager>>(list, CacheApiWrapper.ExtensionCacheName);
			foreach (BaseManager item in list)
			{
				item.Initialize();
			}
		}

		public override void LevelCleanup()
		{
			List<BaseManager> instance = CacheApi.GetInstance<List<BaseManager>>(CacheApiWrapper.ExtensionCacheName);
			foreach (BaseManager item in instance)
			{
				item.LevelCleanup();
			}
		}

		public override void LevelReached(Level level)
		{
			LogManager.Message("LevelReached in the Expansion Manager.");
			List<BaseManager> instance = CacheApi.GetInstance<List<BaseManager>>(CacheApiWrapper.ExtensionCacheName);
			foreach (BaseManager item in instance)
			{
				item.LevelReached(level);
			}
		}

		public override void LevelInitialized(Level level)
		{
			LogManager.Message("LevelInitialized in the Expansion Manager.");
			List<BaseManager> instance = CacheApi.GetInstance<List<BaseManager>>(CacheApiWrapper.ExtensionCacheName);
			foreach (BaseManager item in instance)
			{
				item.LevelInitialized(level);
			}
		}

		private List<BaseManager> CreateManagers()
		{
			List<BaseManager> list = new List<BaseManager>();
			string path = Path.Combine(base.FolderPath, "ExpansionsActive.json");
			ActiveExpansions activeExpansions = JsonSerializer.Deserialize<ActiveExpansions>(File.ReadAllText(path));
			LogManager.Debug("CreateManagers method.");
			if (activeExpansions != null)
			{
				if (activeExpansions.DoubleJumpAbility)
				{
					list.Add(new DoubleJumpManager());
				}
				if (activeExpansions.StartingXp)
				{
					list.Add(new StartingLevelXpManager());
				}
				if (activeExpansions.LivingBioAbility)
				{
					list.Add(new ClientSidedBioTrackerManager());
				}
			}
			return list;
		}

		private void WriteDefaultData()
		{
			if (!Directory.Exists(base.FolderPath))
			{
				Directory.CreateDirectory(base.FolderPath);
			}
			string path = Path.Combine(base.FolderPath, "ExpansionsActive.json");
			if (!File.Exists(path))
			{
				File.WriteAllText(path, JsonSerializer.Serialize(new ActiveExpansions(startingXp: false, doubleJumpAbility: true)));
			}
		}
	}
	public class ExplosionAbilityManager : BaseManager
	{
		public const string ExplosionHarmonyInstanceId = "Endskill.ExplosionAbility";

		public Harmony ExplosionHarmony { get; private set; }

		public ExplosionAbilityManager()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			ExplosionHarmony = new Harmony("Endskill.ExplosionAbility");
		}

		public override void Initialize()
		{
		}

		public override void LevelReached(Level level)
		{
		}

		public override void LevelCleanup()
		{
		}
	}
	public static class LogManager
	{
		private static ManualLogSource logger;

		internal static bool _debugMessagesActive;

		internal static void SetLogger(ManualLogSource log)
		{
			logger = log;
		}

		public static void Verbose(object msg)
		{
			if (_debugMessagesActive)
			{
				logger.LogInfo(msg);
			}
		}

		public static void Debug(object msg)
		{
			if (_debugMessagesActive)
			{
				logger.LogDebug(msg);
			}
		}

		public static void Message(object msg)
		{
			if (_debugMessagesActive)
			{
				logger.LogMessage(msg);
			}
		}

		public static void Error(object msg)
		{
			logger.LogError(msg);
		}

		public static void Warn(object msg)
		{
			logger.LogWarning(msg);
		}
	}
	internal class StartingLevelXpManager : BaseManager
	{
		private const string _expansionFileName = "StartingXP.json";

		public override void Initialize()
		{
			WriteDefaultJsonBlocks();
			UpdateEverything();
		}

		public override void LevelReached(Level level)
		{
		}

		public override void LevelInitialized(Level level)
		{
			ExpeditionInTierData expedition = RundownManager.ActiveExpedition;
			List<StartingXpData> instance = CacheApi.GetInstance<List<StartingXpData>>(CacheApiWrapper.ExtensionCacheName);
			StartingXpData startingXpData = instance.FirstOrDefault((StartingXpData it) => it.LevelLayoutData == expedition.LevelLayoutData);
			if (startingXpData != null)
			{
				XpApi.AddXp(startingXpData.StartingXp);
			}
		}

		private void UpdateEverything()
		{
			CacheApi.SaveInstance<List<StartingXpData>>(JsonSerializer.Deserialize<List<StartingXpData>>(File.ReadAllText(Path.Combine(base.FolderPath, "StartingXP.json"))), CacheApiWrapper.ExtensionCacheName);
		}

		private void WriteDefaultJsonBlocks()
		{
			if (!Directory.Exists(base.FolderPath))
			{
				Directory.CreateDirectory(base.FolderPath);
			}
			string path = Path.Combine(base.FolderPath, "StartingXP.json");
			if (!File.Exists(path))
			{
				JsonSerializerOptions options = new JsonSerializerOptions
				{
					IncludeFields = false,
					ReadCommentHandling = JsonCommentHandling.Skip,
					PropertyNameCaseInsensitive = true,
					WriteIndented = true
				};
				File.WriteAllText(path, JsonSerializer.Serialize(GetDefaultData(), options));
			}
		}

		private List<StartingXpData> GetDefaultData()
		{
			List<StartingXpData> list = new List<StartingXpData>();
			foreach (RundownDataBlock allBlock in GameDataBlockBase<RundownDataBlock>.GetAllBlocks())
			{
				Enumerator<ExpeditionInTierData> enumerator2 = allBlock.TierD.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					ExpeditionInTierData current2 = enumerator2.Current;
					list.Add(new StartingXpData(current2.LevelLayoutData, 100u));
				}
			}
			return list;
		}
	}
}
namespace XpExpansions.Information
{
	public class ActiveExpansions
	{
		public bool DoubleJumpAbility { get; set; }

		public bool StartingXp { get; set; }

		public bool LivingBioAbility { get; set; }

		public ActiveExpansions(bool startingXp, bool doubleJumpAbility)
		{
			DoubleJumpAbility = doubleJumpAbility;
			StartingXp = startingXp;
		}
	}
}
namespace XpExpansions.Information.StartingXp
{
	public class StartingXpData
	{
		public uint LevelLayoutData { get; set; }

		public uint StartingXp { get; set; }

		public StartingXpData(uint levelLayoutData, uint startingXp)
		{
			LevelLayoutData = levelLayoutData;
			StartingXp = startingXp;
		}
	}
}
namespace XpExpansions.Information.Explosion
{
	public class ExplosionAbilityData
	{
		public int LevelLayoutPersistentId { get; set; }

		public int UnlockAtLevel { get; set; }

		public ExplosionAbilityData(int levelLayoutPersistentId, int unlockAtLevel)
		{
			LevelLayoutPersistentId = levelLayoutPersistentId;
			UnlockAtLevel = unlockAtLevel;
		}
	}
}
namespace XpExpansions.Information.DoubleJump
{
	internal class DoubleJumpData
	{
		public int LevelLayoutPersistentId { get; set; }

		public int UnlockAtLevel { get; set; }

		public DoubleJumpData(int levelLayoutPersistentId, int unlockAtLevel)
		{
			LevelLayoutPersistentId = levelLayoutPersistentId;
			UnlockAtLevel = unlockAtLevel;
		}
	}
}
namespace XpExpansions.Information.BioTrackerLocal
{
	internal class LocalBioTrackerData
	{
		public int LevelLayoutPersistentId { get; set; }

		public int UnlockAtLevel { get; set; }

		public LocalBioTrackerData(int levelLayoutPersistentId, int unlockAtLevel)
		{
			LevelLayoutPersistentId = levelLayoutPersistentId;
			UnlockAtLevel = unlockAtLevel;
		}
	}
}
namespace XpExpansions.Extensions
{
	public static class CacheApiWrapper
	{
		internal static string ExtensionCacheName = "XpExtensions";

		private const string _folderPath = "FolderPath";

		public static void SetFolderPath(string path)
		{
			CacheApi.SaveInformation((object)"FolderPath", (object)path, ExtensionCacheName);
		}

		public static string GetFolderPath()
		{
			return CacheApi.GetInformation<string>((object)"FolderPath", ExtensionCacheName);
		}
	}
}

EndskApi.dll

Decompiled 8 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.Json.Serialization;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using BoosterImplants;
using CellMenu;
using EndskApi.Api;
using EndskApi.Enums.EnemyKill;
using EndskApi.Enums.Menus;
using EndskApi.Information.Configs;
using EndskApi.Information.EnemyKill;
using EndskApi.Information.Menus;
using EndskApi.Information.WeaponSwitcher;
using EndskApi.Manager;
using EndskApi.Manager.Internal;
using EndskApi.NativePatches;
using EndskApi.Patches.Checkpoint;
using EndskApi.Patches.EndLevel;
using EndskApi.Patches.Init;
using EndskApi.Patches.StartLevel;
using EndskApi.Scripts;
using Enemies;
using GTFO.API;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("EndskApi")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+gitc03396b-dirty-master")]
[assembly: AssemblyProduct("EndskApi")]
[assembly: AssemblyTitle("EndskApi")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace EndskApi
{
	[BepInPlugin("Endskill.EndskApi", "EndskApi", "1.0.1")]
	public class BepInExLoader : BasePlugin
	{
		public const string MODNAME = "EndskApi";

		public const string AUTHOR = "Endskill";

		public const string GUID = "Endskill.EndskApi";

		public const string VERSION = "1.0.1";

		public static Harmony Harmony { get; private set; }

		public static ConfigFile ConfigLoader { get; private set; }

		public override void Load()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			LogManager.SetLogger(((BasePlugin)this).Log);
			LogManager._debugMessagesActive = ((BasePlugin)this).Config.Bind<bool>("Dev Settings", "DebugMessages", false, "This settings activates/deactivates debug messages in the console for this specific plugin.").Value;
			ConfigLoader = ((BasePlugin)this).Config;
			ClassInjector.RegisterTypeInIl2Cpp<BaseMenu>();
			ClassInjector.RegisterTypeInIl2Cpp<MainMenu>();
			Harmony = new Harmony("Endskill.EndskApi");
		}
	}
	[GeneratedCode("VersionInfoGenerator", "2.0.0+git50a4b1a-master")]
	[CompilerGenerated]
	internal static class VersionInfo
	{
		public const string RootNamespace = "EndskApi";

		public const string Version = "1.0.0";

		public const string VersionPrerelease = null;

		public const string VersionMetadata = "gitc03396b-dirty-master";

		public const string SemVer = "1.0.0+gitc03396b-dirty-master";

		public const string GitRevShort = "c03396b-dirty";

		public const string GitRevLong = "c03396b43dd7f0dd7f6be64a74260c9045444f6f-dirty";

		public const string GitBranch = "master";

		public const string GitTag = null;

		public const bool GitIsDirty = true;
	}
}
namespace EndskApi.Util
{
	public static class MtfoUtils
	{
		public static string CustomPath { get; private set; }

		public static string Version { get; private set; }

		public static bool PluginExists { get; private set; }

		static MtfoUtils()
		{
			CustomPath = string.Empty;
			Version = string.Empty;
			PluginExists = false;
			if (!((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.TryGetValue("com.dak.MTFO", out var info))
			{
				return;
			}
			PluginExists = true;
			try
			{
				Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly x) => !x.IsDynamic && x.Location == info.Location);
				if (assembly == null)
				{
					throw new Exception("couldn't locate the MTFO assembly");
				}
				Type[] types = assembly.GetTypes();
				Type type = types.FirstOrDefault((Type x) => x.Name == "ConfigManager");
				Type type2 = types.FirstOrDefault((Type x) => x.Name == "MTFO");
				if (type2 == null)
				{
					throw new Exception("couldn't locate MTFO's EntryPoint");
				}
				if (type == null)
				{
					throw new Exception("couldn't locate MTFO's ConfigManager");
				}
				FieldInfo field = type2.GetField("VERSION", BindingFlags.Static | BindingFlags.Public);
				FieldInfo field2 = type.GetField("CustomPath", BindingFlags.Static | BindingFlags.Public);
				if (field == null)
				{
					throw new Exception("couldn't locate MTFO's Version");
				}
				if (field2 == null)
				{
					throw new Exception("couldn't locate MTFO's CustomPath");
				}
				CustomPath = (string)field2.GetValue(null);
				Version = (string)field.GetValue(null);
				Type type3 = types.FirstOrDefault((Type x) => x.Name == "HotReloader");
			}
			catch (Exception ex)
			{
				LogManager.Error(ex.ToString());
			}
		}
	}
}
namespace EndskApi.Scripts
{
	public class BaseMenu : MonoBehaviour
	{
		protected static string _currentGeomorph;

		protected static bool _guiInitialized = false;

		protected static GUIStyle _normalStyle;

		protected static GUIStyle _titleStyle;

		protected static readonly float _menuX = 30f;

		protected static readonly float _menuY = (float)(Screen.height / 2) - 100f;

		protected MenuStates _currentState;

		protected List<Tool> _tools;

		public string PageTitle { get; set; }

		protected static string PageTitlePostfix { get; set; } = "";


		public BaseMenu(IntPtr intPtr)
			: base(intPtr)
		{
			_tools = new List<Tool>();
		}

		protected virtual void Update()
		{
			if (_currentState != MenuStates.Deactivated)
			{
				DefaultCheatsInputCheck();
			}
		}

		protected virtual void OnGUI()
		{
			if (_currentState == MenuStates.Active)
			{
				CreateUi(_tools, PageTitle);
			}
		}

		public virtual void SetState(MenuStates newState)
		{
			_currentState = newState;
			if (newState == MenuStates.Deactivated)
			{
				((Behaviour)this).enabled = false;
			}
			else
			{
				((Behaviour)this).enabled = true;
			}
		}

		protected void DefaultCheatsInputCheck()
		{
			foreach (Tool tool in _tools)
			{
				if (tool.CheckInput.CheckKeyDown())
				{
					tool.UseTool(tool);
				}
			}
		}

		[HideFromIl2Cpp]
		public static void CreateUi(List<Tool> cheats, string pageTitle)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_003f: 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)
			//IL_0052: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if (!_guiInitialized)
			{
				_titleStyle = new GUIStyle(GUI.skin.GetStyle("label"))
				{
					fontSize = 22
				};
				_normalStyle = new GUIStyle(GUI.skin.GetStyle("label"))
				{
					fontSize = 20
				};
				_guiInitialized = true;
			}
			GUI.contentColor = Color.white;
			GUI.Label(new Rect(_menuX, _menuY - 25f, 400f, 30f), _currentGeomorph, _normalStyle);
			GUI.Label(new Rect(_menuX, _menuY, 400f, 30f), pageTitle + PageTitlePostfix, _titleStyle);
			float num = 25f;
			foreach (Tool cheat in cheats)
			{
				GUI.Label(new Rect(_menuX, _menuY + num, 400f, 30f), cheat.ToString(), _normalStyle);
				num += 22f;
			}
		}

		[HideFromIl2Cpp]
		protected void ToggleTool(Tool cheat)
		{
			cheat.Toggle();
		}
	}
	internal class MainMenu : BaseMenu
	{
		private Dictionary<Tool, BaseMenu> _toolToMenuMap;

		private List<BaseMenu> _unknownMenus;

		private List<IExtendedTool> _middleMouseClickTools = new List<IExtendedTool>();

		private List<IExtendedTool> _timedTools = new List<IExtendedTool>();

		private List<Tool> _hiddenTools = new List<Tool>();

		private float _lastToolActive = Time.time;

		private (uint enemyId, string enemyName)[] _enemyNamesIdMap;

		private int _currentEnemyIndex = 0;

		private int _keypadCounter;

		[HideFromIl2Cpp]
		internal static MainMenu Instance { get; private set; }

		public int CurrentEnemyIndex
		{
			get
			{
				return _currentEnemyIndex;
			}
			set
			{
				if (value >= _enemyNamesIdMap.Count() || value < 0)
				{
					value = _currentEnemyIndex;
				}
				_currentEnemyIndex = value;
				BaseMenu.PageTitlePostfix = ": " + _enemyNamesIdMap[value].enemyName;
			}
		}

		public MainMenu(IntPtr intPtr)
			: base(intPtr)
		{
			base.PageTitle = "MainMenu";
			_toolToMenuMap = new Dictionary<Tool, BaseMenu>();
			_unknownMenus = new List<BaseMenu>();
			_currentState = MenuStates.HiddenAndActive;
			Instance = this;
		}

		public void Awake()
		{
			Il2CppArrayBase<EnemyDataBlock> allBlocks = GameDataBlockBase<EnemyDataBlock>.GetAllBlocks();
			_enemyNamesIdMap = new(uint, string)[allBlocks.Count];
			for (int i = 0; i < allBlocks.Count; i++)
			{
				_enemyNamesIdMap[i] = (((GameDataBlockBase<EnemyDataBlock>)(object)allBlocks[i]).persistentID, ((GameDataBlockBase<EnemyDataBlock>)(object)allBlocks[i]).name);
			}
			CurrentEnemyIndex = 0;
		}

		[HideFromIl2Cpp]
		public void ActivateUnknownMenu<TScript>(TScript menu) where TScript : BaseMenu
		{
			MenuToggleUpdated(null, newToggle: false);
			_currentState = MenuStates.HiddenAndActive;
			_unknownMenus.Add(menu);
		}

		[HideFromIl2Cpp]
		public void AddPage(string ToolName, BaseMenu menu)
		{
			AddPage(new Tool(ToolName, GetFreeKeypadInput(), isToggle: false, base.ToggleTool, MenuToggleUpdated), menu);
		}

		[HideFromIl2Cpp]
		public void AddPage(Tool Tool, BaseMenu menu)
		{
			_toolToMenuMap.Add(Tool, menu);
			_tools.Add(Tool);
			_currentState = MenuStates.Active;
		}

		[HideFromIl2Cpp]
		public void AddMiddleMouseClickTool(IExtendedTool Tool)
		{
			_middleMouseClickTools.Add(Tool);
		}

		public void RemoveMiddleMouseClickTool(IExtendedTool Tool)
		{
			_middleMouseClickTools.Remove(Tool);
		}

		public void AddTimedTool(IExtendedTool tool)
		{
			_timedTools.Add(tool);
		}

		public void RemoveTimedTool(IExtendedTool tool)
		{
			_timedTools.Remove(tool);
		}

		public void AddHiddenTool(Tool tool)
		{
			_hiddenTools.Add(tool);
		}

		public void RemoveHiddenTool(Tool tool)
		{
			_hiddenTools.Remove(tool);
		}

		protected override void Update()
		{
			if (Input.GetKeyDown((KeyCode)277))
			{
				if (_currentState == MenuStates.Active || _currentState == MenuStates.HiddenAndActive)
				{
					_currentState = MenuStates.Deactivated;
				}
				else
				{
					_currentState = MenuStates.Active;
				}
				foreach (KeyValuePair<Tool, BaseMenu> item in _toolToMenuMap)
				{
					item.Key.CurrentToggleState = false;
					item.Value.SetState(MenuStates.Deactivated);
				}
			}
			if (_currentState != MenuStates.Deactivated)
			{
				foreach (Tool hiddenTool in _hiddenTools)
				{
					if (hiddenTool.CheckInput.CheckKeyDown())
					{
						hiddenTool.UseTool(hiddenTool);
					}
				}
			}
			base.Update();
			MainMenuSpecificUpdate();
		}

		private void MainMenuSpecificUpdate()
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Invalid comparison between Unknown and I4
			if (Input.GetKeyDown((KeyCode)275))
			{
				CurrentEnemyIndex++;
			}
			if (Input.GetKeyDown((KeyCode)276))
			{
				CurrentEnemyIndex--;
			}
			if (Input.GetMouseButtonDown(2))
			{
				foreach (IExtendedTool middleMouseClickTool in _middleMouseClickTools)
				{
					middleMouseClickTool.ExtraToolAction(GetInformationPackage(middleMouseClickTool.InformationId));
				}
			}
			if (!(_lastToolActive < Time.time))
			{
				return;
			}
			foreach (IExtendedTool timedTool in _timedTools)
			{
				timedTool.ExtraToolAction(GetInformationPackage(timedTool.InformationId));
			}
			if ((int)GameStateManager.CurrentStateName == 10)
			{
				BaseMenu._currentGeomorph = ((Object)((Agent)PlayerManager.GetLocalPlayerAgent()).CourseNode.m_area.m_geomorph).name;
			}
			else
			{
				BaseMenu._currentGeomorph = "";
			}
			_lastToolActive = Time.time + 0.25f;
		}

		private object GetInformationPackage(InformationId id)
		{
			return id switch
			{
				InformationId.None => null, 
				InformationId.EnemyId => _enemyNamesIdMap[CurrentEnemyIndex], 
				_ => null, 
			};
		}

		private void MenuToggleUpdated(Tool Tool, bool newToggle)
		{
			foreach (BaseMenu unknownMenu in _unknownMenus)
			{
				unknownMenu.SetState(MenuStates.Deactivated);
			}
			_unknownMenus.Clear();
			foreach (KeyValuePair<Tool, BaseMenu> item in _toolToMenuMap)
			{
				if (item.Key.Equals(Tool))
				{
					item.Value.SetState((!newToggle) ? MenuStates.Deactivated : MenuStates.Active);
					item.Key.CurrentToggleState = newToggle;
				}
				else
				{
					item.Key.CurrentToggleState = false;
					item.Value.SetState(MenuStates.Deactivated);
				}
			}
			_currentState = (_toolToMenuMap.Any<KeyValuePair<Tool, BaseMenu>>((KeyValuePair<Tool, BaseMenu> it) => it.Key.CurrentToggleState) ? MenuStates.HiddenAndActive : MenuStates.Active);
		}

		private InputTool GetFreeKeypadInput()
		{
			_keypadCounter++;
			switch (_keypadCounter)
			{
			case 1:
				return MenuInputProvider.KeyPad1;
			case 2:
				return MenuInputProvider.KeyPad2;
			case 3:
				return MenuInputProvider.KeyPad3;
			case 4:
				return MenuInputProvider.KeyPad4;
			case 5:
				return MenuInputProvider.KeyPad5;
			case 6:
				return MenuInputProvider.KeyPad6;
			case 7:
				return MenuInputProvider.KeyPad7;
			case 8:
				return MenuInputProvider.KeyPad8;
			case 9:
				return MenuInputProvider.KeyPad9;
			default:
				LogManager.Error("There are no free Keypad keys, for the added Menu page!\nPlease ask @Endskill#4992 to finally do his Page system.");
				throw new IndexOutOfRangeException("There are no free keypad keys to add this specific page.");
			}
		}
	}
}
namespace EndskApi.Patches.StartLevel
{
	[HarmonyPatch(typeof(GS_InLevel))]
	internal class GsInLevelPatches
	{
		[HarmonyPatch("Enter")]
		[HarmonyPostfix]
		public static void EnterLevelPostfix()
		{
			LevelApi.InvokeStartLevelCallbacks();
		}
	}
}
namespace EndskApi.Patches.Init
{
	[HarmonyPatch(typeof(GuiManager))]
	internal class GUIManagerPatches
	{
		[HarmonyPatch("Setup")]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		public static void SetupPrefix()
		{
			InitApi.InvokeInitCallbacks();
		}
	}
	[HarmonyPatch(typeof(CM_PageRundown_New))]
	internal class PageRundownNewPatches
	{
		[HarmonyPatch("PlaceRundown")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		public static void PlaceRundownPostFix()
		{
			InitApi.InvokeInitCallbacks();
		}
	}
}
namespace EndskApi.Patches.EnemyKill
{
	[HarmonyBefore(new string[] { "Endskill.EndskApi", "com.dak.DamageNumbers" })]
	[HarmonyPatch(typeof(Dam_EnemyDamageBase))]
	internal class EnemyDamageBasePatches
	{
		[HarmonyPatch("ReceiveMeleeDamage")]
		[HarmonyPrefix]
		public static void MeleePrefix(Dam_EnemyDamageBase __instance, out bool __state)
		{
			__state = ((Agent)__instance.Owner).Alive;
		}

		[HarmonyPatch("ReceiveMeleeDamage")]
		[HarmonyPostfix]
		public static void MeleePostfix(Dam_EnemyDamageBase __instance, bool __state, pFullDamageData data)
		{
			if (!__state)
			{
				return;
			}
			Agent val = default(Agent);
			((pAgent)(ref data.source)).TryGet(ref val);
			if (val != null)
			{
				PlayerAgent val2 = ((Il2CppObjectBase)val).TryCast<PlayerAgent>();
				DamageDistributionAddDamageDealt(__instance.Owner, val2, ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax));
				if (!((Agent)__instance.Owner).Alive)
				{
					EnemyDied(__instance.Owner, val2, LastHitType.Melee);
				}
			}
		}

		[HarmonyPatch("ReceiveBulletDamage")]
		[HarmonyPrefix]
		public static void BulletPrefix(Dam_EnemyDamageBase __instance, out bool __state)
		{
			__state = ((Agent)__instance.Owner).Alive;
		}

		[HarmonyPatch("ReceiveBulletDamage")]
		[HarmonyPostfix]
		public static void BulletPostfix(Dam_EnemyDamageBase __instance, bool __state, pBulletDamageData data)
		{
			if (!__state)
			{
				return;
			}
			Agent val = default(Agent);
			((pAgent)(ref data.source)).TryGet(ref val);
			if (val != null)
			{
				PlayerAgent val2 = ((Il2CppObjectBase)val).TryCast<PlayerAgent>();
				DamageDistributionAddDamageDealt(__instance.Owner, val2, ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)__instance).HealthMax));
				if (!((Agent)__instance.Owner).Alive)
				{
					EnemyDied(__instance.Owner, val2, LastHitType.ShootyWeapon);
				}
			}
		}

		[HarmonyPatch("ExplosionDamage")]
		[HarmonyPrefix]
		public static void ExplosionPrefix(Dam_EnemyDamageBase __instance, out bool __state)
		{
			__state = ((Agent)__instance.Owner).Alive && SNet.IsMaster;
		}

		[HarmonyPatch("ExplosionDamage")]
		[HarmonyPostfix]
		public static void ExplosionPostfix(Dam_EnemyDamageBase __instance, bool __state)
		{
			if (__state && !((Agent)__instance.Owner).Alive)
			{
				EnemyDied(__instance.Owner, null, LastHitType.Explosion);
			}
		}

		private static void DamageDistributionAddDamageDealt(EnemyAgent hitEnemy, PlayerAgent damageDealer, float damageDealt)
		{
			Dictionary<string, EnemyKillDistribution> instance = CacheApi.GetInstance<Dictionary<string, EnemyKillDistribution>>("EndskApi");
			if (!instance.ContainsKey(((Object)hitEnemy).name))
			{
				EnemyKillDistribution enemyKillDistribution = new EnemyKillDistribution(hitEnemy);
				enemyKillDistribution.AddDamageDealtByPlayerAgent(damageDealer, damageDealt);
				instance[((Object)hitEnemy).name] = enemyKillDistribution;
			}
			else
			{
				instance[((Object)hitEnemy).name].AddDamageDealtByPlayerAgent(damageDealer, damageDealt);
			}
		}

		private static void EnemyDied(EnemyAgent hitEnemy, PlayerAgent lastHit, LastHitType lastHitType)
		{
			Dictionary<string, EnemyKillDistribution> instance = CacheApi.GetInstance<Dictionary<string, EnemyKillDistribution>>("EndskApi");
			if (instance.TryGetValue(((Object)hitEnemy).name, out var value))
			{
				value.LastHitDealtBy = lastHit;
				value.lastHitType = lastHitType;
				EnemyKillApi.InvokeEnemyKilledCallbacks(value);
			}
		}
	}
}
namespace EndskApi.Patches.EndLevel
{
	[HarmonyPatch(typeof(GS_AfterLevel))]
	public class GsAfterLevelPatches
	{
		[HarmonyPatch("CleanupAfterExpedition")]
		[HarmonyPrefix]
		public static void CleanupPrefix()
		{
			LevelApi.InvokeEndLevelCallbacks();
		}
	}
}
namespace EndskApi.Patches.Checkpoint
{
	[HarmonyPatch(typeof(CheckpointManager))]
	internal static class CheckpointManagerPatches
	{
		[HarmonyPatch("StoreCheckpoint")]
		[HarmonyPostfix]
		public static void StoreCheackpointPostfix()
		{
			CheckpointApi.InvokeCheckpointReachedCallbacks();
			NetworkManager.SendCheckpointReached();
		}

		[HarmonyPatch("OnLevelCleanup")]
		[HarmonyPostfix]
		public static void OnLevelCleanupPostfix()
		{
			CheckpointApi.InvokeCheckpointCleanupCallbacks();
			NetworkManager.SendCheckpointCleanups();
		}
	}
}
namespace EndskApi.NativePatches
{
	internal class EnemyDamageBaseNatviePatches
	{
		public unsafe delegate void ReceiveMeleeDamage(IntPtr _this, pFullDamageData* data, Il2CppMethodInfo* methodInfo);

		public unsafe delegate void ReceiveBulletDamage(IntPtr _this, pBulletDamageData* data, Il2CppMethodInfo* methodInfo);

		public unsafe delegate void ReceiveExplosionDamage(IntPtr _this, pExplosionDamageData* data, Il2CppMethodInfo* methodInfo);

		public unsafe delegate bool ProcessReceivedDamage(IntPtr _this, float damage, IntPtr _damageSource, Vector3* position, Vector3* direction, ES_HitreactType hitreact, [MarshalAs(UnmanagedType.I1)] bool tryForceHitreact, int limbID, float staggerDamageMulti, DamageNoiseLevel damageNoiseLevel, Il2CppMethodInfo* methodInfo);

		private readonly ReceiveMeleeDamage _originalReceiveMeleeDamage;

		private readonly ReceiveBulletDamage _originalReceiveBulletDamage;

		private readonly ReceiveExplosionDamage _originalReceiveExplosionDamage;

		private readonly ProcessReceivedDamage _originalProcessReceivedDamage;

		private readonly List<INativeDetour> _detours;

		public unsafe EnemyDamageBaseNatviePatches()
		{
			_detours = new List<INativeDetour>
			{
				INativeDetour.CreateAndApply<ReceiveMeleeDamage>((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod<Dam_EnemyDamageBase>("ReceiveMeleeDamage", "System.Void", false, new string[1] { "pFullDamageData" }), (ReceiveMeleeDamage)ReceiveMeleeDamagePatch, ref _originalReceiveMeleeDamage),
				INativeDetour.CreateAndApply<ReceiveBulletDamage>((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod<Dam_EnemyDamageBase>("ReceiveBulletDamage", "System.Void", false, new string[1] { "pBulletDamageData" }), (ReceiveBulletDamage)ReceiveBulletDamagePatch, ref _originalReceiveBulletDamage),
				INativeDetour.CreateAndApply<ReceiveExplosionDamage>((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod<Dam_EnemyDamageBase>("ReceiveExplosionDamage", "System.Void", false, new string[1] { "pExplosionDamageData" }), (ReceiveExplosionDamage)ReceiveExplosionDamagePatch, ref _originalReceiveExplosionDamage)
			};
		}

		public unsafe void ReceiveMeleeDamagePatch(IntPtr _this, pFullDamageData* data, Il2CppMethodInfo* methodInfo)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			try
			{
				Dam_EnemyDamageBase instance = new Dam_EnemyDamageBase(_this);
				EnemyDamageBasePatchApi.InvokeReceiveMeleePrefix(instance, ref Unsafe.AsRef<pFullDamageData>((void*)data));
				_originalReceiveMeleeDamage(_this, data, methodInfo);
				EnemyDamageBasePatchApi.InvokeReceiveMeleePostfix(instance, ref Unsafe.AsRef<pFullDamageData>((void*)data));
			}
			catch (Exception ex)
			{
				LogManager.Error(ex);
				LogManager.Error(ex.StackTrace);
			}
		}

		public unsafe void ReceiveBulletDamagePatch(IntPtr _this, pBulletDamageData* data, Il2CppMethodInfo* methodInfo)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			try
			{
				Dam_EnemyDamageBase instance = new Dam_EnemyDamageBase(_this);
				EnemyDamageBasePatchApi.InvokeReceiveBulletPrefix(instance, ref Unsafe.AsRef<pBulletDamageData>((void*)data));
				_originalReceiveBulletDamage(_this, data, methodInfo);
				EnemyDamageBasePatchApi.InvokeReceiveBulletPostfix(instance, ref Unsafe.AsRef<pBulletDamageData>((void*)data));
			}
			catch (Exception ex)
			{
				LogManager.Error(ex);
				LogManager.Error(ex.StackTrace);
			}
		}

		public unsafe void ReceiveExplosionDamagePatch(IntPtr _this, pExplosionDamageData* data, Il2CppMethodInfo* methodInfo)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			try
			{
				Dam_EnemyDamageBase instance = new Dam_EnemyDamageBase(_this);
				EnemyDamageBasePatchApi.InvokeReceiveExplosionPrefix(instance, ref Unsafe.AsRef<pExplosionDamageData>((void*)data));
				_originalReceiveExplosionDamage(_this, data, methodInfo);
				EnemyDamageBasePatchApi.InvokeReceiveExplosionPostfix(instance, ref Unsafe.AsRef<pExplosionDamageData>((void*)data));
			}
			catch (Exception ex)
			{
				LogManager.Error(ex);
				LogManager.Error(ex.StackTrace);
			}
		}
	}
}
namespace EndskApi.Manager
{
	public static class LogManager
	{
		private static ManualLogSource logger;

		internal static bool _debugMessagesActive;

		internal static void SetLogger(ManualLogSource log)
		{
			logger = log;
		}

		public static void Verbose(object msg)
		{
			if (_debugMessagesActive)
			{
				logger.LogInfo(msg);
			}
		}

		public static void Debug(object msg)
		{
			if (_debugMessagesActive)
			{
				logger.LogDebug(msg);
			}
		}

		public static void Message(object msg)
		{
			if (_debugMessagesActive)
			{
				logger.LogMessage(msg);
			}
		}

		public static void Error(object msg)
		{
			logger.LogError(msg);
		}

		public static void Warn(object msg)
		{
			logger.LogWarning(msg);
		}
	}
	public static class MenuInputProvider
	{
		private static MenuRebinding _bindings;

		public static InputTool F1 => new InputTool(_bindings.F1, $": [{_bindings.F1}]");

		public static InputTool F2 => new InputTool(_bindings.F2, $": [{_bindings.F2}]");

		public static InputTool F3 => new InputTool(_bindings.F3, $": [{_bindings.F3}]");

		public static InputTool F4 => new InputTool(_bindings.F4, $": [{_bindings.F4}]");

		public static InputTool F5 => new InputTool(_bindings.F5, $": [{_bindings.F5}]");

		public static InputTool F6 => new InputTool(_bindings.F6, $": [{_bindings.F6}]");

		public static InputTool F7 => new InputTool(_bindings.F7, $": [{_bindings.F7}]");

		public static InputTool F8 => new InputTool(_bindings.F8, $": [{_bindings.F8}]");

		public static InputTool F9 => new InputTool(_bindings.F9, $": [{_bindings.F9}]");

		public static InputTool F10 => new InputTool(_bindings.F10, $": [{_bindings.F10}]");

		public static InputTool KeyPad1 => new InputTool(_bindings.Keypad1, $": [{_bindings.Keypad1}]");

		public static InputTool KeyPad2 => new InputTool(_bindings.Keypad2, $": [{_bindings.Keypad2}]");

		public static InputTool KeyPad3 => new InputTool(_bindings.Keypad3, $": [{_bindings.Keypad3}]");

		public static InputTool KeyPad4 => new InputTool(_bindings.Keypad4, $": [{_bindings.Keypad4}]");

		public static InputTool KeyPad5 => new InputTool(_bindings.Keypad5, $": [{_bindings.Keypad5}]");

		public static InputTool KeyPad6 => new InputTool(_bindings.Keypad6, $": [{_bindings.Keypad6}]");

		public static InputTool KeyPad7 => new InputTool(_bindings.Keypad7, $": [{_bindings.Keypad7}]");

		public static InputTool KeyPad8 => new InputTool(_bindings.Keypad8, $": [{_bindings.Keypad8}]");

		public static InputTool KeyPad9 => new InputTool(_bindings.Keypad9, $": [{_bindings.Keypad9}]");

		static MenuInputProvider()
		{
			JsonSerializerOptions options = new JsonSerializerOptions
			{
				Converters = { (JsonConverter)new JsonStringEnumConverter() }
			};
			ConfigEntry<string> val = BepInExLoader.ConfigLoader.Bind<string>("MenuApi", "KeyBindings", "{\"F1\":\"F1\",\"F2\":\"F2\",\"F3\":\"F3\",\"F4\":\"F4\",\"F5\":\"F5\",\"F6\":\"F6\",\"F7\":\"F7\",\"F8\":\"F8\",\"F9\":\"F9\",\"F10\":\"None\",\"Keypad1\":\"Keypad1\",\"Keypad2\":\"Keypad2\",\"Keypad3\":\"Keypad3\",\"Keypad4\":\"Keypad4\",\"Keypad5\":\"Keypad5\",\"Keypad6\":\"Keypad6\",\"Keypad7\":\"Keypad7\",\"Keypad8\":\"Keypad8\",\"Keypad9\":\"Keypad9\"}", "You can remap keys here.");
			_bindings = JsonSerializer.Deserialize<MenuRebinding>(val.Value, options);
		}
	}
}
namespace EndskApi.Manager.Internal
{
	public class InformationCache
	{
		private readonly Dictionary<string, Dictionary<object, object>> _cache;

		public static InformationCache Instance { get; } = new InformationCache();


		public InformationCache()
		{
			_cache = new Dictionary<string, Dictionary<object, object>>();
		}

		public void SaveInformation(object key, object info, string mod)
		{
			GetCacheOfMod(mod)[key] = info;
		}

		public T GetInformation<T>(object key, string mod)
		{
			if (GetCacheOfMod(mod).TryGetValue(key, out object value))
			{
				return (T)value;
			}
			LogManager.Error($"There was no information with the key {key}");
			throw new KeyNotFoundException($"There was no information with the key {key}!");
		}

		public bool TryGetInformation<T>(object key, out T info, string mod, bool logNotFound = true)
		{
			if (GetCacheOfMod(mod).TryGetValue(key, out object value))
			{
				info = (T)value;
				return true;
			}
			if (logNotFound)
			{
				LogManager.Warn($"There was no informaiton with the key {key}");
			}
			info = default(T);
			return false;
		}

		public void RemoveInformation(object key, string mod)
		{
			if (TryGetCacheOfMod(mod, out Dictionary<object, object> cache))
			{
				cache.Remove(key);
			}
		}

		public bool ContainsKey(object key, string mod)
		{
			Dictionary<object, object> cache;
			return TryGetCacheOfMod(mod, out cache) && cache.ContainsKey(key);
		}

		private Dictionary<object, object> GetCacheOfMod(string mod)
		{
			if (!_cache.TryGetValue(mod, out Dictionary<object, object> value))
			{
				value = new Dictionary<object, object>();
				_cache[mod] = value;
			}
			return value;
		}

		private bool TryGetCacheOfMod(string mod, out Dictionary<object, object> cache)
		{
			return _cache.TryGetValue(mod, out cache);
		}
	}
	internal static class NetworkManager
	{
		[StructLayout(LayoutKind.Sequential, Size = 1)]
		internal struct DummyStruct
		{
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		internal struct EquipGearStruct
		{
		}

		private const string _sendCheckpointReachedKey = "CheckpointHasBeenReached";

		private const string _sendCheckpointCleanupKey = "CheckpointCleanup";

		public static void Setup()
		{
			NetworkAPI.RegisterEvent<DummyStruct>("CheckpointCleanup", (Action<ulong, DummyStruct>)ReceiveCheckpointCleanup);
			NetworkAPI.RegisterEvent<DummyStruct>("CheckpointHasBeenReached", (Action<ulong, DummyStruct>)ReceiveCheckpointReached);
		}

		private static void ReceiveCheckpointReached(ulong snetPlayer, DummyStruct _)
		{
			CheckpointApi.InvokeCheckpointReachedCallbacks();
		}

		private static void ReceiveCheckpointCleanup(ulong snetPlayer, DummyStruct _)
		{
			CheckpointApi.InvokeCheckpointCleanupCallbacks();
		}

		public static void SendCheckpointReached()
		{
			NetworkAPI.InvokeEvent<DummyStruct>("CheckpointHasBeenReached", default(DummyStruct), (SNet_ChannelType)2);
		}

		public static void SendCheckpointCleanups()
		{
			NetworkAPI.InvokeEvent<DummyStruct>("CheckpointCleanup", default(DummyStruct), (SNet_ChannelType)2);
		}

		public static void SendEquipGear(GearInfo info)
		{
		}
	}
}
namespace EndskApi.Information.WeaponSwitcher
{
	public class GearInfo
	{
		public InventorySlotAmmo InventorySlotAmmo { get; set; }

		public InventorySlot Slot { get; set; }

		public AmmoType AmmoType { get; set; }

		public GearIDRange GearId { get; set; }

		public int AmmunitionInMagazine { get; set; }

		public GearInfo(GearIDRange gearId, int ammunitionInMagazine, InventorySlotAmmo inventorySlotAmmo)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			GearId = gearId;
			AmmunitionInMagazine = ammunitionInMagazine;
			InventorySlotAmmo = inventorySlotAmmo;
			AmmoType = inventorySlotAmmo.AmmoType;
			Slot = inventorySlotAmmo.Slot;
		}
	}
}
namespace EndskApi.Information.Menus
{
	public interface IExtendedTool
	{
		Action<object> ExtraToolAction { get; set; }

		InformationId InformationId { get; set; }
	}
	public class InputTool
	{
		public KeyCode InputKey { get; set; }

		public string Postfix { get; set; }

		public InputTool(KeyCode inputKey, string postfix)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			InputKey = inputKey;
			Postfix = postfix;
		}

		public virtual bool CheckKeyDown()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Input.GetKeyDown(InputKey);
		}

		public virtual bool CheckKey()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Input.GetKey(InputKey);
		}
	}
	public class Tool
	{
		public string Text { get; set; }

		public string TextPostfix { get; set; }

		public InputTool CheckInput { get; }

		public Action<Tool> UseTool { get; set; }

		public Action<Tool, bool> OnToggleUpdate { get; set; }

		public bool IsToggle { get; set; }

		public bool CurrentToggleState { get; set; }

		public object Extra { get; set; }

		public Tool()
		{
		}

		public Tool(string text, InputTool input, Action<Tool, bool> onToggleUpdate, bool startState)
		{
			Text = text;
			CheckInput = input;
			IsToggle = true;
			UseTool = ToggleTool;
			OnToggleUpdate = onToggleUpdate;
			CurrentToggleState = startState;
		}

		public Tool(string text, InputTool input, bool isToggle, Action<Tool> useCheat, Action<Tool, bool> onToggleUpdate = null, bool currentToggleState = false)
		{
			Text = text;
			CheckInput = input;
			IsToggle = isToggle;
			UseTool = useCheat;
			OnToggleUpdate = onToggleUpdate;
			CurrentToggleState = currentToggleState;
		}

		public void Toggle()
		{
			CurrentToggleState = !CurrentToggleState;
			OnToggleUpdate?.Invoke(this, CurrentToggleState);
		}

		public override string ToString()
		{
			if (IsToggle)
			{
				return $"{Text}{TextPostfix}{CheckInput.Postfix} {(CurrentToggleState ? "ON" : "OFF")}";
			}
			return Text + TextPostfix + CheckInput.Postfix;
		}

		private static void ToggleTool(Tool tool)
		{
			tool.Toggle();
		}
	}
	public class ToolExtended : Tool, IExtendedTool
	{
		public Action<object> ExtraToolAction { get; set; }

		public InformationId InformationId { get; set; }

		public ToolExtended(string text, InputTool input, bool isToggle, Action<Tool> useCheat, Action<object> extraCheatAction, Action<Tool, bool> onToggleUpdate = null, bool currentToggleState = false, InformationId infoId = InformationId.None)
			: base(text, input, isToggle, useCheat, onToggleUpdate, currentToggleState)
		{
			ExtraToolAction = extraCheatAction;
			InformationId = infoId;
		}

		public override string ToString()
		{
			return base.ToString();
		}
	}
}
namespace EndskApi.Information.EnemyKill
{
	public class EnemyKillDistribution
	{
		public EnemyAgent KilledEnemyAgent { get; set; }

		public List<DamageDistribution> DamageDistributions { get; set; }

		public PlayerAgent LastHitDealtBy { get; set; }

		public LastHitType lastHitType { get; set; }

		public EnemyKillDistribution(EnemyAgent agentToKill)
		{
			KilledEnemyAgent = agentToKill;
			DamageDistributions = new List<DamageDistribution>();
		}

		public void AddDamageDealtByPlayerAgent(PlayerAgent agent, float damage)
		{
			DamageDistributions.Add(new DamageDistribution(agent.PlayerSlotIndex, damage));
		}

		public float GetDamageDealtBySnet(SNet_Player player)
		{
			int slotIndex = player.PlayerSlotIndex();
			return DamageDistributions.Where((DamageDistribution it) => it.PlayerSlotIndex == slotIndex).Sum((DamageDistribution it) => it.DamageDealt);
		}
	}
	public class DamageDistribution
	{
		public int PlayerSlotIndex { get; set; }

		public float DamageDealt { get; set; }

		public DamageDistribution(int slotIndex, float damage)
		{
			PlayerSlotIndex = slotIndex;
			DamageDealt = damage;
		}
	}
}
namespace EndskApi.Information.Configs
{
	public class MenuRebinding
	{
		public KeyCode F1 { get; set; }

		public KeyCode F2 { get; set; }

		public KeyCode F3 { get; set; }

		public KeyCode F4 { get; set; }

		public KeyCode F5 { get; set; }

		public KeyCode F6 { get; set; }

		public KeyCode F7 { get; set; }

		public KeyCode F8 { get; set; }

		public KeyCode F9 { get; set; }

		public KeyCode F10 { get; set; }

		public KeyCode Keypad1 { get; set; }

		public KeyCode Keypad2 { get; set; }

		public KeyCode Keypad3 { get; set; }

		public KeyCode Keypad4 { get; set; }

		public KeyCode Keypad5 { get; set; }

		public KeyCode Keypad6 { get; set; }

		public KeyCode Keypad7 { get; set; }

		public KeyCode Keypad8 { get; set; }

		public KeyCode Keypad9 { get; set; }

		public MenuRebinding()
		{
			F1 = (KeyCode)282;
			F2 = (KeyCode)283;
			F3 = (KeyCode)284;
			F4 = (KeyCode)285;
			F5 = (KeyCode)286;
			F6 = (KeyCode)287;
			F7 = (KeyCode)288;
			F8 = (KeyCode)289;
			F9 = (KeyCode)290;
			Keypad1 = (KeyCode)257;
			Keypad2 = (KeyCode)258;
			Keypad3 = (KeyCode)259;
			Keypad4 = (KeyCode)260;
			Keypad5 = (KeyCode)261;
			Keypad6 = (KeyCode)262;
			Keypad7 = (KeyCode)263;
			Keypad8 = (KeyCode)264;
			Keypad9 = (KeyCode)265;
		}
	}
}
namespace EndskApi.Information.BoosterInfo
{
	public class BoosterCondition
	{
		public string Name { get; set; }

		public string ShortName { get; set; }

		public BoosterCondition Condition { get; set; }
	}
	public class BoosterEffect
	{
		public string Name { get; set; }

		public string ShortName { get; set; }

		public AgentModifier Effect { get; set; }

		public float Value { get; set; }

		public BoosterEffect(string name, string shortName, AgentModifier effect, float value)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			ShortName = shortName;
			Effect = effect;
			Value = value;
		}
	}
	public interface IBooster
	{
		object Category { get; set; }

		List<BoosterEffect> BoosterEffects { get; set; }

		List<BoosterCondition> BoosterConditions { get; set; }
	}
}
namespace EndskApi.Enums.Menus
{
	public enum InformationId
	{
		None,
		EnemyId
	}
	public enum MenuStates
	{
		Active,
		HiddenAndActive,
		Deactivated
	}
}
namespace EndskApi.Enums.EnemyKill
{
	public enum LastHitType
	{
		Melee,
		ShootyWeapon,
		Explosion
	}
}
namespace EndskApi.Enums.Booster
{
	public enum CustomBoosterCategory
	{
		Muted,
		Bold,
		Aggressive,
		NotAccessible
	}
	public enum CustomBoosterModifiers
	{
		None = 0,
		RegenerationCap = 1,
		RegenerationSpeed = 2,
		HealSupport = 3,
		ReviveSpeedSupport = 4,
		ReviveStartHealthSupport = 5,
		MeleeResistance = 6,
		ProjectileResistance = 7,
		InfectionResistance = 8,
		PistolDamage = 50,
		SMGDamage = 51,
		DMRDamage = 52,
		AssaultRifleDamage = 53,
		CarbineDamage = 54,
		AutoPistolDamage = 55,
		HELDamage = 56,
		ShotgunDamage = 58,
		RevolverDamage = 59,
		SniperDamage = 60,
		BurstCannonDamage = 61,
		MachineGunDamage = 62,
		MachinePistolDamage = 63,
		RifleDamage = 64,
		BurstRifleDamage = 65,
		DoubleTapRifle = 66,
		BullpupRifleDamage = 67,
		CombatShotgunDamage = 68,
		ChokeModShotgunDamage = 69,
		StandardWeaponDamage = 70,
		SpecialWeaponDamage = 71,
		GlueStrength = 100,
		GlueEfficiency = 101,
		SentryGunSpeed = 102,
		SentryGunDamage = 103,
		SentryGunLongRangeDamage = 104,
		SentryGunShortRangeDamage = 105,
		TripMineDamage = 106,
		ScannerRechargeSpeed = 107,
		AmmoSupport = 108,
		HackingProficiency = 150,
		ComputerProcessingSpeed = 151,
		InitialAmmoStandard = 152,
		InitialAmmoSpecial = 153,
		InitialAmmoTool = 154,
		FogRepellerEffect = 155,
		GlowstickEffect = 156,
		BioscanSpeed = 157,
		MeleeDamage = 200
	}
}
namespace EndskApi.Api
{
	public static class CacheApi
	{
		private const string GlobalCache = "GlobalCache";

		internal const string InternalCache = "EndskApi";

		private static readonly InformationCache _informationCache;

		static CacheApi()
		{
			_informationCache = InformationCache.Instance;
		}

		public static void SaveInformation(object key, object info, string mod = "GlobalCache")
		{
			_informationCache.SaveInformation(key, info, mod);
		}

		public static void SaveInstance<T>(T info, string mod = "GlobalCache")
		{
			SaveInformation(typeof(T), info, mod);
		}

		public static T GetInformation<T>(object key, string mod = "GlobalCache")
		{
			return _informationCache.GetInformation<T>(key, mod);
		}

		public static T GetInstance<T>(string mod = "GlobalCache")
		{
			return GetInformation<T>(typeof(T), mod);
		}

		public static bool TryGetInformation<T>(object key, out T information, string mod = "GlobalCache", bool logNotFound = true)
		{
			return _informationCache.TryGetInformation<T>(key, out information, mod, logNotFound);
		}

		public static bool TryGetInstance<T>(out T information, string mod = "GlobalCache", bool logNotFound = true)
		{
			return _informationCache.TryGetInformation<T>(typeof(T), out information, mod, logNotFound);
		}

		public static void RemoveInformation(object key, string mod = "GlobalCache")
		{
			_informationCache.RemoveInformation(key, mod);
		}

		public static void RemoveInstance<T>(string mod = "GlobalCache")
		{
			RemoveInformation(typeof(T), mod);
		}

		public static bool ContainsKey(object key, string mod = "GlobalCache")
		{
			return _informationCache.ContainsKey(key, mod);
		}

		public static InformationCache GetInformationCache()
		{
			return _informationCache;
		}
	}
	public static class CheckpointApi
	{
		private const string CheckpointReachedKey = "CheckpointReachedKey";

		private const string CleanupCheckpointKey = "CheckpointCleanupKey";

		static CheckpointApi()
		{
			BepInExLoader.Harmony.PatchAll(typeof(CheckpointManagerPatches));
			NetworkManager.Setup();
		}

		public static void AddCheckpointReachedCallback(Action callBack)
		{
			if (!CacheApi.TryGetInformation<List<Action>>("CheckpointReachedKey", out var information, "EndskApi", logNotFound: false))
			{
				information = new List<Action>();
				CacheApi.SaveInformation("CheckpointReachedKey", information, "EndskApi");
			}
			information.Add(callBack);
		}

		public static void AddCheckpointCleanupCallback(Action callBack)
		{
			if (!CacheApi.TryGetInformation<List<Action>>("CheckpointCleanupKey", out var information, "EndskApi", logNotFound: false))
			{
				information = new List<Action>();
				CacheApi.SaveInformation("CheckpointCleanupKey", information, "EndskApi");
			}
			information.Add(callBack);
		}

		public static void RemoveCheckpointReachedCallback(Action callBack)
		{
			if (CacheApi.TryGetInformation<List<Action>>("CheckpointReachedKey", out var information, "EndskApi", logNotFound: false))
			{
				information.Remove(callBack);
			}
		}

		public static void RemoveCheckpointCleanupCallback(Action callBack)
		{
			if (CacheApi.TryGetInformation<List<Action>>("CheckpointCleanupKey", out var information, "EndskApi", logNotFound: false))
			{
				information.Remove(callBack);
			}
		}

		internal static void InvokeCheckpointReachedCallbacks()
		{
			if (!CacheApi.TryGetInformation<List<Action>>("CheckpointReachedKey", out var information, "EndskApi", logNotFound: false))
			{
				return;
			}
			foreach (Action item in information)
			{
				item();
			}
		}

		internal static void InvokeCheckpointCleanupCallbacks()
		{
			if (!CacheApi.TryGetInformation<List<Action>>("CheckpointCleanupKey", out var information, "EndskApi", logNotFound: false))
			{
				return;
			}
			foreach (Action item in information)
			{
				item();
			}
		}
	}
	public static class EnemyDamageBasePatchApi
	{
		public delegate void ReceiveMeleeDamage(Dam_EnemyDamageBase instance, ref pFullDamageData data);

		public delegate void ReceiveBulletDamage(Dam_EnemyDamageBase instance, ref pBulletDamageData data);

		public delegate void ReceiveExplosionDamage(Dam_EnemyDamageBase instance, ref pExplosionDamageData data);

		public delegate void ProcessReceivedDamage(Dam_EnemyDamageBase instance, ref float damage, Agent damageSource, ref Vector3 position, ref Vector3 direction, ref ES_HitreactType hitreact, ref bool tryForceHitreact, ref int limbID, ref float staggerDamageMulti, ref DamageNoiseLevel damageNoiseLevel);

		private static bool _setup;

		internal static List<(double, ReceiveMeleeDamage)> MeleePrefixCallbacks
		{
			get
			{
				return CacheApi.GetInstance<List<(double, ReceiveMeleeDamage)>>("EndskApi");
			}
			set
			{
				CacheApi.SaveInstance(value, "EndskApi");
			}
		}

		internal static List<(double, ReceiveMeleeDamage)> MeleePostfixCallbacks
		{
			get
			{
				return CacheApi.GetInstance<List<(double, ReceiveMeleeDamage)>>();
			}
			set
			{
				CacheApi.SaveInstance(value);
			}
		}

		internal static List<(double, ReceiveBulletDamage)> BulletPrefixCallbacks
		{
			get
			{
				return CacheApi.GetInstance<List<(double, ReceiveBulletDamage)>>("EndskApi");
			}
			set
			{
				CacheApi.SaveInstance(value, "EndskApi");
			}
		}

		internal static List<(double, ReceiveBulletDamage)> BulletPostfixCallbacks
		{
			get
			{
				return CacheApi.GetInstance<List<(double, ReceiveBulletDamage)>>();
			}
			set
			{
				CacheApi.SaveInstance(value);
			}
		}

		internal static List<(double, ReceiveExplosionDamage)> ExplosionPrefixCallbacks
		{
			get
			{
				return CacheApi.GetInstance<List<(double, ReceiveExplosionDamage)>>("EndskApi");
			}
			set
			{
				CacheApi.SaveInstance(value, "EndskApi");
			}
		}

		internal static List<(double, ReceiveExplosionDamage)> ExplosionPostfixCallbacks
		{
			get
			{
				return CacheApi.GetInstance<List<(double, ReceiveExplosionDamage)>>();
			}
			set
			{
				CacheApi.SaveInstance(value);
			}
		}

		internal static void Setup()
		{
			if (!_setup)
			{
				CacheApi.SaveInstance(new EnemyDamageBaseNatviePatches(), "EndskApi");
				MeleePrefixCallbacks = new List<(double, ReceiveMeleeDamage)>();
				MeleePostfixCallbacks = new List<(double, ReceiveMeleeDamage)>();
				BulletPrefixCallbacks = new List<(double, ReceiveBulletDamage)>();
				BulletPostfixCallbacks = new List<(double, ReceiveBulletDamage)>();
				ExplosionPrefixCallbacks = new List<(double, ReceiveExplosionDamage)>();
				ExplosionPostfixCallbacks = new List<(double, ReceiveExplosionDamage)>();
				_setup = true;
			}
		}

		public static void AddReceiveMeleePrefix(double priority, ReceiveMeleeDamage method)
		{
			Setup();
			MeleePrefixCallbacks.Add((priority, method));
			MeleePrefixCallbacks = new List<(double, ReceiveMeleeDamage)>(MeleePrefixCallbacks.OrderBy<(double, ReceiveMeleeDamage), double>(((double, ReceiveMeleeDamage) x) => x.Item1));
		}

		public static void AddReceiveMeleePostfix(double priority, ReceiveMeleeDamage method)
		{
			Setup();
			MeleePostfixCallbacks.Add((priority, method));
			MeleePostfixCallbacks = new List<(double, ReceiveMeleeDamage)>(MeleePostfixCallbacks.OrderBy<(double, ReceiveMeleeDamage), double>(((double, ReceiveMeleeDamage) x) => x.Item1));
		}

		public static void AddReceiveBulletPrefix(double priority, ReceiveBulletDamage method)
		{
			Setup();
			BulletPrefixCallbacks.Add((priority, method));
			BulletPrefixCallbacks = new List<(double, ReceiveBulletDamage)>(BulletPrefixCallbacks.OrderBy<(double, ReceiveBulletDamage), double>(((double, ReceiveBulletDamage) x) => x.Item1));
		}

		public static void AddReceiveBulletPostfix(double priority, ReceiveBulletDamage method)
		{
			Setup();
			BulletPostfixCallbacks.Add((priority, method));
			BulletPostfixCallbacks = new List<(double, ReceiveBulletDamage)>(BulletPostfixCallbacks.OrderBy<(double, ReceiveBulletDamage), double>(((double, ReceiveBulletDamage) x) => x.Item1));
		}

		public static void AddReceiveExplosionPrefix(double priority, ReceiveExplosionDamage method)
		{
			Setup();
			ExplosionPrefixCallbacks.Add((priority, method));
			ExplosionPrefixCallbacks = new List<(double, ReceiveExplosionDamage)>(ExplosionPrefixCallbacks.OrderBy<(double, ReceiveExplosionDamage), double>(((double, ReceiveExplosionDamage) x) => x.Item1));
		}

		public static void AddReceiveExplosionPostfix(double priority, ReceiveExplosionDamage method)
		{
			Setup();
			ExplosionPostfixCallbacks.Add((priority, method));
			ExplosionPostfixCallbacks = new List<(double, ReceiveExplosionDamage)>(ExplosionPostfixCallbacks.OrderBy<(double, ReceiveExplosionDamage), double>(((double, ReceiveExplosionDamage) x) => x.Item1));
		}

		internal static void InvokeReceiveMeleePrefix(Dam_EnemyDamageBase instance, ref pFullDamageData data)
		{
			foreach (var meleePrefixCallback in MeleePrefixCallbacks)
			{
				meleePrefixCallback.Item2(instance, ref data);
			}
		}

		internal static void InvokeReceiveMeleePostfix(Dam_EnemyDamageBase instance, ref pFullDamageData data)
		{
			foreach (var meleePostfixCallback in MeleePostfixCallbacks)
			{
				meleePostfixCallback.Item2(instance, ref data);
			}
		}

		internal static void InvokeReceiveBulletPrefix(Dam_EnemyDamageBase instance, ref pBulletDamageData data)
		{
			foreach (var bulletPrefixCallback in BulletPrefixCallbacks)
			{
				bulletPrefixCallback.Item2(instance, ref data);
			}
		}

		internal static void InvokeReceiveBulletPostfix(Dam_EnemyDamageBase instance, ref pBulletDamageData data)
		{
			foreach (var bulletPostfixCallback in BulletPostfixCallbacks)
			{
				bulletPostfixCallback.Item2(instance, ref data);
			}
		}

		internal static void InvokeReceiveExplosionPrefix(Dam_EnemyDamageBase instance, ref pExplosionDamageData data)
		{
			foreach (var explosionPrefixCallback in ExplosionPrefixCallbacks)
			{
				explosionPrefixCallback.Item2(instance, ref data);
			}
		}

		internal static void InvokeReceiveExplosionPostfix(Dam_EnemyDamageBase instance, ref pExplosionDamageData data)
		{
			foreach (var explosionPostfixCallback in ExplosionPostfixCallbacks)
			{
				explosionPostfixCallback.Item2(instance, ref data);
			}
		}
	}
	public static class EnemyKillApi
	{
		private const string EnemyKillKey = "EnemyKillCallbacks";

		private static bool _setup = false;

		private static Dictionary<IntPtr, bool> _enemyStates = new Dictionary<IntPtr, bool>();

		public static void AddEnemyKilledCallback(Action<EnemyKillDistribution> callBack)
		{
			Setup();
			if (!CacheApi.TryGetInformation<List<Action<EnemyKillDistribution>>>("EnemyKillCallbacks", out var information, "EndskApi", logNotFound: false))
			{
				information = new List<Action<EnemyKillDistribution>>();
				CacheApi.SaveInformation("EnemyKillCallbacks", information, "EndskApi");
			}
			information.Add(callBack);
		}

		internal static void InvokeEnemyKilledCallbacks(EnemyKillDistribution enemyKill)
		{
			if (!CacheApi.TryGetInformation<List<Action<EnemyKillDistribution>>>("EnemyKillCallbacks", out var information, "EndskApi", logNotFound: false))
			{
				return;
			}
			foreach (Action<EnemyKillDistribution> item in information)
			{
				item(enemyKill);
			}
		}

		private static void Setup()
		{
			if (!_setup)
			{
				EnemyDamageBasePatchApi.AddReceiveMeleePrefix(1.0, ReceiveMeleePrefix);
				EnemyDamageBasePatchApi.AddReceiveMeleePostfix(1.0, ReceiveMeleePostfix);
				EnemyDamageBasePatchApi.AddReceiveBulletPrefix(1.0, ReceiveBulletPrefix);
				EnemyDamageBasePatchApi.AddReceiveBulletPostfix(1.0, ReceiveBulletPostfix);
				EnemyDamageBasePatchApi.AddReceiveExplosionPrefix(1.0, ReceiveExplosionPrefix);
				EnemyDamageBasePatchApi.AddReceiveExplosionPostfix(1.0, ReceiveExplosionPostfix);
				CacheApi.SaveInstance(new Dictionary<IntPtr, EnemyKillDistribution>(), "EndskApi");
				LevelApi.AddEndLevelCallback(delegate
				{
					_enemyStates = new Dictionary<IntPtr, bool>();
					CacheApi.SaveInstance(new Dictionary<IntPtr, EnemyKillDistribution>(), "EndskApi");
				});
				_setup = true;
			}
		}

		private static void ReceiveMeleePrefix(Dam_EnemyDamageBase instance, ref pFullDamageData data)
		{
			LogManager.Debug($"Receive Melee EnemyKillApi Prefix State = {((Agent)instance.Owner).Alive}");
			_enemyStates[((Il2CppObjectBase)instance).Pointer] = ((Agent)instance.Owner).Alive;
		}

		private static void ReceiveMeleePostfix(Dam_EnemyDamageBase instance, ref pFullDamageData data)
		{
			LogManager.Debug($"Receive Melee EnemyKillApi Postfix State = {((Agent)instance.Owner).Alive}");
			if (!(_enemyStates.TryGetValue(((Il2CppObjectBase)instance).Pointer, out var value) && value))
			{
				return;
			}
			Agent val = default(Agent);
			((pAgent)(ref data.source)).TryGet(ref val);
			if (val != null)
			{
				PlayerAgent val2 = ((Il2CppObjectBase)val).TryCast<PlayerAgent>();
				DamageDistributionAddDamageDealt(instance.Owner, val2, ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)instance).HealthMax));
				if (!((Agent)instance.Owner).Alive)
				{
					EnemyDied(instance.Owner, val2, LastHitType.Melee);
				}
			}
		}

		private static void ReceiveBulletPrefix(Dam_EnemyDamageBase instance, ref pBulletDamageData data)
		{
			_enemyStates[((Il2CppObjectBase)instance).Pointer] = ((Agent)instance.Owner).Alive;
		}

		private static void ReceiveBulletPostfix(Dam_EnemyDamageBase instance, ref pBulletDamageData data)
		{
			if (!(_enemyStates.TryGetValue(((Il2CppObjectBase)instance).Pointer, out var value) && value))
			{
				return;
			}
			Agent val = default(Agent);
			((pAgent)(ref data.source)).TryGet(ref val);
			if (val != null)
			{
				PlayerAgent val2 = ((Il2CppObjectBase)val).TryCast<PlayerAgent>();
				DamageDistributionAddDamageDealt(instance.Owner, val2, ((UFloat16)(ref data.damage)).Get(((Dam_SyncedDamageBase)instance).HealthMax));
				if (!((Agent)instance.Owner).Alive)
				{
					EnemyDied(instance.Owner, val2, LastHitType.ShootyWeapon);
				}
			}
		}

		private static void ReceiveExplosionPrefix(Dam_EnemyDamageBase instance, ref pExplosionDamageData data)
		{
			_enemyStates[((Il2CppObjectBase)instance).Pointer] = ((Agent)instance.Owner).Alive;
		}

		private static void ReceiveExplosionPostfix(Dam_EnemyDamageBase instance, ref pExplosionDamageData data)
		{
			if (_enemyStates.TryGetValue(((Il2CppObjectBase)instance).Pointer, out var value) && value && !((Agent)instance.Owner).Alive)
			{
				EnemyDied(instance.Owner, null, LastHitType.Explosion);
			}
		}

		private static void DamageDistributionAddDamageDealt(EnemyAgent hitEnemy, PlayerAgent damageDealer, float damageDealt)
		{
			Dictionary<IntPtr, EnemyKillDistribution> instance = CacheApi.GetInstance<Dictionary<IntPtr, EnemyKillDistribution>>("EndskApi");
			if (!instance.ContainsKey(((Il2CppObjectBase)hitEnemy).Pointer))
			{
				EnemyKillDistribution enemyKillDistribution = new EnemyKillDistribution(hitEnemy);
				enemyKillDistribution.AddDamageDealtByPlayerAgent(damageDealer, damageDealt);
				instance[((Il2CppObjectBase)hitEnemy).Pointer] = enemyKillDistribution;
			}
			else
			{
				instance[((Il2CppObjectBase)hitEnemy).Pointer].AddDamageDealtByPlayerAgent(damageDealer, damageDealt);
			}
		}

		private static void EnemyDied(EnemyAgent hitEnemy, PlayerAgent lastHit, LastHitType lastHitType)
		{
			Dictionary<IntPtr, EnemyKillDistribution> instance = CacheApi.GetInstance<Dictionary<IntPtr, EnemyKillDistribution>>("EndskApi");
			if (instance.TryGetValue(((Il2CppObjectBase)hitEnemy).Pointer, out var value))
			{
				value.LastHitDealtBy = lastHit;
				value.lastHitType = lastHitType;
				InvokeEnemyKilledCallbacks(value);
			}
		}
	}
	public static class GearSwitchApi
	{
		static GearSwitchApi()
		{
			LevelApi.AddEndLevelCallback(LevelEndedCallback);
			SetGearInfoCache(new Dictionary<IntPtr, GearInfo>());
		}

		public static GearInfo CreateNewWeaponInfo(InventorySlot slot, AmmoType ammoType, GearIDRange gearId)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_000f: 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_0019: Invalid comparison between Unknown and I4
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			PlayerDataBlock block = GameDataBlockBase<PlayerDataBlock>.GetBlock(1u);
			InventorySlotAmmo val = new InventorySlotAmmo();
			val.Slot = slot;
			val.AmmoInPack = (((int)ammoType == 1) ? block.AmmoSpecialInitial : block.AmmoStandardInitial);
			val.AmmoMaxCap = (((int)ammoType == 1) ? block.AmmoSpecialMaxCap : block.AmmoStandardMaxCap);
			GearInfo gearInfo = new GearInfo(gearId, 0, val);
			GearCategoryDataBlock block2 = GameDataBlockBase<GearCategoryDataBlock>.GetBlock(gearId.GetCompID((eGearComponent)2));
			uint archetypeID = GearBuilder.GetArchetypeID(block2, (eWeaponFireMode)gearId.GetCompID((eGearComponent)1));
			ArchetypeDataBlock block3 = GameDataBlockBase<ArchetypeDataBlock>.GetBlock(archetypeID);
			gearInfo.InventorySlotAmmo.BulletClipSize = block3.DefaultClipSize;
			gearInfo.AmmunitionInMagazine = block3.DefaultClipSize;
			LogManager.Debug($"Putting {gearInfo.AmmunitionInMagazine} into {block2.PublicName}");
			return gearInfo;
		}

		public static void EquipGear(GearInfo newGear, out GearInfo oldGear)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			AddWeaponInfo(newGear);
			SyncAmmonitionWithRegisteredWeapon(newGear.Slot, out oldGear);
			EquipGear(newGear);
		}

		public static void SyncAmmonitionWithRegisteredWeapon(InventorySlot slot, out GearInfo changedWeapon)
		{
			//IL_0001: 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)
			if (TryGetItemEquippableInSlot(slot, out ItemEquippable item) && (Object)(object)item != (Object)null)
			{
				LogManager.Debug("SyncAmmunitionWithRegisteredWeapon actually found Weapon itemequippable");
				InventorySlotAmmo inventorySlotAmmo = PlayerBackpackManager.LocalBackpack.AmmoStorage.GetInventorySlotAmmo(slot);
				if (GetGearInfo().TryGetValue(((Il2CppObjectBase)inventorySlotAmmo).Pointer, out changedWeapon))
				{
					changedWeapon.AmmunitionInMagazine = item.GetCurrentClip();
					LogManager.Debug($"Updated Ammo to {changedWeapon.AmmunitionInMagazine}, Max is {changedWeapon.InventorySlotAmmo.BulletClipSize}");
				}
			}
			else
			{
				changedWeapon = null;
			}
		}

		public static void AddWeaponInfo(GearInfo info)
		{
			Dictionary<IntPtr, GearInfo> gearInfo = GetGearInfo();
			if (!gearInfo.ContainsKey(((Il2CppObjectBase)info.InventorySlotAmmo).Pointer))
			{
				gearInfo.Add(((Il2CppObjectBase)info.InventorySlotAmmo).Pointer, info);
			}
		}

		public static void UnregisterWeapon(GearInfo info)
		{
			GetGearInfo().Remove(((Il2CppObjectBase)info.InventorySlotAmmo).Pointer);
		}

		private static void EquipGear(GearInfo info)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			GearInfo info2 = info;
			PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack;
			localBackpack.SpawnAndEquipGearAsync(info2.Slot, info2.GearId, delBackpackItemCallback.op_Implicit((Action<BackpackItem>)BackPackItemCreatedCallBack));
			SetAmmoStorage(info2, localBackpack.AmmoStorage);
			void BackPackItemCreatedCallBack(BackpackItem backpackItem)
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				ItemEquippable val = ((Il2CppObjectBase)backpackItem.Instance).TryCast<ItemEquippable>();
				if ((Object)(object)val != (Object)null)
				{
					val.SetCurrentClip(info2.AmmunitionInMagazine);
					PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
					localPlayerAgent.Sync.WantsToWieldSlot(info2.Slot, false);
				}
			}
		}

		private static bool TryGetItemEquippableInSlot(InventorySlot slot, out ItemEquippable item)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack;
			BackpackItem val = default(BackpackItem);
			if (!localBackpack.TryGetBackpackItem(slot, ref val))
			{
				item = null;
				return false;
			}
			item = ((Il2CppObjectBase)val.Instance).TryCast<ItemEquippable>();
			return (Object)(object)item != (Object)null;
		}

		private static void SetAmmoStorage(GearInfo info, PlayerAmmoStorage storage)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected I4, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			((Il2CppArrayBase<InventorySlotAmmo>)(object)storage.m_ammoStorage)[(int)info.AmmoType] = info.InventorySlotAmmo;
			AmmoType ammoType = info.AmmoType;
			AmmoType val = ammoType;
			if ((int)val != 0)
			{
				if ((int)val == 1)
				{
					storage.SpecialAmmo = info.InventorySlotAmmo;
				}
			}
			else
			{
				storage.StandardAmmo = info.InventorySlotAmmo;
			}
		}

		internal static void LevelEndedCallback()
		{
			SetGearInfoCache(new Dictionary<IntPtr, GearInfo>());
		}

		private static Dictionary<IntPtr, GearInfo> GetGearInfo()
		{
			return CacheApi.GetInstance<Dictionary<IntPtr, GearInfo>>("EndskApi");
		}

		private static void SetGearInfoCache(Dictionary<IntPtr, GearInfo> dic)
		{
			CacheApi.SaveInstance(dic, "EndskApi");
		}
	}
	public static class InitApi
	{
		private const string InitKey = "InitKey";

		static InitApi()
		{
			BepInExLoader.Harmony.PatchAll(typeof(PageRundownNewPatches));
			BepInExLoader.Harmony.PatchAll(typeof(GUIManagerPatches));
		}

		public static void AddInitCallback(Action callBack)
		{
			if (!CacheApi.TryGetInformation<List<Action>>("InitKey", out var information, "EndskApi", logNotFound: false))
			{
				information = new List<Action>();
				CacheApi.SaveInformation("InitKey", information, "EndskApi");
			}
			information.Add(callBack);
		}

		internal static void InvokeInitCallbacks()
		{
			if (!CacheApi.TryGetInformation<List<Action>>("InitKey", out var information, "EndskApi", logNotFound: false))
			{
				return;
			}
			foreach (Action item in information)
			{
				try
				{
					item();
				}
				catch (Exception ex)
				{
					LogManager.Error(ex.ToString());
				}
			}
			CacheApi.RemoveInformation("InitKey", "EndskApi");
		}
	}
	public static class LevelApi
	{
		private const string EndLevelKey = "EndLevelKey";

		private const string StartLevelKey = "StartLevelKey";

		static LevelApi()
		{
			BepInExLoader.Harmony.PatchAll(typeof(GsAfterLevelPatches));
			BepInExLoader.Harmony.PatchAll(typeof(GsInLevelPatches));
		}

		public static void AddBeginLevelCallback(Action callBack)
		{
			if (!CacheApi.TryGetInformation<List<Action>>("StartLevelKey", out var information, "EndskApi", logNotFound: false))
			{
				information = new List<Action>();
				CacheApi.SaveInformation("StartLevelKey", information, "EndskApi");
			}
			information.Add(callBack);
		}

		public static void AddEndLevelCallback(Action callBack)
		{
			if (!CacheApi.TryGetInformation<List<Action>>("EndLevelKey", out var information, "EndskApi", logNotFound: false))
			{
				information = new List<Action>();
				CacheApi.SaveInformation("EndLevelKey", information, "EndskApi");
			}
			information.Add(callBack);
		}

		internal static void InvokeEndLevelCallbacks()
		{
			if (!CacheApi.TryGetInformation<List<Action>>("EndLevelKey", out var information, "EndskApi", logNotFound: false))
			{
				return;
			}
			foreach (Action item in information)
			{
				try
				{
					item();
				}
				catch (Exception msg)
				{
					LogManager.Error(msg);
				}
			}
		}

		internal static void InvokeStartLevelCallbacks()
		{
			if (!CacheApi.TryGetInformation<List<Action>>("StartLevelKey", out var information, "EndskApi", logNotFound: false))
			{
				return;
			}
			foreach (Action item in information)
			{
				try
				{
					item();
				}
				catch (Exception msg)
				{
					LogManager.Error(msg);
				}
			}
		}
	}
	public static class MenuApi
	{
		private static bool _setup;

		static MenuApi()
		{
			_setup = false;
		}

		internal static void Setup()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			if (!_setup)
			{
				GameObject val = new GameObject("EndskApi_Menu");
				CacheApi.SaveInstance(val.AddComponent<MainMenu>(), "EndskApi");
				Object.DontDestroyOnLoad((Object)(object)val);
				_setup = true;
			}
		}

		public static void ActivateUnknownMenu<TScript>(TScript menu) where TScript : BaseMenu
		{
			Setup();
			CacheApi.GetInstance<MainMenu>("EndskApi").ActivateUnknownMenu(menu);
		}

		public static TScript AddMenu<TScript>(string pageName) where TScript : BaseMenu
		{
			Setup();
			MainMenu instance = CacheApi.GetInstance<MainMenu>("EndskApi");
			TScript val = ((Component)instance).gameObject.AddComponent<TScript>();
			instance.AddPage(pageName, val);
			CacheApi.SaveInstance(val, "EndskApi");
			return val;
		}

		public static TScript GetMenu<TScript>() where TScript : BaseMenu
		{
			Setup();
			return CacheApi.GetInstance<TScript>("EndskApi");
		}

		public static void AddMiddleMouseClickTool(IExtendedTool tool)
		{
			Setup();
			MainMenu instance = CacheApi.GetInstance<MainMenu>("EndskApi");
			instance.AddMiddleMouseClickTool(tool);
		}

		public static void RemoveMiddleMouseClickTool(IExtendedTool tool)
		{
			Setup();
			MainMenu instance = CacheApi.GetInstance<MainMenu>("EndskApi");
			instance.RemoveMiddleMouseClickTool(tool);
		}

		public static void AddTimerTool(IExtendedTool tool)
		{
			Setup();
			MainMenu instance = CacheApi.GetInstance<MainMenu>("EndskApi");
			instance.AddTimedTool(tool);
		}

		public static void RemoveTimerTool(IExtendedTool tool)
		{
			Setup();
			MainMenu instance = CacheApi.GetInstance<MainMenu>("EndskApi");
			instance.RemoveTimedTool(tool);
		}

		public static void AddHiddenFunction(Tool tool)
		{
			Setup();
			MainMenu instance = CacheApi.GetInstance<MainMenu>("EndskApi");
			instance.AddHiddenTool(tool);
		}

		public static void RemoveHiddenFunction(Tool tool)
		{
			Setup();
			MainMenu instance = CacheApi.GetInstance<MainMenu>("EndskApi");
			instance.RemoveHiddenTool(tool);
		}
	}
	public static class ProfileIndependentDataApi
	{
		private static readonly string _localLowPath;

		static ProfileIndependentDataApi()
		{
			string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).Replace("Roaming", "LocalLow");
			_localLowPath = Path.Combine(path, "10 Chambers Collective", "Mods");
			if (!Directory.Exists(_localLowPath))
			{
				Directory.CreateDirectory(_localLowPath);
			}
		}

		public static T Load<T>(string fileName, JsonSerializerOptions option = null) where T : new()
		{
			if (TryLoadFromCache<T>(fileName, out var cachedObj))
			{
				return cachedObj;
			}
			if (option == null)
			{
				option = new JsonSerializerOptions
				{
					IncludeFields = false,
					ReadCommentHandling = JsonCommentHandling.Skip,
					PropertyNameCaseInsensitive = true,
					WriteIndented = true
				};
			}
			if (File.Exists(CreatePath(fileName)))
			{
				return JsonSerializer.Deserialize<T>(File.ReadAllText(CreatePath(fileName)), option);
			}
			return new T();
		}

		public static void Save(object obj, string fileName, JsonSerializerOptions option = null)
		{
			SaveIntoCache(fileName, obj);
			if (option == null)
			{
				option = new JsonSerializerOptions
				{
					IncludeFields = false,
					ReadCommentHandling = JsonCommentHandling.Skip,
					PropertyNameCaseInsensitive = true,
					WriteIndented = true
				};
			}
			File.WriteAllText(CreatePath(fileName), JsonSerializer.Serialize(obj, option));
		}

		internal static bool TryLoadFromCache<T>(string fileName, out T cachedObj)
		{
			return CacheApi.TryGetInformation<T>(fileName, out cachedObj, "ProfileIndependentApi", logNotFound: false);
		}

		internal static void SaveIntoCache(string fileName, object obj)
		{
			CacheApi.SaveInformation(fileName, obj, "ProfileIndependentApi");
		}

		private static string CreatePath(string fileName)
		{
			if (fileName.EndsWith(".json"))
			{
				return Path.Combine(_localLowPath, fileName);
			}
			return Path.Combine(_localLowPath, fileName + ".json");
		}
	}
}

GTFuckingXP.dll

Decompiled 8 months ago
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using EndskApi.Api;
using EndskApi.Enums.Menus;
using EndskApi.Information.EnemyKill;
using EndskApi.Information.Menus;
using EndskApi.Manager;
using EndskApi.Scripts;
using Enemies;
using FloatingTextAPI;
using GTFO.API;
using GTFuckingXP.Communication;
using GTFuckingXP.Enums;
using GTFuckingXP.Extensions;
using GTFuckingXP.Information;
using GTFuckingXP.Information.ClassSelector;
using GTFuckingXP.Information.Enemies;
using GTFuckingXP.Information.Level;
using GTFuckingXP.Information.NetworkingInfo;
using GTFuckingXP.Managers;
using GTFuckingXP.Patches;
using GTFuckingXP.Patches.SelectLevelPatches;
using GTFuckingXP.Scripts;
using GTFuckingXP.StolenCode;
using GTFuckingXp.Managers;
using GTFuckingXp.Patches;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Localization;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("GTFuckingXp")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+gitc03396b-dirty-master")]
[assembly: AssemblyProduct("GTFuckingXp")]
[assembly: AssemblyTitle("GTFuckingXp")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace GTFuckingXp
{
	[GeneratedCode("VersionInfoGenerator", "2.0.0+git50a4b1a-master")]
	[CompilerGenerated]
	internal static class VersionInfo
	{
		public const string RootNamespace = "GTFuckingXp";

		public const string Version = "1.0.0";

		public const string VersionPrerelease = null;

		public const string VersionMetadata = "gitc03396b-dirty-master";

		public const string SemVer = "1.0.0+gitc03396b-dirty-master";

		public const string GitRevShort = "c03396b-dirty";

		public const string GitRevLong = "c03396b43dd7f0dd7f6be64a74260c9045444f6f-dirty";

		public const string GitBranch = "master";

		public const string GitTag = null;

		public const bool GitIsDirty = true;
	}
}
namespace GTFuckingXp.Patches
{
	[HarmonyPatch(typeof(Dam_EnemyDamageBase))]
	public static class EnemyDamageBasePatches
	{
		[HarmonyPatch("MeleeDamage")]
		[HarmonyPrefix]
		public static void MeleePrefix(Dam_EnemyDamageBase __instance, ref float dam, Agent sourceAgent)
		{
			if (((Agent)__instance.Owner).Alive && (Object)(object)sourceAgent != (Object)null && sourceAgent.IsLocallyOwned)
			{
				float num = dam;
				LogManager.Debug($"Melee damage from local player registered. {num} was scaled up to:");
				num *= CacheApiWrapper.GetActiveLevel().MeleeDamageMultiplier;
				LogManager.Debug($"{num}");
				dam = num;
			}
		}

		[HarmonyBefore(new string[] { "Endskill.GTFuckingXP", "com.dak.DamageNumbers" })]
		[HarmonyPatch("BulletDamage")]
		[HarmonyPrefix]
		public static void BulletPostfix(Dam_EnemyDamageBase __instance, ref float dam, Agent sourceAgent)
		{
			if (((Agent)__instance.Owner).Alive && (Object)(object)sourceAgent != (Object)null && sourceAgent.IsLocallyOwned)
			{
				float num = dam;
				LogManager.Debug($"Bullet damage from local player registered. {num} was scaled to:");
				num *= CacheApiWrapper.GetActiveLevel().WeaponDamageMultiplier;
				LogManager.Debug($"{num}");
				dam = num;
			}
		}
	}
}
namespace GTFuckingXp.Managers
{
	public static class EnemyKillManager
	{
		public static void Setup()
		{
			EnemyKillApi.AddEnemyKilledCallback((Action<EnemyKillDistribution>)EnemyKilled);
		}

		public static void EnemyKilled(EnemyKillDistribution info)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//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)
			//IL_0186: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			if ((int)info.lastHitType == 2)
			{
				GiveXpToEveryone(info.KilledEnemyAgent);
				return;
			}
			EnemyXp enemyXp = GetEnemyXp(info.KilledEnemyAgent);
			Vector3 position = info.KilledEnemyAgent.Position;
			position.y += 1f;
			Enumerator<SNet_Player> enumerator = SNet.LobbyPlayers.GetEnumerator();
			XpHandler xpHandler = default(XpHandler);
			while (enumerator.MoveNext())
			{
				SNet_Player current = enumerator.Current;
				if (current.IsBot)
				{
					continue;
				}
				if (info.LastHitDealtBy.Owner.PlayerSlot.index == current.PlayerSlot.index)
				{
					if (current.IsLocal)
					{
						if (CacheApi.TryGetInstance<XpHandler>(ref xpHandler, "GTF_XP", true))
						{
							xpHandler.AddXp(enemyXp, position);
						}
					}
					else
					{
						NetworkApiXpManager.SendReceiveXp(current, enemyXp, position, forceDebuffXp: false);
					}
					continue;
				}
				float damageDealtBySnet = info.GetDamageDealtBySnet(current);
				if (damageDealtBySnet > 0.5f)
				{
					float num = damageDealtBySnet / ((Dam_SyncedDamageBase)info.KilledEnemyAgent.Damage).HealthMax;
					LogManager.Debug($"percentageDealt = {num} and damageDealt is {damageDealtBySnet}");
					NetworkApiXpManager.SendStaticXpInfo(current, (uint)((float)enemyXp.XpGain * num), (uint)((float)enemyXp.DebuffXp * num), (int)((float)enemyXp.LevelScalingXpDecrese * num), position);
				}
			}
		}

		private static void GiveXpToEveryone(EnemyAgent killedEnemy)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			EnemyXp enemyXp = GetEnemyXp(killedEnemy);
			Vector3 position = killedEnemy.Position;
			position.y += 1f;
			XpHandler xpHandler = default(XpHandler);
			if (CacheApi.TryGetInstance<XpHandler>(ref xpHandler, "GTF_XP", true))
			{
				xpHandler.AddXp(enemyXp, position, forceDebuffXp: true, "<#F30>");
			}
			NetworkApiXpManager.SendHalfAssedXp(enemyXp, position, forceDebuffXp: true);
		}

		private static EnemyXp GetEnemyXp(EnemyAgent killedEnemy)
		{
			EnemyAgent killedEnemy2 = killedEnemy;
			List<EnemyXp> instance = CacheApi.GetInstance<List<EnemyXp>>("GTF_XP");
			EnemyXp enemyXp = instance.FirstOrDefault((EnemyXp it) => it.EnemyId == killedEnemy2.EnemyDataID);
			if (enemyXp == null)
			{
				LogManager.Warn($"There was no enemy XP data found for {killedEnemy2.EnemyDataID}!");
				enemyXp = new EnemyXp(killedEnemy2.EnemyDataID, ((Object)killedEnemy2).name, 0u, 0u, 0);
				instance.Add(enemyXp);
				CacheApi.SaveInstance<List<EnemyXp>>(instance, "GTF_XP");
			}
			LogManager.Debug($"Enemy kill was registered. Enemy XpData was {enemyXp.XpGain}.");
			return enemyXp;
		}
	}
}
namespace GTFuckingXp.Information
{
	public class DefaultConstants
	{
		public const string DoubleJumpExpansion = "[\r\n  {\r\n    \"LevelLayoutPersistentId\": 13,\r\n    \"UnlockAtLevel\": 10\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 14,\r\n    \"UnlockAtLevel\": 6\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 7,\r\n    \"UnlockAtLevel\": 5\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 8,\r\n    \"UnlockAtLevel\": 5\r\n  },\r\n  {\r\n    \"LevelLayoutPersistentId\": 15,\r\n    \"UnlockAtLevel\": 5\r\n  }\r\n]";

		public const string ExpansionsActive = "\r\n{\r\n    \"ExplosionAbility\": false,\r\n    \"DoubleJumpAbility\": true\r\n}\r\n";

		public const string BoosterEffects = "\r\n[\r\n  {\r\n    \"ClassLayoutPersistentId\": 2,\r\n    \"ActiveLevels\": [\r\n      10\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 1.35\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.03,\r\n      \"ProjectileResistance\": 1.03,\r\n      \"InfectionResistance\": 1.03\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.06,\r\n      \"ProjectileResistance\": 1.06,\r\n      \"InfectionResistance\": 1.06\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.09,\r\n      \"ProjectileResistance\": 1.09,\r\n      \"InfectionResistance\": 1.09\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.12,\r\n      \"ProjectileResistance\": 1.12,\r\n      \"InfectionResistance\": 1.12\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.15,\r\n      \"ProjectileResistance\": 1.15,\r\n      \"InfectionResistance\": 1.15\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      6\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.18,\r\n      \"ProjectileResistance\": 1.18,\r\n      \"InfectionResistance\": 1.18\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      7\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.21,\r\n      \"ProjectileResistance\": 1.21,\r\n      \"InfectionResistance\": 1.21\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      8\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.24,\r\n      \"ProjectileResistance\": 1.24,\r\n      \"InfectionResistance\": 1.24\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      9\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.27,\r\n      \"ProjectileResistance\": 1.27,\r\n      \"InfectionResistance\": 1.27\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      10\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.3,\r\n      \"ProjectileResistance\": 1.3,\r\n      \"InfectionResistance\": 1.3\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      11\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.33,\r\n      \"ProjectileResistance\": 1.33,\r\n      \"InfectionResistance\": 1.33\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      12\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.36,\r\n      \"ProjectileResistance\": 1.36,\r\n      \"InfectionResistance\": 1.36\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      13\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.39,\r\n      \"ProjectileResistance\": 1.39,\r\n      \"InfectionResistance\": 1.39\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      14\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.42,\r\n      \"ProjectileResistance\": 1.42,\r\n      \"InfectionResistance\": 1.42\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 3,\r\n    \"ActiveLevels\": [\r\n      15\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.45,\r\n      \"ProjectileResistance\": 1.45,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 4,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 1.35,\r\n      \"ReviveSpeedSupport\": 1.25\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 4,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 1.7,\r\n      \"ReviveSpeedSupport\": 1.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 4,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.05,\r\n      \"ReviveSpeedSupport\": 1.75\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 4,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.40,\r\n      \"ReviveSpeedSupport\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 4,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.75,\r\n      \"ReviveSpeedSupport\": 2.25,\r\n      \"MeleeResistance\": 1.15,\r\n      \"ProjectileResistance\": 1.15\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 15,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 12,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 1.35,\r\n      \"ReviveSpeedSupport\": 1.1,\r\n      \"MeleeResistance\": 1.04,\r\n      \"ProjectileResistance\": 1.04,\r\n      \"InfectionResistance\": 1.05\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 12,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 1.7,\r\n      \"ReviveSpeedSupport\": 1.2,\r\n      \"MeleeResistance\": 1.08,\r\n      \"ProjectileResistance\": 1.08,\r\n      \"InfectionResistance\": 1.1\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 12,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.05,\r\n      \"ReviveSpeedSupport\": 1.3,\r\n      \"MeleeResistance\": 1.12,\r\n      \"ProjectileResistance\": 1.12,\r\n      \"InfectionResistance\": 1.15\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 12,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.40,\r\n      \"ReviveSpeedSupport\": 1.4,\r\n      \"MeleeResistance\": 1.16,\r\n      \"ProjectileResistance\": 1.16,\r\n      \"InfectionResistance\": 1.2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 12,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.75,\r\n      \"ReviveSpeedSupport\": 1.5,\r\n      \"MeleeResistance\": 1.2,\r\n      \"ProjectileResistance\": 1.2,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 5,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.55,\r\n      \"ScannerRechargeSpeed\": 1.15,\r\n      \"SentryGunDamage\": 1.15,\r\n      \"GlueEfficiency\": 1.15,\r\n      \"TripMineDamage\": 1.15,\r\n      \"ComputerProcessingSpeed\": 1.2,\r\n      \"FogRepellerEffect\": 1.2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 5,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 2.1,\r\n      \"ScannerRechargeSpeed\": 1.3,\r\n      \"SentryGunDamage\": 1.3,\r\n      \"GlueEfficiency\": 1.3,\r\n      \"TripMineDamage\": 1.3,\r\n      \"ComputerProcessingSpeed\": 1.4,\r\n      \"FogRepellerEffect\": 1.4\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 5,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 2.65,\r\n      \"ScannerRechargeSpeed\": 1.45,\r\n      \"SentryGunDamage\": 1.45,\r\n      \"GlueEfficiency\": 1.45,\r\n      \"TripMineDamage\": 1.45,\r\n      \"ComputerProcessingSpeed\": 1.6,\r\n      \"FogRepellerEffect\": 1.6\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 5,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 3.2,\r\n      \"ScannerRechargeSpeed\": 1.6,\r\n      \"SentryGunDamage\": 1.6,\r\n      \"GlueEfficiency\": 1.6,\r\n      \"TripMineDamage\": 1.6,\r\n      \"ComputerProcessingSpeed\": 1.8,\r\n      \"FogRepellerEffect\": 1.8\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 5,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 999.0,\r\n      \"ScannerRechargeSpeed\": 1.8,\r\n      \"SentryGunDamage\": 1.75,\r\n      \"GlueEfficiency\": 1.75,\r\n      \"TripMineDamage\": 1.75,\r\n      \"ComputerProcessingSpeed\": 999.0,\r\n      \"FogRepellerEffect\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 6,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.5,\r\n      \"ProjectileResistance\": 0.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 6,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 1.5,\r\n      \"MeleeResistance\": 0.46,\r\n      \"ProjectileResistance\": 0.46\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 6,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.0,\r\n      \"MeleeResistance\": 0.42,\r\n      \"ProjectileResistance\": 0.42\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 6,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 2.5,\r\n      \"MeleeResistance\": 0.38,\r\n      \"ProjectileResistance\": 0.38\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 6,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 3.0,\r\n      \"MeleeResistance\": 0.34,\r\n      \"ProjectileResistance\": 0.34\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 6,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"RegenerationSpeed\": 3.5,\r\n      \"MeleeResistance\": 0.3,\r\n      \"ProjectileResistance\": 0.3\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 7,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.04,\r\n      \"ProjectileResistance\": 1.04\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 7,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.08,\r\n      \"ProjectileResistance\": 1.08\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 7,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.12,\r\n      \"ProjectileResistance\": 1.12\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 7,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.16,\r\n      \"ProjectileResistance\": 1.16\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 7,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.2,\r\n      \"ProjectileResistance\": 1.2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 8,\r\n    \"ActiveLevels\": [\r\n      0\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.55,\r\n      \"ProjectileResistance\": 0.55\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 8,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.6,\r\n      \"ProjectileResistance\": 0.6\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 8,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.65,\r\n      \"ProjectileResistance\": 0.65\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 8,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.7,\r\n      \"ProjectileResistance\": 0.7\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 8,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.75,\r\n      \"ProjectileResistance\": 0.75\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 8,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.8,\r\n      \"ProjectileResistance\": 0.8\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      0\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.6,\r\n      \"ProjectileResistance\": 0.6\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.63,\r\n      \"ProjectileResistance\": 0.63\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.66,\r\n      \"ProjectileResistance\": 0.66\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.69,\r\n      \"ProjectileResistance\": 0.69\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.72,\r\n      \"ProjectileResistance\": 0.72\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.75,\r\n      \"ProjectileResistance\": 0.75\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      6\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.78,\r\n      \"ProjectileResistance\": 0.78\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      7\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.81,\r\n      \"ProjectileResistance\": 0.81\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      8\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.84,\r\n      \"ProjectileResistance\": 0.84\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      9\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.87,\r\n      \"ProjectileResistance\": 0.87\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 9,\r\n    \"ActiveLevels\": [\r\n      10\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 0.9,\r\n      \"ProjectileResistance\": 0.9\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.02,\r\n      \"ProjectileResistance\": 1.05,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.04,\r\n      \"ProjectileResistance\": 1.1,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.06,\r\n      \"ProjectileResistance\": 1.15,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.08,\r\n      \"ProjectileResistance\": 1.2,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.10,\r\n      \"ProjectileResistance\": 1.25,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      6\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.12,\r\n      \"ProjectileResistance\": 1.3,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      7\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.14,\r\n      \"ProjectileResistance\": 1.35,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      8\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.16,\r\n      \"ProjectileResistance\": 1.4,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      9\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.18,\r\n      \"ProjectileResistance\": 1.45,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      10\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.2,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      11\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.22,\r\n      \"ProjectileResistance\": 1.55,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      12\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.24,\r\n      \"ProjectileResistance\": 1.6,\r\n      \"InfectionResistance\": 2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      13\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.26,\r\n      \"ProjectileResistance\": 1.65,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      14\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.28,\r\n      \"ProjectileResistance\": 1.7,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 11,\r\n    \"ActiveLevels\": [\r\n      15\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.3,\r\n      \"ProjectileResistance\": 1.75,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 16,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"ScannerRechargeSpeed\": 1.15,\r\n      \"SentryGunDamage\": 1.15,\r\n      \"GlueEfficiency\": 1.15,\r\n      \"TripMineDamage\": 1.15,\r\n      \"FogRepellerEffect\": 1.6,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 16,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"ScannerRechargeSpeed\": 1.3,\r\n      \"SentryGunDamage\": 1.3,\r\n      \"GlueEfficiency\": 1.3,\r\n      \"TripMineDamage\": 1.3,\r\n      \"FogRepellerEffect\": 2.2,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 16,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"ScannerRechargeSpeed\": 1.45,\r\n      \"SentryGunDamage\": 1.45,\r\n      \"GlueEfficiency\": 1.45,\r\n      \"TripMineDamage\": 1.45,\r\n      \"FogRepellerEffect\": 2.8,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 16,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"ScannerRechargeSpeed\": 1.6,\r\n      \"SentryGunDamage\": 1.6,\r\n      \"GlueEfficiency\": 1.6,\r\n      \"TripMineDamage\": 1.6,\r\n      \"FogRepellerEffect\": 3.4,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 16,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"ScannerRechargeSpeed\": 1.15,\r\n      \"SentryGunDamage\": 1.75,\r\n      \"GlueEfficiency\": 1.75,\r\n      \"TripMineDamage\": 1.75,\r\n      \"FogRepellerEffect\": 15.0,\r\n      \"InfectionResistance\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      1\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.1,\r\n      \"ScannerRechargeSpeed\": 1.05,\r\n      \"SentryGunDamage\": 1.05,\r\n      \"GlueEfficiency\": 1.05,\r\n      \"TripMineDamage\": 1.05,\r\n      \"ComputerProcessingSpeed\": 1.05,\r\n      \"FogRepellerEffect\": 1.05,\r\n      \"MeleeResistance\": 1.02,\r\n      \"ProjectileResistance\": 1.02,\r\n      \"InfectionResistance\": 1.02\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      2\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.2,\r\n      \"ScannerRechargeSpeed\": 1.1,\r\n      \"SentryGunDamage\": 1.1,\r\n      \"GlueEfficiency\": 1.1,\r\n      \"TripMineDamage\": 1.1,\r\n      \"ComputerProcessingSpeed\": 1.1,\r\n      \"FogRepellerEffect\": 1.1,\r\n      \"MeleeResistance\": 1.04,\r\n      \"ProjectileResistance\": 1.04,\r\n      \"InfectionResistance\": 1.04\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.3,\r\n      \"ScannerRechargeSpeed\": 1.15,\r\n      \"SentryGunDamage\": 1.15,\r\n      \"GlueEfficiency\": 1.15,\r\n      \"TripMineDamage\": 1.15,\r\n      \"ComputerProcessingSpeed\": 1.15,\r\n      \"FogRepellerEffect\": 1.15,\r\n      \"MeleeResistance\": 1.06,\r\n      \"ProjectileResistance\": 1.06,\r\n      \"InfectionResistance\": 1.06\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.4,\r\n      \"ScannerRechargeSpeed\": 1.2,\r\n      \"SentryGunDamage\": 1.2,\r\n      \"GlueEfficiency\": 1.2,\r\n      \"TripMineDamage\": 1.2,\r\n      \"ComputerProcessingSpeed\": 1.2,\r\n      \"FogRepellerEffect\": 1.2,\r\n      \"MeleeResistance\": 1.08,\r\n      \"ProjectileResistance\": 1.08,\r\n      \"InfectionResistance\": 1.08\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.5,\r\n      \"ScannerRechargeSpeed\": 1.25,\r\n      \"SentryGunDamage\": 1.25,\r\n      \"GlueEfficiency\": 1.25,\r\n      \"TripMineDamage\": 1.25,\r\n      \"ComputerProcessingSpeed\": 1.25,\r\n      \"FogRepellerEffect\": 1.25,\r\n      \"MeleeResistance\": 1.1,\r\n      \"ProjectileResistance\": 1.1,\r\n      \"InfectionResistance\": 1.1\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      6\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.6,\r\n      \"ScannerRechargeSpeed\": 1.3,\r\n      \"SentryGunDamage\": 1.3,\r\n      \"GlueEfficiency\": 1.3,\r\n      \"TripMineDamage\": 1.3,\r\n      \"ComputerProcessingSpeed\": 1.3,\r\n      \"FogRepellerEffect\": 1.3,\r\n      \"MeleeResistance\": 1.12,\r\n      \"ProjectileResistance\": 1.12,\r\n      \"InfectionResistance\": 1.12\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      7\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.7,\r\n      \"ScannerRechargeSpeed\": 1.35,\r\n      \"SentryGunDamage\": 1.35,\r\n      \"GlueEfficiency\": 1.35,\r\n      \"TripMineDamage\": 1.35,\r\n      \"ComputerProcessingSpeed\": 1.35,\r\n      \"FogRepellerEffect\": 1.35,\r\n      \"MeleeResistance\": 1.14,\r\n      \"ProjectileResistance\": 1.14,\r\n      \"InfectionResistance\": 1.14\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      8\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.8,\r\n      \"ScannerRechargeSpeed\": 1.4,\r\n      \"SentryGunDamage\": 1.4,\r\n      \"GlueEfficiency\": 1.4,\r\n      \"TripMineDamage\": 1.4,\r\n      \"ComputerProcessingSpeed\": 1.4,\r\n      \"FogRepellerEffect\": 1.4,\r\n      \"MeleeResistance\": 1.16,\r\n      \"ProjectileResistance\": 1.16,\r\n      \"InfectionResistance\": 1.16\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      9\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 1.9,\r\n      \"ScannerRechargeSpeed\": 1.45,\r\n      \"SentryGunDamage\": 1.45,\r\n      \"GlueEfficiency\": 1.45,\r\n      \"TripMineDamage\": 1.45,\r\n      \"ComputerProcessingSpeed\": 1.45,\r\n      \"FogRepellerEffect\": 1.45,\r\n      \"MeleeResistance\": 1.18,\r\n      \"ProjectileResistance\": 1.18,\r\n      \"InfectionResistance\": 1.18\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 13,\r\n    \"ActiveLevels\": [\r\n      10\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"HackingProficiency\": 2.0,\r\n      \"ScannerRechargeSpeed\": 1.5,\r\n      \"SentryGunDamage\": 1.5,\r\n      \"GlueEfficiency\": 1.5,\r\n      \"TripMineDamage\": 1.5,\r\n      \"ComputerProcessingSpeed\": 1.5,\r\n      \"FogRepellerEffect\": 1.5,\r\n      \"MeleeResistance\": 1.2,\r\n      \"ProjectileResistance\": 1.2,\r\n      \"InfectionResistance\": 1.2\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      3\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 1.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      4\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 1.5,\r\n      \"RegenerationSpeed\": 2.0,\r\n      \"RegenerationCap\": 2.0\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      5\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 1.5,\r\n      \"RegenerationSpeed\": 2.0,\r\n      \"RegenerationCap\": 2.0,\r\n      \"ComputerProcessingSpeed\": 999,\r\n      \"HackingProficiency\": 999.0,\r\n      \"ScannerRechargeSpeed\": 1.5,\r\n      \"SentryGunDamage\": 1.5,\r\n      \"GlueEfficiency\": 1.5,\r\n      \"TripMineDamage\": 1.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      6\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 1.5,\r\n      \"RegenerationSpeed\": 2.0,\r\n      \"RegenerationCap\": 2.0,\r\n      \"ComputerProcessingSpeed\": 999,\r\n      \"HackingProficiency\": 999.0,\r\n      \"ScannerRechargeSpeed\": 1.5,\r\n      \"SentryGunDamage\": 1.5,\r\n      \"GlueEfficiency\": 1.5,\r\n      \"TripMineDamage\": 1.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      7\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 1.5,\r\n      \"RegenerationSpeed\": 2.0,\r\n      \"RegenerationCap\": 2.0,\r\n      \"ComputerProcessingSpeed\": 999,\r\n      \"HackingProficiency\": 999.0,\r\n      \"ScannerRechargeSpeed\": 1.5,\r\n      \"SentryGunDamage\": 1.5,\r\n      \"GlueEfficiency\": 1.5,\r\n      \"TripMineDamage\": 1.5,\r\n      \"BioscanSpeed\": 1.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      8\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 1.5,\r\n      \"RegenerationSpeed\": 2.0,\r\n      \"RegenerationCap\": 2.0,\r\n      \"ComputerProcessingSpeed\": 999,\r\n      \"HackingProficiency\": 999.0,\r\n      \"ScannerRechargeSpeed\": 1.5,\r\n      \"SentryGunDamage\": 1.5,\r\n      \"GlueEfficiency\": 1.5,\r\n      \"TripMineDamage\": 1.5,\r\n      \"BioscanSpeed\": 1.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      9\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 2.0,\r\n      \"RegenerationSpeed\": 2.0,\r\n      \"RegenerationCap\": 2.0,\r\n      \"ComputerProcessingSpeed\": 999,\r\n      \"HackingProficiency\": 999.0,\r\n      \"ScannerRechargeSpeed\": 1.5,\r\n      \"SentryGunDamage\": 1.5,\r\n      \"GlueEfficiency\": 1.5,\r\n      \"TripMineDamage\": 1.5,\r\n      \"BioscanSpeed\": 1.5\r\n    }\r\n  },\r\n  {\r\n    \"ClassLayoutPersistentId\": 14,\r\n    \"ActiveLevels\": [\r\n      10\r\n    ],\r\n    \"ValueToBoosterEffects\": {\r\n      \"MeleeResistance\": 1.5,\r\n      \"ProjectileResistance\": 1.5,\r\n      \"InfectionResistance\": 2.0,\r\n      \"RegenerationSpeed\": 3.5,\r\n      \"RegenerationCap\": 2.0,\r\n      \"ComputerProcessingSpeed\": 999,\r\n      \"HackingProficiency\": 999.0,\r\n      \"ScannerRechargeSpeed\": 1.5,\r\n      \"SentryGunDamage\": 1.5,\r\n      \"GlueEfficiency\": 1.5,\r\n      \"TripMineDamage\": 1.5,\r\n      \"BioscanSpeed\": 1.5\r\n    }\r\n  }\r\n]\r\n";

		public const string Groups = "\r\n[\r\n  {\r\n    \"PersistentId\": 0,\r\n    \"VisibleForPlayerCount\": [\r\n      1,\r\n      2,\r\n      3,\r\n      4\r\n    ],\r\n    \"Name\": \"Combat\"\r\n  },\r\n  {\r\n    \"PersistentId\": 1,\r\n    \"VisibleForPlayerCount\": [\r\n      1,\r\n      2,\r\n      3,\r\n      4\r\n    ],\r\n    \"Name\": \"Survival\"\r\n  },\r\n  {\r\n    \"PersistentId\": 2,\r\n    \"VisibleForPlayerCount\": [\r\n      1,\r\n      2,\r\n      3,\r\n      4\r\n    ],\r\n    \"Name\": \"Utility\"\r\n  },\r\n  {\r\n    \"PersistentId\": 3,\r\n    \"VisibleForPlayerCount\": [\r\n      1\r\n    ],\r\n    \"Name\": \"Solo\"\r\n  }\r\n]\r\n";

		public const string ClassLayouts = "\r\n[\r\n  {\r\n    \"Header\": \"Generalist\",\r\n    \"GroupPersistentId\": 2,\r\n    \"PersistentId\": 13,\r\n    \"InfoText\": \"Good at everything, best at nothing.\\nMax LV 10 Bonus: Double Jump\\n\\nBonuses Each LV up:\\n+2% Damage\\n+2% Armor\\n+2% Infection Resist\\n+10% Hack Skill\\n-5% Terminal Delay\\n+5% Tool Power\\n+5% Repeller Power\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\\n1% Speed\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 100% -> 102%\\nArmor 100% -> 102%\\nInfect Res. 0% -> 2%\\nHacking 100% - > 110%\\nTerminal Delay 100% -> 95%\\nTool Power 100% -> 105%\\nRepeller 100% -> 105%\\nSpeed 100% -> 101%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.0,\r\n        \"WeaponDamageMultiplier\": 1.0,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 300,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 102% -> 104%\\nArmor 102% -> 104%\\nInfect Res. 2% -> 4%\\nHacking 110% - > 120%\\nTerminal Delay 95% -> 90%\\nTool Power 105% -> 110%\\nRepeller 105% -> 110%\\nSpeed 101% -> 102%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.02,\r\n        \"WeaponDamageMultiplier\": 1.02,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.01\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 800,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 104% -> 106%\\nArmor 104% -> 106%\\nInfect Res. 4% -> 6%\\nHacking 120% - > 130%\\nTerminal Delay 90% -> 85%\\nTool Power 110% -> 115%\\nRepeller 110% -> 115%\\nSpeed 102% -> 103%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.04,\r\n        \"WeaponDamageMultiplier\": 1.04,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.02\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 1450,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 106% -> 108%\\nArmor 106% -> 108%\\nInfect Res. 6% -> 8%\\nHacking 130% - > 140%\\nTerminal Delay 85% -> 80%\\nTool Power 115% -> 120%\\nRepeller 115% -> 120%\\nSpeed 103% -> 104%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.06,\r\n        \"WeaponDamageMultiplier\": 1.06,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.03\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 2200,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 108% -> 110%\\nArmor 108% -> 110%\\nInfect Res. 8% -> 10%\\nHacking 140% - > 150%\\nTerminal Delay 80% -> 75%\\nTool Power 120% > 125%\\nRepeller 120% -> 125%\\nSpeed 104% -> 105%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.08,\r\n        \"WeaponDamageMultiplier\": 1.08,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.04\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 3025,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 110% -> 112%\\nArmor 110% -> 112%\\nInfect Res. 10% -> 12%\\nHacking 150% -> 160%\\nTerminal Delay 75% -> 70%\\nTool Power 125% -> 130%\\nRepeller 125% -> 130%\\nSpeed 105% -> 106%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.1,\r\n        \"WeaponDamageMultiplier\": 1.1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.05\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 6,\r\n        \"TotalXpRequired\": 3975,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 112% -> 114%\\nArmor 112% -> 114%\\nInfect Res. 12% -> 14%\\nHacking 160% -> 170%\\nTerminal Delay 70% -> 65%\\nTool Power 130% -> 135%\\nRepeller 130% -> 135%\\nSpeed 106% -> 107%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.12,\r\n        \"WeaponDamageMultiplier\": 1.12,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.06\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 7,\r\n        \"TotalXpRequired\": 5100,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 114% -> 116%\\nArmor 114% -> 116%\\nInfect Res. 14% -> 16%\\nHacking 170% -> 180%\\nTerminal Delay 65% -> 60%\\nTool Power 135% -> 140%\\nRepeller 135% -> 140%\\nSpeed 107% -> 108%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.14,\r\n        \"WeaponDamageMultiplier\": 1.14,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.07\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 8,\r\n        \"TotalXpRequired\": 6300,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 116% -> 118%\\nArmor 116% -> 118%\\nInfect Res. 16% -> 18%\\nHacking 180% -> 190%\\nTerminal Delay 60% -> 55%\\nTool Power 140% -> 145%\\nRepeller 140% -> 145%\\nSpeed 108% -> 109%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.16,\r\n        \"WeaponDamageMultiplier\": 1.16,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.08\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 9,\r\n        \"TotalXpRequired\": 7575,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 118% -> 120%\\nArmor 118% -> 120%\\nInfect Res. 18% -> 20%\\nHacking 190% -> 200%\\nTerminal Delay 55% -> 50%\\nTool Power 145% -> 150%\\nRepeller 145% -> 150%\\nSpeed 109% -> 110%\\nJump -> Double Jump\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.18,\r\n        \"WeaponDamageMultiplier\": 1.18,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.09\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 10,\r\n        \"TotalXpRequired\": 8925,\r\n        \"CustomLevelUpPopupText\": \"MAX LV!\\n+Double Jump\\n2% Ammo Refill\\n2% Tool Refill\\n4% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Generalist\\n{0}\\nDamage 120%\\nArmor 120%\\nInfect Res. 20%\\nHacking 200%\\nTerminal Delay 50%\\nTool Power 150%\\nRepeller 150%\\nSpeed 110%\\nDouble Jump\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.2,\r\n        \"WeaponDamageMultiplier\": 1.2,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.1\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionTool\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.02\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.02\r\n          }\r\n        ]\r\n      }\r\n    ]\r\n  },\r\n  {\r\n    \"Header\": \"Soldier\",\r\n    \"GroupPersistentId\": 0,\r\n    \"PersistentId\": 2,\r\n    \"InfoText\": \"Specialized in ranged combat. Stronger guns with ammo refunds on each level up.\\nMax LV 10 bonus: +35% HP Regen Speed\\n\\nBonuses Each LV up:\\n+4% Gun Damage\\n+4% Ammo Refill\\n\\nBonus Each 5 LVs:\\n+6% Ammo Refill\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 100% -> 104%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 100,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 104% -> 108%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.04,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 108% -> 112%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.08,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 1200,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 112% -> 116%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.12,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 1900,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 116% -> 120%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.16,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 2700,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n10% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 120% -> 124%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.2,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.1\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 6,\r\n        \"TotalXpRequired\": 3600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 124% -> 128%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.24,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 7,\r\n        \"TotalXpRequired\": 4600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 128% -> 132%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.28,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 8,\r\n        \"TotalXpRequired\": 5700,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 132% -> 136%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.32,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 9,\r\n        \"TotalXpRequired\": 6900,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +4%\\n4% Ammo Refill\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 136% -> 140%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.36,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.04\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.04\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 10,\r\n        \"TotalXpRequired\": 8200,\r\n        \"CustomLevelUpPopupText\": \"MAX LV!\\nGun Damage +4%\\n10% Ammo Refill\\nRegen Speed +35%\",\r\n        \"CustomLevelStatsText\": \"Class: Soldier\\n{0}\\nGun Damage 140%\\nRegen Speed 135%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.4,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"AmmunitionMain\",\r\n            \"Value\": 0.1\r\n          },\r\n          {\r\n            \"SingleBuff\": \"AmmunitionSpecial\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      }\r\n    ]\r\n  },\r\n  {\r\n    \"Header\": \"Marine\",\r\n    \"GroupPersistentId\": 0,\r\n    \"PersistentId\": 9,\r\n    \"InfoText\": \"Specialized in ranged combat. Powerful weapons but with poor Armor.\\n<color=red>Starting Debuff: -40% Armor</color>\\nMax LV 10\\n\\nBonuses Each LV up:\\n+8% Gun Damage\\n+3% Armor\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 100% -> 108%\\nArmor 60% -> 63%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 85,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 108% -> 116%\\nArmor 63% -> 66%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.08,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 510,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 116% -> 124%\\nArmor 66% -> 69%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.16,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 1020,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 124% -> 132%\\nArmor 69% -> 72%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.24,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 1615,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 132% -> 140%\\nArmor 72% -> 75%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.32,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 2295,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 140% -> 148%\\nArmor 75% -> 78%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.4,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 6,\r\n        \"TotalXpRequired\": 3060,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 148% -> 156%\\nArmor 78% -> 81%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.48,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 7,\r\n        \"TotalXpRequired\": 3910,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 156% -> 164%\\nArmor 81% -> 84%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.56,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 8,\r\n        \"TotalXpRequired\": 4845,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 164% -> 172%\\nArmor 84% -> 87%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.64,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 9,\r\n        \"TotalXpRequired\": 5865,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 172% -> 180%\\nArmor 87% -> 90%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.72,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 10,\r\n        \"TotalXpRequired\": 6970,\r\n        \"CustomLevelUpPopupText\": \"MAX LV!\\nGun Damage +8%\\nArmor +3%\",\r\n        \"CustomLevelStatsText\": \"Class: Marine\\n{0}\\nGun Damage 180%\\nArmor 90%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1.8,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      }\r\n    ]\r\n  },\r\n  {\r\n    \"Header\": \"Hunter\",\r\n    \"GroupPersistentId\": 0,\r\n    \"PersistentId\": 7,\r\n    \"InfoText\": \"Specialized in melee combat. Deal high melee damage while gaining light Armor for survivability.\\nMax LV 5 bonus: Double Jump\\nLV 1 bonus: 125% Melee Damage\\n\\nBonuses Each LV up:\\n+4% Armor\\n+4% Speed\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Hunter\\n{0}\\nMelee 100% -> 225%\\nArmor 100% -> 104%\\nSpeed 100% -> 104%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.0,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 450,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee +125%\\nArmor +4%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Hunter\\n{0}\\nMelee 225%\\nArmor 104% -> 108%\\nSpeed 104% -> 108%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 2.25,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.04\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 1150,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +4%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Hunter\\n{0}\\nMelee 225%\\nArmor 108% -> 112%\\nSpeed 108% -> 112%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 2.25,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.08\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 2200,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +4%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Hunter\\n{0}\\nMelee 225%\\nArmor 112% -> 116%\\nSpeed 112% -> 116%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 2.25,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.2\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 3700,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +4%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Hunter\\n{0}\\nMelee 225%\\nArmor 116% -> 120%\\nSpeed 116% -> 120%\\nJump -> Double Jump\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 2.25,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.16\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 5650,\r\n        \"CustomLevelUpPopupText\": \"MAX LV!\\nArmor +4%\\nSpeed +4%\\n+Double Jump\",\r\n        \"CustomLevelStatsText\": \"Class: Hunter\\n{0}\\nMelee 225%\\nArmor 120%\\nSpeed 120%\\nDouble Jump\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 2.25,\r\n        \"WeaponDamageMultiplier\": 1.0,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.2\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      }\r\n    ]\r\n  },\r\n  {\r\n    \"Header\": \"Assassin\",\r\n    \"GroupPersistentId\": 0,\r\n    \"PersistentId\": 8,\r\n    \"InfoText\": \"Specialized in melee combat. Devastating in stealth and combat but with very poor survivability.\\n<color=red>Starting Debuff: -45% Armor</color>\\nMax LV 5 bonus: Double Jump\\nLV 1 bonus: 215% Melee Damage\\n\\nBonuses Each LV up:\\n+5% Armor\\n+4% Speed\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Assassin\\n{0}\\nMelee 100% -> 315%\\nArmor 55% -> 60%\\nSpeed 100% -> 104%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.0,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.0\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 450,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee +215%\\nArmor +5%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Assassin\\n{0}\\nMelee 315%\\nArmor 60% -> 65%\\nSpeed 104% -> 108%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 3.15,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.04\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 1150,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +5%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Assassin\\n{0}\\nMelee 315%\\nArmor 65% -> 70%\\nSpeed 108% -> 112%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 3.15,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.08\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 2200,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +5%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Assassin\\n{0}\\nMelee 315%\\nArmor 70% -> 75%\\nSpeed 112% -> 116%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 3.15,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.12\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 3700,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +5%\\nSpeed +4%\",\r\n        \"CustomLevelStatsText\": \"Class: Assassin\\n{0}\\nMelee 315%\\nArmor 75% -> 80%\\nSpeed 116% -> 120%\\nJump -> Double Jump\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 3.15,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.16\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 5650,\r\n        \"CustomLevelUpPopupText\": \"MAX LV!\\nArmor +5%\\nSpeed +4%\\n+Double Jump\",\r\n        \"CustomLevelStatsText\": \"Class: Assassin\\n{0}\\nMelee 315%\\nArmor 80%\\nSpeed 120%\\nDouble Jump\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 3.15,\r\n        \"WeaponDamageMultiplier\": 1.0,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.2\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      }\r\n    ]\r\n  },\r\n  {\r\n    \"Header\": \"Fighter\",\r\n    \"GroupPersistentId\": 0,\r\n    \"PersistentId\": 10,\r\n    \"InfoText\": \"Specialized in general combat. Improved damage with all guns and melee.\\nMax LV 10\\n\\nBonuses Each LV up:\\n+3% Gun Damage\\n+6% Melee Damage\\n+1% Speed\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 100% -> 103%\\nMelee Damage 100% -> 106%\\nSpeed 100% -> 101%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 100,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +6%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 103% -> 106%\\nMelee Damage 106% -> 112%\\nSpeed 101% -> 102%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.06,\r\n        \"WeaponDamageMultiplier\": 1.03,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.01\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 106% -> 109%\\nMelee Damage 112% -> 118%\\nSpeed 102% -> 103%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.12,\r\n        \"WeaponDamageMultiplier\": 1.06,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.02\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 1200,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 109% -> 112%\\nMelee Damage 118% -> 124%\\nSpeed 103% -> 104%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.18,\r\n        \"WeaponDamageMultiplier\": 1.09,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.03\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 1900,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 112% -> 115%\\nMelee Damage 124% -> 130%\\nSpeed 104% -> 105%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.24,\r\n        \"WeaponDamageMultiplier\": 1.12,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.04\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 2700,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 115% -> 118%\\nMelee Damage 130% -> 136%\\nSpeed 105% -> 106%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.3,\r\n        \"WeaponDamageMultiplier\": 1.15,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.05\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 6,\r\n        \"TotalXpRequired\": 3600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 118% -> 121%\\nMelee Damage 136% -> 142%\\nSpeed 106% -> 107%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.36,\r\n        \"WeaponDamageMultiplier\": 1.18,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.06\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 7,\r\n        \"TotalXpRequired\": 4600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 121% -> 124%\\nMelee Damage 142% -> 148%\\nSpeed 107% -> 108%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.42,\r\n        \"WeaponDamageMultiplier\": 1.21,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.07\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 8,\r\n        \"TotalXpRequired\": 5700,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 124% -> 127%\\nMelee Damage 148% -> 154%\\nSpeed 108% -> 109%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.48,\r\n        \"WeaponDamageMultiplier\": 1.24,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.08\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 9,\r\n        \"TotalXpRequired\": 6900,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 127% -> 130%\\nMelee Damage 154% -> 160%\\nSpeed 109% -> 110%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.54,\r\n        \"WeaponDamageMultiplier\": 1.27,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.09\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 10,\r\n        \"TotalXpRequired\": 8200,\r\n        \"CustomLevelUpPopupText\": \"MAX LV!\\nGun Damage +3%\\nMelee Damage +7%\\nSpeed +1%\",\r\n        \"CustomLevelStatsText\": \"Class: Fighter\\n{0}\\nGun Damage 130%\\nMelee Damage 160%\\nSpeed 110%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1.6,\r\n        \"WeaponDamageMultiplier\": 1.3,\r\n        \"CustomScaling\": [\r\n          {\r\n            \"CustomBuff\": \"MovementSpeedMultiplier\",\r\n            \"Value\": 1.1\r\n          }\r\n        ],\r\n        \"LevelUpBonus\": []\r\n      }\r\n    ]\r\n  },\r\n  {\r\n    \"Header\": \"Survivalist\",\r\n    \"GroupPersistentId\": 1,\r\n    \"PersistentId\": 3,\r\n    \"InfoText\": \"Increased odds of survival in extreme conditions. Endure any scenario.\\nMax LV 15 bonus: Infect Immune\\n\\nBonuses Each LV up:\\n+3% Armor\\n+3% Infect Resist\\n10% Heal\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 100% -> 103%\\nInfect Res. 0% -> 3%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 100,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 103% -> 106%\\nInfect Res. 0% -> 3%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 106% -> 109%\\nInfect Res. 3% -> 6%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 1200,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 109% -> 112%\\nInfect Res. 6% -> 9%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 1850,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 112% -> 115%\\nInfect Res. 9% -> 12%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 2550,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n20% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 115% -> 118%\\nInfect Res. 12% -> 15%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.2\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 6,\r\n        \"TotalXpRequired\": 3300,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 118% -> 121%\\nInfect Res. 15% -> 18%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 7,\r\n        \"TotalXpRequired\": 4100,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 121% -> 124%\\nInfect Res. 18% -> 21%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 8,\r\n        \"TotalXpRequired\": 4950,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 124% -> 127%\\nInfect Res. 21% -> 24%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 9,\r\n        \"TotalXpRequired\": 5850,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 127% -> 130%\\nInfect Res. 24% -> 27%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 10,\r\n        \"TotalXpRequired\": 6850,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n20% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 130% -> 133%\\nInfect Res. 27% -> 30%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.2\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 11,\r\n        \"TotalXpRequired\": 7950,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 133% -> 136%\\nInfect Res. 30% -> 33%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 12,\r\n        \"TotalXpRequired\": 9150,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 136% -> 139%\\nInfect Res. 33% -> 36%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 13,\r\n        \"TotalXpRequired\": 10450,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 139% -> 142%\\nInfect Res. 36% -> 39%\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 14,\r\n        \"TotalXpRequired\": 11850,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nArmor +3%\\nInfection Res. +3%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 142% -> 145%\\nInfect Res. 39% -> Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 15,\r\n        \"TotalXpRequired\": 13350,\r\n        \"CustomLevelUpPopupText\": \"MAX LV!\\nArmor +3%\\nInfection Res. +61%\\n20% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Survivalist\\n{0}\\nArmor 145%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.2\r\n          }\r\n        ]\r\n      }\r\n    ]\r\n  },\r\n  {\r\n    \"Header\": \"Outlander\",\r\n    \"GroupPersistentId\": 1,\r\n    \"PersistentId\": 11,\r\n    \"InfoText\": \"Specialized for surviving on the run. Greatly improved Projectile Armor and Infect Resist.\\nMax LV 15\\nLV 1 bonus: Infect Immune\\n\\nBonuses Each LV up:\\n+2% Melee Armor\\n+5% Projectile Armor\\n10% Heal\",\r\n    \"Levels\": [\r\n      {\r\n        \"LevelNumber\": 0,\r\n        \"TotalXpRequired\": 0,\r\n        \"CustomLevelUpPopupText\": null,\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 100% -> 102%\\nProjectile Armor 100% -> 105%\\nInfect Res. 0% -> Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": []\r\n      },\r\n      {\r\n        \"LevelNumber\": 1,\r\n        \"TotalXpRequired\": 100,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 102% -> 104%\\nProjectile Armor 105% -> 110%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 2,\r\n        \"TotalXpRequired\": 600,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 104% -> 106%\\nProjectile Armor 110% -> 115%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 3,\r\n        \"TotalXpRequired\": 1200,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 106% -> 108%\\nProjectile Armor 115% -> 120%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 4,\r\n        \"TotalXpRequired\": 1850,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 108% -> 110%\\nProjectile Armor 120% -> 125%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 5,\r\n        \"TotalXpRequired\": 2550,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n20% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 110% -> 112%\\nProjectile Armor 125% -> 130%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.2\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 6,\r\n        \"TotalXpRequired\": 3300,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 112% -> 114%\\nProjectile Armor 130% -> 135%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 7,\r\n        \"TotalXpRequired\": 4100,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 114% -> 116%\\nProjectile Armor 135% -> 140%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 8,\r\n        \"TotalXpRequired\": 4950,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 116% -> 118%\\nProjectile Armor 140% -> 145%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 9,\r\n        \"TotalXpRequired\": 5850,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 118% -> 120%\\nProjectile Armor 145% -> 150%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 10,\r\n        \"TotalXpRequired\": 6850,        \r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n20% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 120% -> 122%\\nProjectile Armor 150% -> 155%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.2\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 11,\r\n        \"TotalXpRequired\": 7950,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 122% -> 124%\\nProjectile Armor 155% -> 160%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 12,\r\n        \"TotalXpRequired\": 9150,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 124% -> 126%\\nProjectile Armor 160% -> 165%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 13,\r\n        \"TotalXpRequired\": 10450,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \"Class: Outlander\\n{0}\\nMelee Armor 126% -> 128%\\nProjectile Armor 165% -> 170%\\nInfect Immune\",\r\n        \"HealthMultiplier\": 1,\r\n        \"MeleeDamageMultiplier\": 1,\r\n        \"WeaponDamageMultiplier\": 1,\r\n        \"CustomScaling\": [],\r\n        \"LevelUpBonus\": [\r\n          {\r\n            \"SingleBuff\": \"Heal\",\r\n            \"Value\": 0.1\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        \"LevelNumber\": 14,\r\n        \"TotalXpRequired\": 11850,\r\n        \"CustomLevelUpPopupText\": \"Lv Up!\\nMelee Armor +2%\\nProjectile Armor +5%\\n10% Heal\",\r\n        \"CustomLevelStatsText\": \