using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Leveling.Misc; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.atomic.leveling")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.7.0")] [assembly: AssemblyInformationalVersion("0.2.7+cd62e60b6116ef824afa81f7e3732e130d1711cd")] [assembly: AssemblyProduct("com.atomic.leveling")] [assembly: AssemblyTitle("Leveling")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.7.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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Leveling { public static class LevelingAPI { private static int _level = 1; private static float _experience = 0f; private static Dictionary _oneUseItems = new Dictionary(); private static readonly Dictionary PlayerLevels = new Dictionary(); private static float ExperienceToNextLevel => _level * 100; public static int Level { get { return _level; } private set { if (_level != value) { _level = value; Netcode.Instance?.SendLevelUpdateRPC(value); LevelingAPI.OnLocalPlayerLevelChanged?.Invoke(value); } } } public static float Experience { get { return _experience; } private set { _experience = value; CheckLevelUp(); } } public static Dictionary OneUseItems { get { return _oneUseItems; } private set { _oneUseItems = value; } } public static event Action OnLocalPlayerLevelChanged; public static event Action OnLocalPlayerExperienceChanged; public static event Action OnRemotePlayerLevelChanged; private static void CheckLevelUp() { while (Experience >= ExperienceToNextLevel) { Experience -= ExperienceToNextLevel; Level++; Plugin.Log.LogInfo((object)$"Player Leveled Up! New Level: {Level}"); } } private static float CalculateMultiplier() { int currentAscent = Ascents.currentAscent; float num = 1f; if (currentAscent >= 0) { return num = Math.Clamp(1f + (float)currentAscent * 0.1f, 1f, 2f); } return num = 0.8f; } public static void SaveLocalData() { SaveManager.SaveData(_level, _experience, _oneUseItems); } public static void AddExperience(float amount, bool applyAscentMultiplier = true, bool allowAwardInAirport = false) { //IL_0016: 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_0038: 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) if (!(amount > 0f) || !(amount <= 2000f)) { return; } Scene activeScene = SceneManager.GetActiveScene(); if (!((Scene)(ref activeScene)).name.ToLower().Contains("airport") || allowAwardInAirport) { activeScene = SceneManager.GetActiveScene(); if ((((Scene)(ref activeScene)).name.ToLower().Contains("level") || allowAwardInAirport) && !RunSettings._isCustomRun) { float num = (applyAscentMultiplier ? CalculateMultiplier() : 1f); amount *= num; Experience += amount; LevelingAPI.OnLocalPlayerExperienceChanged?.Invoke(amount); Plugin.Log.LogInfo((object)$"Gained {amount} XP. Current XP: {Experience}/{ExperienceToNextLevel}"); } } } public static void AddOneUseItem(string itemName) { if (!string.IsNullOrEmpty(itemName) && !_oneUseItems.ContainsKey(itemName)) { _oneUseItems.Add(itemName, value: false); SaveManager.SaveData(_level, _experience, _oneUseItems); } } public static void SetOneUseItem(string itemName) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(itemName) && _oneUseItems.ContainsKey(itemName)) { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name.ToLower().Contains("level")) { _oneUseItems[itemName] = true; SaveManager.SaveData(_level, _experience, _oneUseItems); Plugin.Log.LogMessage((object)("Set " + itemName + " to true for being a one use item.")); } } } public static void LoadLocalPlayerStats(PlayerSaveData data) { _level = data.Level; _experience = data.Experience; _oneUseItems = data.OneUseItems; Dictionary defaultOneUseItems = SaveManager.GetDefaultOneUseItems(); foreach (KeyValuePair item in defaultOneUseItems) { if (!_oneUseItems.ContainsKey(item.Key)) { _oneUseItems.Add(item.Key, item.Value); Plugin.Log.LogMessage((object)$"DefaultItems was missing {item}, this has now been added."); } } SaveManager.SaveData(_level, _experience, _oneUseItems); Plugin.Log.LogInfo((object)$"Local player stats initialized to Lvl: {_level}, Exp: {_experience}"); } public static void SetRemotePlayerLevel(Player player, int level) { if (!PlayerLevels.TryGetValue(player, out var value) || value != level) { PlayerLevels[player] = level; Plugin.Log.LogInfo((object)$"Internal level set for {player.NickName}: Lvl {level}"); LevelingAPI.OnRemotePlayerLevelChanged?.Invoke(player, level); } } public static int GetPlayerLevel(Player player) { if (player.IsLocal) { return Level; } if (PlayerLevels.TryGetValue(player, out var value)) { return value; } return 1; } } [BepInPlugin("com.atomic.leveling", "Leveling", "0.2.7")] public class Plugin : BaseUnityPlugin { public enum XPSource { Winning, Luggages, Badges, Items, Climbing, Other } private Harmony harmony; public static ConfigEntry automaticBackups; public static ConfigEntry backupsBeforeDeletion; public static ConfigEntry backupToLoad; public static ConfigEntry showExperienceGainUI; public static ConfigEntry showLevelGainUI; public static ConfigEntry showAscentMultiplier; public static ConfigEntry showLevelingUsersOnly; public static float XPGainedThisRun; public static float XPGained_Climbing; public static float XPGained_Items; public static float XPGained_Winning; public static float XPGained_Badges; public static float XPGained_Luggages; public static float XPGained_Mods; public static float XPGained_Other; public const string Id = "com.atomic.leveling"; internal static ManualLogSource Log { get; private set; } public static string Name => "Leveling"; public static string Version => "0.2.7"; private void Awake() { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)("Plugin " + Name + " is loaded!")); showExperienceGainUI = ((BaseUnityPlugin)this).Config.Bind("UI", "Show Experience Gain", true, "When enabled, you will see when you gain XP, usually shown a +5XP"); showLevelGainUI = ((BaseUnityPlugin)this).Config.Bind("UI", "Show Level Gain", true, "When enabled, you will see when you level up."); showAscentMultiplier = ((BaseUnityPlugin)this).Config.Bind("UI", "Show Ascent Multiplier", true, "When enabled, the ascent multiplier will be shown on the boarding pass screen. Turn it off if incompatible with localization or other mods change it."); showLevelingUsersOnly = ((BaseUnityPlugin)this).Config.Bind("UI", "Show Leveling Users Only", false, "When enabled, only players using the leveling mod will have their levels shown, if off then everyone without the mod will have [1]. REQUIRES REJOIN"); automaticBackups = ((BaseUnityPlugin)this).Config.Bind("Backups", "Automatic Backups", true, "Creates backups of your save file automatically on game startup"); backupsBeforeDeletion = ((BaseUnityPlugin)this).Config.Bind("Backups", "Backups Before Deletion", 6, "How many backups can be created before it starts deleting old backups."); string[] backupDataForConfig = SaveManager.GetBackupDataForConfig(); List list = new List { "Current Save" }; list.AddRange(backupDataForConfig); ConfigDescription val = new ConfigDescription("Select a backup to load. The selection will replace your main save file on game start. Leave as 'Current Save' to skip loading a backup. Game restart is required after selection.", (AcceptableValueBase)(object)new AcceptableValueList(list.ToArray()), Array.Empty()); backupToLoad = ((BaseUnityPlugin)this).Config.Bind("Backups", "Backup To Load", "Current Save", val); if (automaticBackups.Value) { SaveManager.CreateBackup(backupsBeforeDeletion.Value); } string value = backupToLoad.Value; if (!value.Equals("Current Save", StringComparison.OrdinalIgnoreCase)) { string text = ParseLabelToFilename(value); Log.LogWarning((object)("Attempting to load selected backup (Label: " + value + ", File: " + text + ")")); if (SaveManager.LoadBackup(text)) { backupToLoad.Value = "Current Save"; ((BaseUnityPlugin)this).Config.Save(); } } Netcode.EnsureInitialized(); PlayerSaveData data = SaveManager.LoadData(); LevelingAPI.LoadLocalPlayerStats(data); LevelingAPI.OnRemotePlayerLevelChanged += HandleRemotePlayerLevelChange; LevelingAPI.OnLocalPlayerExperienceChanged += ExperienceGain; LevelingAPI.OnLocalPlayerLevelChanged += LevelGain; harmony = new Harmony("com.atomic.leveling"); harmony.PatchAll(); } private void OnApplicationQuit() { LevelingAPI.SaveLocalData(); } private static float CalculateMultiplier() { int currentAscent = Ascents.currentAscent; float num = 1f; if (currentAscent >= 0) { return num = Math.Clamp(1f + (float)currentAscent * 0.1f, 1f, 2f); } return num = 0.8f; } public static void IncreaseXPSource(XPSource source, float amount, bool ascentMultiplier = true) { //IL_0016: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!(amount > 0f) || !(amount <= 2000f)) { return; } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name.ToLower().Contains("airport")) { return; } activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name.ToLower().Contains("level")) { float num = (ascentMultiplier ? CalculateMultiplier() : 1f); amount *= num; switch (source) { case XPSource.Winning: XPGained_Winning += amount; break; case XPSource.Luggages: XPGained_Luggages += amount; break; case XPSource.Badges: XPGained_Badges += amount; break; case XPSource.Items: XPGained_Items += amount; break; case XPSource.Climbing: XPGained_Climbing += amount; break; case XPSource.Other: XPGained_Other += amount; break; } } } private string ParseLabelToFilename(string label) { try { int num = label.IndexOf("Level: ") + "Level: ".Length; int num2 = label.IndexOf(" || Experience:"); if (num2 == -1) { num2 = label.IndexOf(" Experience:"); } if (num < "Level: ".Length || num2 == -1 || num2 <= num) { Log.LogError((object)("Failed to find Level component in label: " + label)); return "Current Save"; } string arg = label.Substring(num, num2 - num).Trim(); int startIndex = label.IndexOf("Experience: ") + "Experience: ".Length; string text = label.Substring(startIndex).Trim(); if (!float.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { Log.LogError((object)("Failed to parse experience string: " + text + ". Defaulting to Current Save.")); return "Current Save"; } int num3 = (int)Math.Floor(result); int num4 = (int)((result - (float)num3) * 1000f); return $"L{arg}_E{num3}_{num4:D3}.backup"; } catch (Exception ex) { Log.LogError((object)("Failed to parse backup label '" + label + "' into filename. Error: " + ex.Message)); return "Current Save"; } } private void HandleRemotePlayerLevelChange(Player player, int newLevel) { if (player != null && !player.IsLocal) { Patches.UpdatePlayerNameText(player, newLevel); string arg = Patches.RemoveLevelTag(player.NickName); player.NickName = $"{arg} [{newLevel}]"; Log.LogInfo((object)("Updated remote player name: " + player.NickName)); } } private void ExperienceGain(float newExp) { Patches.UpdateAccoladesText(); if (showExperienceGainUI.Value) { Log.LogInfo((object)"Trying to create ui."); CreateExperienceGUI(newExp, out GameObject _, xpOrLevel: false); } } private void LevelGain(int newLevel) { Patches.UpdateAccoladesText(); if (showLevelGainUI.Value) { Log.LogInfo((object)"Trying to create ui."); CreateExperienceGUI(0f, out GameObject _, xpOrLevel: true); } } private void CreateExperienceGUI(float xpGain, out GameObject expTextObj, bool xpOrLevel) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI heroDayText = GUIManager.instance.heroDayText; if ((Object)(object)heroDayText == (Object)null) { Log.LogError((object)"Could not find HeroDayText! XP UI cannot be created."); expTextObj = null; return; } GameObject val = new GameObject("XPGainCanvas"); val.transform.SetParent(((Component)GUIManager.instance).transform, false); Canvas val2 = val.AddComponent(); val2.renderMode = (RenderMode)0; val.AddComponent(); val.AddComponent(); expTextObj = new GameObject("ExperienceText"); expTextObj.transform.SetParent(val.transform, false); expTextObj.AddComponent(); TextMeshProUGUI val3 = expTextObj.AddComponent(); ((TMP_Text)val3).font = ((TMP_Text)heroDayText).font; ((Graphic)val3).color = ((Graphic)heroDayText).color; ((TMP_Text)val3).alignment = (TextAlignmentOptions)514; ((TMP_Text)val3).fontSize = ((TMP_Text)heroDayText).fontSize / 2.5f; ((TMP_Text)val3).outlineWidth = 0.1f; ((TMP_Text)val3).outlineColor = Color32.op_Implicit(((Graphic)heroDayText).color - new Color(0.5f, 0.5f, 0.5f, 0f)); XPAnimator xPAnimator = expTextObj.AddComponent(); xPAnimator.text = val3; if (xpOrLevel) { ((TMP_Text)val3).text = $"LEVEL UP! LVL {LevelingAPI.Level}"; xPAnimator.isLevelUp = true; } else { XPGainedThisRun += xpGain; ((TMP_Text)val3).text = $"+{Math.Round(xpGain, 2)} XP"; } RectTransform component = expTextObj.GetComponent(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(200f, 80f); if (xpOrLevel) { if (showExperienceGainUI.Value) { component.anchoredPosition = new Vector2(100f, -10f); } else { component.anchoredPosition = new Vector2(100f, 5f); } } else { component.anchoredPosition = new Vector2(100f, 5f); } Log.LogInfo((object)$"Created XP Gain GUI: +{xpGain} XP"); } } [HarmonyPatch] public class Patches { private static TextMeshProUGUI? localLevelUIText; private static Dictionary playerNames = new Dictionary(); [HarmonyPostfix] [HarmonyPatch(typeof(PlayerHandler), "RegisterCharacter")] public static void Character_Reg_Postfix(Character character) { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)((MonoBehaviourPun)character).photonView)) { Player owner = ((MonoBehaviourPun)character).photonView.Owner; if (owner != null && owner.IsLocal) { int playerLevel = LevelingAPI.GetPlayerLevel(owner); Netcode.Instance?.SendLevelUpdateRPC(playerLevel); Netcode.Instance?.RequestAllPlayerLevels(); } } } public static string RemoveLevelTag(string nickname) { int num = nickname.LastIndexOf('['); if (num > 0 && nickname.EndsWith("]")) { string text = nickname.Substring(num); return nickname.Substring(0, num).Trim(); } return nickname; } [HarmonyPostfix] [HarmonyPatch(typeof(PauseMenuAccoladesPage), "Start")] public static void Accolades_OnPageEnter_Postfix(PauseMenuAccoladesPage __instance) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)__instance).gameObject; Transform val = gameObject.transform.Find("Level"); if ((Object)(object)val != (Object)null) { localLevelUIText = ((Component)val).GetComponent(); } else { GameObject gameObject2 = ((Component)gameObject.transform.Find("Peaks")).gameObject; GameObject val2 = Object.Instantiate(gameObject2, gameObject2.transform.parent); ((Object)val2).name = "Level"; val2.transform.localPosition = gameObject2.transform.localPosition + new Vector3(0f, -35f, 0f); localLevelUIText = val2.GetComponent(); } UpdateAccoladesText(); } public static void UpdateAccoladesText() { if ((Object)(object)localLevelUIText != (Object)null && (Object)(object)((Component)localLevelUIText).gameObject != (Object)null) { ((TMP_Text)localLevelUIText).text = $"Level: {LevelingAPI.Level} XP: {Math.Round(LevelingAPI.Experience, 2)}/{LevelingAPI.Level * 100}"; } } public static void UpdatePlayerNameText(Player player, int level) { if (playerNames.TryGetValue(player.ActorNumber, out PlayerName value) && (Object)(object)value != (Object)null && (Object)(object)value.text != (Object)null) { string arg = RemoveLevelTag(player.NickName); ((TMP_Text)value.text).text = $"{arg} [{level}]"; return; } UIPlayerNames val = Object.FindFirstObjectByType(); if (!((Object)(object)val != (Object)null)) { return; } PlayerName[] playerNameText = val.playerNameText; foreach (PlayerName val2 in playerNameText) { if ((Object)(object)val2.text == (Object)null) { continue; } CharacterInteractible characterInteractable = val2.characterInteractable; object obj; if (characterInteractable == null) { obj = null; } else { Character character = characterInteractable.character; obj = ((character != null) ? ((MonoBehaviourPun)character).photonView : null); } if (!((Object)obj == (Object)null)) { Player owner = ((MonoBehaviourPun)val2.characterInteractable.character).photonView.Owner; playerNames[owner.ActorNumber] = val2; if (owner == player) { string arg2 = RemoveLevelTag(player.NickName); ((TMP_Text)val2.text).text = $"{arg2} [{level}]"; } } } } [HarmonyPostfix] [HarmonyPatch(typeof(UIPlayerNames), "Init")] public static void UIPlayerNames_Init_Postfix(UIPlayerNames __instance) { PlayerName[] playerNameText = __instance.playerNameText; foreach (PlayerName val in playerNameText) { if ((Object)(object)val.text == (Object)null) { continue; } CharacterInteractible characterInteractable = val.characterInteractable; object obj; if (characterInteractable == null) { obj = null; } else { Character character = characterInteractable.character; obj = ((character != null) ? ((MonoBehaviourPun)character).photonView : null); } if ((Object)obj == (Object)null) { continue; } Player owner = ((MonoBehaviourPun)val.characterInteractable.character).photonView.Owner; if (owner != null && !owner.IsLocal) { if (!playerNames.ContainsKey(owner.ActorNumber)) { playerNames.Add(owner.ActorNumber, val); } else { playerNames[owner.ActorNumber] = val; } if (!Plugin.showLevelingUsersOnly.Value) { int playerLevel = LevelingAPI.GetPlayerLevel(owner); string arg = RemoveLevelTag(owner.NickName); ((TMP_Text)val.text).text = $"{arg} [{playerLevel}]"; } } } } [HarmonyPostfix] [HarmonyPatch(typeof(RunManager), "StartRun")] public static void RunManager_StartRun_Postfix() { playerNames.Clear(); Plugin.XPGainedThisRun = 0f; Plugin.XPGained_Winning = 0f; Plugin.XPGained_Luggages = 0f; Plugin.XPGained_Badges = 0f; Plugin.XPGained_Mods = 0f; Plugin.XPGained_Items = 0f; Plugin.XPGained_Climbing = 0f; Plugin.XPGained_Other = 0f; } [HarmonyPostfix] [HarmonyPatch(typeof(EndScreen), "Start")] public static void EndScreen_Start_Postfix(EndScreen __instance) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)__instance).transform.Find("Panel/Margin/Layout/Window_BADGES/Title (1)"); TextMeshProUGUI component = ((Component)val).gameObject.GetComponent(); if (!((TMP_Text)component).text.Contains("(+")) { ((TMP_Text)component).text = $"{((TMP_Text)component).text} (LEVEL {LevelingAPI.Level})"; if (!RunSettings._isCustomRun) { Plugin.XPGained_Mods = Plugin.XPGainedThisRun - Plugin.XPGained_Winning - Plugin.XPGained_Luggages - Plugin.XPGained_Badges - Plugin.XPGained_Items - Plugin.XPGained_Climbing - Plugin.XPGained_Other; Transform val2 = ((Component)__instance).transform.Find("Panel/Margin"); Transform val3 = val2.Find("Mtn."); Color32 val4 = Color32.op_Implicit(((Graphic)((Component)((Component)__instance).transform.Find("Panel/BG")).GetComponent()).color); GameObject val5 = Object.Instantiate(((Component)val3).gameObject, val2); Transform transform = val5.transform; transform.localPosition += new Vector3(-310f, 0f, 0f); ((Graphic)val5.GetComponent()).color = Color32.op_Implicit(val4); ((Object)val5).name = "Leveling_Icon"; Transform val6 = ((Component)__instance).transform.Find("Panel/Margin/SCOUTING_REPORT"); GameObject val7 = Object.Instantiate(((Component)val6).gameObject, val2); val7.transform.localPosition = val5.transform.localPosition + new Vector3(0f, -30f, 0f); Object.Destroy((Object)(object)val7.GetComponent()); ((TMP_Text)val7.GetComponent()).text = "LEVELING"; ((Graphic)val7.GetComponent()).color = Color32.op_Implicit(val4); ((Object)val7).name = "Leveling_Title"; int currentAscent = Ascents.currentAscent; float num = 1f; num = ((currentAscent >= 0) ? (1f + (float)currentAscent * 0.1f) : 0.8f); CreateEndScreenSection(__instance, "Winning", Plugin.XPGained_Winning); CreateEndScreenSection(__instance, "Luggages", Plugin.XPGained_Luggages); CreateEndScreenSection(__instance, "Badges", Plugin.XPGained_Badges); CreateEndScreenSection(__instance, "Items", Plugin.XPGained_Items); CreateEndScreenSection(__instance, "Climbing", Plugin.XPGained_Climbing); CreateEndScreenSection(__instance, "Other", Plugin.XPGained_Other); CreateEndScreenSection(__instance, "Mods", Plugin.XPGained_Mods); CreateEndScreenSection(__instance, "Ascent", num); CreateEndScreenSection(__instance, "Total", Plugin.XPGainedThisRun); } } } private static void CreateEndScreenSection(EndScreen __instance, string name, float value) { //IL_0061: 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) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) if (value < 1f) { return; } Transform val = ((Component)__instance).transform.Find("Panel/Margin"); Transform val2 = val.Find("Leveling_Title"); if ((Object)(object)val2 == (Object)null) { return; } float num = 24f; float rowWidth = 180f; float entryFontSize = 15f; int num2 = CountExistingEntries(__instance); Color32 themeColor = Color32.op_Implicit(((Graphic)((Component)val2).GetComponent()).color); GameObject val3 = new GameObject("LevelingEntry_" + name); val3.transform.SetParent(val, false); float num3 = -20f - (float)num2 * num; val3.transform.localPosition = ((Component)val2).transform.localPosition + new Vector3(0f, num3, 0f); GameObject val4 = new GameObject("Separator"); val4.transform.SetParent(val3.transform, false); Image val5 = val4.AddComponent(); ((Graphic)val5).color = Color32.op_Implicit(themeColor); RectTransform component = val4.GetComponent(); component.sizeDelta = new Vector2(rowWidth, 2f); ((Transform)component).localPosition = new Vector3(0f, 10f, 0f); Action action = delegate(GameObject obj, string txt, TextAlignmentOptions align, float xPos) { //IL_0033: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)obj.GetComponent())) { Object.Destroy((Object)(object)obj.GetComponent()); } TextMeshProUGUI component2 = obj.GetComponent(); ((TMP_Text)component2).text = txt; ((TMP_Text)component2).fontSize = entryFontSize; ((TMP_Text)component2).alignment = align; ((Graphic)component2).color = Color32.op_Implicit(themeColor); ((TMP_Text)component2).enableAutoSizing = false; ((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0; RectTransform component3 = obj.GetComponent(); component3.sizeDelta = new Vector2(rowWidth / 2f, 20f); obj.transform.localPosition = new Vector3(xPos, 0f, 0f); }; GameObject arg = Object.Instantiate(((Component)val2).gameObject, val3.transform); action(arg, name.ToUpper(), (TextAlignmentOptions)513, 0f - rowWidth / 2f + rowWidth / 4f); GameObject arg2 = Object.Instantiate(((Component)val2).gameObject, val3.transform); if (name == "Ascent") { action(arg2, $"{Math.Round(value, 2)}X", (TextAlignmentOptions)516, rowWidth / 2f - rowWidth / 4f); } else { action(arg2, $"+{Math.Round(value, 3)}XP", (TextAlignmentOptions)516, rowWidth / 2f - rowWidth / 4f); } } private static int CountExistingEntries(EndScreen __instance) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown Transform val = ((Component)__instance).transform.Find("Panel/Margin"); int num = 0; foreach (Transform item in val) { Transform val2 = item; if (((Object)val2).name.StartsWith("LevelingEntry_")) { num++; } } return num; } [HarmonyPostfix] [HarmonyPatch(typeof(BoardingPass), "UpdateAscent")] public static void BoardingPass_UpdateAscent_Postfix(BoardingPass __instance) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.showAscentMultiplier.Value) { return; } if (RunSettings._isCustomRun) { GameObject gameObject = ((Component)((Component)__instance).transform.Find("BoardingPass/Panel/Ascent/Description")).gameObject; if (Object.op_Implicit((Object)(object)((Component)__instance).transform.Find("BoardingPass/Panel/Ascent/Leveling_Warning"))) { GameObject gameObject2 = ((Component)((Component)__instance).transform.Find("BoardingPass/Panel/Ascent/Leveling_Warning")).gameObject; gameObject2.SetActive(true); return; } GameObject val = Object.Instantiate(gameObject, gameObject.transform.parent); ((Object)val).name = "Leveling_Warning"; val.transform.localPosition = gameObject.transform.localPosition + new Vector3(0f, -30f, 0f); ((TMP_Text)val.GetComponent()).text = "You cannot gain XP in custom runs."; ((Graphic)val.GetComponent()).color = Color.red; return; } Transform val2 = ((Component)__instance).transform.Find("BoardingPass/Panel/Ascent/Leveling_Warning"); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(false); } int ascentIndex = __instance._ascentIndex; float num = 1f; num = ((ascentIndex >= 0) ? (1f + (float)ascentIndex * 0.1f) : 0.8f); GameObject gameObject3 = ((Component)((Component)__instance).transform.Find("BoardingPass/Panel/Ascent/Title")).gameObject; TextMeshProUGUI component = gameObject3.GetComponent(); ((TMP_Text)component).text = $"{((TMP_Text)component).text} (XP: {num}X)"; } } } namespace Leveling.Misc { public class Netcode : MonoBehaviourPun { private static Netcode _instance; private PhotonView _photonView; public static Netcode Instance { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("LevelingNetcode"); _instance = val.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val); } return _instance; } } public static void EnsureInitialized() { _ = Instance; } private void Awake() { if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } _instance = this; _photonView = ((Component)this).GetComponent(); if ((Object)(object)_photonView == (Object)null) { _photonView = ((Component)this).gameObject.AddComponent(); _photonView.ViewID = 8437; } Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } public void SendLevelUpdateRPC(int newLevel) { if (PhotonNetwork.InRoom) { _photonView.RPC("RPC_ReceiveLevelUpdate", (RpcTarget)0, new object[1] { newLevel }); Plugin.Log.LogInfo((object)$"Broadcasted level update: Lvl {newLevel}"); } } public void RequestAllPlayerLevels() { if (PhotonNetwork.InRoom) { _photonView.RPC("RPC_RequestPlayerLevels", (RpcTarget)2, Array.Empty()); Plugin.Log.LogInfo((object)"Requested all existing player levels from Master Client."); } } [PunRPC] public void RPC_RequestPlayerLevels(PhotonMessageInfo info) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient) { _photonView.RPC("RPC_RespondWithMyLevel", info.Sender, new object[1] { LevelingAPI.Level }); Plugin.Log.LogInfo((object)$"Master Client responding to {info.Sender.NickName}'s level request with own level: Lvl {LevelingAPI.Level}"); } } [PunRPC] public void RPC_RespondWithMyLevel(int level, PhotonMessageInfo info) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Player sender = info.Sender; if (sender != null && !sender.IsLocal) { LevelingAPI.SetRemotePlayerLevel(sender, level); Plugin.Log.LogInfo((object)$"Received level sync from {sender.NickName}: Lvl {level}"); } } [PunRPC] public void RPC_ReceiveLevelUpdate(int level, PhotonMessageInfo info) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Player sender = info.Sender; if (sender != null && !sender.IsLocal) { LevelingAPI.SetRemotePlayerLevel(sender, level); Plugin.Log.LogInfo((object)$"Received level update from {sender.NickName}: Lvl {level}"); } } } public class PlayerSaveData { public int Level { get; set; } = 1; public float Experience { get; set; } public Dictionary OneUseItems { get; set; } = new Dictionary { { "BUGLEBBNO", false } }; } public static class SaveManager { private const string SAVE_FILE_NAME = "player_stats.sav"; private const string BACKUP_FILE_EXTENSION = ".backup"; private static readonly byte[] MagicHeader = new byte[5] { 254, 202, 222, 175, 1 }; private static readonly byte[] MagicFooter = new byte[5] { 2, 239, 205, 186, 253 }; private static string BaseDirPath { get { string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); string text = Path.Combine(folderPath, "LandCrab", "PEAK", "PEAKLeveling"); if (!Directory.Exists(text)) { Directory.CreateDirectory(text); } return text; } } private static string SaveFilePath => Path.Combine(BaseDirPath, "player_stats.sav"); public static Dictionary GetDefaultOneUseItems() { return new Dictionary(new PlayerSaveData().OneUseItems); } private static string GetSaveFilePath(string fileName) { return Path.Combine(BaseDirPath, fileName); } public static void SaveData(int level, float experience, Dictionary oneUseItems) { try { PlayerSaveData playerSaveData = new PlayerSaveData { Level = level, Experience = experience, OneUseItems = oneUseItems }; string s = JsonConvert.SerializeObject((object)playerSaveData); byte[] bytes = Encoding.UTF8.GetBytes(s); byte[] array = new byte[MagicHeader.Length + bytes.Length + MagicFooter.Length]; Buffer.BlockCopy(MagicHeader, 0, array, 0, MagicHeader.Length); Buffer.BlockCopy(bytes, 0, array, MagicHeader.Length, bytes.Length); Buffer.BlockCopy(MagicFooter, 0, array, MagicHeader.Length + bytes.Length, MagicFooter.Length); string contents = Convert.ToBase64String(array); File.WriteAllText(SaveFilePath, contents); Plugin.Log.LogInfo((object)("Saved data (obfuscated) to: " + SaveFilePath)); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to save data: " + ex.Message)); } } public static PlayerSaveData LoadData() { if (!File.Exists(SaveFilePath)) { Plugin.Log.LogInfo((object)"Save file not found. Loading default new game data (Lvl 1, Exp 0)."); return new PlayerSaveData(); } try { string s = File.ReadAllText(SaveFilePath); byte[] array = Convert.FromBase64String(s); int num = MagicHeader.Length + MagicFooter.Length; if (array.Length < num) { throw new InvalidDataException("Save file too short after decoding. File is corrupt or invalid."); } for (int i = 0; i < MagicHeader.Length; i++) { if (array[i] != MagicHeader[i]) { throw new InvalidDataException("Magic Header mismatch. File is corrupt or modified."); } } int num2 = array.Length - MagicFooter.Length; for (int j = 0; j < MagicFooter.Length; j++) { if (array[num2 + j] != MagicFooter[j]) { throw new InvalidDataException("Magic Footer mismatch. File is corrupt or modified."); } } int num3 = array.Length - num; byte[] array2 = new byte[num3]; Buffer.BlockCopy(array, MagicHeader.Length, array2, 0, num3); string @string = Encoding.UTF8.GetString(array2); PlayerSaveData playerSaveData = JsonConvert.DeserializeObject(@string); Plugin.Log.LogInfo((object)$"Loaded data (obfuscated) from: {SaveFilePath} (Lvl {playerSaveData.Level}, Exp {playerSaveData.Experience})"); return playerSaveData; } catch (Exception ex) { Plugin.Log.LogError((object)("Error loading or deserializing save file. Possible corruption/tampering. Loading default new game data. Error: " + ex.Message)); return new PlayerSaveData(); } } private static string GetBackupFileName(PlayerSaveData data) { int num = (int)Math.Floor(data.Experience); int num2 = (int)((data.Experience - (float)num) * 1000f); return string.Format("L{0}_E{1}_{2:D3}{3}", data.Level, num, num2, ".backup"); } private static string GetBackupFileBasePattern(PlayerSaveData data) { int num = (int)Math.Floor(data.Experience); return $"L{data.Level}_E{num}_"; } private static PlayerSaveData DecodeBackup(string filePath) { try { string s = File.ReadAllText(filePath); byte[] array = Convert.FromBase64String(s); int num = MagicHeader.Length + MagicFooter.Length; if (array.Length < num) { throw new InvalidDataException("Backup too short."); } for (int i = 0; i < MagicHeader.Length; i++) { if (array[i] != MagicHeader[i]) { throw new InvalidDataException("Backup Header mismatch."); } } int num2 = array.Length - MagicFooter.Length; for (int j = 0; j < MagicFooter.Length; j++) { if (array[num2 + j] != MagicFooter[j]) { throw new InvalidDataException("Backup Footer mismatch."); } } int num3 = array.Length - num; byte[] array2 = new byte[num3]; Buffer.BlockCopy(array, MagicHeader.Length, array2, 0, num3); string @string = Encoding.UTF8.GetString(array2); return JsonConvert.DeserializeObject(@string); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not decode backup file: " + Path.GetFileName(filePath) + ". Error: " + ex.Message)); return null; } } public static void CreateBackup(int maxBackups) { if (!File.Exists(SaveFilePath)) { Plugin.Log.LogInfo((object)"Cannot create backup: No main save file exists yet."); return; } PlayerSaveData playerSaveData = LoadData(); if (playerSaveData == null) { Plugin.Log.LogError((object)"Failed to load current save data for backup check."); return; } string backupFileName = GetBackupFileName(playerSaveData); string baseMatchPattern = GetBackupFileBasePattern(playerSaveData); List source = GetBackupFilesInternal().ToList(); List list = source.Where((FileInfo f) => f.Name.StartsWith(baseMatchPattern, StringComparison.OrdinalIgnoreCase)).ToList(); bool flag = false; foreach (FileInfo item in list) { PlayerSaveData existingData = DecodeBackup(item.FullName); if (existingData != null) { bool flag2 = playerSaveData.Level == existingData.Level; bool flag3 = playerSaveData.Experience == existingData.Experience; bool flag4 = playerSaveData.OneUseItems.Count == existingData.OneUseItems.Count && playerSaveData.OneUseItems.All>((KeyValuePair pair) => existingData.OneUseItems.ContainsKey(pair.Key) && existingData.OneUseItems[pair.Key] == pair.Value); if (flag2 && flag3 && flag4) { Plugin.Log.LogInfo((object)"Skipping backup: Current save data is identical to an existing backup."); flag = true; break; } } } if (flag) { return; } foreach (FileInfo item2 in list) { try { File.Delete(item2.FullName); Plugin.Log.LogInfo((object)("Deleted old backup for replacement: " + item2.Name)); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to delete old backup " + item2.Name + " for replacement: " + ex.Message)); } } string destFileName = Path.Combine(BaseDirPath, backupFileName); try { File.Copy(SaveFilePath, destFileName, overwrite: true); Plugin.Log.LogInfo((object)("Created new backup: " + backupFileName)); } catch (Exception ex2) { Plugin.Log.LogError((object)("Failed to create backup: " + ex2.Message)); } CleanupOldBackups(maxBackups); } private static void CleanupOldBackups(int maxBackups) { if (maxBackups <= 0) { return; } IEnumerable backupFilesInternal = GetBackupFilesInternal(); List list = backupFilesInternal.OrderBy((FileInfo f) => f.CreationTime).Skip(maxBackups).ToList(); foreach (FileInfo item in list) { try { File.Delete(item.FullName); Plugin.Log.LogInfo((object)("Deleted old backup: " + item.Name)); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to delete old backup " + item.Name + ": " + ex.Message)); } } } private static IEnumerable GetBackupFilesInternal() { DirectoryInfo directoryInfo = new DirectoryInfo(BaseDirPath); return from f in directoryInfo.GetFiles("*.backup") orderby f.CreationTime descending select f; } public static string[] GetBackupDataForConfig() { List list = new List(); List list2 = GetBackupFilesInternal().ToList(); if (!list2.Any()) { return list.ToArray(); } int num = 1; foreach (FileInfo item2 in list2) { PlayerSaveData playerSaveData = DecodeBackup(item2.FullName); if (playerSaveData != null) { string arg = $"Level: {playerSaveData.Level} || Experience: {Math.Round(playerSaveData.Experience, 3)}"; string item = string.Format("{0} backup{1} ago || {2}", num, (num > 1) ? "s" : "", arg); list.Add(item); num++; } } return list.ToArray(); } public static bool LoadBackup(string backupFileName) { if (backupFileName.Equals("Current Save", StringComparison.OrdinalIgnoreCase)) { Plugin.Log.LogInfo((object)"Attempted to load 'Current Save' backup. No action taken."); return true; } string saveFilePath = GetSaveFilePath(backupFileName); if (!File.Exists(saveFilePath)) { Plugin.Log.LogError((object)("Backup file not found at path: " + saveFilePath)); return false; } try { File.Copy(saveFilePath, SaveFilePath, overwrite: true); Plugin.Log.LogInfo((object)("Successfully loaded backup '" + backupFileName + "' over main save file.")); return true; } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to copy backup file: " + ex.Message)); return false; } } } public class XPAnimator : MonoBehaviour { [CompilerGenerated] private sealed class d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public XPAnimator <>4__this; private Color 5__2; private RectTransform 5__3; private Vector2 5__4; private Vector2 5__5; private float 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0034: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; XPAnimator xPAnimator = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = ((Graphic)xPAnimator.text).color; 5__2.a = 0f; ((Graphic)xPAnimator.text).color = 5__2; 5__3 = ((TMP_Text)xPAnimator.text).rectTransform; 5__4 = 5__3.anchoredPosition; 5__5 = 5__4 + new Vector2(0f, xPAnimator.floatDistance); 5__6 = 0f; goto IL_0103; case 1: <>1__state = -1; goto IL_0103; case 2: <>1__state = -1; 5__6 = 0f; break; case 3: { <>1__state = -1; break; } IL_0103: if (5__6 < xPAnimator.fadeInTime) { 5__6 += Time.deltaTime; float a = 5__6 / xPAnimator.fadeInTime; 5__2.a = a; ((Graphic)xPAnimator.text).color = 5__2; <>2__current = null; <>1__state = 1; return true; } <>2__current = (object)new WaitForSeconds(xPAnimator.stayTime); <>1__state = 2; return true; } if (5__6 < xPAnimator.floatUpTime) { 5__6 += Time.deltaTime; float a2 = 1f - 5__6 / xPAnimator.floatUpTime; 5__2.a = a2; ((Graphic)xPAnimator.text).color = 5__2; if (!xPAnimator.isLevelUp) { 5__3.anchoredPosition = Vector2.Lerp(5__4, 5__5, 5__6 / xPAnimator.floatUpTime); } <>2__current = null; <>1__state = 3; return true; } Object.Destroy((Object)(object)((Component)xPAnimator).gameObject); 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(); } } public TextMeshProUGUI text; public bool isLevelUp; public float fadeInTime = 0.3f; public float stayTime = 2f; public float floatUpTime = 1f; public float floatDistance = 50f; private void Start() { ((MonoBehaviour)this).StartCoroutine(Animate()); } [IteratorStateMachine(typeof(d__7))] private IEnumerator Animate() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { <>4__this = this }; } } } namespace Leveling.Awarders { [HarmonyPatch] internal class AchievementPatches { private const float BadgeExp = 10f; private static bool IsAscentAchievement(ACHIEVEMENTTYPE type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)type >= 33) { return (int)type <= 39; } return false; } [HarmonyPatch(typeof(AchievementManager), "ThrowAchievement")] [HarmonyPrefix] private static void AddRepeatedAchievements(AchievementManager __instance, ACHIEVEMENTTYPE type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!__instance.runBasedValueData.steamAchievementsPreviouslyUnlocked.Contains(type) && !IsAscentAchievement(type)) { Plugin.IncreaseXPSource(Plugin.XPSource.Badges, 10f); LevelingAPI.AddExperience(10f); } } } [HarmonyPatch] public class CampfirePatches { private static float xpToAward = 10f; [HarmonyPostfix] [HarmonyPatch(typeof(Campfire), "Light_Rpc")] public static void Campfire_Light_Rpc_Patch(Campfire __instance) { //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected I4, but got Unknown Segment advanceToSegment = __instance.advanceToSegment; float amount = xpToAward + (advanceToSegment - 1) switch { 0 => 0f, 1 => 5f, 2 => 10f, 3 => 15f, _ => 0f, }; Plugin.IncreaseXPSource(Plugin.XPSource.Other, amount); LevelingAPI.AddExperience(amount); } } [HarmonyPatch] internal class CharacterPatches { private static float moraleBoostCooldown = 60f; private static float lastMoraleBoostXPTime = float.NegativeInfinity; private static float climbSpamPreventionTime = float.NegativeInfinity; [HarmonyPostfix] [HarmonyPatch(typeof(Character), "Zombify")] private static void Character_Zombify_Postfix(Character __instance) { if (__instance.IsLocal) { int num = 50; Plugin.IncreaseXPSource(Plugin.XPSource.Other, num); LevelingAPI.AddExperience(num); Plugin.Log.LogInfo((object)$"Awarded {num} XP for zombifying."); } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "GetFedItemRPC")] private static void Character_GetFedItemRPC_Postfix(Character __instance) { if (__instance.IsLocal) { int num = 10; Plugin.IncreaseXPSource(Plugin.XPSource.Other, num); LevelingAPI.AddExperience(num); Plugin.Log.LogInfo((object)$"Awarded {num} XP for being fed."); } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "RPCA_Die")] private static void Character_Die_Postfix(Character __instance) { if (__instance.IsLocal) { int num = 5; Plugin.IncreaseXPSource(Plugin.XPSource.Other, num); LevelingAPI.AddExperience(num); Plugin.Log.LogInfo((object)$"Awarded {num} XP for dying."); } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "MoraleBoost")] private static void Character_MoraleBoost_Postfix(Character __instance) { if (__instance.IsLocal && !(Time.time - lastMoraleBoostXPTime < moraleBoostCooldown)) { lastMoraleBoostXPTime = Time.time; int num = 10; Plugin.IncreaseXPSource(Plugin.XPSource.Other, num); LevelingAPI.AddExperience(num); Plugin.Log.LogInfo((object)$"Awarded {num} XP for morale boost."); } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "OnStartClimb")] private static void Character_OnStartClimb_Postfix(Character __instance) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!__instance.IsLocal) { return; } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "Airport" && !(Time.time - climbSpamPreventionTime < 15f)) { int num = Random.Range(0, 100); if (num <= 5) { climbSpamPreventionTime = Time.time; int num2 = 15; Plugin.IncreaseXPSource(Plugin.XPSource.Climbing, num2); LevelingAPI.AddExperience(num2); Plugin.Log.LogInfo((object)$"Awarded {num2} XP for climbing."); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "RPCA_Revive")] private static void Character_RPCA_Revive_Postfix(Character __instance) { if (__instance.IsLocal) { int num = 25; Plugin.IncreaseXPSource(Plugin.XPSource.Other, num); LevelingAPI.AddExperience(num); Plugin.Log.LogInfo((object)$"Awarded {num} XP for being revived."); } else { int num2 = 50; Plugin.IncreaseXPSource(Plugin.XPSource.Other, num2); LevelingAPI.AddExperience(num2); Plugin.Log.LogInfo((object)$"Awarded {num2} XP for reviving someone."); } } } [HarmonyPatch] internal class GlobalEventsPatches { private static float CalculateEscapeExperience() { int currentAscent = Ascents.currentAscent; if (currentAscent < 0) { return 250f; } return 500f + (float)currentAscent * 50f; } [HarmonyPatch(typeof(GlobalEvents), "TriggerRunEnded")] [HarmonyPostfix] public static void GlobalEvents_TriggerRunEnded() { Character localCharacter = Character.localCharacter; if (localCharacter.refs.stats.won) { float num = CalculateEscapeExperience(); Plugin.IncreaseXPSource(Plugin.XPSource.Winning, num, ascentMultiplier: false); LevelingAPI.AddExperience(num, applyAscentMultiplier: false); Plugin.Log.LogInfo((object)$"Awarded {num} XP for winning the game."); } else if (localCharacter.refs.stats.somebodyElseWon) { float num2 = 50f; Plugin.IncreaseXPSource(Plugin.XPSource.Winning, num2, ascentMultiplier: false); LevelingAPI.AddExperience(num2, applyAscentMultiplier: false); Plugin.Log.LogInfo((object)$"Awarded {num2} XP for teamate winning"); } } } [HarmonyPatch] internal class LuaggagePatches { private const float OpenLuggageExp = 15f; private const float MinimumDistanceFromLuggage = 7f; private static float LocalCharacterDistanceFrom(Vector3 position) { //IL_0000: 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) return Vector3.Distance(position, Character.localCharacter.Center) * CharacterStats.unitsToMeters; } [HarmonyPatch(typeof(GlobalEvents), "TriggerLuggageOpened")] [HarmonyPostfix] public static void IncrementOpenedLuggages(Luggage luggage, Character character) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!(LocalCharacterDistanceFrom(((Component)luggage).transform.position) > 7f)) { switch (luggage.displayName) { case "Ancient Luggage": Plugin.IncreaseXPSource(Plugin.XPSource.Luggages, 35f); LevelingAPI.AddExperience(35f); break; case "Explorer's Luggage": Plugin.IncreaseXPSource(Plugin.XPSource.Luggages, 25f); LevelingAPI.AddExperience(25f); break; case "Big Luggage": Plugin.IncreaseXPSource(Plugin.XPSource.Luggages, 20f); LevelingAPI.AddExperience(20f); break; default: Plugin.IncreaseXPSource(Plugin.XPSource.Luggages, 15f); LevelingAPI.AddExperience(15f); break; } } } } internal class TrackedItem { private Item item; private float lastTimeUsed; } [HarmonyPatch] internal class UseItemPatches { private const Rarity FallbackRarity = 0; private const float CooldownTime = 30f; private static List blacklistedItems = new List { "Passport", "Bing Bong", "Binoculars", "Torn Page", "Scroll", "Guidebook", "Parasol" }; private static List trackedItemNames = new List { "Faerie Lantern", "Lantern", "Torch" }; private static readonly Dictionary itemCooldowns = new Dictionary(); private static float CalculateExperience(Rarity itemRarity) { //IL_000b: 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) float num = 100f; if (LootData.RarityWeights.ContainsKey(itemRarity)) { num = LootData.RarityWeights[itemRarity]; } return 100f / num * Mathf.Log10(num); } private static bool TryGetItemRarity(GameObject itemObject, out Rarity itemRarity) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected I4, but got Unknown LootData component = itemObject.GetComponent(); if ((Object)(object)component == (Object)null) { itemRarity = (Rarity)0; return false; } itemRarity = (Rarity)(int)component.Rarity; return true; } [HarmonyPatch(typeof(Item), "FinishCastPrimary")] [HarmonyPostfix] public static void OnPrimaryUse(Item __instance) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) string itemName = __instance.UIData.itemName; Dictionary oneUseItems = LevelingAPI.OneUseItems; if (!__instance.lastHolderCharacter.IsLocal || __instance.OnPrimaryFinishedCast == null || blacklistedItems.Contains(itemName) || (oneUseItems.TryGetValue(itemName, out var value) && value)) { return; } if (trackedItemNames.Contains(itemName)) { float time = Time.time; if (itemCooldowns.TryGetValue(itemName, out var value2) && time < value2 + 30f) { return; } itemCooldowns[itemName] = time; } if (!TryGetItemRarity(((Component)__instance).gameObject, out var itemRarity)) { itemRarity = (Rarity)0; } float num = 1f; if (__instance.totalUses > 0) { num = __instance.totalUses; } float amount = CalculateExperience(itemRarity) / num; Plugin.IncreaseXPSource(Plugin.XPSource.Items, amount); LevelingAPI.AddExperience(amount); LevelingAPI.SetOneUseItem(itemName); } [HarmonyPatch(typeof(Item), "FinishCastSecondary")] [HarmonyPostfix] public static void OnSecondaryUse(Item __instance) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) string itemName = __instance.UIData.itemName; Dictionary oneUseItems = LevelingAPI.OneUseItems; if (!__instance.lastHolderCharacter.IsLocal || __instance.OnSecondaryFinishedCast == null || blacklistedItems.Contains(itemName) || (oneUseItems.TryGetValue(itemName, out var value) && value)) { return; } if (trackedItemNames.Contains(itemName)) { float time = Time.time; if (itemCooldowns.TryGetValue(itemName, out var value2) && time < value2 + 30f) { return; } itemCooldowns[itemName] = time; } Rarity itemRarity = (Rarity)0; TryGetItemRarity(((Component)__instance).gameObject, out itemRarity); float num = 1f; if (__instance.totalUses > 0) { num = __instance.totalUses; } float amount = CalculateExperience(itemRarity) / num; Plugin.IncreaseXPSource(Plugin.XPSource.Items, amount); LevelingAPI.AddExperience(amount); LevelingAPI.SetOneUseItem(itemName); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }