Decompiled source of Simple Progression v2026.1.0

plugins/SimpleProgression.dll

Decompiled a day ago
using System;
using System.Collections;
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 AssetShards;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BoosterImplants;
using CellMenu;
using Clonesoft.Json;
using DropServer;
using DropServer.BoosterImplants;
using DropServer.VanityItems;
using GameData;
using Globals;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Threading.Tasks;
using Microsoft.CodeAnalysis;
using PlayFab.ClientModels;
using SimpleProgression.Core;
using SimpleProgression.Impl;
using SimpleProgression.Interfaces;
using SimpleProgression.Models;
using SimpleProgression.Models.Boosters;
using SimpleProgression.Models.Progression;
using SimpleProgression.Models.Vanity;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("2026.1.0")]
[assembly: AssemblyInformationalVersion("2026.1.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("2026.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal class ManifestInfo
{
	internal const string TSName = "Simple_Progression";

	internal const string TSDescription = "A LocalProgression implementation, including local vanity item and booster drops.";

	internal const string TSVersion = "2026.1.0";

	internal const string TSAuthor = "AuriRex";

	internal const string TSWebsite = "https://github.com/AuriRex/GTFO_SimpleProgression";
}
namespace SimpleProgression
{
	public static class Extensions
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass1_0
		{
			public uint item;

			internal bool <GetNonOwned>b__0(LocalVanityItemStorage.LocalVanityItem i)
			{
				return i.ItemID != item;
			}
		}

		[CompilerGenerated]
		private sealed class <GetNonOwned>d__1 : IEnumerable<uint>, IEnumerable, IEnumerator<uint>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private uint <>2__current;

			private int <>l__initialThreadId;

			private VanityItemsGroupDataBlock self;

			public VanityItemsGroupDataBlock <>3__self;

			private LocalVanityItemStorage playerData;

			public LocalVanityItemStorage <>3__playerData;

			private Enumerator<uint> <>7__wrap1;

			uint IEnumerator<uint>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetNonOwned>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>7__wrap1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>7__wrap1 = self.Items.GetEnumerator();
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				while (<>7__wrap1.MoveNext())
				{
					<>c__DisplayClass1_0 CS$<>8__locals0 = new <>c__DisplayClass1_0
					{
						item = <>7__wrap1.Current
					};
					if (playerData.Items.All((LocalVanityItemStorage.LocalVanityItem i) => i.ItemID != CS$<>8__locals0.item))
					{
						<>2__current = CS$<>8__locals0.item;
						<>1__state = 1;
						return true;
					}
				}
				<>7__wrap1 = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<uint> IEnumerable<uint>.GetEnumerator()
			{
				<GetNonOwned>d__1 <GetNonOwned>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetNonOwned>d__ = this;
				}
				else
				{
					<GetNonOwned>d__ = new <GetNonOwned>d__1(0);
				}
				<GetNonOwned>d__.self = <>3__self;
				<GetNonOwned>d__.playerData = <>3__playerData;
				return <GetNonOwned>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<uint>)this).GetEnumerator();
			}
		}

		public static bool TryPickRandom<T>(this IEnumerable<T> enumerable, out T value)
		{
			T[] array = enumerable.ToArray();
			if (array.Length == 0)
			{
				value = default(T);
				return false;
			}
			value = array[Random.Range(0, array.Length)];
			return true;
		}

		[IteratorStateMachine(typeof(<GetNonOwned>d__1))]
		public static IEnumerable<uint> GetNonOwned(this VanityItemsGroupDataBlock self, LocalVanityItemStorage playerData)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetNonOwned>d__1(-2)
			{
				<>3__self = self,
				<>3__playerData = playerData
			};
		}

		public static bool HasAllOwned(this VanityItemsGroupDataBlock self, LocalVanityItemStorage playerData)
		{
			Enumerator<uint> enumerator = self.Items.GetEnumerator();
			while (enumerator.MoveNext())
			{
				uint itemId = enumerator.Current;
				if (playerData.Items.All((LocalVanityItemStorage.LocalVanityItem i) => i.ItemID != itemId))
				{
					return false;
				}
			}
			return true;
		}
	}
	public class Logger : ILogger
	{
		private readonly ManualLogSource _log;

		public Logger(ManualLogSource logger)
		{
			_log = logger;
		}

		public void Debug(string msg)
		{
			_log.LogDebug((object)msg);
		}

		public void Error(string msg)
		{
			_log.LogError((object)msg);
		}

		public void Exception(Exception ex)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			ManualLogSource log = _log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(3, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetType().Name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\n");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.StackTrace);
			}
			log.LogError(val);
		}

		public void Fail(string msg)
		{
			_log.LogError((object)msg);
		}

		public void Info(string msg)
		{
			_log.LogMessage((object)msg);
		}

		public void Msg(ConsoleColor col, string msg)
		{
			_log.LogMessage((object)msg);
		}

		public void Notice(string msg)
		{
			_log.LogWarning((object)msg);
		}

		public void Success(string msg)
		{
			_log.LogMessage((object)msg);
		}

		public void Warning(string msg)
		{
			_log.LogWarning((object)msg);
		}
	}
	public static class Paths
	{
		private static string _saveFolderPath;

		private static string _vanityItemsLayerDropsPath;

		private static string _vanityItemsFilePath;

		private static string _vanityUnlockGroupsFilePath;

		private static string _vanityFolderPath;

		private static string _boostersPath;

		private static string _titleDataPath;

		public static string SaveFolderPath
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_saveFolderPath))
				{
					_saveFolderPath = Path.Combine(Paths.BepInExRootPath, "LocalProgression/");
					Directory.CreateDirectory(_saveFolderPath);
				}
				return _saveFolderPath;
			}
		}

		public static string VanityItemsLayerDropsPath
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_vanityItemsLayerDropsPath))
				{
					_vanityItemsLayerDropsPath = Path.Combine(VanityFolderPath, "VanityLayerDrops.json");
				}
				return _vanityItemsLayerDropsPath;
			}
		}

		public static string VanityItemsFilePath
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_vanityItemsFilePath))
				{
					_vanityItemsFilePath = Path.Combine(VanityFolderPath, "VanityData.json");
				}
				return _vanityItemsFilePath;
			}
		}

		public static string VanityUnlockGroupsFilePath
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_vanityUnlockGroupsFilePath))
				{
					_vanityUnlockGroupsFilePath = Path.Combine(Paths.ConfigPath, "SimpleProgression_VanityGroupUnlockData.json");
				}
				return _vanityUnlockGroupsFilePath;
			}
		}

		public static string VanityFolderPath
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_vanityFolderPath))
				{
					_vanityFolderPath = Path.Combine(SaveFolderPath, "Vanity/");
					Directory.CreateDirectory(_vanityFolderPath);
				}
				return _vanityFolderPath;
			}
		}

		public static string BoostersFilePath
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_boostersPath))
				{
					string text = Path.Combine(SaveFolderPath, "Boosters/");
					Directory.CreateDirectory(text);
					_boostersPath = Path.Combine(text, "BoosterData.json");
				}
				return _boostersPath;
			}
		}

		public static string LocalTitleDataFolderPath
		{
			get
			{
				if (string.IsNullOrWhiteSpace(_titleDataPath))
				{
					_titleDataPath = Path.Combine(SaveFolderPath, "TitleData/");
					Directory.CreateDirectory(_titleDataPath);
				}
				return _titleDataPath;
			}
		}
	}
	[BepInPlugin("dev.aurirex.gtfo.simpleprogression", "Simple_Progression", "2026.1.0")]
	public class Plugin : BasePlugin
	{
		public const string ALLVANITY_GUID = "dev.aurirex.gtfo.allvanity";

		public const string GUID = "dev.aurirex.gtfo.simpleprogression";

		public const string MOD_NAME = "Simple_Progression";

		public const string VERSION = "2026.1.0";

		internal static Logger L;

		private static readonly Harmony _harmony = new Harmony("dev.aurirex.gtfo.simpleprogression");

		private const string CONFIG_FILE_NAME = "SimpleProgression_Config.json";

		internal static SPConfig SPConfig = new SPConfig();

		internal static bool IsAllVanityLoaded => ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.Any((KeyValuePair<string, PluginInfo> kvp) => string.Equals(kvp.Key, "dev.aurirex.gtfo.allvanity", StringComparison.InvariantCultureIgnoreCase));

		public override void Load()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			L = new Logger(((BasePlugin)this).Log);
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExMessageLogInterpolatedStringHandler val = new BepInExMessageLogInterpolatedStringHandler(13, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Initializing ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Simple_Progression");
			}
			log.LogMessage(val);
			LoadConfig();
			RegisterTypeOptions val2 = new RegisterTypeOptions();
			val2.set_Interfaces(Il2CppInterfaceCollection.op_Implicit(new Type[1] { typeof(IDropServerClientAPI) }));
			val2.set_LogSuccess(true);
			ClassInjector.RegisterTypeInIl2Cpp<LocalDropServerAPI>(val2);
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
		}

		private void LoadConfig()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			try
			{
				string path = Path.Combine(Paths.ConfigPath, "SimpleProgression_Config.json");
				if (File.Exists(path))
				{
					SPConfig = JsonConvert.DeserializeObject<SPConfig>(File.ReadAllText(path));
					return;
				}
				string contents = JsonConvert.SerializeObject((object)new SPConfig(), (Formatting)1);
				File.WriteAllText(path, contents);
			}
			catch (Exception ex)
			{
				ManualLogSource log = ((BasePlugin)this).Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(35, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error while loading config file: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.GetType().FullName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogError(val);
				ManualLogSource log2 = ((BasePlugin)this).Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(12, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("StackTrace:\n");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.StackTrace);
				}
				log2.LogWarning(val2);
				SPConfig = new SPConfig();
			}
		}

		internal static void OnDataBlocksReady()
		{
			if (SPConfig.UnlockAllLevels)
			{
				Global.AllowFullRundown = true;
			}
			int maxBoosterCountPerCategory = (int)SPConfig.MaxBoosterCountPerCategory;
			for (int i = 0; i < 3; i++)
			{
				((Il2CppArrayBase<int>)(object)BoosterImplantConstants.InventoryLimitPerCategory)[i] = maxBoosterCountPerCategory;
				((Il2CppArrayBase<float>)(object)BoosterImplantConstants.ARTIFACT_TO_BOOSTER_RATIO_FOR_FULL_HEAT)[i] = 0.15f;
			}
			try
			{
				LocalVanityItemDropper.Instance.Init();
				LocalBoosterDropper.Instance.Init();
			}
			catch (Exception ex)
			{
				L.Exception(ex);
			}
		}
	}
}
namespace SimpleProgression.Patches
{
	[HarmonyPatch(typeof(Achievement_ReadAllLogs), "CheckCompletion")]
	public static class Achievement_ReadAllLogs__CheckCompletion__Patch
	{
		public static bool Prefix(Achievement_ReadAllLogs __instance)
		{
			if (__instance.m_allLogs.Count != Achievement_ReadAllLogs.TOTAL_LOGS_FOR_ACHIEVEMENT)
			{
				return false;
			}
			if (SteamManager.Current.GetAchievement(((AchievementTask)__instance).AchievementKey))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(ArtifactInventory), "OnStateChange")]
	public static class ArtifactInventory__OnStateChange__Patch
	{
		public static void Postfix(ArtifactInventory __instance)
		{
			LocalProgressionManager.Instance.ArtifactCountUpdated(__instance.CommonCount, __instance.UncommonCount, __instance.RareCount);
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(AssetShardManager), "Setup")]
	internal class AssetShardManager__Setup__Patch
	{
		[HarmonyPriority(0)]
		public static void Postfix()
		{
			Plugin.OnDataBlocksReady();
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(CheckpointManager), "StoreCheckpoint")]
	public class CheckpointManager__StoreCheckpoint__Patch
	{
		public static void Prefix()
		{
			LocalProgressionManager.Instance.SaveAtCheckpoint();
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(CheckpointManager), "ReloadCheckpoint")]
	public class CheckpointManager__ReloadCheckpoint__Patch
	{
		public static void Prefix()
		{
			LocalProgressionManager.Instance.ReloadFromCheckpoint();
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(DropServerManager), "OnTitleDataUpdated")]
	internal class DropServerManager__OnTitleDataUpdated__Patch
	{
		public static bool Prefix(DropServerManager __instance)
		{
			__instance.ClientApi = ((Il2CppObjectBase)new LocalDropServerAPI()).TryCast<IDropServerClientAPI>();
			return false;
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(DropServerManager), "GetStatusText")]
	internal class DropServerManager__GetStatusText__Patch
	{
		public static bool Prefix(DropServerManager __instance, ref string __result)
		{
			if (!__instance.IsBusy)
			{
				__result = null;
				return false;
			}
			__result = "STORAGE SYNC";
			return false;
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(GameDataInit), "Initialize")]
	public class GameDataInit__Initialize__Patch
	{
		private static bool _first = true;

		public static void Postfix()
		{
			if (_first)
			{
				_first = false;
				return;
			}
			Plugin.L.Warning("MTFO Hot-Relead triggered, reloading templates, groups and drop data ...");
			try
			{
				LocalVanityItemDropper.Instance.LoadTemplatesGroupsAndDropData();
				LocalBoosterDropper.Instance.Load();
			}
			catch (Exception ex)
			{
				Plugin.L.Exception(ex);
			}
		}
	}
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(GS_InLevel), "Enter")]
	public class GS_InLevel__Enter__Patch
	{
		public static void Postfix()
		{
			LocalProgressionManager.Instance.OnLevelEntered();
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "TryGetRundownTimerData")]
	internal static class PlayFabManager__TryGetRundownTimerData__Patch
	{
		public static bool Prefix(ref bool __result, out RundownTimerData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			data = new RundownTimerData();
			data.ShowScrambledTimer = Plugin.SPConfig.ShowScrambledTimer;
			data.ShowCountdownTimer = Plugin.SPConfig.ShowScrambledTimer;
			DateTime dateTime = DateTime.Today.AddDays(20.0);
			data.UTC_Target_Day = dateTime.Day;
			data.UTC_Target_Hour = dateTime.Hour;
			data.UTC_Target_Minute = dateTime.Minute;
			data.UTC_Target_Month = dateTime.Month;
			data.UTC_Target_Year = dateTime.Year;
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "TryGetStartupScreenData")]
	internal static class PlayFabManager__TryGetStartupScreenData__Patch
	{
		public static bool Prefix(ref bool __result, out StartupScreenData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			data = new StartupScreenData();
			data.AllowedToStartGame = true;
			data.ShowOvertoneButton = false;
			data.IntroText = "Startup Override :)";
			data.ShowBugReportButton = false;
			data.ShowIntroText = false;
			data.ShowRoadmapButton = false;
			data.ShowDiscordButton = false;
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "OnGetAuthSessionTicketResponse")]
	internal static class PlayFabManager__OnGetAuthSessionTicketResponse__Patch
	{
		public static string PLAYFAB_ID = "idk_lol";

		private static string _entityId;

		private static string _entityToken;

		public static string EntityID => _entityId ?? (_entityId = "Player_" + new Random().Next(int.MinValue, int.MaxValue));

		public static string EntityToken => _entityToken ?? (_entityToken = "EntityToken_" + new Random().Next(int.MinValue, int.MaxValue));

		public static bool Prefix()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			Plugin.L.Notice("Tricking the game into thinking we're logged in ...");
			PlayFabManager current = PlayFabManager.Current;
			current.m_globalTitleDataLoaded = true;
			current.m_playerDataLoaded = true;
			current.m_entityId = EntityID;
			current.m_entityType = "Player";
			current.m_entityToken = EntityToken;
			current.m_entityLoggedIn = true;
			current.m_globalTitleData = new Dictionary<string, string>();
			PlayFabManager.PlayFabId = PLAYFAB_ID;
			PlayFabManager.LoggedInDateTime = default(DateTime);
			PlayFabManager.LoggedInSeconds = Clock.Time;
			PlayFabFilesManager.OnLoggedIn();
			PlayFabManager.GlobalTitleData["DropServer"] = "https://localhost:12345";
			Action onLoginSuccess = PlayFabManager.OnLoginSuccess;
			if (onLoginSuccess != null)
			{
				onLoginSuccess.Invoke();
			}
			Action onTitleDataUpdated = PlayFabManager.OnTitleDataUpdated;
			if (onTitleDataUpdated != null)
			{
				onTitleDataUpdated.Invoke();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "GetEntityTokenAsync")]
	internal static class PlayFabManager__GetEntityTokenAsync__Patch
	{
		public static bool Prefix(ref Task<string> __result)
		{
			__result = Task.FromResult<string>(PlayFabManager__OnGetAuthSessionTicketResponse__Patch.EntityToken);
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "RefreshGlobalTitleDataForKeys")]
	internal static class PlayFabManager__RefreshGlobalTitleDataForKeys_Patch
	{
		public static bool Prefix(List<string> keys, Action OnSuccess)
		{
			if (keys != null)
			{
				Enumerator<string> enumerator = keys.GetEnumerator();
				while (enumerator.MoveNext())
				{
					string current = enumerator.Current;
					Plugin.L.Msg(ConsoleColor.DarkYellow, "RefreshGlobalTitleDataForKeys -> Key:" + current);
				}
			}
			if (OnSuccess != null)
			{
				OnSuccess.Invoke();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "AddToOrUpdateLocalPlayerTitleData", new Type[]
	{
		typeof(string),
		typeof(string),
		typeof(Action)
	})]
	internal static class PlayFabManager__AddToOrUpdateLocalPlayerTitleData__Patch
	{
		public static bool Prefix(string key, string value, Action OnSuccess)
		{
			Plugin.L.Debug("Canceled AddToOrUpdateLocalPlayerTitleData: Key:" + key + " - Value:" + value);
			PlayFabFilesManager.UpdateLocalPlayerTitleData(key, value);
			if (OnSuccess != null)
			{
				OnSuccess.Invoke();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "AddToOrUpdateLocalPlayerTitleData", new Type[]
	{
		typeof(Dictionary<string, string>),
		typeof(Action)
	})]
	internal static class PlayFabManager__AddToOrUpdateLocalPlayerTitleDataOverload__Patch
	{
		public static bool Prefix(Dictionary<string, string> keys, Action OnSuccess)
		{
			Plugin.L.Debug($"Canceled AddToOrUpdateLocalPlayerTitleData(OverloadMethod): Count:{keys?.Count}");
			if (keys != null)
			{
				Enumerator<string, string> enumerator = keys.GetEnumerator();
				while (enumerator.MoveNext())
				{
					KeyValuePair<string, string> current = enumerator.Current;
					PlayFabFilesManager.UpdateLocalPlayerTitleData(current.Key, current.Value);
				}
			}
			if (OnSuccess != null)
			{
				OnSuccess.Invoke();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "CloudGiveAlwaysInInventory")]
	internal static class PlayFabManager__CloudGiveAlwaysInInventory__Patch
	{
		public static bool Prefix(Action onSucess)
		{
			return PlayFabFilesManager.SkipOriginalAndInvoke(onSucess);
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "CloudGiveItemToLocalPlayer")]
	internal static class PlayFabManager__CloudGiveItemToLocalPlayer__Patch
	{
		public static bool Prefix(string ItemId, Action onSucess)
		{
			return PlayFabFilesManager.SkipOriginalAndInvoke(onSucess);
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "JSONTest")]
	internal static class PlayFabManager__JSONTest__Patch
	{
		public static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "RefreshItemCatalog")]
	internal static class PlayFabManager__RefreshItemCatalog__Patch
	{
		public static bool Prefix(delUpdateItemCatalogDone OnSuccess, string catalogVersion)
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "RefreshLocalPlayerInventory")]
	internal static class PlayFabManager__RefreshLocalPlayerInventory__Patch
	{
		public static bool Prefix(delUpdatePlayerInventoryDone OnSuccess)
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "RefreshLocalPlayerTitleData")]
	internal static class PlayFabManager__RefreshLocalPlayerTitleData__Patch
	{
		public static bool Prefix(Action OnSuccess)
		{
			return PlayFabFilesManager.SkipOriginalAndInvoke(OnSuccess);
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "RefreshGlobalTitleData")]
	internal static class PlayFabManager__RefreshGlobalTitleData__Patch
	{
		public static bool Prefix(Action OnSuccess)
		{
			return PlayFabFilesManager.SkipOriginalAndInvoke(OnSuccess);
		}
	}
	[HarmonyPatch(typeof(PlayFabManager), "RefreshStoreItems")]
	internal static class PlayFabManager__RefreshStoreItems__Patch
	{
		public static bool Prefix(string storeID, delUpdateStoreItemsDone OnSuccess)
		{
			if (OnSuccess != null)
			{
				OnSuccess.Invoke((Dictionary<string, StoreItem>)null);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(CM_PageRundown_New), "Setup")]
	public static class CM_PageRundown_New__Setup__Patch
	{
		public static readonly Vector3 YEET_VECTOR = new Vector3(-5000f, -20000f, 0f);

		public static void Postfix(CM_PageRundown_New __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			((Component)__instance.m_matchmakeAllButton).gameObject.transform.position = YEET_VECTOR;
		}
	}
	[HarmonyPatch(typeof(CM_PlayerLobbyBar), "SetupFromPage")]
	public static class CM_PlayerLobbyBar__SetupFromPage__Patch
	{
		public static void Postfix(CM_PlayerLobbyBar __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			((Component)__instance.m_matchmakeButton).gameObject.transform.position = CM_PageRundown_New__Setup__Patch.YEET_VECTOR;
			__instance.m_matchmakeIcon.gameObject.transform.position = CM_PageRundown_New__Setup__Patch.YEET_VECTOR;
		}
	}
}
namespace SimpleProgression.Models
{
	public class SPConfig
	{
		public class RandomizationOptions
		{
			public int MutedUsesMin { get; set; } = 1;


			public int MutedUsesMax { get; set; } = 1;


			public int BoldUsesMin { get; set; } = 1;


			public int BoldUsesMax { get; set; } = 2;


			public int AggressiveUsesMin { get; set; } = 2;


			public int AggressiveUsesMax { get; set; } = 3;

		}

		public bool UnlockAllLevels { get; set; }

		public bool ShowScrambledTimer { get; set; }

		public uint MaxBoosterCountPerCategory { get; set; } = 20u;


		public float ArtifactRewardMultiplier { get; set; } = 1f;


		public int NewBoosterDropCost { get; set; } = 1000;


		public bool ForceOneHundredArtifactHeat { get; set; }

		public RandomizationOptions DropRandomization { get; set; } = new RandomizationOptions();

	}
}
namespace SimpleProgression.Models.Vanity
{
	public class AllVanityGroupsToUnlock
	{
		[JsonIgnore]
		public static readonly IReadOnlyList<string> GAME_DEFAULT_GROUPS = new List<string>
		{
			"Initial Helmet DONOTDELETE", "Initial Torso DONOTDELETE", "Initial Legs DONOTDELETE", "Initial Backpack DONOTDELETE", "Initial Palette DONOTDELETE", "MainDrops", "MainStoryDrops", "SecondaryDrops", "OverloadDrops", "MainCompletedDrops",
			"StoryCompletedDrops", "SecondaryCompletedDrops", "OverloadCompletedDrops", "R7MainStoryDrops", "R7SecondaryDrops", "R7OverloadDrops", "R7MainCompletedDrops", "R7StoryCompletedDrops", "R7SecondaryCompletedDrops", "R7OverloadCompletedDrops",
			"R1Completion", "R2Completion", "R3Completion", "R4Completion", "R5Completion", "R6Completion", "R8Completion", "EarlyAccessDrops DONOTDELETE", "ChineseNewYear2022 DONOTDELETE", "ExtraExpeditions6.5 DONOTDELETE",
			"Gamescom2022 DONOTDELETE", "Halloween2022 DONOTDELETE", "BlackFriday2022 DONOTDELETE", "ChineseNewYear2023 DONOTDELETE", "ALT R4 Timed Drop 2023 DONOTDELETE", "Halloween2023 DONOTDELETE"
		};

		public string Comment { get; set; } = "This are all the VanityItemsGroupDataBlocks (name) that will be unlocked by Simple Progression if AllVanity is installed.";


		public List<string> GroupsToUnlock { get; set; } = new List<string>(GAME_DEFAULT_GROUPS);

	}
	public class LocalVanityAcquiredLayerDrops
	{
		public HashSet<string> ClaimedDrops { get; set; } = new HashSet<string>();


		public bool HasBeenClaimed(string key)
		{
			return ClaimedDrops.Contains(key);
		}

		public void Claim(string key)
		{
			ClaimedDrops.Add(key);
		}
	}
	public class LocalVanityItemStorage
	{
		public class LocalVanityItem
		{
			public uint ItemID { get; set; }

			public VanityItemFlags Flags { get; set; }

			[JsonIgnore]
			public bool IsCustom => !string.IsNullOrWhiteSpace(CustomKey);

			public string CustomKey { get; set; }
		}

		[Flags]
		public enum VanityItemFlags
		{
			None = 0,
			Acknowledged = 1,
			Touched = 2,
			ALL = 3
		}

		[CompilerGenerated]
		private sealed class <GetValidItemsAndFixCustomIDs>d__6 : IEnumerable<LocalVanityItem>, IEnumerable, IEnumerator<LocalVanityItem>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private LocalVanityItem <>2__current;

			private int <>l__initialThreadId;

			public LocalVanityItemStorage <>4__this;

			private List<LocalVanityItem>.Enumerator <>7__wrap1;

			LocalVanityItem IEnumerator<LocalVanityItem>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetValidItemsAndFixCustomIDs>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(List<LocalVanityItem>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					int num = <>1__state;
					LocalVanityItemStorage localVanityItemStorage = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>7__wrap1 = localVanityItemStorage.Items.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap1.MoveNext())
					{
						LocalVanityItem current = <>7__wrap1.Current;
						if (current.IsCustom)
						{
							if (!LocalVanityItemDropper.Instance.TryGetBlockFromCustomKey(current.CustomKey, out var block))
							{
								Plugin.L.Warning("Could not find custom item \"" + current.CustomKey + "\"! It won't be in your inventory in game!");
								continue;
							}
							current.ItemID = ((GameDataBlockBase<VanityItemsTemplateDataBlock>)(object)block).persistentID;
						}
						<>2__current = current;
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>7__wrap1 = default(List<LocalVanityItem>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<LocalVanityItem> IEnumerable<LocalVanityItem>.GetEnumerator()
			{
				<GetValidItemsAndFixCustomIDs>d__6 result;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					result = this;
				}
				else
				{
					result = new <GetValidItemsAndFixCustomIDs>d__6(0)
					{
						<>4__this = <>4__this
					};
				}
				return result;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<LocalVanityItem>)this).GetEnumerator();
			}
		}

		public List<LocalVanityItem> Items { get; set; } = new List<LocalVanityItem>();


		public void SetFlag(uint id, VanityItemFlags flag)
		{
			Items.Where((LocalVanityItem x) => x.ItemID == id).ToList().ForEach(delegate(LocalVanityItem x)
			{
				x.Flags |= flag;
			});
		}

		public void UnsetFlag(uint id, VanityItemFlags flag)
		{
			Items.Where((LocalVanityItem x) => x.ItemID == id).ToList().ForEach(delegate(LocalVanityItem x)
			{
				x.Flags &= ~flag;
			});
		}

		[IteratorStateMachine(typeof(<GetValidItemsAndFixCustomIDs>d__6))]
		public IEnumerable<LocalVanityItem> GetValidItemsAndFixCustomIDs()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetValidItemsAndFixCustomIDs>d__6(-2)
			{
				<>4__this = this
			};
		}

		public VanityItemPlayerData ToBaseGame()
		{
			return ToBaseGame(this);
		}

		public static VanityItemPlayerData ToBaseGame(LocalVanityItemStorage customData)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			List<LocalVanityItem> validItems = customData.GetValidItemsAndFixCustomIDs().ToList();
			if (Plugin.IsAllVanityLoaded)
			{
				AddNonOwnedBlocks(ref validItems);
			}
			VanityItemPlayerData val = new VanityItemPlayerData(ClassInjector.DerivedConstructorPointer<VanityItemPlayerData>());
			val.Items = new Il2CppReferenceArray<VanityItem>((long)validItems.Count);
			for (int i = 0; i < validItems.Count; i++)
			{
				LocalVanityItem localVanityItem = validItems[i];
				VanityItem val2 = new VanityItem
				{
					ItemId = localVanityItem.ItemID,
					Flags = (InventoryItemFlags)(byte)localVanityItem.Flags
				};
				((Il2CppArrayBase<VanityItem>)(object)val.Items)[i] = val2;
			}
			return val;
		}

		private static void AddNonOwnedBlocks(ref List<LocalVanityItem> validItems)
		{
			List<string> groupsToUnlock = LocalVanityItemManager.Instance.AllVanityGroupsToUnlock.GroupsToUnlock;
			HashSet<uint> allTemplateIds = new HashSet<uint>();
			foreach (VanityItemsGroupDataBlock allBlock in GameDataBlockBase<VanityItemsGroupDataBlock>.GetAllBlocks())
			{
				if (groupsToUnlock.Contains(((GameDataBlockBase<VanityItemsGroupDataBlock>)(object)allBlock).name))
				{
					Enumerator<uint> enumerator2 = allBlock.Items.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						uint current2 = enumerator2.Current;
						allTemplateIds.Add(current2);
					}
				}
			}
			List<LocalVanityItem> list = validItems;
			foreach (VanityItemsTemplateDataBlock item in ((IEnumerable<VanityItemsTemplateDataBlock>)GameDataBlockBase<VanityItemsTemplateDataBlock>.GetAllBlocks()).Where((VanityItemsTemplateDataBlock block) => allTemplateIds.Contains(((GameDataBlockBase<VanityItemsTemplateDataBlock>)(object)block).persistentID) && list.All((LocalVanityItem vi) => vi.ItemID != ((GameDataBlockBase<VanityItemsTemplateDataBlock>)(object)block).persistentID)))
			{
				validItems.Add(new LocalVanityItem
				{
					ItemID = ((GameDataBlockBase<VanityItemsTemplateDataBlock>)(object)item).persistentID,
					Flags = VanityItemFlags.ALL
				});
			}
		}

		public static LocalVanityItemStorage FromBaseGame(VanityItemPlayerData vanityPlayerData)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected I4, but got Unknown
			List<LocalVanityItem> list = new List<LocalVanityItem>();
			foreach (VanityItem item in (Il2CppArrayBase<VanityItem>)(object)vanityPlayerData.Items)
			{
				list.Add(new LocalVanityItem
				{
					ItemID = item.ItemId,
					Flags = (VanityItemFlags)item.Flags
				});
			}
			return new LocalVanityItemStorage
			{
				Items = list
			};
		}
	}
}
namespace SimpleProgression.Models.Progression
{
	public struct ExpeditionCompletionData
	{
		public readonly bool Success => RawSessionData.ExpeditionSurvived;

		public readonly string RundownKey => RawSessionData.RundownKey;

		public uint RundownId { get; internal set; }

		public eRundownTier ExpeditionTier { get; internal set; }

		public int ExpeditionIndex { get; internal set; }

		public readonly string ExpeditionId => RawSessionData.ExpeditionId;

		public readonly string SessionId => RawSessionData.SessionId;

		public readonly int ArtifactsCollected => RawSessionData.ArtifactsCollected;

		public readonly bool WasPrisonerEfficiencyClear => RawSessionData.PrisonerEfficiencyCompleted;

		public bool WasFirstTimeCompletion { get; internal set; }

		public ExpeditionSession RawSessionData { get; internal set; }

		public float PreArtifactHeat { get; internal set; }

		public float NewArtifactHeat { get; internal set; }
	}
	public class ExpeditionSession
	{
		public class ExpeditionSessionData
		{
			private readonly ILogger _logger;

			public Dictionary<Layers, LayerState> LayerStates { get; private set; } = new Dictionary<Layers, LayerState>();


			internal ExpeditionSessionData(ILogger logger)
			{
				_logger = logger;
			}

			internal void SetOnlyIncreaseLayerState(Layers layer, LayerState state)
			{
				if (LayerStates.TryGetValue(layer, out var value))
				{
					if (value < state)
					{
						LayerStates.Remove(layer);
						_logger.Debug($"[{"ExpeditionSessionData"}] Set layer {layer} from {value} to {state}");
						LayerStates.Add(layer, state);
					}
				}
				else
				{
					_logger.Debug($"[{"ExpeditionSessionData"}] Set layer {layer} to {state}");
					LayerStates.Add(layer, state);
				}
			}

			internal void SetLayerState(Layers layer, LayerState state)
			{
				if (LayerStates.TryGetValue(layer, out var value))
				{
					LayerStates.Remove(layer);
					_logger.Debug($"[{"ExpeditionSessionData"}] Set layer {layer} from {value} to {state}");
				}
				else
				{
					_logger.Debug($"[{"ExpeditionSessionData"}] Set layer {layer} to {state}");
				}
				LayerStates.Add(layer, state);
			}

			public override string ToString()
			{
				string text = string.Empty;
				foreach (KeyValuePair<Layers, LayerState> layerState in LayerStates)
				{
					text += $"{layerState.Key}: {layerState.Value}, ";
				}
				return text.Substring(0, text.Length - 2);
			}

			public ExpeditionSessionData Clone()
			{
				ExpeditionSessionData expeditionSessionData = new ExpeditionSessionData(_logger);
				foreach (KeyValuePair<Layers, LayerState> layerState in LayerStates)
				{
					expeditionSessionData.LayerStates.Add(layerState.Key, layerState.Value);
				}
				return expeditionSessionData;
			}
		}

		private readonly ILogger _logger;

		private ExpeditionSessionData SavedData { get; set; }

		public ExpeditionSessionData CurrentData { get; private set; }

		public bool HasCheckpointBeenUsed { get; private set; }

		public bool ExpeditionSurvived { get; private set; }

		public DateTimeOffset DropTime { get; private set; }

		public DateTimeOffset StartTime { get; private set; }

		public DateTimeOffset EndTime { get; private set; }

		public string RundownKey { get; private set; }

		public string ExpeditionId { get; private set; }

		public string SessionId { get; private set; }

		public int ArtifactsCollected => MutedArtifactsCollected + BoldArtifactsCollected + AggressiveArtifactsCollected;

		public int MutedArtifactsCollected { get; internal set; }

		public int BoldArtifactsCollected { get; internal set; }

		public int AggressiveArtifactsCollected { get; internal set; }

		public bool PrisonerEfficiencyCompleted
		{
			get
			{
				if (CurrentData.LayerStates.Count() == 3)
				{
					return CurrentData.LayerStates.All((KeyValuePair<Layers, LayerState> x) => x.Value == LayerState.Completed);
				}
				return false;
			}
		}

		private ExpeditionSession(string rundownKey, string expeditionId, string sessionId, ILogger logger)
		{
			RundownKey = rundownKey;
			ExpeditionId = expeditionId;
			SessionId = sessionId;
			_logger = logger;
			DropTime = DateTimeOffset.UtcNow;
			CurrentData = new ExpeditionSessionData(logger);
			SetLayer(Layers.Main, LayerState.Entered);
		}

		internal static ExpeditionSession InitNewSession(string rundownKey, string expeditionId, string sessionId, ILogger logger)
		{
			ExpeditionSession result = new ExpeditionSession(rundownKey, expeditionId, sessionId, logger);
			logger.Info($"[{"ExpeditionSession"}] New expedition session started! (R:{rundownKey}, E:{expeditionId}, S:{sessionId})");
			return result;
		}

		internal void OnLevelEntered()
		{
			StartTime = DateTimeOffset.UtcNow;
		}

		internal void OnCheckpointSave()
		{
			_logger.Info("Saving current ExpeditionSessionData at checkpoint.");
			SavedData = CurrentData.Clone();
		}

		internal void OnCheckpointReset()
		{
			if (!HasCheckpointBeenUsed)
			{
				_logger.Notice("Checkpoint has been used!");
			}
			HasCheckpointBeenUsed = true;
			if (SavedData != null)
			{
				_logger.Info("Resetting previous ExpeditionSessionData from checkpoint.");
				CurrentData = SavedData.Clone();
			}
		}

		internal void OnExpeditionCompleted(bool success)
		{
			EndTime = DateTimeOffset.UtcNow;
			_logger.Info($"[{"ExpeditionSession"}] Expedition session has ended! (R:{RundownKey}, E:{ExpeditionId}, S:{SessionId}){(success ? " Expedition Successful!" : string.Empty)}");
			if (success)
			{
				ExpeditionSurvived = true;
				SetLayer(Layers.Main, LayerState.Completed);
			}
			_logger.Info($"[{"ExpeditionSession"}] Data: {CurrentData}");
		}

		internal void SetLayer(Layers layer, LayerState state)
		{
			CurrentData.SetOnlyIncreaseLayerState(layer, state);
		}

		public bool HasLayerBeenCompleted(Layers layer)
		{
			if (!CurrentData.LayerStates.TryGetValue(layer, out var value))
			{
				return false;
			}
			return value == LayerState.Completed;
		}
	}
	public static class LayerExtensions
	{
		public static Layers ToCustom(this ExpeditionLayers layer)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			return (Layers)layer;
		}

		public static ExpeditionLayers ToBasegame(this Layers layer)
		{
			return (ExpeditionLayers)layer;
		}

		public static LayerState ToCustom(this LayerProgressionState state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			return (LayerState)state;
		}

		public static LayerProgressionState ToBasegame(this LayerState layer)
		{
			return (LayerProgressionState)layer;
		}
	}
	[Flags]
	public enum LayerFlags
	{
		None = 0,
		Main = 1,
		Secondary = 2,
		Third = 4,
		All = 7
	}
	public enum Layers
	{
		Main,
		Secondary,
		Third
	}
	public enum LayerState
	{
		Undiscovered,
		Discovered,
		Entered,
		Completed
	}
	public class LocalRundownProgression
	{
		public class Expedition
		{
			public class Layer
			{
				public LayerState State;

				public int CompletionCount;

				public void IncreaseStateAndCompletion(LayerState newState)
				{
					if (State < newState)
					{
						State = newState;
					}
					if (newState == LayerState.Completed)
					{
						CompletionCount++;
					}
				}

				public static Layer FromBaseGame(Layer baseGameType)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_0007: 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)
					return new Layer
					{
						State = baseGameType.State.ToCustom(),
						CompletionCount = baseGameType.CompletionCount
					};
				}

				public Layer ToBaseGame()
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					//IL_001d: Unknown result type (might be due to invalid IL or missing references)
					//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)
					Layer result = default(Layer);
					result.CompletionCount = CompletionCount;
					result.State = State.ToBasegame();
					return result;
				}
			}

			public int AllLayerCompletionCount;

			public LayerSet Layers = new LayerSet();

			public float ArtifactHeat = 1f;

			public bool HasBeenCompletedBefore()
			{
				return (Layers?.Main?.CompletionCount).GetValueOrDefault() > 0;
			}

			public static Expedition FromBaseGame(Expedition baseGameExpedition)
			{
				return new Expedition
				{
					AllLayerCompletionCount = baseGameExpedition.AllLayerCompletionCount,
					Layers = LayerSet.FromBaseGame(baseGameExpedition.Layers)
				};
			}

			public Expedition ToBaseGame()
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Expected O, but got Unknown
				Expedition val = new Expedition(ClassInjector.DerivedConstructorPointer<Expedition>())
				{
					AllLayerCompletionCount = AllLayerCompletionCount,
					Layers = (Layers?.ToBaseGameLayers() ?? new LayerSet<Layer>())
				};
				SetArtifactHeat(val);
				return val;
			}

			[MethodImpl(MethodImplOptions.NoInlining)]
			private void SetArtifactHeat(Expedition bgExp)
			{
				if (Plugin.SPConfig.ForceOneHundredArtifactHeat)
				{
					bgExp.ArtifactHeat = 1f;
				}
				else
				{
					bgExp.ArtifactHeat = ArtifactHeat;
				}
			}
		}

		public class LayerSet
		{
			public Expedition.Layer Main { get; set; }

			public Expedition.Layer Secondary { get; set; }

			public Expedition.Layer Third { get; set; }

			public static LayerSet FromBaseGame(LayerSet<Layer> baseGameLayers)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				return new LayerSet
				{
					Main = Expedition.Layer.FromBaseGame(baseGameLayers.Main),
					Secondary = Expedition.Layer.FromBaseGame(baseGameLayers.Secondary),
					Third = Expedition.Layer.FromBaseGame(baseGameLayers.Third)
				};
			}

			public Expedition.Layer GetOrAddLayer(Layers layer)
			{
				Expedition.Layer layer2 = GetLayer(layer);
				if (layer2 == null)
				{
					layer2 = new Expedition.Layer();
					SetLayer(layer, layer2);
				}
				return layer2;
			}

			public Expedition.Layer GetLayer(Layers layer)
			{
				return layer switch
				{
					Layers.Main => Main, 
					Layers.Secondary => Secondary, 
					Layers.Third => Third, 
					_ => throw new Exception($"Unknown layer enum {layer}"), 
				};
			}

			public void SetLayer(Layers layer, Expedition.Layer data)
			{
				switch (layer)
				{
				case Layers.Main:
					Main = data;
					break;
				case Layers.Secondary:
					Secondary = data;
					break;
				case Layers.Third:
					Third = data;
					break;
				default:
					throw new Exception($"Unknown layer enum {layer}");
				}
			}

			public LayerSet<Layer> ToBaseGameLayers()
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				return new LayerSet<Layer>
				{
					Main = (Layer)(((??)Main?.ToBaseGame()) ?? default(Layer)),
					Secondary = (Layer)(((??)Secondary?.ToBaseGame()) ?? default(Layer)),
					Third = (Layer)(((??)Third?.ToBaseGame()) ?? default(Layer))
				};
			}
		}

		public Dictionary<string, Expedition> Expeditions = new Dictionary<string, Expedition>();

		private ILogger _logger;

		public static float ARTIFACT_HEAT_MIN { get; set; } = 0.2f;


		public static float ARTIFACT_HEAT_UNCOMPLETED_MIN { get; set; } = 0.5f;


		public int GetUniqueExpeditionLayersStateCount(Layers layer = Layers.Main, LayerState state = LayerState.Completed)
		{
			return Expeditions.Count(delegate(KeyValuePair<string, Expedition> x)
			{
				Expedition value = x.Value;
				return value != null && value.Layers?.GetLayer(layer)?.State == state;
			});
		}

		internal bool AddSessionResults(ExpeditionSession session, out ExpeditionCompletionData completionData)
		{
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			if (session == null)
			{
				completionData = default(ExpeditionCompletionData);
				return false;
			}
			if (Expeditions == null)
			{
				Expeditions = new Dictionary<string, Expedition>();
			}
			Expedition orAdd = GetOrAdd(Expeditions, session.ExpeditionId);
			bool flag = !orAdd.HasBeenCompletedBefore();
			foreach (KeyValuePair<Layers, LayerState> layerState2 in session.CurrentData.LayerStates)
			{
				Layers key = layerState2.Key;
				LayerState layerState = layerState2.Value;
				if (!session.ExpeditionSurvived && layerState == LayerState.Completed)
				{
					layerState = LayerState.Entered;
				}
				orAdd.Layers.GetOrAddLayer(key).IncreaseStateAndCompletion(layerState);
			}
			if (session.ExpeditionSurvived && session.PrisonerEfficiencyCompleted)
			{
				orAdd.AllLayerCompletionCount++;
			}
			float artifactHeat = orAdd.ArtifactHeat;
			if (session.ArtifactsCollected > 0)
			{
				float val = (flag ? ARTIFACT_HEAT_MIN : ARTIFACT_HEAT_UNCOMPLETED_MIN);
				float val2 = orAdd.ArtifactHeat - (float)session.ArtifactsCollected * 1.5f / 100f;
				orAdd.ArtifactHeat = Math.Max(val, val2);
				foreach (Expedition value2 in Expeditions.Values)
				{
					if (value2 != orAdd && value2 != null && !(value2.ArtifactHeat >= 1f))
					{
						float val3 = value2.ArtifactHeat + (float)session.ArtifactsCollected * 0.5f / 100f;
						value2.ArtifactHeat = Math.Min(1f, val3);
					}
				}
			}
			if (!uint.TryParse(session.RundownKey.Replace("Local_", string.Empty), out var result))
			{
				_logger?.Error($"[{"LocalRundownProgression"}.{"AddSessionResults"}] Could not parse rundown id from \"{session.RundownKey}\"!");
				result = 0u;
			}
			char value = session.ExpeditionId[0];
			int result2 = ((!int.TryParse(session.ExpeditionId.Substring(1), out result2)) ? (-1) : (result2 - 1));
			if (!Enum.TryParse<eRundownTier>($"Tier{value}", out eRundownTier result3))
			{
				result3 = (eRundownTier)1;
			}
			completionData = new ExpeditionCompletionData
			{
				RundownId = result,
				ExpeditionIndex = result2,
				ExpeditionTier = result3,
				PreArtifactHeat = artifactHeat,
				NewArtifactHeat = orAdd.ArtifactHeat,
				WasFirstTimeCompletion = flag,
				RawSessionData = session
			};
			return true;
		}

		public RundownProgression ToBaseGameProgression()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			RundownProgression val = new RundownProgression(ClassInjector.DerivedConstructorPointer<RundownProgression>());
			val.Expeditions = new Dictionary<string, Expedition>();
			if (Expeditions == null)
			{
				Expeditions = new Dictionary<string, Expedition>();
			}
			foreach (KeyValuePair<string, Expedition> expedition in Expeditions)
			{
				string key = expedition.Key;
				Expedition val2 = expedition.Value.ToBaseGame();
				val.Expeditions.Add(key, val2);
			}
			return val;
		}

		public Expedition GetOrAdd(Dictionary<string, Expedition> dict, string keyName)
		{
			if (dict.TryGetValue(keyName, out var value))
			{
				return value;
			}
			Expedition expedition = new Expedition();
			dict.Add(keyName, expedition);
			return expedition;
		}
	}
}
namespace SimpleProgression.Models.Boosters
{
	public class LocalBoosterImplant
	{
		public struct Effect
		{
			public uint Id;

			public float Value;
		}

		public enum SaveBoosterImplantCategory
		{
			Muted,
			Bold,
			Aggressive
		}

		public static string TraitConditionColor { get; private set; }

		public static string TraitNegativeColor { get; private set; }

		public static string TraitPositiveColor { get; private set; }

		public uint TemplateId { get; set; }

		public SaveBoosterImplantCategory Category { get; set; }

		public int Uses { get; set; }

		public Effect[] Effects { get; set; }

		[JsonIgnore]
		public BoosterImplantTemplateDataBlock Template { get; set; }

		public uint InstanceId { get; set; }

		public uint[] Conditions { get; set; }

		public LocalBoosterImplant()
		{
		}

		public LocalBoosterImplant(uint templateId, uint instanceId, int uses, Effect[] effects, uint[] conditions)
		{
			TemplateId = templateId;
			InstanceId = instanceId;
			Uses = uses;
			Effects = effects ?? Array.Empty<Effect>();
			Conditions = conditions ?? Array.Empty<uint>();
		}

		public static void CopyTraitColorsFromBasegame()
		{
			TraitConditionColor = BoosterImplant.TraitConditionColor;
			TraitNegativeColor = BoosterImplant.TraitNegativeColor;
			TraitPositiveColor = BoosterImplant.TraitPositiveColor;
		}

		protected static BoosterImplantInventoryItem ToBaseGame(LocalDropServerBoosterImplantInventoryItem custom, BoosterImplantInventoryItem baseGame)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			BoosterImplantInventoryItem val = new BoosterImplantInventoryItem(ClassInjector.DerivedConstructorPointer<BoosterImplantInventoryItem>());
			((BoosterImplantBase)val).Effects = Il2CppStructArray<BoosterImplantEffect>.op_Implicit((BoosterImplantEffect[])(object)new BoosterImplantEffect[custom.Effects.Length]);
			for (int i = 0; i < custom.Effects.Length; i++)
			{
				Effect effect = custom.Effects[i];
				((Il2CppArrayBase<BoosterImplantEffect>)(object)((BoosterImplantBase)val).Effects)[i] = new BoosterImplantEffect
				{
					Id = effect.Id,
					Param = effect.Value
				};
			}
			((BoosterImplantBase)val).TemplateId = custom.TemplateId;
			((BoosterImplantBase)val).Id = custom.InstanceId;
			((BoosterImplantBase)val).Conditions = Il2CppStructArray<uint>.op_Implicit(new uint[custom.Conditions.Length]);
			for (int j = 0; j < custom.Conditions.Length; j++)
			{
				((Il2CppArrayBase<uint>)(object)((BoosterImplantBase)val).Conditions)[j] = custom.Conditions[j];
			}
			((BoosterImplantBase)val).UsesRemaining = custom.Uses;
			return val;
		}
	}
	public class LocalBoosterImplantPlayerData
	{
		public class CustomCategory
		{
			[JsonIgnore]
			public const int MAX_BOOSTERS_R5 = 10;

			[JsonIgnore]
			public const int MAX_BOOSTERS_R6 = 20;

			private int _currency;

			public LocalBoosterImplant.SaveBoosterImplantCategory CategoryType { get; set; }

			public int Currency
			{
				get
				{
					return _currency;
				}
				set
				{
					_currency = ((value > 0) ? value : 0);
				}
			}

			public int Missed { get; set; }

			public int MissedAck { get; set; }

			public LocalDropServerBoosterImplantInventoryItem[] Inventory { get; set; } = new LocalDropServerBoosterImplantInventoryItem[0];


			[JsonIgnore]
			public static int MaxBoostersInCategoryInventory => GetMaxBoostersInCategory();

			[JsonIgnore]
			public bool InventoryIsFull => Inventory.Length >= MaxBoostersInCategoryInventory;

			[JsonIgnore]
			public bool HasEnoughCurrencyForDrop => Currency >= CurrencyNewBoosterCost;

			public CustomCategory()
			{
			}

			public CustomCategory(LocalBoosterImplant.SaveBoosterImplantCategory cat)
			{
				CategoryType = cat;
			}

			public uint[] GetUsedIds()
			{
				uint[] array = new uint[Inventory.Length];
				for (int i = 0; i < Inventory.Length; i++)
				{
					array[i] = Inventory[i].InstanceId;
				}
				return array;
			}

			public bool TryAddBooster(LocalDropServerBoosterImplantInventoryItem newBooster)
			{
				if (InventoryIsFull)
				{
					return false;
				}
				LocalDropServerBoosterImplantInventoryItem[] array = new LocalDropServerBoosterImplantInventoryItem[Inventory.Length + 1];
				for (int i = 0; i < Inventory.Length; i++)
				{
					array[i] = Inventory[i];
				}
				array[^1] = newBooster;
				Inventory = array;
				return true;
			}

			internal void ConsumeOrDropBoostersWithIds(uint[] boostersToBeConsumed)
			{
				List<LocalDropServerBoosterImplantInventoryItem> list = new List<LocalDropServerBoosterImplantInventoryItem>();
				LocalDropServerBoosterImplantInventoryItem[] inventory = Inventory;
				foreach (LocalDropServerBoosterImplantInventoryItem item in inventory)
				{
					if (boostersToBeConsumed.Any((uint toConsumeId) => item.InstanceId == toConsumeId))
					{
						if (item.Uses <= 1)
						{
							continue;
						}
						item.Uses--;
					}
					list.Add(item);
				}
				Inventory = list.ToArray();
			}

			internal void DropBoostersWithIds(uint[] boostersToBeDropped)
			{
				List<LocalDropServerBoosterImplantInventoryItem> list = new List<LocalDropServerBoosterImplantInventoryItem>();
				LocalDropServerBoosterImplantInventoryItem[] inventory = Inventory;
				foreach (LocalDropServerBoosterImplantInventoryItem item in inventory)
				{
					if (!boostersToBeDropped.Any((uint toDropId) => item.InstanceId == toDropId))
					{
						list.Add(item);
					}
				}
				Inventory = list.ToArray();
			}

			internal void SetBoostersTouchedWithIds(uint[] boostersThatWereTouched)
			{
				LocalDropServerBoosterImplantInventoryItem[] inventory = Inventory;
				foreach (LocalDropServerBoosterImplantInventoryItem item in inventory)
				{
					if (boostersThatWereTouched.Any((uint toTouchId) => item.InstanceId == toTouchId))
					{
						item.IsTouched = true;
					}
				}
			}

			public Category ToBaseGame()
			{
				return ToBaseGame(this);
			}

			public static Category ToBaseGame(CustomCategory customCat)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Expected O, but got Unknown
				Category val = new Category(ClassInjector.DerivedConstructorPointer<Category>());
				val.Currency = customCat.Currency;
				val.Missed = customCat.Missed;
				val.Inventory = new Il2CppReferenceArray<BoosterImplantInventoryItem>((long)customCat.Inventory.Length);
				for (int i = 0; i < customCat.Inventory.Length; i++)
				{
					((Il2CppArrayBase<BoosterImplantInventoryItem>)(object)val.Inventory)[i] = customCat.Inventory[i].ToBaseGame();
				}
				return val;
			}

			public static CustomCategory FromBaseGame(Category cat)
			{
				CustomCategory customCategory = new CustomCategory();
				customCategory.Currency = cat.Currency;
				customCategory.Missed = cat.Missed;
				customCategory.MissedAck = cat.MissedAck;
				List<LocalDropServerBoosterImplantInventoryItem> list = new List<LocalDropServerBoosterImplantInventoryItem>();
				foreach (BoosterImplantInventoryItem item in (Il2CppArrayBase<BoosterImplantInventoryItem>)(object)cat.Inventory)
				{
					list.Add(LocalDropServerBoosterImplantInventoryItem.FromBaseGame(item));
				}
				customCategory.Inventory = list.ToArray();
				return customCategory;
			}

			public static int GetMaxBoostersInCategory()
			{
				return (int)Plugin.SPConfig.MaxBoosterCountPerCategory;
			}
		}

		public static int CurrencyNewBoosterCost
		{
			get
			{
				if (Plugin.SPConfig.NewBoosterDropCost <= 0)
				{
					return 1000;
				}
				return Plugin.SPConfig.NewBoosterDropCost;
			}
		}

		public static float CurrencyGainMultiplier => Plugin.SPConfig.ArtifactRewardMultiplier;

		public CustomCategory Basic { get; set; } = new CustomCategory(LocalBoosterImplant.SaveBoosterImplantCategory.Muted);


		public CustomCategory Advanced { get; set; } = new CustomCategory(LocalBoosterImplant.SaveBoosterImplantCategory.Bold);


		public CustomCategory Specialized { get; set; } = new CustomCategory(LocalBoosterImplant.SaveBoosterImplantCategory.Aggressive);


		public uint[] New { get; set; } = new uint[0];


		public void AcknowledgeMissedBoostersWithIds(Missed acknowledgeMissed)
		{
			Basic.MissedAck = acknowledgeMissed.Basic;
			Advanced.MissedAck = acknowledgeMissed.Advanced;
			Specialized.MissedAck = acknowledgeMissed.Specialized;
		}

		public CustomCategory[] GetCategoriesWhereCurrencyCostHasBeenReached()
		{
			List<CustomCategory> list = new List<CustomCategory>();
			if (Basic.Currency >= CurrencyNewBoosterCost)
			{
				list.Add(Basic);
			}
			if (Advanced.Currency >= CurrencyNewBoosterCost)
			{
				list.Add(Advanced);
			}
			if (Specialized.Currency >= CurrencyNewBoosterCost)
			{
				list.Add(Specialized);
			}
			return list.ToArray();
		}

		public void AcknowledgeBoostersWithIds(uint[] boostersToAcknowledge)
		{
			List<uint> list = new List<uint>();
			uint[] @new = New;
			foreach (uint id in @new)
			{
				if (!boostersToAcknowledge.Any((uint idToAcknowledge) => id == idToAcknowledge))
				{
					list.Add(id);
				}
			}
			New = list.ToArray();
		}

		public void SetBoostersTouchedWithIds(uint[] boostersThatWereTouched)
		{
			Basic.SetBoostersTouchedWithIds(boostersThatWereTouched);
			Advanced.SetBoostersTouchedWithIds(boostersThatWereTouched);
			Specialized.SetBoostersTouchedWithIds(boostersThatWereTouched);
		}

		public void ConsumeBoostersWithIds(uint[] boostersToBeConsumed)
		{
			Basic.ConsumeOrDropBoostersWithIds(boostersToBeConsumed);
			Advanced.ConsumeOrDropBoostersWithIds(boostersToBeConsumed);
			Specialized.ConsumeOrDropBoostersWithIds(boostersToBeConsumed);
		}

		public void DropBoostersWithIds(uint[] boostersToBeDropped)
		{
			Basic.DropBoostersWithIds(boostersToBeDropped);
			Advanced.DropBoostersWithIds(boostersToBeDropped);
			Specialized.DropBoostersWithIds(boostersToBeDropped);
		}

		public void AddCurrency(PerBoosterCategoryInt boosterCurrency)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Basic.Currency += (int)((float)boosterCurrency.Basic * CurrencyGainMultiplier);
			Advanced.Currency += (int)((float)boosterCurrency.Advanced * CurrencyGainMultiplier);
			Specialized.Currency += (int)((float)boosterCurrency.Specialized * CurrencyGainMultiplier);
		}

		public bool TryAddBooster(LocalDropServerBoosterImplantInventoryItem newBooster)
		{
			if (!GetCategory(newBooster.Category).TryAddBooster(newBooster))
			{
				return false;
			}
			uint[] array = new uint[New.Length + 1];
			for (int i = 0; i < New.Length; i++)
			{
				array[i] = New[i];
			}
			array[New.Length] = newBooster.InstanceId;
			New = array;
			return true;
		}

		public uint[] GetUsedIds()
		{
			CustomCategory[] allCategories = GetAllCategories();
			List<uint> list = new List<uint>();
			CustomCategory[] array = allCategories;
			for (int i = 0; i < array.Length; i++)
			{
				uint[] usedIds = array[i].GetUsedIds();
				foreach (uint item in usedIds)
				{
					list.Add(item);
				}
			}
			return list.ToArray();
		}

		public CustomCategory[] GetAllCategories()
		{
			return new CustomCategory[3] { Basic, Advanced, Specialized };
		}

		public CustomCategory GetCategory(LocalBoosterImplant.SaveBoosterImplantCategory category)
		{
			return category switch
			{
				LocalBoosterImplant.SaveBoosterImplantCategory.Muted => Basic, 
				LocalBoosterImplant.SaveBoosterImplantCategory.Bold => Advanced, 
				LocalBoosterImplant.SaveBoosterImplantCategory.Aggressive => Specialized, 
				_ => null, 
			};
		}

		public BoosterImplantPlayerData ToBaseGame()
		{
			return ToBaseGame(this);
		}

		public static BoosterImplantPlayerData ToBaseGame(LocalBoosterImplantPlayerData customData)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			return new BoosterImplantPlayerData(ClassInjector.DerivedConstructorPointer<BoosterImplantPlayerData>())
			{
				New = Il2CppStructArray<uint>.op_Implicit(customData.New),
				Basic = customData.Basic.ToBaseGame(),
				Advanced = customData.Advanced.ToBaseGame(),
				Specialized = customData.Specialized.ToBaseGame()
			};
		}

		public static LocalBoosterImplantPlayerData FromBaseGame(BoosterImplantPlayerData data)
		{
			LocalBoosterImplantPlayerData localBoosterImplantPlayerData = new LocalBoosterImplantPlayerData();
			localBoosterImplantPlayerData.Basic = CustomCategory.FromBaseGame(data.Basic);
			localBoosterImplantPlayerData.Basic.CategoryType = LocalBoosterImplant.SaveBoosterImplantCategory.Muted;
			localBoosterImplantPlayerData.Advanced = CustomCategory.FromBaseGame(data.Advanced);
			localBoosterImplantPlayerData.Advanced.CategoryType = LocalBoosterImplant.SaveBoosterImplantCategory.Bold;
			localBoosterImplantPlayerData.Specialized = CustomCategory.FromBaseGame(data.Specialized);
			localBoosterImplantPlayerData.Specialized.CategoryType = LocalBoosterImplant.SaveBoosterImplantCategory.Aggressive;
			localBoosterImplantPlayerData.New = new uint[((Il2CppArrayBase<uint>)(object)data.New).Count];
			for (int i = 0; i < ((Il2CppArrayBase<uint>)(object)data.New).Count; i++)
			{
				localBoosterImplantPlayerData.New[i] = ((Il2CppArrayBase<uint>)(object)data.New)[i];
			}
			return localBoosterImplantPlayerData;
		}
	}
	public class LocalDropServerBoosterImplantInventoryItem : LocalBoosterImplant
	{
		public uint Flags { get; set; }

		[JsonIgnore]
		public bool IsTouched
		{
			get
			{
				return (Flags & 1) != 0;
			}
			set
			{
				if (value)
				{
					Flags |= 1u;
					return;
				}
				uint num = 4294967294u;
				Flags &= num;
			}
		}

		[JsonConstructor]
		public LocalDropServerBoosterImplantInventoryItem()
		{
		}

		public LocalDropServerBoosterImplantInventoryItem(uint templateId, uint instanceId, int uses, Effect[] effects, uint[] conditions)
			: base(templateId, instanceId, uses, effects, conditions)
		{
		}

		public BoosterImplantInventoryItem ToBaseGame()
		{
			return ToBaseGame(this);
		}

		public static BoosterImplantInventoryItem ToBaseGame(LocalDropServerBoosterImplantInventoryItem custom)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			BoosterImplantInventoryItem val = new BoosterImplantInventoryItem(ClassInjector.DerivedConstructorPointer<BoosterImplantInventoryItem>());
			((BoosterImplantBase)val).Effects = Il2CppStructArray<BoosterImplantEffect>.op_Implicit((BoosterImplantEffect[])(object)new BoosterImplantEffect[custom.Effects.Length]);
			for (int i = 0; i < custom.Effects.Length; i++)
			{
				Effect effect = custom.Effects[i];
				((Il2CppArrayBase<BoosterImplantEffect>)(object)((BoosterImplantBase)val).Effects)[i] = new BoosterImplantEffect
				{
					Id = effect.Id,
					Param = effect.Value
				};
			}
			((BoosterImplantBase)val).TemplateId = custom.TemplateId;
			((BoosterImplantBase)val).Id = custom.InstanceId;
			((BoosterImplantBase)val).Conditions = Il2CppStructArray<uint>.op_Implicit(new uint[custom.Conditions.Length]);
			for (int j = 0; j < custom.Conditions.Length; j++)
			{
				((Il2CppArrayBase<uint>)(object)((BoosterImplantBase)val).Conditions)[j] = custom.Conditions[j];
			}
			((BoosterImplantBase)val).UsesRemaining = custom.Uses;
			val.Flags = custom.Flags;
			return val;
		}

		public static LocalDropServerBoosterImplantInventoryItem FromBaseGame(BoosterImplantInventoryItem implant)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			LocalDropServerBoosterImplantInventoryItem localDropServerBoosterImplantInventoryItem = new LocalDropServerBoosterImplantInventoryItem();
			Effect[] array = new Effect[((Il2CppArrayBase<BoosterImplantEffect>)(object)((BoosterImplantBase)implant).Effects).Length];
			LocalBoosterImplant localBoosterImplant = new LocalBoosterImplant();
			for (int i = 0; i < ((Il2CppArrayBase<BoosterImplantEffect>)(object)((BoosterImplantBase)implant).Effects).Length; i++)
			{
				BoosterImplantEffect val = ((Il2CppArrayBase<BoosterImplantEffect>)(object)((BoosterImplantBase)implant).Effects)[i];
				array[i] = new Effect
				{
					Value = val.Param,
					Id = val.Id
				};
			}
			localBoosterImplant.TemplateId = ((BoosterImplantBase)implant).TemplateId;
			localBoosterImplant.InstanceId = ((BoosterImplantBase)implant).Id;
			localBoosterImplant.Uses = ((BoosterImplantBase)implant).UsesRemaining;
			localBoosterImplant.Effects = array;
			localBoosterImplant.Conditions = Il2CppArrayBase<uint>.op_Implicit((Il2CppArrayBase<uint>)(object)((BoosterImplantBase)implant).Conditions);
			localDropServerBoosterImplantInventoryItem.Flags = implant.Flags;
			return localDropServerBoosterImplantInventoryItem;
		}
	}
}
namespace SimpleProgression.Interfaces
{
	public interface ILogger
	{
		void Success(string msg);

		void Notice(string msg);

		void Msg(ConsoleColor col, string msg);

		void Info(string msg);

		void Fail(string msg);

		void Debug(string msg);

		void Warning(string msg);

		void Error(string msg);

		void Exception(Exception ex);
	}
}
namespace SimpleProgression.Impl
{
	internal class LocalDropServerAPI : Object
	{
		public LocalDropServerAPI()
			: base(ClassInjector.DerivedConstructorPointer<LocalDropServerAPI>())
		{
			ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this);
		}

		public LocalDropServerAPI(IntPtr ptr)
			: base(ptr)
		{
			ClassInjector.DerivedConstructorBody((Il2CppObjectBase)(object)this);
		}

		public Task<RundownProgressionResult> RundownProgressionAsync(RundownProgressionRequest request)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			Plugin.L.Warning($"{"LocalDropServerAPI"}: {"RundownProgressionAsync"}: {request.Rundown}");
			LocalRundownProgression orCreateLocalProgression = LocalProgressionManager.Instance.GetOrCreateLocalProgression(request.Rundown);
			return Task.FromResult<RundownProgressionResult>(new RundownProgressionResult
			{
				Rundown = orCreateLocalProgression.ToBaseGameProgression()
			});
		}

		public Task<ClearRundownProgressionResult> ClearRundownProgressionAsync(ClearRundownProgressionRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: ClearRundownProgressionAsync");
			return Task.FromResult<ClearRundownProgressionResult>(new ClearRundownProgressionResult());
		}

		public Task<NewSessionResult> NewSessionAsync(NewSessionRequest request)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			Plugin.L.Warning($"{"LocalDropServerAPI"}: {"NewSessionAsync"}: {request.Rundown} {request.Expedition} {request.SessionId}");
			LocalProgressionManager.Instance.StartNewExpeditionSession(request.Rundown, request.Expedition, request.SessionId);
			LocalBoosterManager.Instance.StartSession(Il2CppArrayBase<uint>.op_Implicit((Il2CppArrayBase<uint>)(object)request.BoosterIds), request.SessionId);
			return Task.FromResult<NewSessionResult>(new NewSessionResult
			{
				SessionBlob = "Chat, is this real?! " + request.SessionId
			});
		}

		public Task<LayerProgressionResult> LayerProgressionAsync(LayerProgressionRequest request)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			Plugin.L.Warning($"{"LocalDropServerAPI"}: {"LayerProgressionAsync"} Layer: {request.Layer}, State: {request.LayerProgressionState}");
			LocalProgressionManager.Instance.IncreaseLayerProgression(request.Layer, request.LayerProgressionState);
			return Task.FromResult<LayerProgressionResult>(new LayerProgressionResult
			{
				SessionBlob = ((SessionRequestBase)request).SessionBlob
			});
		}

		public Task<EndSessionResult> EndSessionAsync(EndSessionRequest request)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			PerBoosterCategoryInt boosterCurrency = request.BoosterCurrency;
			Plugin.L.Warning($"{"LocalDropServerAPI"}: {"EndSessionAsync"} Success: {request.Success}, BoosterCurrency: M:{boosterCurrency.Basic}, B:{boosterCurrency.Advanced}, A:{boosterCurrency.Specialized}");
			LocalProgressionManager.Instance.EndCurrentExpeditionSession(request.Success);
			LocalBoosterManager.Instance.EndSession(request.BoosterCurrency);
			return Task.FromResult<EndSessionResult>(new EndSessionResult());
		}

		public Task<GetBoosterImplantPlayerDataResult> GetBoosterImplantPlayerDataAsync(GetBoosterImplantPlayerDataRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: GetBoosterImplantPlayerDataAsync");
			return Task.FromResult<GetBoosterImplantPlayerDataResult>(new GetBoosterImplantPlayerDataResult
			{
				Data = LocalBoosterManager.Instance.GetBoosterImplantPlayerData(request.MaxBackendTemplateId)
			});
		}

		public Task<UpdateBoosterImplantPlayerDataResult> UpdateBoosterImplantPlayerDataAsync(UpdateBoosterImplantPlayerDataRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: UpdateBoosterImplantPlayerDataAsync");
			return Task.FromResult<UpdateBoosterImplantPlayerDataResult>(new UpdateBoosterImplantPlayerDataResult
			{
				Data = LocalBoosterManager.Instance.UpdateBoosterImplantPlayerData(request.Transaction)
			});
		}

		public Task<ConsumeBoostersResult> ConsumeBoostersAsync(ConsumeBoostersRequest request)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: ConsumeBoostersAsync");
			LocalBoosterManager.Instance.ConsumeBoosters(((SessionRequestBase)request).SessionBlob);
			return Task.FromResult<ConsumeBoostersResult>(new ConsumeBoostersResult
			{
				SessionBlob = ((SessionRequestBase)request).SessionBlob
			});
		}

		public Task<GetInventoryPlayerDataResult> GetInventoryPlayerDataAsync(GetInventoryPlayerDataRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: GetInventoryPlayerDataAsync");
			return Task.FromResult<GetInventoryPlayerDataResult>(new GetInventoryPlayerDataResult
			{
				Boosters = LocalBoosterManager.Instance.GetBoosterImplantPlayerData(request.MaxBackendTemplateId),
				VanityItems = LocalVanityItemManager.Instance.GetVanityItemPlayerData()
			});
		}

		public Task<UpdateVanityItemPlayerDataResult> UpdateVanityItemPlayerDataAsync(UpdateVanityItemPlayerDataRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: UpdateVanityItemPlayerDataAsync");
			return Task.FromResult<UpdateVanityItemPlayerDataResult>(new UpdateVanityItemPlayerDataResult
			{
				Data = LocalVanityItemManager.Instance.ProcessTransaction(request.Transaction)
			});
		}

		public Task<DebugBoosterImplantResult> DebugBoosterImplantAsync(DebugBoosterImplantRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: DebugBoosterImplantAsync");
			return Task.FromResult<DebugBoosterImplantResult>(new DebugBoosterImplantResult());
		}

		public Task<DebugVanityItemResult> DebugVanityItemAsync(DebugVanityItemRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: DebugVanityItemAsync");
			return Task.FromResult<DebugVanityItemResult>(new DebugVanityItemResult());
		}

		public Task<AddResult> AddAsync(AddRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: AddAsync");
			return Task.FromResult<AddResult>(new AddResult
			{
				Sum = request.X + request.Y
			});
		}

		public Task<IsTesterResult> IsTesterAsync(IsTesterRequest request)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Plugin.L.Warning("LocalDropServerAPI: IsTesterAsync");
			return Task.FromResult<IsTesterResult>(new IsTesterResult
			{
				IsTester = false
			});
		}
	}
}
namespace SimpleProgression.Core
{
	public class LocalBoosterDropper
	{
		private static LocalBoosterDropper _instance;

		private readonly ILogger _logger;

		public static LocalBoosterDropper Instance => _instance ?? (_instance = new LocalBoosterDropper(Plugin.L));

		public bool Inited { get; private set; }

		public BoosterImplantTemplateDataBlock[] MutedTemplates { get; private set; }

		public BoosterImplantTemplateDataBlock[] BoldTemplates { get; private set; }

		public BoosterImplantTemplateDataBlock[] AgrressiveTemplates { get; private set; }

		public BoosterImplantEffectDataBlock[] Effects { get; private set; }

		public BoosterImplantConditionDataBlock[] Conditions { get; private set; }

		public static int BOOSTER_DROP_MAX_REROLL_COUNT { get; internal set; } = 25;


		private LocalBoosterDropper(ILogger logger)
		{
			_logger = logger;
		}

		public void Init()
		{
			if (Inited)
			{
				_logger.Info("LocalBoosterDropper already setup, skipping ...");
				return;
			}
			_logger.Info("Setting up LocalBoosterDropper ...");
			Load();
			Inited = true;
		}

		internal void Load()
		{
			BoosterImplantTemplateDataBlock[] source = Il2CppArrayBase<BoosterImplantTemplateDataBlock>.op_Implicit(GameDataBlockBase<BoosterImplantTemplateDataBlock>.GetAllBlocks());
			MutedTemplates = source.Where((BoosterImplantTemplateDataBlock t) => (int)t.ImplantCategory == 0).ToArray();
			BoldTemplates = source.Where((BoosterImplantTemplateDataBlock t) => (int)t.ImplantCategory == 1).ToArray();
			AgrressiveTemplates = source.Where((BoosterImplantTemplateDataBlock t) => (int)t.ImplantCategory == 2).ToArray();
			Effects = Il2CppArrayBase<BoosterImplantEffectDataBlock>.op_Implicit(GameDataBlockBase<BoosterImplantEffectDataBlock>.GetAllBlocks());
			Conditions = Il2CppArrayBase<BoosterImplantConditionDataBlock>.op_Implicit(GameDataBlockBase<BoosterImplantConditionDataBlock>.GetAllBlocks());
			if (MutedTemplates.Length == 0 && BoldTemplates.Length == 0 && AgrressiveTemplates.Length == 0)
			{
				LocalBoosterManager.Instance.Disabled = true;
				_logger.Msg(ConsoleColor.Magenta, "LocalBoosterDropper.Init() complete, no templates set -> boosters disabled!");
				return;
			}
			_logger.Msg(ConsoleColor.Magenta, $"{"LocalBoosterDropper"}.{"Init"}() complete, retrieved {MutedTemplates.Length} Muted, {BoldTemplates.Length} Bold and {AgrressiveTemplates.Length} Agrressive Templates as well as {Effects?.Length} Effects and {Conditions?.Length} Conditions.");
		}

		private void InitCheck()
		{
			if (!Inited)
			{
				throw new InvalidOperationException("LocalVanityItemDropper has not been initialized yet!");
			}
		}

		public LocalDropServerBoosterImplantInventoryItem GenerateBooster(LocalBoosterImplant.SaveBoosterImplantCategory category, uint[] usedIds)
		{
			InitCheck();
			float num = 1f;
			int num2 = 0;
			BoosterImplantTemplateDataBlock val;
			do
			{
				val = (BoosterImplantTemplateDataBlock)(category switch
				{
					LocalBoosterImplant.SaveBoosterImplantCategory.Bold => BoldTemplates[Random.Range(0, BoldTemplates.Length)], 
					LocalBoosterImplant.SaveBoosterImplantCategory.Aggressive => AgrressiveTemplates[Random.Range(0, AgrressiveTemplates.Length)], 
					_ => MutedTemplates[Random.Range(0, MutedTemplates.Length)], 
				});
				if (val != null)
				{
					if (num2 > BOOSTER_DROP_MAX_REROLL_COUNT)
					{
						break;
					}
					num = 1f;
					if (val.DropWeight != 0f)
					{
						num = 1f / val.DropWeight;
					}
					num2++;
				}
			}
			while (val == null || Random.Range(0f, 1f) > num);
			SPConfig.RandomizationOptions dropRandomization = Plugin.SPConfig.DropRandomization;
			int uses = category switch
			{
				LocalBoosterImplant.SaveBoosterImplantCategory.Bold => Random.Range(dropRandomization.BoldUsesMin, dropRandomization.BoldUsesMax + 1), 
				LocalBoosterImplant.SaveBoosterImplantCategory.Aggressive => Random.Range(dropRandomization.AggressiveUsesMin, dropRandomization.AggressiveUsesMax + 1), 
				_ => Random.Range(dropRandomization.MutedUsesMin, dropRandomization.MutedUsesMax + 1), 
			};
			List<uint> conditionIds = new List<uint>();
			List<LocalBoosterImplant.Effect> effects = new List<LocalBoosterImplant.Effect>();
			Enumerator<BoosterImplantEffectInstance> enumerator = val.Effects.GetEnumerator();
			while (enumerator.MoveNext())
			{
				BoosterImplantEffectInstance current = enumerator.Current;
				effects.Add(new LocalBoosterImplant.Effect
				{
					Id = current.BoosterImplantEffect,
					Value = Random.Range(current.MinValue, current.MaxValue)
				});
			}
			Enumerator<List<BoosterImplantEffectInstance>> enumerator2 = val.RandomEffects.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				List<BoosterImplantEffectInstance> current2 = enumerator2.Current;
				if (current2 != null && current2.Count >= 1)
				{
					BoosterImplantEffectInstance val2 = current2[Random.Range(0, current2.Count)];
					effects.Add(new LocalBoosterImplant.Effect
					{
						Id = val2.BoosterImplantEffect,
						Value = Random.Range(val2.MinValue, val2.MaxValue)
					});
				}
			}
			Enumerator<uint> enumerator3 = val.Conditions.GetEnumerator();
			while (enumerator3.MoveNext())
			{
				uint current3 = enumerator3.Current;
				conditionIds.Add(current3);
			}
			if (val.RandomConditions != null && val.RandomConditions.Count > 0)
			{
				conditionIds.Add(val.RandomConditions[Random.Range(0, val.RandomConditions.Count)]);
			}
			uint instanceId = GenerateInstanceId(usedIds);
			LocalDropServerBoosterImplantInventoryItem localDropServerBoosterImplantInventoryItem = new LocalDropServerBoosterImplantInventoryItem(((GameDataBlockBase<BoosterImplantTemplateDataBlock>)(object)val).persistentID, instanceId, uses, effects.ToArray(), conditionIds.ToArray());
			localDropServerBoosterImplantInventoryItem.Category = category;
			localDropServerBoosterImplantInventoryItem.Template = val;
			BoosterImplantEffectDataBlock val3 = null;
			BoosterImplantConditionDataBlock val4 = null;
			try
			{
				if (effects.Count > 0)
				{
					val3 = Effects.First((BoosterImplantEffectDataBlock ef) => ((GameDataBlockBase<BoosterImplantEffectDataBlock>)(object)ef).persistentID == effects[0].Id);
				}
				if (conditionIds.Count > 0)
				{
					val4 = Conditions.First((BoosterImplantConditionDataBlock cd) => ((GameDataBlockBase<BoosterImplantConditionDataBlock>)(object)cd).persistentID == conditionIds[0]);
				}
			}
			catch (Exception)
			{
			}
			_logger.Msg(ConsoleColor.Magenta, $"Generated booster: {val.PublicName} - {((val3 != null) ? val3.PublicShortName : null)} {((val4 != null) ? val4.PublicShortName : null)} ({((val3 != null) ? val3.PublicName : null)} when {((val4 != null) ? val4.PublicName : null)})");
			return localDropServerBoosterImplantInventoryItem;
		}

		private static uint GenerateInstanceId(uint[] usedIds)
		{
			if (usedIds == null || usedIds.Length == 0)
			{
				return 1u;
			}
			uint count;
			for (count = 1u; usedIds.Any((uint i) => i == count); count++)
			{
			}
			return count;
		}

		public void GenerateAndAddBooster(ref LocalBoosterImplantPlayerData data, LocalBoosterImplant.SaveBoosterImplantCategory category)
		{
			InitCheck();
			LocalDropServerBoosterImplantInventoryItem newBooster = GenerateBooster(category, data.GetUsedIds());
			if (!data.TryAddBooster(newBooster))
			{
				_logger.Info($"Did not add Booster as the inventory for category {category} is full! (This message should not appear!)");
			}
		}
	}
	public class LocalBoosterManager
	{
		private static LocalBoosterManager _instance;

		private readonly ILogger _logger;

		private static LocalBoosterImplantPlayerData _localBoosterImplantPlayerData = null;

		public static LocalBoosterManager Instance => _instance ?? (_instance = new LocalBoosterManager(Plugin.L));

		public bool Disabled { get; internal set; }

		public static bool DoConsumeBoosters { get; set; } = true;


		public static LocalBoosterImplantPlayerData LocalBoosterImplantPlayerData => _localBoosterImplantPlayerData ?? (_localBoosterImplantPlayerData = LoadFromBoosterFile());

		public static uint[] BoostersToBeConsumed { get; private set; } = Array.Empty<uint>();


		public static LocalBoosterDropper BoosterDropper => LocalBoosterDropper.Instance;

		private LocalBoosterManager(ILogger logger)
		{
			_logger = logger;
		}

		internal static void SaveBoostersToDisk()
		{
			SaveToBoosterFile(LocalBoosterImplantPlayerData);
		}

		internal BoosterImplantPlayerData UpdateBoosterImplantPlayerData(BoosterImplantTransaction transaction)
		{
			if (Instance.Disabled)
			{
				return LocalBoosterImplantPlayerData.ToBaseGame();
			}
			if (transaction.DropIds != null)
			{
				LocalBoosterImplantPlayerData.DropBoostersWithIds(((IEnumerable<uint>)transaction.DropIds).ToArray());
			}
			if (transaction.TouchIds != null)
			{
				LocalBoosterImplantPlayerData.SetBoostersTouchedWithIds(((IEnumerable<uint>)transaction.TouchIds).ToArray());
			}
			if (transaction.AcknowledgeIds != null)
			{
				LocalBoosterImplantPlayerData.AcknowledgeBoostersWithIds(((IEnumerable<uint>)transaction.AcknowledgeIds).ToArray());
			}
			if (transaction.AcknowledgeMissed != null)
			{
				LocalBoosterImplantPlayerData.AcknowledgeMissedBoostersWithIds(transaction.AcknowledgeMissed);
			}
			SaveBoostersToDisk();
			return LocalBoosterImplantPlayerData.ToBaseGame();
		}

		public BoosterImplantPlayerData GetBoosterImplantPlayerData(uint maxBackendTemplateId)
		{
			SaveBoostersToDisk();
			return LocalBoosterImplantPlayerData.ToBaseGame();
		}

		public void ConsumeBoosters(string sessionBlob)
		{
			if (!Instance.Disabled)
			{
				if (DoConsumeBoosters)
				{
					LocalBoosterImplantPlayerData.ConsumeBoostersWithIds(BoostersToBeConsumed);
					SaveBoostersToDisk();
				}
				BoostersToBeConsumed = Array.Empty<uint>();
			}
		}

		internal void EndSession(PerBoosterCategoryInt boosterCurrency)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (Instance.Disabled)
			{
				return;
			}
			LocalBoosterImplantPlayerData.AddCurrency(boosterCurrency);
			LocalBoosterImplantPlayerData.CustomCategory[] categoriesWhereCurrencyCostHasBeenReached = LocalBoosterImplantPlayerData.GetCategoriesWhereCurrencyCostHasBeenReached();
			foreach (LocalBoosterImplantPlayerData.CustomCategory customCategory in categoriesWhereCurrencyCostHasBeenReached)
			{
				while (customCategory.HasEnoughCurrencyForDrop)
				{
					customCategory.Currency -= LocalBoosterImplantPlayerData.CurrencyNewBoosterCost;
					if (customCategory.InventoryIsFull)
					{
						_logger.Warning($"Inventory full, missed 1 {customCategory.CategoryType} booster.");
						customCategory.Missed++;
					}
					else
					{
						_logger.Notice($"Generating 1 {customCategory.CategoryType} booster ... [CurrencyRemaining:{customCategory.Currency}]");
						BoosterDropper.GenerateAndAddBooster(ref _localBoosterImplantPlayerData, customCategory.CategoryType);
					}
				}
			}
			SaveBoostersToDisk();
		}

		internal void StartSession(uint[] boosterIds, string sessionId)
		{
			BoostersToBeConsumed = boosterIds;
		}

		private static void SaveToBoosterFile(LocalBoosterImplantPlayerData data)
		{
			if (!Instance.Disabled)
			{
				if (data == null)
				{
					throw new ArgumentNullException("data");
				}
				Instance._logger.Msg(ConsoleColor.DarkRed, "Saving boosters to disk at: " + Paths.BoostersFilePath);
				string contents = JsonConvert.SerializeObject((object)data, (Formatting)1);
				File.WriteAllText(Paths.BoostersFilePath, contents);
			}
		}

		private static LocalBoosterImplantPlayerData LoadFromBoosterFile()
		{
			if (Instance.Disabled)
			{
				return new LocalBoosterImplantPlayerData();
			}
			Instance._logger.Msg(ConsoleColor.Green, "Loading boosters from disk at: " + Paths.BoostersFilePath);
			if (!File.Exists(Paths.BoostersFilePath))
			{
				return new LocalBoosterImplantPlayerData();
			}
			return JsonConvert.DeserializeObject<LocalBoosterImplantPlayerData>(File.ReadAllText(Paths.BoostersFilePath));
		}
	}
	public class LocalProgressionManager
	{
		private static LocalProgressionManager _instance;

		private readonly ILogger _logger;

		public static LocalProgressionManager Instance => _instance ?? (_instance = new LocalProgressionManager(Plugin.L));

		public ExpeditionSession CurrentActiveSession { get; private set; }

		public Dictionary<string, LocalRundownProgression> LoadedProgressionData { get; } = new Dictionary<string, LocalRundownProgression>();


		public static event Action<ExpeditionSession> OnExpeditionEntered;

		public static event Action<ExpeditionCompletionData> OnExpeditionCompleted;

		private LocalProgressionManager(ILogger logger)
		{
			_logger = logger;
		}

		public bool TryGetLocalProgression(string rundownKey, out LocalRundownProgression progression)
		{
			return LoadedProgressionData.TryGetValue(rundownKey, out progression);
		}

		public LocalRundownProgression GetOrCreateLocalProgression(uint rundownDataBlockPersistentId)
		{
			return GetOrCreateLocalProgression($"Local_{rundownDataBlockPersistentId}");
		}

		public LocalRundownProgression GetOrCreateLocalProgression(string rundownKeyToLoad)
		{
			if (string.IsNullOrWhiteSpace(rundownKeyToLoad))
			{
				throw new ArgumentException(null, "rundownKeyToLoad");
			}
			if (TryGetLocalProgression(rundownKeyToLoad, out var progression))
			{
				return progression;
			}
			LocalRundownProgression localRundownProgression = LoadFromProgressionFile(rundownKeyToLoad);
			LoadedProgressionData.Add(rundownKeyToLoad, localRundownProgression);
			return localRundownProgression;
		}

		public void StartNewExpeditionSession(string rundownKey, string expeditionId, string sessionId)
		{
			CurrentActiveSession = ExpeditionSession.InitNewSession(rundownKey, expeditionId, sessionId, _logger);
		}

		public void OnLevelEntered()
		{
			CurrentActiveSession?.OnLevelEntered();
			LocalProgressionManager.OnExpeditionEntered?.Invoke(CurrentActiveSession);
		}

		internal void IncreaseLayerProgression(string strLayer, string strState)
		{
			if (!Enum.TryParse<Layers>(strLayer, out var result) | !Enum.TryParse<LayerState>(strState, out var result2))
			{
				_logger.Error($"Either {"Layers"} and/or {"LayerState"} could not be parsed! ({strLayer}, {strState})");
			}
			else
			{
				CurrentActiveSession?.SetLayer(result, result2);
			}
		}

		internal void SaveAtCheckpoint()
		{
			CurrentActiveSession?.OnCheckpointSave();
		}

		internal void ReloadFromCheckpoint()
		{
			CurrentActiveSession?.OnCheckpointReset();
		}

		internal void ArtifactCountUpdated(int mutedCount, int boldCount, int aggressiveCount)
		{
			if (CurrentActiveSession != null)
			{
				CurrentActiveSession.MutedArtifactsCollected = mutedCount;
				CurrentActiveSession.BoldArtifactsCollected = boldCount;
				CurrentActiveSession.AggressiveArtifactsCollected = aggressiveCount;
				_logger.Info($"current Artifact count: Muted:{mutedCount}, Bold:{boldCount}, Aggressive:{aggressiveCount}");
			}
		}

		internal void EndCurrentExpeditionSession(bool success)
		{
			CurrentActiveSession?.OnExpeditionCompleted(success);
			string text = CurrentActiveSession?.RundownKey;
			LocalRundownProgression orCreateLocalProgression = GetOrCreateLocalProgression(text);
			ExpeditionCompletionData completionData;
			bool num = orCreateLocalProgression.AddSessionResults(CurrentActiveSession, out completionData);
			SaveToProgressionFile(orCreateLocalProgression, text);
			CurrentActiveSession = null;
			if (num)
			{
				_logger.Notice($"Expedition time: {completionData.RawSessionData.EndTime - completionData.RawSessionData.StartTime}");
				LocalProgressionManager.OnExpeditionCompleted?.Invoke(completionData);
			}
		}

		private void SaveToProgressionFile(LocalRundownProgression data, string rundownKey)
		{
			SaveToProgressionFile(data, rundownKey, out var path);
			Instance._logger.Msg(ConsoleColor.DarkRed, "Saved progression file to disk at: " + path);
		}

		private static void SaveToProgressionFile(LocalRundownProgression data, string rundownKeyToSave, out string path)
		{
			if (data == null)
			{
				throw new ArgumentNullException("data");
			}
			if (string.IsNullOrEmpty(rundownKeyToSave))
			{
				throw new InvalidOperationException("rundownKeyToSave");
			}
			path = GetLocalProgressionFilePath(rundownKeyToSave);
			string contents = JsonConvert.SerializeObject((object)data, (Formatting)1);
			File.WriteAllText(path, contents);
		}

		private static string GetLocalProgressionFilePath(string rundownKey)
		{
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			foreach (char oldChar in invalidFileNameChars)
			{
				rundownKey = rundownKey.Replace(oldChar, '_');
			}
			return Path.Combine(Paths.SaveFolderPath, rundownKey + ".json");
		}

		private LocalRundownProgression LoadFromProgressionFile(string rundownKey)
		{
			string path;
			bool isNew;
			LocalRundownProgression localRundownProgression = LoadFromProgressionFile(rundownKey, out path, out isNew);
			if (isNew)
			{
				Instance._logger.Msg(ConsoleColor.Green, "Created progression file at: " + path);
				SaveToProgressionFile(localRundownProgression, rundownKey, out var path2);
				Instance._logger.Msg(ConsoleColor.DarkRed, "Saved fresh progression file to disk at: " + path2);
			}
			else
			{
				Instance._logger.Msg(ConsoleColor.Green, "Loaded progression file from disk at: " + path);
			}
			return localRundownProgression;
		}

		private static LocalRundownProgression LoadFromProgressionFile(string rundownKey, out string path, out bool isNew)
		{
			path = GetLocalProgressionFilePath(rundownKey);
			if (!File.Exists(path))
			{
				isNew = true;
				return new LocalRundownProgression();
			}
			isNew = false;
			return JsonConvert.DeserializeObject<LocalRundownProgression>(File.ReadAllText(path));
		}
	}
	public class LocalVanityItemDropper
	{
		private static LocalVanityItemDropper _instance;

		private readonly ILogger _logger;

		public static LocalVanityItemDropper Instance => _instance ?? (_instance = new LocalVanityItemDropper(Plugin.L));

		public bool IsSetup { get; private set; }

		public VanityItemsGroupDataBlock[] ItemGroups { get; private set; }

		public VanityItemsTemplateDataBlock[] ItemTemplates { get; private set; }

		public VanityItemsLayerDropsDataBlock[] ItemDropData { get; private set; }

		public static event Action<LocalVanityItemDropper> OnSetupDone;

		private LocalVanityItemDropper(ILogger logger)
		{
			_logger = logger;
		}

		private void InitCheck()
		{
			if (!IsSetup)
			{
				throw new InvalidOperationException("LocalVanityItemDropper has not been initialized yet!");
			}
		}

		internal void Init()
		{
			if (IsSetup)
			{
				_logger.Info("LocalVanityItemDropper already setup, skipping ...");
				return;
			}
			LoadTemplatesGroupsAndDropData();
			IsSetup = true;
			LocalVanityItemDropper.OnSetupDone?.Invoke(this);
		}

		internal void LoadTemplatesGroupsAndDropData()
		{
			ItemGroups = Il2CppArrayBase<VanityItemsGroupDataBlock>.op_Implicit(GameDataBlockBase<VanityItemsGroupDataBlock>.GetAllBlocks());
			ItemTemplates = Il2CppArrayBase<VanityItemsTemplateDataBlock>.op_Implicit(GameDataBlockBase<VanityItemsTemplateDataBlock>.GetAllBlocks());
			ItemDropData = Il2CppArrayBase<VanityItemsLayerDropsDataBlock>.op_Implicit(GameDataBlockBase<VanityItemsLayerDropsDataBlock>.GetAllBlocks());
			if (ItemGroups.Length == 0 && ItemDropData.Length == 0)
			{
				_logger.Msg(ConsoleColor.Magenta, $"{"LocalVanityItemDropper"}.{"Init"}() complete, no groups or layer drops set! (Found {ItemTemplates.Length} Templates)");
				return;
			}
			_logger.Msg(ConsoleColor.Magenta, $"{"LocalVanityItemDropper"}.{"Init"}() complete, retrieved {ItemTemplates.Length} Templates, {ItemGroups.Length} Groups and {ItemDropData.Length} Layer Drops. Layer Drops:");
			VanityItemsLayerDropsDataBlock[] itemDropData = ItemDropData;
			foreach (VanityItemsLayerDropsDataBlock val in itemDropData)
			{
				_logger.Info($" > {((GameDataBlockBase<VanityItemsLayerDropsDataBlock>)(object)val).name}: #Drops: {val.LayerDrops?.Count ?? 0}, Enabled: {((GameDataBlockBase<VanityItemsLayerDropsDataBlock>)(object)val).internalEnabled}");
			}
		}

		public bool TryGetGroup(uint persistentID, out VanityItemsGroupDataBlock itemGroup)
		{
			InitCheck();
			VanityItemsGroupDataBlock[] itemGroups = ItemGroups;
			foreach (VanityItemsGroupDataBlock val in itemGroups)
			{
				if (((GameDataBlockBase<VanityItemsGroupDataBlock>)(object)val).persistentID == persistentID)
				{
					itemGroup = val;
					return true;
				}
			}
			itemGroup = null;
			return false;
		}

		public bool DropRandomFromGroup(uint groupID, LocalVanityItemStorage playerData, bool silentDrop = false)
		{
			InitCheck();
			if (!TryGetGroup(groupID, out var itemGroup) || itemGroup.HasAllOwned(playerData))
			{
				return false;
			}
			_logger.Msg(ConsoleColor.Magenta, $"Attempting drop of 1 Vanity Item from group \"{((GameDataBlockBase<VanityItemsGroupDataBlock>)(object)itemGroup).name}\" (ID:{groupID})");
			if (!itemGroup.GetNonOwned(playerData).TryPickRandom(out var value))
			{
				_logger.Info("All items in group already in local player inventory, not dropping!");
				return false;
			}
			if (!TryGetTemplate(value, out var template))
			{
				_logger.Warning($"Template with ID {value} wasn't found!");
			}
			LocalVanityItemStorage.LocalVanityItem item = new LocalVanityItemStorage.LocalVanityItem
			{
				ItemID = value,
				Flags = (silentDrop ? LocalVanityItemStorage.VanityItemFlags.ALL : LocalVanityItemStorage.VanityItemFlags.None),
				CustomKey = (IsCustomGroup(itemGroup) ? ((GameDataBlockBase<VanityItemsTemplateDataBlock>)(object)template).name : null)
			};
			playerData.Items.Add(item);
			_logger.Info("Dropped Vanity Item \"" + (((template != null) ? template.publicName : null) ?? $"ID:{value}") + "\"!");
			return true;
		}

		public bool TryDropCustomItem(VanityItemsTemplateDataBlock template, bool silentDrop = false, bool doDropAlreadyOwnedItem = false)
		{
			InitCheck();
			LocalVanityItemStorage localVanityItemPlayerData = LocalVanityItemManager.Instance.LocalVanityItemPlayerData;
			if (doDropAlreadyOwnedItem || localVanityItemPlayerData.Items.FirstOrDefault((LocalVanityItemStorage.LocalVanityItem item) => item.IsCustom && item.CustomKey == ((GameDataBlockBase<VanityItemsTemplateDataBlock>