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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.atomic.leveling")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: AssemblyInformationalVersion("0.1.6+c766263ec5361d8fb5d5c0247cc71ea1130a9f58")]
[assembly: AssemblyProduct("com.atomic.leveling")]
[assembly: AssemblyTitle("Leveling")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.6.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<string, bool> _oneUseItems = new Dictionary<string, bool>();
private static readonly Dictionary<Player, int> PlayerLevels = new Dictionary<Player, int>();
private static float ExperienceToNextLevel => _level * 100;
public static int Level
{
get
{
return _level;
}
private set
{
if (_level != value)
{
_level = value;
Netcode.Instance?.SendLevelUpdateRPC(value);
SaveManager.SaveData(_level, _experience, _oneUseItems);
LevelingAPI.OnLocalPlayerLevelChanged?.Invoke(value);
}
}
}
public static float Experience
{
get
{
return _experience;
}
private set
{
_experience = value;
CheckLevelUp();
SaveManager.SaveData(_level, _experience, _oneUseItems);
}
}
public static Dictionary<string, bool> OneUseItems
{
get
{
return _oneUseItems;
}
private set
{
_oneUseItems = value;
SaveManager.SaveData(_level, _experience, _oneUseItems);
}
}
public static event Action<int> OnLocalPlayerLevelChanged;
public static event Action<float> OnLocalPlayerExperienceChanged;
public static event Action<Player, int> 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 = 0.8f;
}
return num = 1f + (float)currentAscent * 0.1f;
}
public static void AddExperience(float amount, bool applyAscentMultiplier = true)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
if (amount > 0f && amount <= 2000f)
{
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name.ToLower().Contains("level"))
{
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_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)
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<string, bool> defaultOneUseItems = SaveManager.GetDefaultOneUseItems();
foreach (KeyValuePair<string, bool> 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.1.6")]
public class Plugin : BaseUnityPlugin
{
private Harmony harmony = null;
public static ConfigEntry<bool> automaticBackups;
public static ConfigEntry<int> backupsBeforeDeletion;
public static ConfigEntry<string> backupToLoad;
public static float XPGainedThisRun;
public const string Id = "com.atomic.leveling";
internal static ManualLogSource Log { get; private set; }
public static string Name => "Leveling";
public static string Version => "0.1.6";
private void Awake()
{
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Expected O, but got Unknown
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01d1: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
automaticBackups = ((BaseUnityPlugin)this).Config.Bind<bool>("Backups", "Automatic Backups", true, "Creates backups of your save file automatically on game startup");
backupsBeforeDeletion = ((BaseUnityPlugin)this).Config.Bind<int>("Backups", "Backups Before Deletion", 6, "How many backups can be created before it starts deleting old backups.");
string[] backupDataForConfig = SaveManager.GetBackupDataForConfig();
List<string> list = new List<string> { "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<string>(list.ToArray()), Array.Empty<object>());
backupToLoad = ((BaseUnityPlugin)this).Config.Bind<string>("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 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)
{
string arg = Patches.RemoveLevelTag(player.NickName);
player.NickName = $"{arg} [{newLevel}]";
Log.LogInfo((object)("Updated remote player name: " + player.NickName));
}
}
private void ExperienceGain(float newExp)
{
Log.LogInfo((object)"Trying to create ui.");
CreateExperienceGUI(newExp, out GameObject _, xpOrLevel: false);
}
private void LevelGain(int newLevel)
{
Log.LogInfo((object)"Trying to create ui.");
CreateExperienceGUI(0f, out GameObject _, xpOrLevel: true);
}
private void CreateExperienceGUI(float xpGain, out GameObject expTextObj, bool xpOrLevel)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Expected O, but got Unknown
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: 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_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
//IL_01db: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: 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<Canvas>();
val2.renderMode = (RenderMode)0;
val.AddComponent<CanvasScaler>();
val.AddComponent<GraphicRaycaster>();
expTextObj = new GameObject("ExperienceText");
expTextObj.transform.SetParent(val.transform, false);
expTextObj.AddComponent<CanvasRenderer>();
TextMeshProUGUI val3 = expTextObj.AddComponent<TextMeshProUGUI>();
((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>();
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<RectTransform>();
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)
{
component.anchoredPosition = new Vector2(100f, -10f);
}
else
{
component.anchoredPosition = new Vector2(100f, 5f);
}
Log.LogInfo((object)$"Created XP Gain GUI: +{xpGain} XP");
}
}
[HarmonyPatch]
public class Patches
{
[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))
{
return;
}
Player owner = ((MonoBehaviourPun)character).photonView.Owner;
if (owner == null)
{
return;
}
int playerLevel = LevelingAPI.GetPlayerLevel(owner);
string text = RemoveLevelTag(owner.NickName);
if (!owner.IsLocal)
{
return;
}
Netcode.Instance?.SendLevelUpdateRPC(playerLevel);
Netcode.Instance?.RequestAllPlayerLevels();
Player[] playerList = PhotonNetwork.PlayerList;
foreach (Player val in playerList)
{
if (!val.IsLocal)
{
int playerLevel2 = LevelingAPI.GetPlayerLevel(val);
string arg = RemoveLevelTag(val.NickName);
val.NickName = $"{arg} [{playerLevel2}]";
}
}
Plugin.Log.LogInfo((object)$"Character Registered (Local): {owner.NickName} is Lvl {playerLevel}. Broadcasting and Requesting Sync.");
}
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_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
GameObject gameObject = ((Component)__instance).gameObject;
if (Object.op_Implicit((Object)(object)gameObject.transform.Find("Level")))
{
((TMP_Text)((Component)gameObject.transform.Find("Level")).GetComponent<TextMeshProUGUI>()).text = $"Level: {LevelingAPI.Level} XP: {LevelingAPI.Experience}/{LevelingAPI.Level * 100}";
return;
}
GameObject gameObject2 = ((Component)gameObject.transform.Find("Peaks")).gameObject;
GameObject levelUI = Object.Instantiate<GameObject>(gameObject2, gameObject2.transform.parent);
((Object)levelUI).name = "Level";
levelUI.transform.localPosition = gameObject2.transform.localPosition + new Vector3(0f, -35f, 0f);
((TMP_Text)levelUI.GetComponent<TextMeshProUGUI>()).text = $"Level: {LevelingAPI.Level} XP: {Math.Round(LevelingAPI.Experience, 2)}/{LevelingAPI.Level * 100}";
LevelingAPI.OnLocalPlayerExperienceChanged += delegate
{
((TMP_Text)levelUI.GetComponent<TextMeshProUGUI>()).text = $"Level: {LevelingAPI.Level} XP: {Math.Round(LevelingAPI.Experience, 2)}/{LevelingAPI.Level * 100}";
};
}
[HarmonyPostfix]
[HarmonyPatch(typeof(UIPlayerNames), "Init")]
public static void UIPlayerNames_Init_Postfix(UIPlayerNames __instance)
{
PlayerName[] playerNameText = __instance.playerNameText;
foreach (PlayerName val in playerNameText)
{
TextMeshProUGUI text = val.text;
if (!((Object)(object)text != (Object)null) || !((Object)(object)val.characterInteractable != (Object)null) || !((Object)(object)val.characterInteractable.character != (Object)null) || !((Object)(object)((MonoBehaviourPun)val.characterInteractable.character).photonView != (Object)null))
{
continue;
}
Player player = ((MonoBehaviourPun)val.characterInteractable.character).photonView.Owner;
int playerLevel = LevelingAPI.GetPlayerLevel(player);
string arg = RemoveLevelTag(player.NickName);
((TMP_Text)text).text = $"{arg} [{playerLevel}]";
LevelingAPI.OnRemotePlayerLevelChanged += delegate(Player changedPlayer, int newLevel)
{
if (!((Object)(object)text == (Object)null) && changedPlayer == player)
{
string arg2 = RemoveLevelTag(changedPlayer.NickName);
((TMP_Text)text).text = $"{arg2} [{newLevel}]";
}
};
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(RunManager), "StartRun")]
public static void RunManager_StartRun_Postfix()
{
Plugin.XPGainedThisRun = 0f;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(EndScreen), "Start")]
public static void EndScreen_Start_Postfix(EndScreen __instance)
{
Transform val = ((Component)__instance).transform.Find("Panel/Margin/Layout/Window_BADGES/Title (1)");
TextMeshProUGUI component = ((Component)val).gameObject.GetComponent<TextMeshProUGUI>();
if (!((TMP_Text)component).text.Contains("(XP GAINED:"))
{
((TMP_Text)component).text = $"{((TMP_Text)component).text} (XP GAINED: +{Plugin.XPGainedThisRun})";
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(BoardingPass), "UpdateAscent")]
public static void BoardingPass_UpdateAscent_Postfix(BoardingPass __instance)
{
int ascentIndex = __instance._ascentIndex;
float num = 1f;
num = ((ascentIndex >= 0) ? (1f + (float)ascentIndex * 0.1f) : 0.8f);
GameObject gameObject = ((Component)((Component)__instance).transform.Find("BoardingPass/Panel/Ascent/Title")).gameObject;
TextMeshProUGUI component = gameObject.GetComponent<TextMeshProUGUI>();
((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 = null;
public static Netcode Instance
{
get
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
if ((Object)(object)_instance == (Object)null)
{
GameObject val = new GameObject("LevelingNetcode");
_instance = val.AddComponent<Netcode>();
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<PhotonView>();
if ((Object)(object)_photonView == (Object)null)
{
_photonView = ((Component)this).gameObject.AddComponent<PhotonView>();
_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<object>());
Plugin.Log.LogInfo((object)"Requested all existing player levels from Master Client.");
}
}
[PunRPC]
public void RPC_RequestPlayerLevels(PhotonMessageInfo info)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: 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_0001: 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_0001: 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; } = 0f;
public Dictionary<string, bool> OneUseItems { get; set; } = new Dictionary<string, bool> { { "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<string, bool> GetDefaultOneUseItems()
{
return new Dictionary<string, bool>(new PlayerSaveData().OneUseItems);
}
private static string GetSaveFilePath(string fileName)
{
return Path.Combine(BaseDirPath, fileName);
}
public static void SaveData(int level, float experience, Dictionary<string, bool> 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<PlayerSaveData>(@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<PlayerSaveData>(@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<FileInfo> source = GetBackupFilesInternal().ToList();
List<FileInfo> 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<string, bool>>((KeyValuePair<string, bool> 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<FileInfo> backupFilesInternal = GetBackupFilesInternal();
List<FileInfo> 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<FileInfo> GetBackupFilesInternal()
{
DirectoryInfo directoryInfo = new DirectoryInfo(BaseDirPath);
return from f in directoryInfo.GetFiles("*.backup")
orderby f.CreationTime descending
select f;
}
public static string[] GetBackupDataForConfig()
{
List<string> list = new List<string>();
List<FileInfo> 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 <Animate>d__7 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public XPAnimator <>4__this;
private Color <c>5__1;
private RectTransform <rt>5__2;
private Vector2 <startPos>5__3;
private Vector2 <endPos>5__4;
private float <t>5__5;
private float <a>5__6;
private float <a>5__7;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Animate>d__7(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<rt>5__2 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Expected O, but got Unknown
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0205: Unknown result type (might be due to invalid IL or missing references)
//IL_021c: Unknown result type (might be due to invalid IL or missing references)
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<c>5__1 = ((Graphic)<>4__this.text).color;
<c>5__1.a = 0f;
((Graphic)<>4__this.text).color = <c>5__1;
<rt>5__2 = ((TMP_Text)<>4__this.text).rectTransform;
<startPos>5__3 = <rt>5__2.anchoredPosition;
<endPos>5__4 = <startPos>5__3 + new Vector2(0f, <>4__this.floatDistance);
<t>5__5 = 0f;
goto IL_013c;
case 1:
<>1__state = -1;
goto IL_013c;
case 2:
<>1__state = -1;
<t>5__5 = 0f;
break;
case 3:
{
<>1__state = -1;
break;
}
IL_013c:
if (<t>5__5 < <>4__this.fadeInTime)
{
<t>5__5 += Time.deltaTime;
<a>5__6 = <t>5__5 / <>4__this.fadeInTime;
<c>5__1.a = <a>5__6;
((Graphic)<>4__this.text).color = <c>5__1;
<>2__current = null;
<>1__state = 1;
return true;
}
<>2__current = (object)new WaitForSeconds(<>4__this.stayTime);
<>1__state = 2;
return true;
}
if (<t>5__5 < <>4__this.floatUpTime)
{
<t>5__5 += Time.deltaTime;
<a>5__7 = 1f - <t>5__5 / <>4__this.floatUpTime;
<c>5__1.a = <a>5__7;
((Graphic)<>4__this.text).color = <c>5__1;
if (!<>4__this.isLevelUp)
{
<rt>5__2.anchoredPosition = Vector2.Lerp(<startPos>5__3, <endPos>5__4, <t>5__5 / <>4__this.floatUpTime);
}
<>2__current = null;
<>1__state = 3;
return true;
}
Object.Destroy((Object)(object)((Component)<>4__this).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 = false;
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(<Animate>d__7))]
private IEnumerator Animate()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Animate>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_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: Invalid comparison between Unknown and I4
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
return (int)type >= 33 && (int)type <= 39;
}
[HarmonyPatch(typeof(AchievementManager), "ThrowAchievement")]
[HarmonyPrefix]
private static void AddRepeatedAchievements(AchievementManager __instance, ACHIEVEMENTTYPE type)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (!__instance.runBasedValueData.steamAchievementsPreviouslyUnlocked.Contains(type) && !IsAscentAchievement(type))
{
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_0002: 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_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected I4, but got Unknown
Segment advanceToSegment = __instance.advanceToSegment;
if (1 == 0)
{
}
float num = (advanceToSegment - 1) switch
{
0 => 0f,
1 => 5f,
2 => 10f,
3 => 15f,
_ => 0f,
};
if (1 == 0)
{
}
float num2 = num;
float amount = xpToAward + num2;
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 = 100;
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;
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;
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;
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_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
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;
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 = 50;
LevelingAPI.AddExperience(num);
Plugin.Log.LogInfo((object)$"Awarded {num} XP for being revived.");
}
else
{
int num2 = 100;
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();
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;
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_0001: 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)
return Vector3.Distance(position, Character.localCharacter.Center) * CharacterStats.unitsToMeters;
}
[HarmonyPatch(typeof(GlobalEvents), "TriggerLuggageOpened")]
[HarmonyPostfix]
public static void IncrementOpenedLuggages(Luggage luggage, Character character)
{
//IL_0007: 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":
LevelingAPI.AddExperience(35f);
break;
case "Explorer's Luggage":
LevelingAPI.AddExperience(25f);
break;
case "Big Luggage":
LevelingAPI.AddExperience(20f);
break;
default:
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<string> blacklistedItems = new List<string> { "Passport", "Bing Bong", "Binoculars", "Torn Page", "Scroll", "Guidebook", "Parasol" };
private static List<string> trackedItemNames = new List<string> { "Faerie Lantern", "Lantern", "Torch" };
private static readonly Dictionary<string, float> itemCooldowns = new Dictionary<string, float>();
private static float CalculateExperience(Rarity itemRarity)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: 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_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected I4, but got Unknown
LootData component = itemObject.GetComponent<LootData>();
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_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
string itemName = __instance.UIData.itemName;
Dictionary<string, bool> 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;
LevelingAPI.AddExperience(amount);
LevelingAPI.SetOneUseItem(itemName);
}
[HarmonyPatch(typeof(Item), "FinishCastSecondary")]
[HarmonyPostfix]
public static void OnSecondaryUse(Item __instance)
{
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
string itemName = __instance.UIData.itemName;
Dictionary<string, bool> 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;
LevelingAPI.AddExperience(amount);
LevelingAPI.SetOneUseItem(itemName);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}