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+3083ba7252749383238904a42c0162c5ca51283d")] [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 static string[] GenerateDraft() { List list = new List(); 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 hashSet = new HashSet(); while (hashSet.Count < UpgradeConfig.DraftCount.Value && 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(hashSet).ToArray(); } } internal static class DraftKeyMap { private static readonly Dictionary map = new Dictionary { { "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 FreeSlotsDict = new Dictionary(); internal static Dictionary LastFreeLevelDict = new Dictionary(); internal static readonly Dictionary RuntimeDrafts = new Dictionary(); 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; } SortedDictionary> 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; } SortedDictionary> 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())) { gameObject.AddComponent(); } } } [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(); component.anchoredPosition = Vector2.zero; REPOButton[] componentsInChildren = ((Component)scroller).GetComponentsInChildren(); float num = 40f; for (int i = 0; i < componentsInChildren.Length; i++) { RectTransform component2 = ((Component)componentsInChildren[i]).GetComponent(); component2.anchoredPosition = new Vector2(0f, (float)i * num); } REPOLabel[] componentsInChildren2 = ((Component)scroller).GetComponentsInChildren(); REPOLabel[] array = componentsInChildren2; foreach (REPOLabel val in array) { RectTransform component3 = ((Component)val).GetComponent(); 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(); 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(); ((TMP_Text)val2).text = $"Free Slots: {remainingFreeSlots}"; ((TMP_Text)val2).fontSize = 24f; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; RectTransform component = ((Component)val2).GetComponent(); 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> Entries = new Dictionary>(); public static Dictionary Probabilities = new Dictionary(); public static ConfigEntry DraftCount; public static ConfigEntry FreePerLevel; public static ConfigEntry OpenUIKey; public static ConfigEntry Stamina; public static ConfigEntry Health; public static ConfigEntry Wings; public static ConfigEntry Launch; public static ConfigEntry Climb; public static ConfigEntry Rest; public static ConfigEntry Speed; public static ConfigEntry Jump; public static ConfigEntry Strength; public static ConfigEntry Range; public static ConfigEntry Battery; public static ConfigEntry MapCount; public static Dictionary> 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 //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown AcceptableValueRange val = new AcceptableValueRange(0, 100); Stamina = config.Bind("UpgradeWeights", "Stamina", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Health = config.Bind("UpgradeWeights", "Health", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Wings = config.Bind("UpgradeWeights", "Wings", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Launch = config.Bind("UpgradeWeights", "Launch", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Climb = config.Bind("UpgradeWeights", "Climb", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Rest = config.Bind("UpgradeWeights", "Rest", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Speed = config.Bind("UpgradeWeights", "Speed", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Jump = config.Bind("UpgradeWeights", "Jump", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Strength = config.Bind("UpgradeWeights", "Strength", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Range = config.Bind("UpgradeWeights", "Range", 100, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); Battery = config.Bind("UpgradeWeights", "Battery", 0, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); MapCount = config.Bind("UpgradeWeights", "Map", 0, new ConfigDescription("Weight (0–100)", (AcceptableValueBase)(object)val, Array.Empty())); WeightDict = new Dictionary> { { "Stamina", Stamina }, { "Health", Health }, { "Wings", Wings }, { "Launch", Launch }, { "Climb", Climb }, { "Rest", Rest }, { "Speed", Speed }, { "Jump", Jump }, { "Strength", Strength }, { "Range", Range }, { "Battery", Battery }, { "Map", MapCount } }; DraftCount = config.Bind("General", "DraftCount", 4, new ConfigDescription("How many upgrades appear (1-4)", (AcceptableValueBase)(object)new AcceptableValueRange(1, 4), Array.Empty())); } public static int GetWeight(string upgradeKey) { if (WeightDict.TryGetValue(upgradeKey, out ConfigEntry value)) { return value.Value; } return 0; } internal static void Load(ConfigFile config) { OpenUIKey = config.Bind("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> 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) { SortedDictionary> 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; } } }