Decompiled source of FreeUpgradeEveryRound v1.0.2

FreeUpgradeEveryRound.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MenuLib;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using REPOUpgradeAPI;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("Kai")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FreeUpgradeEveryRound")]
[assembly: AssemblyTitle("FreeUpgradeEveryRound")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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;
		}
	}
}
namespace FreeUpgradeEveryRound
{
	internal static class DraftGenerator
	{
		internal static readonly string[] UpgradeKeys = new string[12]
		{
			"Stamina", "Health", "Wings", "Launch", "Climb", "Rest", "Speed", "Jump", "Strength", "Range",
			"Battery", "Map"
		};

		internal const int DraftCount = 4;

		internal static string[] GenerateDraft()
		{
			List<string> list = new List<string>();
			string[] upgradeKeys = UpgradeKeys;
			foreach (string text in upgradeKeys)
			{
				int weight = UpgradeConfig.GetWeight(text);
				if (weight > 0)
				{
					for (int j = 0; j < weight; j++)
					{
						list.Add(text);
					}
				}
			}
			HashSet<string> hashSet = new HashSet<string>();
			while (hashSet.Count < 4 && list.Count > 0)
			{
				int index = Random.Range(0, list.Count);
				string chosen = list[index];
				hashSet.Add(chosen);
				list.RemoveAll((string x) => x == chosen);
			}
			return new List<string>(hashSet).ToArray();
		}
	}
	internal static class DraftKeyMap
	{
		private static readonly Dictionary<string, string> map = new Dictionary<string, string>
		{
			{ "Stamina", "energy" },
			{ "Health", "health" },
			{ "Wings", "wings" },
			{ "Launch", "launch" },
			{ "Climb", "climb" },
			{ "Rest", "crouch" },
			{ "Speed", "sprint" },
			{ "Jump", "jump" },
			{ "Strength", "grabstr" },
			{ "Range", "grabrange" },
			{ "Battery", "battery" },
			{ "Map", "mapcount" }
		};

		public static string ToAPIKey(string draftKey)
		{
			if (draftKey == null)
			{
				return string.Empty;
			}
			if (map.TryGetValue(draftKey, out string value))
			{
				return value;
			}
			FreeUpgradeEveryRound.Logger.LogWarning((object)("[FreeUpgrade] Unknown draft key: " + draftKey));
			return draftKey.ToLowerInvariant();
		}
	}
	[BepInPlugin("Kai.FreeUpgradeEveryRound", "FreeUpgradeEveryRound", "0.1.2")]
	public class FreeUpgradeEveryRound : BaseUnityPlugin
	{
		internal static Dictionary<string, int> FreeSlotsDict = new Dictionary<string, int>();

		internal static Dictionary<string, int> LastFreeLevelDict = new Dictionary<string, int>();

		internal static readonly Dictionary<string, string[]> RuntimeDrafts = new Dictionary<string, string[]>();

		internal static bool HasSyncedFromSave = false;

		internal static FreeUpgradeEveryRound Instance { get; private set; } = null;


		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			UpgradeConfig.Load(((BaseUnityPlugin)this).Config);
			UpgradeConfig.Init(((BaseUnityPlugin)this).Config);
			Patch();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		internal void Patch()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0025: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static void SyncFreeSlotForPlayer(string steamID, int currentLevel)
		{
			if (!FreeSlotsDict.ContainsKey(steamID))
			{
				FreeSlotsDict[steamID] = 0;
			}
			if (!LastFreeLevelDict.ContainsKey(steamID))
			{
				LastFreeLevelDict[steamID] = 0;
			}
			int num = LastFreeLevelDict[steamID];
			int num2 = currentLevel - num;
			if (num2 > 0)
			{
				FreeSlotsDict[steamID] += num2;
				LastFreeLevelDict[steamID] = currentLevel;
				Logger.LogInfo((object)$"[FreeUpgrade] steamID={steamID} level jump {num} → {currentLevel}, +{num2} free slots (now={FreeSlotsDict[steamID]})");
			}
		}

		internal static void SyncFromStatsManager()
		{
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Logger.LogWarning((object)"[FreeUpgrade] StatsManager が見つかりませんでした。同期をスキップ");
				return;
			}
			Dictionary<string, Dictionary<string, int>> dictionaryOfDictionaries = instance.dictionaryOfDictionaries;
			if (dictionaryOfDictionaries.TryGetValue("FreeUpgrade_freeSlots", out var value))
			{
				FreeSlotsDict = value;
			}
			if (dictionaryOfDictionaries.TryGetValue("FreeUpgrade_lastFreeLevel", out var value2))
			{
				LastFreeLevelDict = value2;
			}
			Logger.LogInfo((object)"[FreeUpgrade] StatsManager → FreeUpgradeEveryRound 辞書へ同期完了");
			HasSyncedFromSave = true;
			foreach (string key in FreeSlotsDict.Keys)
			{
				int levelsCompleted = RunManager.instance.levelsCompleted;
				SyncFreeSlotForPlayer(key, levelsCompleted);
			}
		}

		internal static void SyncToStatsManager()
		{
			StatsManager instance = StatsManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Logger.LogWarning((object)"[FreeUpgrade] StatsManager が見つかりませんでした。同期をスキップ");
				return;
			}
			Dictionary<string, Dictionary<string, int>> dictionaryOfDictionaries = instance.dictionaryOfDictionaries;
			dictionaryOfDictionaries["FreeUpgrade_freeSlots"] = FreeSlotsDict;
			dictionaryOfDictionaries["FreeUpgrade_lastFreeLevel"] = LastFreeLevelDict;
			Logger.LogInfo((object)"[FreeUpgrade] FreeSlots と LastFreeLevel を StatsManager と同期しました");
		}
	}
	public class FreeUpgradeNet : MonoBehaviourPun
	{
		public static FreeUpgradeNet Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
		}

		[PunRPC]
		public void FUE_ReceiveDraft(string steamID, string[] draft)
		{
			FreeUpgradeEveryRound.RuntimeDrafts[steamID] = draft;
			string playerSteamID = PlayerController.instance.playerSteamID;
			if (playerSteamID != steamID)
			{
				return;
			}
			if (FreeUpgradeEveryRound.FreeSlotsDict.TryGetValue(steamID, out var value) && value <= 0)
			{
				if ((Object)(object)MenuManager.instance != (Object)null)
				{
					MenuManager.instance.PageCloseAll();
				}
			}
			else
			{
				MenuManager.instance.PageCloseAll();
				FreeUpgrade_InputPatch.OpenUI(steamID);
			}
		}

		[PunRPC]
		public void FUE_UpdateFreeSlots(string steamID, int newFreeSlots)
		{
			FreeUpgradeEveryRound.FreeSlotsDict[steamID] = newFreeSlots;
			FreeUpgradeEveryRound.Logger.LogInfo((object)$"[FreeUpgrade] Free slots updated for {steamID}: {newFreeSlots}");
			if ((Object)(object)PlayerController.instance != (Object)null && PlayerController.instance.playerSteamID == steamID)
			{
				if ((Object)(object)MenuManager.instance != (Object)null)
				{
					MenuManager.instance.PageCloseAll();
				}
				FreeUpgrade_InputPatch.OpenUI(steamID);
			}
		}

		[PunRPC]
		public void FUE_SelectUpgrade(string steamID, string typeKey, PhotonMessageInfo info)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			if (!FreeUpgradeEveryRound.FreeSlotsDict.TryGetValue(steamID, out var value) || value <= 0)
			{
				FreeUpgradeEveryRound.Logger.LogWarning((object)("[FreeUpgrade] Player " + steamID + " has no free slots."));
				return;
			}
			FreeUpgradeEveryRound.FreeSlotsDict[steamID] = value - 1;
			((MonoBehaviourPun)Instance).photonView.RPC("FUE_UpdateFreeSlots", (RpcTarget)0, new object[2]
			{
				steamID,
				FreeUpgradeEveryRound.FreeSlotsDict[steamID]
			});
			string text = DraftKeyMap.ToAPIKey(typeKey);
			UpgradeAPI.Add(text, 1, steamID);
			FreeUpgradeEveryRound.Logger.LogInfo((object)$"[FreeUpgrade] {steamID} selected {typeKey} → internal:{text}. Free slots now: {FreeUpgradeEveryRound.FreeSlotsDict[steamID]}");
			if (FreeUpgradeEveryRound.FreeSlotsDict[steamID] > 0)
			{
				string[] array = DraftGenerator.GenerateDraft();
				FreeUpgradeEveryRound.RuntimeDrafts[steamID] = array;
				if ((Object)(object)Instance == (Object)null || (Object)(object)((MonoBehaviourPun)Instance).photonView == (Object)null)
				{
					Debug.LogError((object)"[FreeUpgrade] FreeUpgradeNet.Instance or photonView is null!");
					return;
				}
				((MonoBehaviourPun)Instance).photonView.RPC("FUE_ReceiveDraft", (RpcTarget)0, new object[2] { steamID, array });
			}
			else if (FreeUpgradeEveryRound.RuntimeDrafts.ContainsKey(steamID))
			{
				FreeUpgradeEveryRound.RuntimeDrafts.Remove(steamID);
			}
		}

		public static void SendDraftToAll(string steamID, string[] draft)
		{
			if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom)
			{
				FreeUpgradeEveryRound.RuntimeDrafts[steamID] = draft;
				FreeUpgrade_InputPatch.OpenUI(steamID);
			}
			else
			{
				((MonoBehaviourPun)Instance).photonView.RPC("FUE_ReceiveDraft", (RpcTarget)0, new object[2] { steamID, draft });
			}
		}

		public static void SendSelectToHost(string steamID, string typeKey)
		{
			if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom)
			{
				FreeUpgradeEveryRound.Logger.LogInfo((object)"[FreeUpgrade] SP mode: direct apply");
				if (!FreeUpgradeEveryRound.FreeSlotsDict.TryGetValue(steamID, out var value) || value <= 0)
				{
					FreeUpgradeEveryRound.Logger.LogWarning((object)("[FreeUpgrade] Player " + steamID + " has no free slots."));
					return;
				}
				FreeUpgradeEveryRound.FreeSlotsDict[steamID] = value - 1;
				string text = DraftKeyMap.ToAPIKey(typeKey);
				UpgradeAPI.Add(text, 1, steamID);
				if (FreeUpgradeEveryRound.FreeSlotsDict[steamID] > 0)
				{
					string[] value2 = DraftGenerator.GenerateDraft();
					FreeUpgradeEveryRound.RuntimeDrafts[steamID] = value2;
					FreeUpgrade_InputPatch.OpenUI(steamID);
					return;
				}
				FreeUpgradeEveryRound.RuntimeDrafts.Remove(steamID);
				if ((Object)(object)MenuManager.instance != (Object)null)
				{
					MenuManager.instance.PageCloseAll();
				}
			}
			else
			{
				((MonoBehaviourPun)Instance).photonView.RPC("FUE_SelectUpgrade", (RpcTarget)2, new object[2] { steamID, typeKey });
			}
		}
	}
	[HarmonyPatch(typeof(PunManager))]
	public static class FreeUpgradeNetPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void AttachNet(PunManager __instance)
		{
			GameObject gameObject = ((Component)__instance).gameObject;
			if (!Object.op_Implicit((Object)(object)gameObject.GetComponent<FreeUpgradeNet>()))
			{
				gameObject.AddComponent<FreeUpgradeNet>();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class FreeUpgrade_InputPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		private static void Postfix(PlayerController __instance)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)PlayerController.instance != (Object)(object)__instance) && !((Object)(object)GameDirector.instance == (Object)null))
			{
				KeyCode value = UpgradeConfig.OpenUIKey.Value;
				if ((int)value != 0 && Input.GetKeyDown(value))
				{
					string playerSteamID = PlayerController.instance.playerSteamID;
					CustomUI.Open(playerSteamID);
				}
				if (Input.GetKeyDown((KeyCode)27) && (Object)(object)StatsUI.instance != (Object)null)
				{
					StatsUI.instance.showStatsTimer = 0f;
				}
			}
		}

		public static void OpenUI(string steamID)
		{
			CustomUI.Open(steamID);
		}
	}
	internal static class CustomUI
	{
		private static REPOPopupPage page;

		public static void Open(string steamID)
		{
			try
			{
				if (!FreeUpgradeEveryRound.RuntimeDrafts.TryGetValue(steamID, out string[] value))
				{
					FreeUpgradeEveryRound.Logger.LogWarning((object)"[FreeUpgrade] No draft available.");
					return;
				}
				if (FreeUpgradeEveryRound.FreeSlotsDict.TryGetValue(steamID, out var value2) && value2 <= 0)
				{
					if ((Object)(object)page != (Object)null)
					{
						page.ClosePage(false);
						Object.Destroy((Object)(object)((Component)page).gameObject);
						page = null;
					}
					if ((Object)(object)StatsUI.instance != (Object)null)
					{
						StatsUI.instance.showStatsTimer = 0f;
					}
					return;
				}
				if ((Object)(object)page != (Object)null)
				{
					page.ClosePage(false);
					Object.Destroy((Object)(object)((Component)page).gameObject);
					page = null;
				}
				if ((Object)(object)StatsUI.instance != (Object)null)
				{
					StatsUI.instance.Fetch();
					StatsUI.instance.showStatsTimer = 999f;
				}
				page = MenuAPI.CreateREPOPopupPage("Free Upgrade UI", (PresetSide)1, false, 0f);
				UpgradeUI.CreateUpgradeSelectionUI(page, steamID, value);
				page.OpenPage(true);
				AdjustUIElementPositions((Transform)(object)page.menuScrollBox.scroller);
				FreeUpgradeEveryRound.Logger.LogInfo((object)"[FreeUpgrade] Custom UI opened.");
			}
			catch (Exception arg)
			{
				FreeUpgradeEveryRound.Logger.LogError((object)$"Custom UI failed: {arg}");
			}
		}

		private static void AdjustUIElementPositions(Transform scroller)
		{
			//IL_0008: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = ((Component)scroller).GetComponent<RectTransform>();
			component.anchoredPosition = Vector2.zero;
			REPOButton[] componentsInChildren = ((Component)scroller).GetComponentsInChildren<REPOButton>();
			float num = 40f;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				RectTransform component2 = ((Component)componentsInChildren[i]).GetComponent<RectTransform>();
				component2.anchoredPosition = new Vector2(0f, (float)i * num);
			}
			REPOLabel[] componentsInChildren2 = ((Component)scroller).GetComponentsInChildren<REPOLabel>();
			REPOLabel[] array = componentsInChildren2;
			foreach (REPOLabel val in array)
			{
				RectTransform component3 = ((Component)val).GetComponent<RectTransform>();
				component3.anchoredPosition = new Vector2(0f, (float)componentsInChildren.Length * num + 20f);
			}
		}
	}
	internal static class UpgradeUI
	{
		public static void CreateUpgradeSelectionUI(REPOPopupPage page, string steamID, string[] draft)
		{
			CreateFreeSlotLabel(page, steamID);
			float num = 60f;
			for (int i = 0; i < draft.Length; i++)
			{
				string upgradeKey = draft[i];
				CreateUpgradeButton(steamID, upgradeKey, i, page, num * (float)i);
			}
		}

		private static void CreateUpgradeButton(string steamID, string upgradeKey, int index, REPOPopupPage page, float yOffset)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			string steamID2 = steamID;
			string upgradeKey2 = upgradeKey;
			REPOButton val = MenuAPI.CreateREPOButton(upgradeKey2, (Action)delegate
			{
				OnUpgradeSelected(steamID2, upgradeKey2);
			}, (Transform)(object)page.menuScrollBox.scroller, default(Vector2));
			RectTransform component = ((Component)val).GetComponent<RectTransform>();
			component.anchoredPosition = new Vector2(0f, 0f - yOffset);
		}

		private static void CreateFreeSlotLabel(REPOPopupPage page, string steamID)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			int remainingFreeSlots = GetRemainingFreeSlots(steamID);
			GameObject val = new GameObject("FreeSlotsLabel");
			val.transform.SetParent((Transform)(object)page.menuScrollBox.scroller);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).text = $"Free Slots: {remainingFreeSlots}";
			((TMP_Text)val2).fontSize = 24f;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
			RectTransform component = ((Component)val2).GetComponent<RectTransform>();
			component.anchoredPosition = new Vector2(0f, 70f);
		}

		private static void OnUpgradeSelected(string steamID, string upgradeKey)
		{
			FreeUpgradeNet.SendSelectToHost(steamID, upgradeKey);
			FreeUpgradeEveryRound.Logger.LogInfo((object)("[FreeUpgrade] Upgrade selected: " + upgradeKey + " by " + steamID));
		}

		private static int GetRemainingFreeSlots(string steamID)
		{
			if (FreeUpgradeEveryRound.FreeSlotsDict.TryGetValue(steamID, out var value))
			{
				return value;
			}
			return 0;
		}
	}
	public static class SceneUtil
	{
		private static bool isSceneLoaded;

		static SceneUtil()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			isSceneLoaded = true;
		}

		public static string GetCurrentLevelName()
		{
			if (!isSceneLoaded)
			{
				FreeUpgradeEveryRound.Logger.LogWarning((object)"[FreeUpgrade] Waiting for scene to load, skipping level check.");
				return string.Empty;
			}
			RunManager instance = RunManager.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.levelCurrent == (Object)null)
			{
				return string.Empty;
			}
			string text = ((Object)instance.levelCurrent).name.ToLowerInvariant();
			FreeUpgradeEveryRound.Logger.LogInfo((object)("[FreeUpgrade] Current Level: " + text));
			return text;
		}

		public static bool IsGameInProgress()
		{
			if (!isSceneLoaded)
			{
				FreeUpgradeEveryRound.Logger.LogWarning((object)"[FreeUpgrade] Waiting for scene to load, skipping game progress check.");
				return false;
			}
			RunManager instance = RunManager.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.levelCurrent == (Object)null)
			{
				return false;
			}
			string text = ((Object)instance.levelCurrent).name.ToLowerInvariant();
			bool flag = text.Contains("museum") || text.Contains("manor") || text.Contains("arctic") || text.Contains("wizard") || text.Contains("shop") || text.Contains("truck");
			FreeUpgradeEveryRound.Logger.LogInfo((object)$"[FreeUpgrade] IsGameInProgress Check: Level={text}, IsInProgress={flag}");
			return flag;
		}
	}
	internal static class UpgradeConfig
	{
		public static Dictionary<string, ConfigEntry<float>> Entries = new Dictionary<string, ConfigEntry<float>>();

		public static Dictionary<string, float> Probabilities = new Dictionary<string, float>();

		public static ConfigEntry<KeyCode> OpenUIKey;

		public static ConfigEntry<int> Stamina;

		public static ConfigEntry<int> Health;

		public static ConfigEntry<int> Wings;

		public static ConfigEntry<int> Launch;

		public static ConfigEntry<int> Climb;

		public static ConfigEntry<int> Rest;

		public static ConfigEntry<int> Speed;

		public static ConfigEntry<int> Jump;

		public static ConfigEntry<int> Strength;

		public static ConfigEntry<int> Range;

		public static ConfigEntry<int> Battery;

		public static ConfigEntry<int> MapCount;

		public static Dictionary<string, ConfigEntry<int>> WeightDict;

		public static void Init(ConfigFile config)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			AcceptableValueRange<int> val = new AcceptableValueRange<int>(0, 100);
			Stamina = config.Bind<int>("UpgradeWeights", "Stamina", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Health = config.Bind<int>("UpgradeWeights", "Health", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Wings = config.Bind<int>("UpgradeWeights", "Wings", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Launch = config.Bind<int>("UpgradeWeights", "Launch", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Climb = config.Bind<int>("UpgradeWeights", "Climb", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Rest = config.Bind<int>("UpgradeWeights", "Rest", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Speed = config.Bind<int>("UpgradeWeights", "Speed", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Jump = config.Bind<int>("UpgradeWeights", "Jump", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Strength = config.Bind<int>("UpgradeWeights", "Strength", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Range = config.Bind<int>("UpgradeWeights", "Range", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			Battery = config.Bind<int>("UpgradeWeights", "Battery", 0, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			MapCount = config.Bind<int>("UpgradeWeights", "Map", 0, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			WeightDict = new Dictionary<string, ConfigEntry<int>>
			{
				{ "Stamina", Stamina },
				{ "Health", Health },
				{ "Wings", Wings },
				{ "Launch", Launch },
				{ "Climb", Climb },
				{ "Rest", Rest },
				{ "Speed", Speed },
				{ "Jump", Jump },
				{ "Strength", Strength },
				{ "Range", Range },
				{ "Battery", Battery },
				{ "Map", MapCount }
			};
		}

		public static int GetWeight(string upgradeKey)
		{
			if (WeightDict.TryGetValue(upgradeKey, out ConfigEntry<int> value))
			{
				return value.Value;
			}
			return 0;
		}

		internal static void Load(ConfigFile config)
		{
			OpenUIKey = config.Bind<KeyCode>("UI", "OpenUIKey", (KeyCode)112, "Key used to reopen the Free Upgrade UI. Set to None to disable.");
			Refresh();
		}

		internal static void Refresh()
		{
			Probabilities.Clear();
			foreach (KeyValuePair<string, ConfigEntry<float>> entry in Entries)
			{
				Probabilities[entry.Key] = entry.Value.Value;
			}
		}
	}
}
namespace FreeUpgradeEveryRound.Patchs
{
	[HarmonyPatch(typeof(SemiFunc))]
	[HarmonyPatch("OnLevelGenDone")]
	public static class FreeUpgrade_LevelPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (!SceneUtil.IsGameInProgress())
			{
				FreeUpgradeEveryRound.Logger.LogWarning((object)"[FreeUpgrade] Game is not in progress, skipping level gen sync.");
				return;
			}
			int levelsCompleted = RunManager.instance.levelsCompleted;
			FreeUpgradeEveryRound.Logger.LogInfo((object)$"[FreeUpgrade] OnLevelGenDone: levelsCompleted={levelsCompleted}");
			foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
			{
				if (!((Object)(object)player == (Object)null))
				{
					PhotonView photonView = player.photonView;
					Player val = (((Object)(object)photonView != (Object)null) ? photonView.Owner : null);
					int num = ((val != null) ? val.ActorNumber : (-1));
					string text = player.steamID;
					if (string.IsNullOrEmpty(text))
					{
						text = (player.steamID = ((num <= 0) ? $"LOCAL_AVATAR_{((Object)player).GetInstanceID()}" : $"LOCAL_{num}"));
						FreeUpgradeEveryRound.Logger.LogWarning((object)("[FreeUpgrade] steamID=null → LocalMultiplayer用に割り当て steamID=" + text));
					}
					FreeUpgradeEveryRound.SyncFreeSlotForPlayer(text, levelsCompleted);
					if (FreeUpgradeEveryRound.FreeSlotsDict.TryGetValue(text, out var value) && value > 0)
					{
						string[] array = DraftGenerator.GenerateDraft();
						FreeUpgradeEveryRound.RuntimeDrafts[text] = array;
						FreeUpgradeNet.SendDraftToAll(text, array);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager))]
	public static class FreeUpgrade_StatsPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void InjectFreeUpgradeDictionaries(StatsManager __instance)
		{
			Dictionary<string, Dictionary<string, int>> dictionaryOfDictionaries = __instance.dictionaryOfDictionaries;
			if (!dictionaryOfDictionaries.ContainsKey("FreeUpgrade_freeSlots"))
			{
				dictionaryOfDictionaries.Add("FreeUpgrade_freeSlots", FreeUpgradeEveryRound.FreeSlotsDict);
			}
			if (!dictionaryOfDictionaries.ContainsKey("FreeUpgrade_lastFreeLevel"))
			{
				dictionaryOfDictionaries.Add("FreeUpgrade_lastFreeLevel", FreeUpgradeEveryRound.LastFreeLevelDict);
			}
			FreeUpgradeEveryRound.Logger.LogInfo((object)"[FreeUpgrade] 永続化辞書を StatsManager に登録しました");
		}
	}
	[HarmonyPatch(typeof(SemiFunc))]
	[HarmonyPatch("OnSceneSwitch")]
	public static class FreeUpgrade_SyncPatch
	{
		[HarmonyPostfix]
		private static void AfterSceneSwitch()
		{
			if (IsGameInProgress())
			{
				FreeUpgradeEveryRound.SyncFromStatsManager();
			}
		}

		private static bool IsGameInProgress()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			Scene activeScene = SceneManager.GetActiveScene();
			string text = ((Scene)(ref activeScene)).name.ToLowerInvariant();
			bool flag = text.Contains("museum") || text.Contains("manor") || text.Contains("arctic") || text.Contains("wizard") || text.Contains("shop") || text.Contains("truck");
			return (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState >= 2 && flag;
		}
	}
}