Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LethalCompanyProgressionPatchFix v2.3.2
LethalProgression.dll
Decompiled 9 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalNetworkAPI; using LethalProgression.Config; using LethalProgression.GUI.HandSlot; using LethalProgression.GUI.Skills; using LethalProgression.GUI.XPBar; using LethalProgression.LessShitConfig; using LethalProgression.LessShitConfig.Attributes; using LethalProgression.LessShitConfig.Internal; using LethalProgression.LessShitConfig.Internal.ClassBuilders; using LethalProgression.LessShitConfig.Sources; using LethalProgression.Network; using LethalProgression.Patches; using LethalProgression.Saving; using LethalProgression.Skills; using LethalProgression.Skills.Upgrades; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Steamworks; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; 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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("LethalProgression")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Leveling and skillpoints through a managed GUI! Patched and bugfixed until official copy updated.")] [assembly: AssemblyFileVersion("2.3.2.0")] [assembly: AssemblyInformationalVersion("2.3.2")] [assembly: AssemblyProduct("LethalProgression")] [assembly: AssemblyTitle("LethalProgression")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LethalProgression { internal class LC_XP : NetworkBehaviour { public LethalNetworkVariable<int> teamLevel = new LethalNetworkVariable<int>("teamLevel") { Value = 0 }; public LethalNetworkVariable<int> teamXP = new LethalNetworkVariable<int>("teamXP") { Value = 0 }; public LethalNetworkVariable<int> teamTotalValue = new LethalNetworkVariable<int>("teamTotalValue") { Value = 0 }; public LethalNetworkVariable<int> teamXPRequired = new LethalNetworkVariable<int>("teamXPRequired") { Value = 0 }; public LethalNetworkVariable<int> teamLootLevel = new LethalNetworkVariable<int>("teamLootLevel") { Value = 0 }; public LethalNetworkVariable<int> teamShipDoorBatteryLevel = new LethalNetworkVariable<int>("teamShipDoorBatteryLevel") { Value = 0 }; public LethalClientEvent playerConnectClientEvent = new LethalClientEvent("playerConnectEvent", (Action)null, (Action<ulong>)null); public LethalServerEvent playerConnectServerEvent = new LethalServerEvent("playerConnectEvent", (Action<ulong>)null); public LethalClientEvent evaluateXPRequirementClientEvent = new LethalClientEvent("evaluateXPRequirementEvent", (Action)null, (Action<ulong>)null); public LethalServerEvent evaluateXPRequirementServerEvent = new LethalServerEvent("evaluateXPRequirementEvent", (Action<ulong>)null); public LethalClientEvent calculateAllPlayersHandSlotsClientEvent = new LethalClientEvent("calculateAllPlayersHandSlotsEvent", (Action)null, (Action<ulong>)null); public LethalServerEvent calculateAllPlayersHandSlotsServerEvent = new LethalServerEvent("calculateAllPlayersHandSlotsEvent", (Action<ulong>)null); public LethalServerMessage<string> sendConfigServerMessage = new LethalServerMessage<string>("sendConfigMessage", (Action<string, ulong>)null); public LethalClientMessage<string> sendConfigClientMessage = new LethalClientMessage<string>("sendConfigMessage", (Action<string>)null, (Action<string, ulong>)null); public LethalServerMessage<ulong> requestProfileDataServerMessage = new LethalServerMessage<ulong>("requestProfileDataMessage", (Action<ulong, ulong>)null); public LethalClientMessage<ulong> requestProfileDataClientMessage = new LethalClientMessage<ulong>("requestProfileDataMessage", (Action<ulong>)null, (Action<ulong, ulong>)null); public LethalServerMessage<string> sendProfileDataServerMessage = new LethalServerMessage<string>("sendProfileDataMessage", (Action<string, ulong>)null); public LethalClientMessage<string> receiveProfileDataClientMessage = new LethalClientMessage<string>("sendProfileDataMessage", (Action<string>)null, (Action<string, ulong>)null); public LethalServerMessage<string> saveProfileDataServerMessage = new LethalServerMessage<string>("saveProfileDataMessage", (Action<string, ulong>)null); public LethalClientMessage<string> saveProfileDataClientMessage = new LethalClientMessage<string>("saveProfileDataMessage", (Action<string>)null, (Action<string, ulong>)null); public LethalServerMessage<int> updateTeamLootLevelServerMessage = new LethalServerMessage<int>("updateTeamLootLevelMessage", (Action<int, ulong>)null); public LethalClientMessage<int> updateTeamLootLevelClientMessage = new LethalClientMessage<int>("updateTeamLootLevelMessage", (Action<int>)null, (Action<int, ulong>)null); public LethalServerMessage<int> updateTeamShipDoorBatteryLevelServerMessage = new LethalServerMessage<int>("updateTeamShipDoorBatteryLevelMessage", (Action<int, ulong>)null); public LethalClientMessage<int> updateTeamShipDoorBatteryLevelClientMessage = new LethalClientMessage<int>("updateTeamShipDoorBatteryLevelMessage", (Action<int>)null, (Action<int, ulong>)null); public LethalServerMessage<int> updateTeamXPServerMessage = new LethalServerMessage<int>("updateTeamXPMessage", (Action<int, ulong>)null); public LethalClientMessage<int> updateTeamXPClientMessage = new LethalClientMessage<int>("updateTeamXPMessage", (Action<int>)null, (Action<int, ulong>)null); public LethalServerMessage<int> updatePlayerSkillpointsServerMessage = new LethalServerMessage<int>("updatePlayerSkillPointsMessage", (Action<int, ulong>)null); public LethalClientMessage<int> updatePlayerSkillpointsClientMessage = new LethalClientMessage<int>("updatePlayerSkillPointsMessage", (Action<int>)null, (Action<int, ulong>)null); public LethalServerMessage<int> updateSPHandSlotsServerMessage = new LethalServerMessage<int>("updateSPHandSlotsMessage", (Action<int, ulong>)null); public LethalClientMessage<int> updateSPHandSlotsClientMessage = new LethalClientMessage<int>("updateSPHandSlotsMessage", (Action<int>)null, (Action<int, ulong>)null); public LethalServerMessage<PlayerHandSlotData> updatePlayerHandSlotsServerMessage = new LethalServerMessage<PlayerHandSlotData>("updatePlayerHandSlotsMessage", (Action<PlayerHandSlotData, ulong>)null); public LethalClientMessage<PlayerHandSlotData> updatePlayerHandSlotsClientMessage = new LethalClientMessage<PlayerHandSlotData>("updatePlayerHandSlotsMessage", (Action<PlayerHandSlotData>)null, (Action<PlayerHandSlotData, ulong>)null); public int skillPoints; public SkillList skillList = new SkillList(); public bool Initialized = false; public bool loadedSave = false; public void Start() { LethalPlugin.Log.LogInfo((object)"XP Network Behavior Made!"); teamLevel.OnValueChanged += OnTeamLevelChange; playerConnectServerEvent.OnReceived += PlayerConnect_C2SEvent; evaluateXPRequirementServerEvent.OnReceived += EvaluateXPRequirements_C2SEvent; calculateAllPlayersHandSlotsServerEvent.OnReceived += RefreshAllPlayerHandSlots_C2SEvent; sendConfigClientMessage.OnReceived += SendHostConfig_S2CMessage; receiveProfileDataClientMessage.OnReceived += LoadProfileData_S2CMessage; updatePlayerSkillpointsClientMessage.OnReceived += UpdateSkillPoints_S2CMessage; updatePlayerHandSlotsClientMessage.OnReceived += UpdatePlayerHandSlots_S2CMessage; requestProfileDataServerMessage.OnReceived += RequestSavedData_C2SMessage; saveProfileDataServerMessage.OnReceived += SaveProfileData_C2SMessage; updateTeamLootLevelServerMessage.OnReceived += UpdateTeamLootLevel_C2SMessage; updateTeamShipDoorBatteryLevelServerMessage.OnReceived += UpdateTeamShipDoorBatteryLevel_C2SMessage; updateTeamXPServerMessage.OnReceived += UpdateTeamXP_C2SMessage; updateSPHandSlotsServerMessage.OnReceived += UpdateSPHandSlots_C2SMessage; playerConnectClientEvent.InvokeServer(); } public override void OnDestroy() { teamLevel.OnValueChanged -= OnTeamLevelChange; teamLootLevel.OnValueChanged -= LethalPlugin.SkillsGUI.TeamLootButtonUpdate; teamShipDoorBatteryLevel.OnValueChanged -= LethalPlugin.SkillsGUI.TeamShipDoorButtonUpdate; playerConnectServerEvent.OnReceived -= PlayerConnect_C2SEvent; evaluateXPRequirementServerEvent.OnReceived -= EvaluateXPRequirements_C2SEvent; calculateAllPlayersHandSlotsServerEvent.OnReceived -= RefreshAllPlayerHandSlots_C2SEvent; sendConfigClientMessage.OnReceived -= SendHostConfig_S2CMessage; receiveProfileDataClientMessage.OnReceived -= LoadProfileData_S2CMessage; updatePlayerSkillpointsClientMessage.OnReceived -= UpdateSkillPoints_S2CMessage; updatePlayerHandSlotsClientMessage.OnReceived -= UpdatePlayerHandSlots_S2CMessage; requestProfileDataServerMessage.OnReceived -= RequestSavedData_C2SMessage; saveProfileDataServerMessage.OnReceived -= SaveProfileData_C2SMessage; updateTeamLootLevelServerMessage.OnReceived -= UpdateTeamLootLevel_C2SMessage; updateTeamShipDoorBatteryLevelServerMessage.OnReceived -= UpdateTeamShipDoorBatteryLevel_C2SMessage; updateTeamXPServerMessage.OnReceived -= UpdateTeamXP_C2SMessage; updateSPHandSlotsServerMessage.OnReceived -= UpdateSPHandSlots_C2SMessage; ((NetworkBehaviour)this).OnDestroy(); } private void OnTeamLevelChange(int newLevel) { ((MonoBehaviour)this).StartCoroutine(WaitUntilInitialisedThenAction(HUDManagerPatch.ShowLevelUp)); } private void OnTeamXPChange(int newXP) { ((MonoBehaviour)this).StartCoroutine(WaitUntilInitialisedThenAction(HUDManagerPatch.ShowXPUpdate)); } public IEnumerator WaitUntilInitialisedThenAction(Action callback) { yield return (object)new WaitUntil((Func<bool>)(() => Initialized)); callback(); } public void PlayerConnect_C2SEvent(ulong clientId) { LethalPlugin.Log.LogDebug((object)$"Received PlayerConnect message from {clientId}"); LessShitConfigSystem.ClearHostConfigs(); string text = LessShitConfigSystem.SerializeLocalConfigs(); LethalPlugin.Log.LogDebug((object)("Sending config -> " + text)); sendConfigServerMessage.SendClient(text, clientId); } public void LoadSharedData() { SaveSharedData? saveSharedData = ES3SaveManager.LoadSharedFile(); if (!saveSharedData.HasValue) { LethalPlugin.Log.LogDebug((object)"Shared data is null!"); return; } SaveSharedData value = saveSharedData.Value; LethalPlugin.Log.LogDebug((object)"Loading Lobby shared data."); teamXP.Value = value.xp; teamLevel.Value = value.level; teamTotalValue.Value = value.quota; teamXPRequired.Value = CalculateXPRequirement(); LethalPlugin.Log.LogDebug((object)$"{value.level} current lvl, {value.xp} XP, {value.quota} Profit, {teamXPRequired.Value} teamXPRequired"); } public IEnumerator LoadProfileData(string data) { LethalPlugin.Log.LogDebug((object)("Received player data from host -> " + data)); yield return (object)new WaitUntil((Func<bool>)(() => Initialized)); if (loadedSave) { LethalPlugin.Log.LogWarning((object)"Already loaded player data from host."); yield return null; } loadedSave = true; SaveData saveData = JsonConvert.DeserializeObject<SaveData>(data); skillPoints = saveData.skillPoints; LethalPlugin.Log.LogDebug((object)$"skillPoints -> {skillPoints}"); int skillCheck = 0; foreach (KeyValuePair<UpgradeType, int> skill in saveData.skillAllocation) { LethalPlugin.Log.LogDebug((object)$"{skill.Key} -> {skill.Value}"); skillList.skills[skill.Key].SetLevel(skill.Value, triggerHostProfileSave: false); skillCheck += skill.Value; LethalPlugin.Log.LogDebug((object)$"skillCheck -> {skillCheck}"); } if (skillCheck + skillPoints < teamLevel.Value + GetDefaultStartingSkillPoints()) { LethalPlugin.Log.LogDebug((object)$"Skill check is less than current level, adding {teamLevel.Value + GetDefaultStartingSkillPoints() - (skillCheck + skillPoints)} skill points."); skillPoints += teamLevel.Value + GetDefaultStartingSkillPoints() - (skillCheck + skillPoints); } LethalPlugin.SkillsGUI.UpdateAllStats(); } public int CalculateXPRequirement() { int connectedPlayersAmount = StartOfRound.Instance.connectedPlayersAmount; int timesFulfilledQuota = TimeOfDay.Instance.timesFulfilledQuota; IGeneralConfig active = LessShitConfigSystem.GetActive<IGeneralConfig>(); int num = connectedPlayersAmount * active.personMultiplier; int num2 = active.minXP + num; int num3 = timesFulfilledQuota * active.quotaMultiplier; num2 += (int)((float)num2 * ((float)num3 / 100f)); if (num2 > active.maxXP) { num2 = active.maxXP; } LethalPlugin.Log.LogInfo((object)$"{connectedPlayersAmount} players, {timesFulfilledQuota} quotas, {active.minXP} initial cost, {num} person value, {num3} quota value, {num2} total cost."); return num2; } public int GetDefaultStartingSkillPoints() { IGeneralConfig active = LessShitConfigSystem.GetActive<IGeneralConfig>(); return active.startSkillPoints; } public int GetXP() { return teamXP.Value; } public int GetLevel() { return teamLevel.Value; } public int GetProfit() { return teamTotalValue.Value; } public int GetSkillPoints() { return skillPoints; } public void SetSkillPoints(int num) { skillPoints = num; } public void EvaluateXPRequirements_C2SEvent(ulong clientId) { ((MonoBehaviour)this).StartCoroutine(XPRequirementCoroutine()); } public IEnumerator XPRequirementCoroutine() { yield return (object)new WaitForSeconds(0.5f); teamXPRequired.Value = CalculateXPRequirement(); } public void UpdateTeamXP_C2SMessage(int xpToAdd, ulong clientId) { LethalNetworkVariable<int> obj = teamXP; obj.Value += xpToAdd; LethalNetworkVariable<int> obj2 = teamTotalValue; obj2.Value += xpToAdd; int num = GetXP(); if (num >= teamXPRequired.Value) { int num2 = 0; while (num >= teamXPRequired.Value) { num2++; num -= teamXPRequired.Value; } teamXP.Value = num; LethalNetworkVariable<int> obj3 = teamLevel; obj3.Value += num2; updatePlayerSkillpointsServerMessage.SendAllClients(num2, true); } } public void UpdateSkillPoints_S2CMessage(int pointsToAdd) { skillPoints += pointsToAdd; } public void UpdateTeamLootLevel_C2SMessage(int change, ulong clientId) { int value = teamLootLevel.Value; if (value + change <= 0) { teamLootLevel.Value = 0; } else { LethalNetworkVariable<int> obj = teamLootLevel; obj.Value += change; } LethalPlugin.Log.LogDebug((object)$"[{clientId}] Requested {change} to Team Loot Value, new value: {teamLootLevel.Value}"); } public void UpdateTeamShipDoorBatteryLevel_C2SMessage(int change, ulong clientId) { int value = teamShipDoorBatteryLevel.Value; if (value + change <= 0) { teamShipDoorBatteryLevel.Value = 0; } else { LethalNetworkVariable<int> obj = teamShipDoorBatteryLevel; obj.Value += change; } LethalPlugin.Log.LogDebug((object)$"[{clientId}] Requested {change} to Team Ship Door Battery Value, new value: {teamShipDoorBatteryLevel.Value}"); } public void UpdateSPHandSlots_C2SMessage(int slotChange, ulong clientId) { if (!LethalPlugin.ReservedSlots) { LethalPlugin.Log.LogInfo((object)$"C2S Received update for Player {clientId} to add {slotChange} slots"); updatePlayerHandSlotsServerMessage.SendAllClients(new PlayerHandSlotData(clientId, slotChange), true); } } public void UpdatePlayerHandSlots_S2CMessage(PlayerHandSlotData data) { LethalPlugin.Log.LogInfo((object)$"S2C Received update for Player {data.clientId} to add {data.additionalSlots} slots"); SetHandSlot(data.clientId, data.additionalSlots); } public void SetHandSlot(ulong playerID, int additionalSlots) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (val.playerClientId != playerID) { continue; } int num = 4 + additionalSlots; List<GrabbableObject> list = val.ItemSlots.ToList(); if (val.currentItemSlot > num - 1) { HandSlots.SwitchItemSlots(val, num - 1); } for (int j = 0; j < list.Count; j++) { if (j > num - 1 && (Object)(object)list[j] != (Object)null) { HandSlots.SwitchItemSlots(val, j); val.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true); } } val.ItemSlots = (GrabbableObject[])(object)new GrabbableObject[num]; for (int k = 0; k < list.Count; k++) { if (!((Object)(object)list[k] == (Object)null)) { val.ItemSlots[k] = list[k]; } } LethalPlugin.Log.LogDebug((object)$"Player {playerID} has {val.ItemSlots.Length} slots after setting."); if ((Object)(object)val == (Object)(object)GameNetworkManager.Instance.localPlayerController) { LethalPlugin.Log.LogDebug((object)"Updating HUD slots."); HandSlots.UpdateHudSlots(); } break; } } public void RefreshAllPlayerHandSlots_C2SEvent(ulong clientId) { if (LethalPlugin.ReservedSlots || !LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.HandSlot)) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (((Component)val).gameObject.activeSelf) { ulong playerClientId = val.playerClientId; int additionalSlots = val.ItemSlots.Length - 4; updatePlayerHandSlotsServerMessage.SendAllClients(new PlayerHandSlotData(playerClientId, additionalSlots), true); } } } public void SendHostConfig_S2CMessage(string serializedConfig) { LessShitConfigSystem.ApplyHostConfigs(serializedConfig); if (!Initialized) { Initialized = true; LP_NetworkManager.xpInstance = this; skillList.InitializeSkills(); if (GameNetworkManager.Instance.isHostingGame) { LoadSharedData(); } teamLootLevel.OnValueChanged += LethalPlugin.SkillsGUI.TeamLootButtonUpdate; teamShipDoorBatteryLevel.OnValueChanged += LethalPlugin.SkillsGUI.TeamShipDoorButtonUpdate; skillPoints = teamLevel.Value + GetDefaultStartingSkillPoints(); calculateAllPlayersHandSlotsClientEvent.InvokeServer(); evaluateXPRequirementClientEvent.InvokeServer(); } } public void RequestSavedData_C2SMessage(ulong steamID, ulong clientId) { string text = ES3SaveManager.LoadPlayerFile(steamID); PlayerControllerB playerController = LethalNetworkExtensions.GetPlayerController(clientId); sendProfileDataServerMessage.SendClient(text, playerController.actualClientId); } public void LoadProfileData_S2CMessage(string saveData) { LethalPlugin.Log.LogDebug((object)("Received LoadProfileData_S2CMessage -> " + saveData)); if (saveData != null) { ((MonoBehaviour)this).StartCoroutine(LoadProfileData(saveData)); } } public void SaveProfileData_C2SMessage(string data, ulong clientId) { SaveProfileData saveProfileData = JsonConvert.DeserializeObject<SaveProfileData>(data); LethalPlugin.Log.LogDebug((object)$"Received SaveData request for {saveProfileData.steamId} with data -> {JsonConvert.SerializeObject((object)saveProfileData.saveData)}"); ES3SaveManager.Save(saveProfileData.steamId, saveProfileData.saveData); ES3SaveManager.SaveShared(teamXP.Value, teamLevel.Value, teamTotalValue.Value); } } [HarmonyPatch] internal class LP_NetworkManager { public static LC_XP xpInstance; public static GameObject xpNetworkObject; [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "Start")] public static void Init() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (!((Object)(object)xpNetworkObject != (Object)null)) { xpNetworkObject = (GameObject)LethalPlugin.skillBundle.LoadAsset("LP_XPHandler"); xpNetworkObject.AddComponent<LC_XP>(); NetworkManager.Singleton.AddNetworkPrefab(xpNetworkObject); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Awake")] private static void SpawnNetworkHandler() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { GameObject val = Object.Instantiate<GameObject>(xpNetworkObject, Vector3.zero, Quaternion.identity); val.GetComponent<NetworkObject>().Spawn(false); xpInstance = val.GetComponent<LC_XP>(); LethalPlugin.Log.LogInfo((object)"XPHandler Initialized."); } } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("TisRyno.LethalProgression", "Lethal Progression", "2.2.1")] internal class LethalPlugin : BaseUnityPlugin { private const string modGUID = "TisRyno.LethalProgression"; private const string modName = "Lethal Progression"; private const string modVersion = "2.2.1"; public static AssetBundle skillBundle; internal static ManualLogSource Log; internal static bool ReservedSlots; public static LethalPlugin Instance { get; private set; } public static XPBarGUI XPBarGUI { get; private set; } public static SkillsGUI SkillsGUI { get; private set; } public static SlotTemplate SlotTemplate { get; private set; } private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown Instance = this; XPBarGUI = new XPBarGUI(); SkillsGUI = new SkillsGUI(); SlotTemplate = new SlotTemplate(); Harmony val = new Harmony("TisRyno.LethalProgression"); val.PatchAll(); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); skillBundle = AssetBundle.LoadFromFile(Path.Combine(directoryName, "skillmenu")); if ((Object)(object)skillBundle == (Object)null) { Log.LogFatal((object)"Failed to load custom assets."); return; } Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Lethal Progression initialised."); LessShitConfigSystem.RegisterSection<IGeneralConfig>(); LessShitConfigSystem.RegisterSection<IBatteryLifeConfig>(); LessShitConfigSystem.RegisterSection<IHandSlotsConfig>(); LessShitConfigSystem.RegisterSection<IHealthRegenConfig>(); LessShitConfigSystem.RegisterSection<IMaxHealthConfig>(); LessShitConfigSystem.RegisterSection<IJumpHeightConfig>(); LessShitConfigSystem.RegisterSection<ILootValueConfig>(); LessShitConfigSystem.RegisterSection<ISprintSpeedConfig>(); LessShitConfigSystem.RegisterSection<IStaminaConfig>(); LessShitConfigSystem.RegisterSection<IStrengthConfig>(); LessShitConfigSystem.RegisterSection<IShipHangarDoorConfig>(); LessShitConfigSystem.RegisterSection<IUIConfig>(); LessShitConfigSystem.Bake(((BaseUnityPlugin)this).Config); LessShitConfigSystem.SerializeLocalConfigs(); Log.LogInfo((object)"Lethal Progression Config loaded."); foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { string gUID = pluginInfo.Value.Metadata.GUID; if (gUID.Contains("ReservedItem")) { ReservedSlots = true; break; } if (gUID.Contains("mikestweaks") && (from entry in pluginInfo.Value.Instance.Config.GetConfigEntries() where entry.Definition.Key == "ExtraItemSlots" where int.TryParse(entry.GetSerializedValue(), out var result) && result > 0 select entry).Any()) { ReservedSlots = true; break; } } SaveDataMigration.MigrateOldSaves(); } public IDictionary<string, object> GetAllConfigEntries() { return ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)((BaseUnityPlugin)this).Config).ToDictionary((KeyValuePair<ConfigDefinition, ConfigEntryBase> entry) => entry.Value.Definition.Key, (KeyValuePair<ConfigDefinition, ConfigEntryBase> entry) => entry.Value.BoxedValue); } } public static class PluginInfo { public const string PLUGIN_GUID = "LethalProgression"; public const string PLUGIN_NAME = "LethalProgression"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace LethalProgression.Skills { internal abstract class Skill { protected readonly Action<int> _callback; public int CurrentLevel { get; protected set; } public abstract string ShortName { get; } public abstract string Name { get; } public abstract string Attribute { get; } public abstract string Description { get; } public abstract UpgradeType UpgradeType { get; } public abstract int Cost { get; } public abstract int MaxLevel { get; } public abstract float Multiplier { get; } public abstract bool IsTeamShared { get; } public Skill(Action<int> callback = null) { CurrentLevel = 0; _callback = callback; } public float GetTrueValue() { return Multiplier * (float)CurrentLevel; } public void SetLevel(int newLevel, bool triggerHostProfileSave = true) { int currentLevel = CurrentLevel; CurrentLevel = newLevel; _callback?.Invoke(newLevel - currentLevel); if (triggerHostProfileSave) { ES3SaveManager.TriggerHostProfileSave(); } } public void AddLevel(int change) { CurrentLevel += change; _callback?.Invoke(change); ES3SaveManager.TriggerHostProfileSave(); } } internal class SkillList { public Dictionary<UpgradeType, Skill> skills = new Dictionary<UpgradeType, Skill>(); public bool IsSkillValid(UpgradeType upgrade) { return skills.ContainsKey(upgrade) && skills[upgrade].CurrentLevel > 0; } public Skill GetSkill(UpgradeType upgrade) { if (!IsSkillValid(upgrade)) { return null; } return skills[upgrade]; } public Dictionary<UpgradeType, Skill> GetSkills() { return skills; } public void InitializeSkills() { IHealthRegenConfig active = LessShitConfigSystem.GetActive<IHealthRegenConfig>(); IMaxHealthConfig active2 = LessShitConfigSystem.GetActive<IMaxHealthConfig>(); IStaminaConfig active3 = LessShitConfigSystem.GetActive<IStaminaConfig>(); IBatteryLifeConfig active4 = LessShitConfigSystem.GetActive<IBatteryLifeConfig>(); IHandSlotsConfig active5 = LessShitConfigSystem.GetActive<IHandSlotsConfig>(); ILootValueConfig active6 = LessShitConfigSystem.GetActive<ILootValueConfig>(); IStrengthConfig active7 = LessShitConfigSystem.GetActive<IStrengthConfig>(); IJumpHeightConfig active8 = LessShitConfigSystem.GetActive<IJumpHeightConfig>(); ISprintSpeedConfig active9 = LessShitConfigSystem.GetActive<ISprintSpeedConfig>(); IShipHangarDoorConfig active10 = LessShitConfigSystem.GetActive<IShipHangarDoorConfig>(); if (active.isEnabled) { skills.Add(UpgradeType.HPRegen, new HPRegen()); } if (active2.isEnabled) { skills.Add(UpgradeType.MaxHealth, new MaxHP()); } if (active3.isEnabled) { skills.Add(UpgradeType.Stamina, new Stamina()); } if (active4.isEnabled) { skills.Add(UpgradeType.Battery, new BatteryLife()); } if (active5.isEnabled && !LethalPlugin.ReservedSlots) { skills.Add(UpgradeType.HandSlot, new HandSlots()); } if (active6.isEnabled) { skills.Add(UpgradeType.Value, new LootValue()); } if (active7.isEnabled) { skills.Add(UpgradeType.Strength, new Strength()); } if (active8.isEnabled) { skills.Add(UpgradeType.JumpHeight, new JumpHeight()); } if (active9.isEnabled) { skills.Add(UpgradeType.SprintSpeed, new SprintSpeed()); } if (active10.isEnabled) { skills.Add(UpgradeType.ShipDoorBattery, new ShipDoorBattery()); } } } internal interface ISkill { string ShortName { get; } string Name { get; } string Attribute { get; } string Description { get; } UpgradeType UpgradeType { get; } int Cost { get; } int MaxLevel { get; } float Multiplier { get; } bool IsTeamShared { get; } int CurrentLevel { get; set; } } public enum UpgradeType { HPRegen, Stamina, Battery, HandSlot, Value, JumpHeight, SprintSpeed, Strength, MaxHealth, ShipDoorBattery } } namespace LethalProgression.Skills.Upgrades { internal class BatteryLife : Skill { public override string ShortName => "BAT"; public override string Name => "Battery Life"; public override string Attribute => "Battery Life"; public override string Description => "The company provides you with better batteries found from exotic moons. Don't forget to recharge them AT THE SHIP'S CHARGER."; public override UpgradeType UpgradeType => UpgradeType.Battery; public override int Cost => 1; public override int MaxLevel { get { IBatteryLifeConfig active = LessShitConfigSystem.GetActive<IBatteryLifeConfig>(); return active.maxLevel; } } public override float Multiplier { get { IBatteryLifeConfig active = LessShitConfigSystem.GetActive<IBatteryLifeConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public static float GetUseItemBatteryUsage(float defaultBatteryUsage) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.Battery)) { return defaultBatteryUsage; } float num = 1f + LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Battery].GetTrueValue() / 100f; float num2 = 1f / num; return defaultBatteryUsage * num2; } public static List<CodeInstruction> UseItemBatteriesOpCode(List<CodeInstruction> codes) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown FieldInfo field = typeof(Item).GetField("batteryUsage"); for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldfld && (FieldInfo)codes[i].operand == field) { codes.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)typeof(BatteryLife).GetMethod("GetUseItemBatteryUsage"))); } } return codes; } public static float GetUpdateBatteryUsage(float defaultBatteryUsage) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.Battery)) { return defaultBatteryUsage; } float num = 1f + LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Battery].GetTrueValue() / 100f; return defaultBatteryUsage * num; } public static List<CodeInstruction> BatteryDegradeUpdateOpCode(List<CodeInstruction> codes) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown FieldInfo field = typeof(Item).GetField("batteryUsage"); for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldfld && (FieldInfo)codes[i].operand == field) { codes.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)typeof(BatteryLife).GetMethod("GetUpdateBatteryUsage"))); } } return codes; } } internal class HandSlots : Skill { public static int currentSlotCount = 4; public override string ShortName => "HND"; public override string Name => "Hand Slot"; public override string Attribute => "Hand Slots"; public override string Description => "The company finally gives you a better belt! Fit more stuff! (One slot every 100%.)"; public override UpgradeType UpgradeType => UpgradeType.HandSlot; public override int Cost => 1; public override int MaxLevel { get { IHandSlotsConfig active = LessShitConfigSystem.GetActive<IHandSlotsConfig>(); return active.maxLevel; } } public override float Multiplier { get { IHandSlotsConfig active = LessShitConfigSystem.GetActive<IHandSlotsConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public HandSlots() : base(HandSlotsUpdate) { } public static void HandSlotsUpdate(int updateValue) { if (!LethalPlugin.ReservedSlots && LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.HandSlot)) { LC_XP xpInstance = LP_NetworkManager.xpInstance; int num = (int)xpInstance.skillList.skills[UpgradeType.HandSlot].GetTrueValue(); int num2 = (int)Math.Floor((double)(num / 100)); ulong playerClientId = GameNetworkManager.Instance.localPlayerController.playerClientId; LethalPlugin.Log.LogInfo((object)$"Updating Player HandSlot {playerClientId}"); xpInstance.updateSPHandSlotsClientMessage.SendServer(num2); } } public static void UpdateHudSlots() { //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) LC_XP xpInstance = LP_NetworkManager.xpInstance; float num = xpInstance.skillList.skills[UpgradeType.HandSlot].GetTrueValue() / 100f; int num2 = 4 + (int)Math.Floor(num); int num3 = num2 - currentSlotCount; GameObject val = GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/Inventory"); List<string> list = new List<string> { "Slot0", "Slot1", "Slot2", "Slot3" }; for (int i = 0; i < val.transform.childCount; i++) { Transform child = val.transform.GetChild(i); if (!list.Contains(((Object)((Component)child).gameObject).name)) { Object.Destroy((Object)(object)((Component)child).gameObject); } } int num4 = (int)xpInstance.skillList.skills[UpgradeType.HandSlot].GetTrueValue(); int num5 = (int)Math.Floor((double)(num4 / 100)); Image[] array = (Image[])(object)new Image[num2]; array[0] = HUDManager.Instance.itemSlotIconFrames[0]; array[1] = HUDManager.Instance.itemSlotIconFrames[1]; array[2] = HUDManager.Instance.itemSlotIconFrames[2]; array[3] = HUDManager.Instance.itemSlotIconFrames[3]; Image[] array2 = (Image[])(object)new Image[num2]; array2[0] = HUDManager.Instance.itemSlotIcons[0]; array2[1] = HUDManager.Instance.itemSlotIcons[1]; array2[2] = HUDManager.Instance.itemSlotIcons[2]; array2[3] = HUDManager.Instance.itemSlotIcons[3]; GameObject val2 = GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/Inventory/Slot3"); GameObject templateSlot = LethalPlugin.SlotTemplate.GetTemplateSlot(); GameObject val3 = val2; currentSlotCount = num2; for (int j = 0; j < (int)num; j++) { GameObject val4 = Object.Instantiate<GameObject>(templateSlot); ((Object)val4).name = $"Slot{3 + (j + 1)}"; val4.transform.SetParent(val.transform); Vector3 localPosition = val3.transform.localPosition; val4.transform.SetLocalPositionAndRotation(new Vector3(localPosition.x + 50f, localPosition.y, localPosition.z), val3.transform.localRotation); val3 = val4; array[3 + (j + 1)] = val4.GetComponent<Image>(); array2[3 + (j + 1)] = ((Component)val4.transform.GetChild(0)).GetComponent<Image>(); val4.SetActive(true); } for (int k = 0; k < array.Length; k++) { Vector3 localPosition2 = ((Component)array[k]).transform.localPosition; ((Component)array[k]).transform.SetLocalPositionAndRotation(new Vector3(localPosition2.x - (float)(num3 * 25), localPosition2.y, localPosition2.z), ((Component)array[k]).transform.localRotation); } HUDManager.Instance.itemSlotIconFrames = array; HUDManager.Instance.itemSlotIcons = array2; } public static bool IsItemSwitchPossible(PlayerControllerB player) { return (double)player.timeSinceSwitchingSlots >= 0.01 && !player.inTerminalMenu && !player.isGrabbingObjectAnimation && !player.inSpecialInteractAnimation && !player.throwingObject && !player.isTypingChat && !player.twoHanded && !player.activatingItem && !player.jetpackControls && !player.disablingJetpackControls; } public static bool SwitchItemSlots(PlayerControllerB player, int requestedSlot) { if (!IsItemSwitchPossible(player) || player.currentItemSlot == requestedSlot) { return false; } LethalPlugin.Log.LogDebug((object)$"Trying to switch to slot {requestedSlot}"); int num = player.currentItemSlot - requestedSlot; bool flag = num > 0; if (Math.Abs(num) == player.ItemSlots.Length - 1) { player.SwitchItemSlotsServerRpc(flag); } else { do { player.SwitchItemSlotsServerRpc(flag); num += ((!flag) ? 1 : (-1)); } while (num != 0); } ShipBuildModeManager.Instance.CancelBuildMode(true); player.playerBodyAnimator.SetBool("GrabValidated", false); LethalPlugin.Log.LogDebug((object)$"Switched to slot {requestedSlot}"); player.SwitchToItemSlot(requestedSlot, (GrabbableObject)null); if ((Object)(object)player.currentlyHeldObjectServer != (Object)null) { ((Component)player.currentlyHeldObjectServer).gameObject.GetComponent<AudioSource>().PlayOneShot(player.currentlyHeldObjectServer.itemProperties.grabSFX, 0.6f); } return true; } } internal class HPRegen : Skill { public override string ShortName => "HPR"; public override string Name => "Health Regen"; public override string Attribute => "Health Regeneration"; public override string Description => "The company installs a basic healer into your suit, letting you regenerate health slowly. Only regenerate up to your max HP."; public override UpgradeType UpgradeType => UpgradeType.HPRegen; public override int Cost => 1; public override int MaxLevel { get { IHealthRegenConfig active = LessShitConfigSystem.GetActive<IHealthRegenConfig>(); return active.maxLevel; } } public override float Multiplier { get { IHealthRegenConfig active = LessShitConfigSystem.GetActive<IHealthRegenConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public static List<CodeInstruction> DisableBaseGameHPRegen(List<CodeInstruction> codes) { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)LP_NetworkManager.xpInstance) || !LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.HPRegen)) { return codes; } FieldInfo field = typeof(PlayerControllerB).GetField("health"); for (int i = 0; i < codes.Count; i++) { if (!(codes[i].opcode != OpCodes.Ldfld) && !((FieldInfo)codes[i].operand != field) && !(codes[i + 1].opcode != OpCodes.Ldc_I4) && (int)codes[i + 1].operand == 20 && !(codes[i + 2].opcode != OpCodes.Bge_S)) { codes.Insert(i + 2, new CodeInstruction(OpCodes.Pop, (object)null)); codes.Insert(i + 3, new CodeInstruction(OpCodes.Dup, (object)null)); } } return codes; } } internal class JumpHeight : Skill { public override string ShortName => "JMP"; public override string Name => "Jump Height"; public override string Attribute => "Jump Height"; public override string Description => "The company installs you with jumping boots! (The company is not responsible for any broken knees.)"; public override UpgradeType UpgradeType => UpgradeType.JumpHeight; public override int Cost => 1; public override int MaxLevel { get { IJumpHeightConfig active = LessShitConfigSystem.GetActive<IJumpHeightConfig>(); return active.maxLevel; } } public override float Multiplier { get { IJumpHeightConfig active = LessShitConfigSystem.GetActive<IJumpHeightConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public static float GetJumpForce(float defaultJumpForce) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.JumpHeight)) { return defaultJumpForce; } float num = 1f + LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.JumpHeight].GetTrueValue() / 100f; return defaultJumpForce * num; } public static List<CodeInstruction> PlayerJumpOpCode(List<CodeInstruction> codes) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown FieldInfo field = typeof(PlayerControllerB).GetField("jumpForce"); for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldfld && (FieldInfo)codes[i].operand == field) { codes.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)typeof(JumpHeight).GetMethod("GetJumpForce"))); } } return codes; } } internal class LootValue : Skill { public override string ShortName => "VAL"; public override string Name => "Loot Value"; public override string Attribute => "Loot Value"; public override string Description => "The company gives you a better pair of eyes, allowing you to see the value in things."; public override UpgradeType UpgradeType => UpgradeType.Value; public override int Cost => 1; public override int MaxLevel { get { ILootValueConfig active = LessShitConfigSystem.GetActive<ILootValueConfig>(); return active.maxLevel; } } public override float Multiplier { get { ILootValueConfig active = LessShitConfigSystem.GetActive<ILootValueConfig>(); return active.multiplier; } } public override bool IsTeamShared => true; public LootValue() : base(LootValueUpdate) { } public static int GetNewScrapValueMultiplier(int defaultScrapValue) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.Value)) { return defaultScrapValue; } float multiplier = LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Value].Multiplier; float num = (float)LP_NetworkManager.xpInstance.teamLootLevel.Value * multiplier; float num2 = 1f + num / 100f; int num3 = (int)Math.Round((float)defaultScrapValue * num2); LethalPlugin.Log.LogDebug((object)$"Current scrap value {defaultScrapValue} multiplied by {num2} to {num3}"); return num3; } public static void LootValueUpdate(int change) { if (LP_NetworkManager.xpInstance.skillList.skills.ContainsKey(UpgradeType.Value)) { LP_NetworkManager.xpInstance.updateTeamLootLevelClientMessage.SendServer(change); } } } internal class MaxHP : Skill { public override string ShortName => "MHP"; public override string Name => "Max Health"; public override string Attribute => "Maximum Health"; public override string Description => "The company is trialling some new inhalents from exotic moons, giving you a health boost."; public override UpgradeType UpgradeType => UpgradeType.MaxHealth; public override int Cost => 1; public override int MaxLevel { get { IMaxHealthConfig active = LessShitConfigSystem.GetActive<IMaxHealthConfig>(); return active.maxLevel; } } public override float Multiplier { get { IMaxHealthConfig active = LessShitConfigSystem.GetActive<IMaxHealthConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public static int GetNewMaxHealth(int defaultValue) { if ((Object)(object)LP_NetworkManager.xpInstance == (Object)null) { return defaultValue; } Skill skill = LP_NetworkManager.xpInstance.skillList.GetSkill(UpgradeType.MaxHealth); if (skill == null) { return defaultValue; } return (int)Math.Floor((float)defaultValue * (1f + skill.GetTrueValue() / 100f)); } public static List<CodeInstruction> UncapMaxHealth(List<CodeInstruction> codes) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown MethodInfo method = typeof(Mathf).GetMethod("Clamp", new Type[3] { typeof(int), typeof(int), typeof(int) }); for (int i = 0; i < codes.Count; i++) { if (CodeInstructionExtensions.Calls(codes[i], method) && codes[i - 2].opcode == OpCodes.Ldc_I4_0 && codes[i - 1].opcode == OpCodes.Ldc_I4_S) { codes.Insert(i, new CodeInstruction(OpCodes.Call, (object)typeof(MaxHP).GetMethod("GetNewMaxHealth"))); break; } } return codes; } } internal class ShipDoorBattery : Skill { public override string ShortName => "DRB"; public override string Name => "Ship Door Battery"; public override string Attribute => "Ship Door Battery"; public override string Description => "The company provides extended life batteries that keep the ship's doors shut for longer."; public override UpgradeType UpgradeType => UpgradeType.ShipDoorBattery; public override int Cost => 1; public override int MaxLevel { get { IShipHangarDoorConfig active = LessShitConfigSystem.GetActive<IShipHangarDoorConfig>(); return active.maxLevel; } } public override float Multiplier { get { IShipHangarDoorConfig active = LessShitConfigSystem.GetActive<IShipHangarDoorConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public ShipDoorBattery() : base(ShipDoorBatteryUpdate) { } public static float GetUpdateBatteryUsage(float defaultBatteryDuration) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.ShipDoorBattery)) { return defaultBatteryDuration; } float num = 1f + LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.ShipDoorBattery].GetTrueValue() / 100f; return defaultBatteryDuration * num; } public static List<CodeInstruction> BatteryDegradeUpdateOpCode(List<CodeInstruction> codes) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown FieldInfo field = typeof(HangarShipDoor).GetField("doorPowerDuration"); for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldfld && (FieldInfo)codes[i].operand == field) { codes.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)typeof(ShipDoorBattery).GetMethod("GetUpdateBatteryUsage"))); } } return codes; } public static void ShipDoorBatteryUpdate(int change) { if (LP_NetworkManager.xpInstance.skillList.skills.ContainsKey(UpgradeType.ShipDoorBattery)) { LP_NetworkManager.xpInstance.updateTeamShipDoorBatteryLevelClientMessage.SendServer(change); } } } internal class SprintSpeed : Skill { public override string ShortName => "SPD"; public override string Name => "Sprint Speed"; public override string Attribute => "Sprint Speed"; public override string Description => "The company empowers you with pure steroids, run, spaceman."; public override UpgradeType UpgradeType => UpgradeType.SprintSpeed; public override int Cost => 1; public override int MaxLevel { get { ISprintSpeedConfig active = LessShitConfigSystem.GetActive<ISprintSpeedConfig>(); return active.maxLevel; } } public override float Multiplier { get { ISprintSpeedConfig active = LessShitConfigSystem.GetActive<ISprintSpeedConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public static float GetSprintSpeed(float defaultSprintSpeed) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.SprintSpeed)) { return defaultSprintSpeed; } float num = 1f + LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.SprintSpeed].GetTrueValue() / 100f; return defaultSprintSpeed * num; } public static List<CodeInstruction> PlayerSprintSpeedOpCode(List<CodeInstruction> codes) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldc_R4 && codes[i].operand.Equals(2.25f)) { codes.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)typeof(SprintSpeed).GetMethod("GetSprintSpeed"))); } } return codes; } } internal class Stamina : Skill { public override string ShortName => "STM"; public override string Name => "Stamina"; public override string Attribute => "Stamina"; public override string Description => "Hours on that company gym finally coming into play. Allows you to run for longer, but has to regenerate it slower."; public override UpgradeType UpgradeType => UpgradeType.Stamina; public override int Cost => 1; public override int MaxLevel { get { IStaminaConfig active = LessShitConfigSystem.GetActive<IStaminaConfig>(); return active.maxLevel; } } public override float Multiplier { get { IStaminaConfig active = LessShitConfigSystem.GetActive<IStaminaConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public static float GetJumpStaminaUsage(float defaultJumpStaminaUsage) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.Stamina)) { return defaultJumpStaminaUsage; } float num = 1f + LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Stamina].GetTrueValue() / 100f; float num2 = 1f / num; return defaultJumpStaminaUsage * num2; } public static List<CodeInstruction> PlayerJumpStaminaOpCode(List<CodeInstruction> codes) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldc_R4 && codes[i].operand.Equals(0.08f)) { codes.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)typeof(Stamina).GetMethod("GetJumpStaminaUsage"))); } } return codes; } public static float GetSprintTime(float defaultStaminaTime) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.Stamina)) { return defaultStaminaTime; } float num = 1f + LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Stamina].GetTrueValue() / 100f; return defaultStaminaTime * num; } public static List<CodeInstruction> PlayerSprintTimeOpCode(List<CodeInstruction> codes) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown FieldInfo field = typeof(PlayerControllerB).GetField("sprintTime"); for (int i = 0; i < codes.Count; i++) { if (codes[i].opcode == OpCodes.Ldfld && (FieldInfo)codes[i].operand == field) { codes.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)typeof(Stamina).GetMethod("GetSprintTime"))); } } return codes; } } [HarmonyPatch] internal class Strength : Skill { public override string ShortName => "STR"; public override string Name => "Strength"; public override string Attribute => "Strength"; public override string Description => "More work at the Company's gym gives you pure muscles! You can carry better. (Reduces weight by a percentage.)"; public override UpgradeType UpgradeType => UpgradeType.Strength; public override int Cost => 1; public override int MaxLevel { get { IStrengthConfig active = LessShitConfigSystem.GetActive<IStrengthConfig>(); return active.maxLevel; } } public override float Multiplier { get { IStrengthConfig active = LessShitConfigSystem.GetActive<IStrengthConfig>(); return active.multiplier; } } public override bool IsTeamShared => false; public Strength() : base(StrengthUpdate) { } public static void StrengthUpdate(int _change = 0) { if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.Strength)) { return; } PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; List<GrabbableObject> list = localPlayerController.ItemSlots.ToList(); LethalPlugin.Log.LogDebug((object)$"Carry weight was {localPlayerController.carryWeight}"); float trueValue = LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Strength].GetTrueValue(); float num = trueValue / 100f; float num2 = 0f; foreach (GrabbableObject item in list) { if (!((Object)(object)item == (Object)null)) { float num3 = item.itemProperties.weight - 1f; num3 *= 1f - num; num2 += num3; LethalPlugin.Log.LogDebug((object)$"Item weight was {item.itemProperties.weight - 1f} and is now {num3}"); LethalPlugin.Log.LogDebug((object)$"Adding carryweight.. now up to {num2}"); } } localPlayerController.carryWeight = Math.Clamp(1f + num2, 0f, 10f); LethalPlugin.Log.LogDebug((object)$"Player carry weight is now {localPlayerController.carryWeight}"); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")] private static void UpdateObjects() { StrengthUpdate(); } [HarmonyPostfix] [HarmonyPatch(typeof(GrabbableObject), "DiscardItem")] private static void UpdateByDiscard(GrabbableObject __instance) { if (((NetworkBehaviour)__instance).IsOwner) { StrengthUpdate(); } } } } namespace LethalProgression.Saving { internal static class ES3SaveManager { public static void TriggerHostProfileSave() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ulong num = SteamId.op_Implicit(SteamClient.SteamId); SaveData saveData = default(SaveData); saveData.steamId = num; saveData.skillPoints = LP_NetworkManager.xpInstance.skillPoints; saveData.skillAllocation = new Dictionary<UpgradeType, int>(); SaveData saveData2 = saveData; foreach (KeyValuePair<UpgradeType, Skill> skill in LP_NetworkManager.xpInstance.skillList.skills) { LethalPlugin.Log.LogDebug((object)$"Skill is {skill.Key} and value is {skill.Value.CurrentLevel}"); saveData2.skillAllocation.Add(skill.Key, skill.Value.CurrentLevel); } LethalPlugin.Log.LogDebug((object)$"Invoke saveProfileDataClientMessage({num}, {JsonConvert.SerializeObject((object)saveData2)})"); LP_NetworkManager.xpInstance.saveProfileDataClientMessage.SendServer(JsonConvert.SerializeObject((object)new SaveProfileData(num, saveData2))); } public static void DeleteSave() { string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName; string[] keys = ES3.GetKeys(currentSaveFileName); string[] array = keys; foreach (string text in array) { if (text.StartsWith("LethalProgression_")) { LethalPlugin.Log.LogDebug((object)("Found key " + text + " to delete in " + currentSaveFileName)); ES3.DeleteKey(text, currentSaveFileName); } } } public static void Save(ulong steamId, SaveData data) { Save(steamId, data, null); } public static void Save(ulong steamId, SaveData data, string overrideSaveFile) { string text = overrideSaveFile; if (overrideSaveFile == null) { text = GameNetworkManager.Instance.currentSaveFileName; } LethalPlugin.Log.LogDebug((object)$"Saving player {steamId} data to {text}"); ES3.Save<string>($"LethalProgression_{steamId}_Data", JsonConvert.SerializeObject((object)data), text); } public static void SaveShared(SaveSharedData data, string overrideSaveFile) { SaveShared(data.xp, data.level, data.quota, overrideSaveFile); } public static void SaveShared(int xp, int level, int quota) { SaveShared(xp, level, quota, null); } public static void SaveShared(int xp, int level, int quota, string overrideSaveFile) { string text = overrideSaveFile; if (overrideSaveFile == null) { text = GameNetworkManager.Instance.currentSaveFileName; } LethalPlugin.Log.LogDebug((object)("Saving to save file " + text)); ES3.Save<string>("LethalProgression_shared_Data", JsonConvert.SerializeObject((object)new SaveSharedData(xp, level, quota)), text); } public static string LoadPlayerFile(ulong steamId) { string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName; if (!ES3.KeyExists($"LethalProgression_{steamId}_Data", currentSaveFileName)) { LethalPlugin.Log.LogDebug((object)$"Player file for {steamId} doesn't exist"); return null; } LethalPlugin.Log.LogDebug((object)$"Player file for {steamId} found"); return (string)ES3.Load($"LethalProgression_{steamId}_Data", currentSaveFileName); } public static SaveSharedData? LoadSharedFile() { string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName; if (!ES3.KeyExists("LethalProgression_shared_Data", currentSaveFileName)) { LethalPlugin.Log.LogDebug((object)"Shared file doesn't exist"); return null; } LethalPlugin.Log.LogDebug((object)"Shared file exists"); string text = (string)ES3.Load("LethalProgression_shared_Data", currentSaveFileName); return JsonConvert.DeserializeObject<SaveSharedData>(text); } } internal struct SaveData { public ulong steamId; public int skillPoints; public Dictionary<UpgradeType, int> skillAllocation; public SaveData(ulong steamId, int skillPoints) { skillAllocation = new Dictionary<UpgradeType, int>(); this.steamId = steamId; this.skillPoints = skillPoints; } public override readonly string ToString() { string text = ""; foreach (UpgradeType key in skillAllocation.Keys) { text += $" | {key}: {skillAllocation[key]}"; } return $"skillPoints: {skillPoints} | Stats {text}"; } } internal static class SaveDataMigration { public static void MigrateOldSaves() { LethalPlugin.Log.LogInfo((object)"Checking for legacy save files to migrate."); if (!Directory.Exists(Application.persistentDataPath + "/lethalprogression")) { LethalPlugin.Log.LogInfo((object)"No legacy save files found to migrate. "); return; } List<string> list = new List<string>(Directory.EnumerateDirectories(Application.persistentDataPath + "/lethalprogression", "save*")); if (list.Count == 0) { LethalPlugin.Log.LogInfo((object)"No legacy save files found to migrate. "); return; } LethalPlugin.Log.LogInfo((object)$"Found {list.Count} saves to migrate."); foreach (string item in list) { string text = item.Substring(item.LastIndexOf(Path.DirectorySeparatorChar) + 1); LethalPlugin.Log.LogInfo((object)("Found " + text + " in " + item + " to migrate.")); if (text.StartsWith("save")) { LethalPlugin.Log.LogWarning((object)("Found save: " + text + " - now migrating to ES3")); MigrateSave(item); } } } public static void MigrateSave(string dir) { string text = dir.Substring(dir.LastIndexOf(Path.DirectorySeparatorChar) + 1); text = text.Replace("save", "LCSaveFile"); List<string> list = new List<string>(Directory.EnumerateFiles(dir)); foreach (string item in list) { string text2 = item.Substring(item.LastIndexOf(Path.DirectorySeparatorChar) + 1); text2 = text2.Replace(".json", ""); if (text2 == "shared") { LethalPlugin.Log.LogInfo((object)("Found shared data at " + item)); string text3 = File.ReadAllText(item); SaveSharedData saveSharedData = JsonConvert.DeserializeObject<SaveSharedData>(text3); LethalPlugin.Log.LogInfo((object)$"Old data: {saveSharedData}"); ES3SaveManager.SaveShared(saveSharedData, text); } else { LethalPlugin.Log.LogInfo((object)("Found player data at " + item)); string text4 = File.ReadAllText(item); ulong.TryParse(text2, out var result); LethalPlugin.Log.LogInfo((object)$"Parsed Steam ID: {result}"); SaveData saveData = JsonConvert.DeserializeObject<SaveData>(text4); LethalPlugin.Log.LogInfo((object)$"Old data: {saveData}"); ES3SaveManager.Save(result, saveData, text); } File.Delete(item); } Directory.Delete(dir); } } internal struct SaveSharedData { public int xp; public int level; public int quota; public SaveSharedData(int xp, int level, int quota) { this.xp = xp; this.level = level; this.quota = quota; } } } namespace LethalProgression.Patches { [HarmonyPatch] internal class EnemyAIPatch { private static Dictionary<string, int> _enemyReward = new Dictionary<string, int> { { "HoarderBug (EnemyType)", 30 }, { "BaboonBird (EnemyType)", 15 }, { "MouthDog (EnemyType)", 200 }, { "Centipede (EnemyType)", 30 }, { "Flowerman (EnemyType)", 200 }, { "SandSpider (EnemyType)", 50 }, { "Crawler (EnemyType)", 50 }, { "Puffer (EnemyType)", 15 } }; [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "KillEnemy")] private static void CalculateXPForEnemyDeath(EnemyAI __instance) { if (!GameNetworkManager.Instance.isHostingGame) { return; } IGeneralConfig active = LessShitConfigSystem.GetActive<IGeneralConfig>(); if (!active.disableEnemyXPGain) { string text = ((object)__instance.enemyType).ToString(); LethalPlugin.Log.LogInfo((object)("Enemy type: " + text)); int num = 30; if (_enemyReward.ContainsKey(text)) { num = _enemyReward[text]; } LP_NetworkManager.xpInstance.updateTeamXPClientMessage.SendServer(num); } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "HitEnemyServerRpc")] private static void HitEnemyTrigger(EnemyAI __instance, int force, int playerWhoHit) { LethalPlugin.Log.LogInfo((object)$"Player {playerWhoHit} hit enemy {((object)__instance).GetType()} with force {force}"); } } [HarmonyPatch] internal class GameNetworkManagerPatch { [HarmonyPrefix] [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPriority(800)] private static void DisconnectXPHandler() { if (LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.Value)) { int currentLevel = LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Value].CurrentLevel; LP_NetworkManager.xpInstance.updateTeamLootLevelClientMessage.SendServer(-currentLevel); } HandSlots.currentSlotCount = 4; LethalPlugin.SkillsGUI.CleanupGUI(); LethalPlugin.SkillsGUI.CloseSkillMenu(); } [HarmonyPrefix] [HarmonyPatch(typeof(GameNetworkManager), "SaveGame")] [HarmonyPriority(800)] private static void SaveGamePrefix() { LethalPlugin.Log.LogDebug((object)"Invoked DoSave via SaveGame"); ES3SaveManager.TriggerHostProfileSave(); } } [HarmonyPatch] internal class GrabbableObjectPatch { [HarmonyTranspiler] [HarmonyPatch(typeof(GrabbableObject), "UseItemBatteries")] private static IEnumerable<CodeInstruction> UseItemBatteriesTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); return BatteryLife.UseItemBatteriesOpCode(codes); } [HarmonyTranspiler] [HarmonyPatch(typeof(GrabbableObject), "Update")] private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); return BatteryLife.BatteryDegradeUpdateOpCode(codes); } } [HarmonyPatch] internal class HangarShipDoorPatch { [HarmonyTranspiler] [HarmonyPatch(typeof(HangarShipDoor), "Update")] private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); return ShipDoorBattery.BatteryDegradeUpdateOpCode(codes); } } [HarmonyPatch] internal class HUDManagerPatch { private static GameObject _tempBar; private static GameObject _bottomMiddle; private static TextMeshProUGUI _tempText; private static float _tempBarTime; private static GameObject levelUpAsset; private static GameObject levelText; private static float levelTextTime; [HarmonyPrefix] [HarmonyPatch(typeof(HUDManager), "AddNewScrapFoundToDisplay")] private static void GiveXPForScrap(GrabbableObject GObject) { if (GameNetworkManager.Instance.isHostingGame) { int scrapValue = GObject.scrapValue; ILootValueConfig active = LessShitConfigSystem.GetActive<ILootValueConfig>(); int num = scrapValue; if (active.isEnabled) { float multiplier = LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.Value].Multiplier; float num2 = (float)LP_NetworkManager.xpInstance.teamLootLevel.Value * multiplier; float num3 = 1f + num2 / 100f; num = (int)Math.Floor((float)scrapValue / num3); } LP_NetworkManager.xpInstance.updateTeamXPClientMessage.SendServer(num); } } public static void ShowXPUpdate() { if (!Object.op_Implicit((Object)(object)_tempBar)) { MakeBar(); } LC_XP xpInstance = LP_NetworkManager.xpInstance; GameObject val = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddleXPStatus/XPUpdate/XPBarProgress"); val.GetComponent<Image>().fillAmount = (float)xpInstance.teamXP.Value / (float)xpInstance.CalculateXPRequirement(); ((TMP_Text)_tempText).text = xpInstance.teamXP.Value + " / " + (float)xpInstance.CalculateXPRequirement(); _tempBarTime = 2f; if (!_tempBar.activeSelf) { ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(XPBarCoroutine()); } } private static IEnumerator XPBarCoroutine() { _tempBar.SetActive(true); while (_tempBarTime > 0f) { float time = _tempBarTime; _tempBarTime = 0f; yield return (object)new WaitForSeconds(time); } _tempBar.SetActive(false); } public static void ShowLevelUp() { IUIConfig active = LessShitConfigSystem.GetActive<IUIConfig>(); if (!active.levelUpDisabled) { if (!Object.op_Implicit((Object)(object)levelText)) { MakeLevelUp(); } levelTextTime = 5f; if (!levelText.gameObject.activeSelf) { ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(LevelUpCoroutine()); } } } public static void MakeLevelUp() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) levelUpAsset = Object.Instantiate<GameObject>(LethalPlugin.skillBundle.LoadAsset<GameObject>("LevelUp")); IUIConfig active = LessShitConfigSystem.GetActive<IUIConfig>(); int num = active.levelUpPosition; if (num < 0 || num > 1) { LethalPlugin.Log.LogWarning((object)$"[Invalid Config] Level Up Position value given {active.levelUpPosition} out of range (0-1)"); num = 1; } levelText = ((Component)levelUpAsset.transform.GetChild(num)).gameObject; levelText.transform.GetChild(0).localScale = new Vector3(active.levelUpScale, active.levelUpScale, 1f); levelText.transform.GetChild(1).localScale = new Vector3(active.levelUpScale, active.levelUpScale, 1f); ((TMP_Text)((Component)levelText.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "Level Up! Spend your skill points."; levelText.gameObject.SetActive(false); } private static IEnumerator LevelUpCoroutine() { levelText.gameObject.SetActive(true); while (levelTextTime > 0f) { float time = levelTextTime; levelTextTime = 0f; yield return (object)new WaitForSeconds(time); } levelText.gameObject.SetActive(false); } private static void MakeBar() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) LethalPlugin.XPBarGUI.CreateAllObjectsIfRequired(); GameObject val = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD"); GameObject val2 = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle"); _bottomMiddle = Object.Instantiate<GameObject>(val2); _bottomMiddle.transform.SetParent(val.transform, false); ((Object)_bottomMiddle).name = "BottomMiddleXPStatus"; foreach (Transform item in _bottomMiddle.transform) { Transform val3 = item; Object.Destroy((Object)(object)((Component)val3).gameObject); } GameObject val4 = GameObject.Find("/Systems/UI/Canvas/QuickMenu/XpInfoContainer/XPBar"); _tempBar = Object.Instantiate<GameObject>(val4); ((Object)_tempBar).name = "XPUpdate"; _tempBar.SetActive(false); _tempText = _tempBar.GetComponentInChildren<TextMeshProUGUI>(); _tempBar.transform.SetParent(_bottomMiddle.transform, false); _tempBar.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f); GameObject val5 = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddleXPStatus/XPUpdate/XPLevel"); Object.Destroy((Object)(object)val5); GameObject val6 = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/BottomMiddleXPStatus/XPUpdate/XPProfit"); Object.Destroy((Object)(object)val6); Vector3 localPosition = _bottomMiddle.transform.localPosition; float x = _bottomMiddle.GetComponent<RectTransform>().sizeDelta.x; float x2 = _tempBar.GetComponent<RectTransform>().sizeDelta.x; LethalPlugin.Log.LogInfo((object)$"Move Bar {x} {x2}"); _tempBar.transform.Translate(0f, 0f, 0f); _tempBar.transform.localPosition = new Vector3(x + 50f, localPosition.y - 30f, localPosition.z); } } [HarmonyPatch] internal class PlayerControllerBPatch { [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] private static void ConnectClientToPlayerObjectHandler() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ulong num = SteamId.op_Implicit(SteamClient.SteamId); LethalPlugin.Log.LogInfo((object)$"Player {num} has joined the game."); LP_NetworkManager.xpInstance.requestProfileDataClientMessage.SendServer(num); } [HarmonyTranspiler] [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static IEnumerable<CodeInstruction> PlayerJumpTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); return JumpHeight.PlayerJumpOpCode(codes); } [HarmonyTranspiler] [HarmonyPatch(typeof(PlayerControllerB), "Jump_performed")] private static IEnumerable<CodeInstruction> Jump_performedTransplier(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); return Stamina.PlayerJumpStaminaOpCode(codes); } [HarmonyTranspiler] [HarmonyPatch(typeof(PlayerControllerB), "Update")] private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); codes = JumpHeight.PlayerJumpOpCode(codes); return SprintSpeed.PlayerSprintSpeedOpCode(codes); } [HarmonyTranspiler] [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] private static IEnumerable<CodeInstruction> LateUpdateTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); codes = HPRegen.DisableBaseGameHPRegen(codes); return Stamina.PlayerSprintTimeOpCode(codes); } [HarmonyTranspiler] [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] private static IEnumerable<CodeInstruction> DamagePlayerTranspiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> codes = new List<CodeInstruction>(instructions); return MaxHP.UncapMaxHealth(codes); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] private static void HPRegenUpdate(PlayerControllerB __instance) { if (!((NetworkBehaviour)__instance).IsOwner || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject) || !__instance.isPlayerControlled || __instance.isPlayerDead) { return; } int newMaxHealth = MaxHP.GetNewMaxHealth(100); if (__instance.health > newMaxHealth) { __instance.health = newMaxHealth; HUDManager.Instance.UpdateHealthUI(__instance.health, false); } if (!LP_NetworkManager.xpInstance.skillList.IsSkillValid(UpgradeType.HPRegen)) { return; } if (__instance.health < 20 && __instance.healthRegenerateTimer > 1f) { __instance.healthRegenerateTimer = 1f; } if (__instance.healthRegenerateTimer > 0f) { __instance.healthRegenerateTimer -= Time.deltaTime; return; } if (__instance.health >= 20) { __instance.MakeCriticallyInjured(false); } if (__instance.health < newMaxHealth) { Skill skill = LP_NetworkManager.xpInstance.skillList.skills[UpgradeType.HPRegen]; float num = 1f / skill.GetTrueValue(); if (__instance.health < 20 && num > 1f) { num = 1f; } __instance.healthRegenerateTimer = num; __instance.health++; HUDManager.Instance.UpdateHealthUI(__instance.health, false); } } } [HarmonyPatch] internal class QuickMenuManagerPatch { [HarmonyPostfix] [HarmonyPatch(typeof(QuickMenuManager), "OpenQuickMenu")] private static void OpenQuickMenu_Postfix(QuickMenuManager __instance) { if (__instance.isMenuOpen) { LethalPlugin.XPBarGUI.Show(); } } [HarmonyPostfix] [HarmonyPatch(typeof(QuickMenuManager), "Update")] private static void QuickMenuManager_Postfix(QuickMenuManager __instance) { LethalPlugin.XPBarGUI.Update(__instance.mainButtonsPanel.activeSelf); if (!LethalPlugin.SkillsGUI.isMenuOpen) { LethalPlugin.SkillsGUI.CloseSkillMenu(); return; } IGeneralConfig active = LessShitConfigSystem.GetActive<IGeneralConfig>(); if (active.enableUnspecInShip && !active.disableUnspec) { if (GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom) { LethalPlugin.SkillsGUI.SetUnspec(show: true); } else { LethalPlugin.SkillsGUI.SetUnspec(show: false); } } if (active.enableUnspecInOrbit) { if (StartOfRound.Instance.inShipPhase) { LethalPlugin.SkillsGUI.SetUnspec(show: true); } else { LethalPlugin.SkillsGUI.SetUnspec(show: false); } } if (active.disableUnspec) { LethalPlugin.SkillsGUI.SetUnspec(show: false); } LethalPlugin.SkillsGUI.OpenSkillMenu(); } [HarmonyPostfix] [HarmonyPatch(typeof(QuickMenuManager), "CloseQuickMenu")] private static void SkillMenuClose() { LethalPlugin.SkillsGUI.CloseSkillMenu(); } } [HarmonyPatch] internal class RoundManagerPatch { [HarmonyPrefix] [HarmonyPatch(typeof(RoundManager), "waitForScrapToSpawnToSync")] [HarmonyPriority(0)] public static void OnWaitForScrapToSpawnToSync(ref NetworkObjectReference[] spawnedScrap, ref int[] scrapValues) { List<int> list = new List<int>(); for (int i = 0; i < scrapValues.Length; i++) { list.Add(LootValue.GetNewScrapValueMultiplier(scrapValues[i])); } scrapValues = list.ToArray(); } } [HarmonyPatch] internal class StartOfRoundPatch { [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "FirePlayersAfterDeadlineClientRpc")] private static void ResetXPValues() { IGeneralConfig active = LessShitConfigSystem.GetActive<IGeneralConfig>(); if (active.keepProgress) { return; } LC_XP xpInstance = LP_NetworkManager.xpInstance; ES3SaveManager.DeleteSave(); xpInstance.teamXPRequired.Value = xpInstance.CalculateXPRequirement(); foreach (Skill value in xpInstance.skillList.skills.Values) { value.SetLevel(0, triggerHostProfileSave: false); } LethalPlugin.SkillsGUI.UpdateAllStats(); ES3SaveManager.TriggerHostProfileSave(); xpInstance.SetSkillPoints(xpInstance.GetDefaultStartingSkillPoints()); xpInstance.teamXP.Value = 0; xpInstance.teamTotalValue.Value = 0; xpInstance.teamLevel.Value = 0; xpInstance.teamLootLevel.Value = 0; xpInstance.teamShipDoorBatteryLevel.Value = 0; } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "ReviveDeadPlayers")] private static void ReviveDeadPlayersPostfix() { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; int num = (localPlayerController.health = MaxHP.GetNewMaxHealth(100)); HUDManager.Instance.UpdateHealthUI(num, false); } } [HarmonyPatch] internal class TimeOfDayPatch { [HarmonyPostfix] [HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")] private static void ProfitQuotaUpdate(TimeOfDay __instance) { if (GameNetworkManager.Instance.isHostingGame) { LP_NetworkManager.xpInstance.teamXPRequired.Value = LP_NetworkManager.xpInstance.CalculateXPRequirement(); } } } } namespace LethalProgression.LessShitConfig { public static class LessShitConfigSystem { private static readonly IDictionary<ConfigDefinition, ConfigEntryData> entries = new Dictionary<ConfigDefinition, ConfigEntryData>(); private static readonly IDictionary<Type, ConfigSectionData> sections = new Dictionary<Type, ConfigSectionData>(); private static readonly IDictionary<Type, LocalConfigBase> localSections = new Dictionary<Type, LocalConfigBase>(); private static readonly IDictionary<Type, DictionaryOverlayConfigBase> activeSections = new Dictionary<Type, DictionaryOverlayConfigBase>(); private static readonly IDictionary<ConfigDefinition, object> hostConfigOverlay = new Dictionary<ConfigDefinition, object>(); public static object ActiveConfig { get; internal set; } public static void RegisterSection<T>() { Type typeFromHandle = typeof(T); LethalPlugin.Log.LogDebug((object)("RegisterSection: " + typeFromHandle.FullName)); if (sections.ContainsKey(typeFromHandle)) { throw new ConfigRegistrationException("The config section defintion has already been registered: " + typeFromHandle.FullName); } ConfigSectionData configSectionData = new ConfigSectionData(typeFromHandle); sections[typeFromHandle] = configSectionData; foreach (ConfigEntryData entry in configSectionData.Entries) { entries[entry.Definition] = entry; } } public static void Bake(ConfigFile configFile) { if (configFile == null) { throw new ArgumentNullException("config"); } if (localSections.Count > 0) { throw new InvalidOperationException("Calling Bind multiple times is not allowed."); } foreach (ConfigEntryData value in entries.Values) { value.Bind(configFile); } foreach (KeyValuePair<Type, ConfigSectionData> section in sections) { LocalConfigSectionClassBuilder localConfigSectionClassBuilder = new LocalConfigSectionClassBuilder(section.Value, configFile); foreach (ConfigEntryData entry in section.Value.Entries) { localConfigSectionClassBuilder.AddEntry(entry); } LocalConfigBase localConfigBase = localConfigSectionClassBuilder.Build(); localSections[section.Key] = localConfigBase; DictionaryOverlayConfigSectionClassBuilder dictionaryOverlayConfigSectionClassBuilder = new DictionaryOverlayConfigSectionClassBuilder(section.Value, localConfigBase, hostConfigOverlay); foreach (ConfigEntryData entry2 in section.Value.Entries) { dictionaryOverlayConfigSectionClassBuilder.AddEntry(entry2); } activeSections[section.Key] = dictionaryOverlayConfigSectionClassBuilder.Build(); } } internal static T GetActive<T>() { return (T)(object)activeSections[typeof(T)]; } internal static string SerializeLocalConfigs() { IDictionary<string, IDictionary<string, string>> dictionary = new Dictionary<string, IDictionary<string, string>>(); foreach (ConfigEntryData value2 in entries.Values) { string section = value2.Definition.Section; if (!(section == "UI")) { string key = value2.Definition.Key; if (!dictionary.ContainsKey(section)) { dictionary[section] = new Dictionary<string, string>(); } object value = localSections[value2.Section.InterfaceType].GetValue(value2.Definition); dictionary[section][key] = TomlTypeConverter.ConvertToString(value, value2.Property.PropertyType); } } return JsonConvert.SerializeObject((object)dictionary); } internal static void ApplyHostConfigs(string configString) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown IDictionary<string, IDictionary<string, string>> dictionary = JsonConvert.DeserializeObject<IDictionary<string, IDictionary<string, string>>>(configString); foreach (KeyValuePair<string, IDictionary<string, string>> item in dictionary) { foreach (KeyValuePair<string, string> item2 in item.Value) { ConfigDefinition val = new ConfigDefinition(item.Key, item2.Key); Type propertyType = entries[val].Property.PropertyType; hostConfigOverlay[val] = TomlTypeConverter.ConvertToValue(item2.Value, propertyType); LethalPlugin.Log.LogInfo((object)$"Applied host config override: {val} = {item2.Value}"); } } } internal static void ClearHostConfigs() { hostConfigOverlay.Clear(); LethalPlugin.Log.LogInfo((object)"Cleared host config overrides"); } } } namespace LethalProgression.LessShitConfig.Internal { public class ConfigEntryData { public readonly ConfigSectionData Section; public readonly PropertyInfo Property; public readonly ConfigDefinition Definition; public readonly ConfigDescription Description; public readonly object DefaultValue; public ConfigEntryData(ConfigSectionData section, PropertyInfo property) { //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Expected O, but got Unknown if (!TomlTypeConverter.CanConvert(property.PropertyType)) { throw new ConfigRegistrationException("There is no TOML converter registered for " + property.PropertyType.FullName + " entries: " + section.InterfaceType.FullName); } if (property.CanWrite) { throw new ConfigRegistrationException("Config section entries must not have property setter: (" + property.Name + " in " + section.InterfaceType.FullName + ")"); } if (!property.CanRead) { throw new ConfigRegistrationException("Config section entries must have property getter: (" + property.Name + " in " + section.InterfaceType.FullName + ")"); } ConfigNameAttribute customAttribute = property.GetCustomAttribute<ConfigNameAttribute>(); if (customAttribute == null) { throw new ConfigRegistrationException("Config section must have a named defined with Configname (" + property.Name + " in " + section.InterfaceType.FullName + ")"); } ConfigDescriptionAttribute customAttribute2 = property.GetCustomAttribute<ConfigDescriptionAttribute>(); ConfigDefaultAttribute customAttribute3 = property.GetCustomAttribute<ConfigDefaultAttribute>(inherit: true); LethalPlugin.Log.LogDebug((object)("Register Property: " + section.Name + " " + customAttribute.name)); Section = section; Property = property; Definition = new ConfigDefinition(section.Name, customAttribute.name); Description = customAttribute2?.Description; DefaultValue = ResolveDefaultValue(customAttribute3); } private object ResolveDefaultValue(ConfigDefaultAttribute defaultValue) { if (defaultValue != null) { return defaultValue.Value; } return Property.PropertyType.IsValueType ? Activator.CreateInstance(Property.PropertyType) : null; } public void Bind(ConfigFile file) { MethodInfo methodInfo = typeof(ConfigFile).GetMethod("Bind", new Type[3] { typeof(ConfigDefinition), Type.MakeGenericMethodParameter(0), typeof(ConfigDescription) }).MakeGenericMethod(Property.PropertyType); methodInfo.Invoke(file, new List<object> { Definition, DefaultValue, Description }.ToArray()); } } public class ConfigRegistrationException : Exception { public ConfigRegistrationException(string message) : base(message) { } } public class ConfigSectionData { public readonly Type InterfaceType; public readonly ICollection<ConfigEntryData> Entries; public readonly string Name; public ConfigDescription Description { get; private set; } public ConfigSectionData(Type type) { if (!type.IsInterface) { throw new ConfigRegistrationException("Config section definitions must be interfaces: " + type.FullName); } ConfigSectionAttribute customAttribute = type.GetCustomAttribute<ConfigSectionAttribute>(); if (customAttribute == null) { throw new ConfigRegistrationException("Cannot register a config section without a ConfigSection attribute: " + type.FullName); } Name = customAttribute.section; InterfaceType = type; Entries = new List<ConfigEntryData>(); MemberInfo[] members = type.GetMembers(); foreach (MemberInfo memberInfo in members) { if (memberInfo.MemberType != MemberTypes.Property) { if (memberInfo.MemberType != MemberTypes.Method || !((MethodInfo)memberInfo).Name.StartsWith("get_")) { throw new ConfigRegistrationException($"Non-property members are not allowed in config section definitions: ({memberInfo.Name} is {memberInfo.MemberType})"); } } else { LethalPlugin.Log.LogDebug((object)("Register: " + type.Name + " = " + memberInfo.Name)); ConfigEntryData item = new ConfigEntryData(this, (PropertyInfo)memberInfo); Entries.Add(item); } } } } } namespace LethalProgression.LessShitConfig.Internal.ClassBuilders { public abstract class ConfigSectionClassBuilder { protected static readonly MethodAttributes propertyMethodAttributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName; protected static readonly MethodInfo AbstractConfigBase_GetDefinitionMethod = typeof(AbstractConfigBase).GetMethod("GetDefinition", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); protected readonly TypeBuilder typeBuilder; protected readonly ILGenerator constructorGenerator; protected readonly ConfigSectionData sectionData; protected abstract Type ConfigBaseType { get; } protected abstract ConstructorInfo BaseConstructor { get; } public ConfigSectionClassBuilder(ConfigSectionData section) { sectionData = section; string text = "DynamicConfigClass_" + ConfigBaseType.Name + "_" + section.Name; AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(text), AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(text); typeBuilder = moduleBuilder.DefineType(ConfigBaseType.Name + "_" + section.Name, TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.BeforeFieldInit, ConfigBaseType, new Type[1] { section.InterfaceType }); Type[] parameterTypes = (from param in BaseConstructor.GetParameters() select param.ParameterType).ToArray(); ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, parameterTypes); constructorGenerator = constructorBuilder.GetILGenerator(); AppendBaseConstructorOpcodes(); } protected abstract void AppendBaseConstructorOpcodes(); public void AddEntry(ConfigEntryData entry) { PropertyInfo property = entry.Property; Type propertyType = property.PropertyType; string fieldName = "Definition_" + property.Name; FieldBuilder field = typeBuilder.DefineField(fieldName, typeof(ConfigDefinition), FieldAttributes.Private); MethodInfo methodInfo = ConfigBaseType.GetMethods().First((MethodInfo m) => m.Name == "GetValue" && m.IsGenericMethod); constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldstr, entry.Definition.Key); constructorGenerator.Emit(OpCodes.Callvirt, AbstractConfigBase_GetDefinitionMethod); constructorGenerator.Emit(OpCodes.Stfld, field); string name = "get_" + property.Name; MethodBuilder methodBuilder = typeBuilder.DefineMethod(name, propertyMethodAttributes, propertyType, Type.EmptyTypes); ILGenerator iLGenerator = methodBuilder.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Ldfld, field); iLGenerator.Emit(OpCodes.Callvirt, methodInfo.MakeGenericMethod(propertyType)); iLGenerator.Emit(OpCodes.Ret); PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(property.Name, PropertyAttributes.None, propertyType, Type.EmptyTypes); propertyBuilder.SetGetMethod(methodBuilder); } public AbstractConfigBase Build() { constructorGenerator.Emit(OpCodes.Ret); Type type = typeBuilder.CreateType(); return ConstructGeneratedType(type); } protected abstract AbstractConfigBase ConstructGeneratedType(Type type); } public class DictionaryOverlayConfigSectionClassBuilder : ConfigSectionClassBuilder { private readonly AbstractConfigBase baseConfig; private readonly IDictionary<ConfigDefinition, object> overlay; protected override Type ConfigBaseType => typeof(DictionaryOverlayConfigBase); protected override ConstructorInfo BaseConstructor => ConfigBaseType.GetConstructor(new Type[3] { typeof(string), typeof(AbstractConfigBase), typeof(Dictionary<ConfigDefinition, object>) }); public DictionaryOverlayConfigSectionClassBuilder(ConfigSectionData section, AbstractConfigBase baseConfig, IDictionary<ConfigDefinition, object> overlay) : base(section) { this.baseConfig = baseConfig; this.overlay = overlay; } protected override void AppendBaseConstructorOpcodes() { constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldarg_1); constructorGenerator.Emit(OpCodes.Ldarg_2); constructorGenerator.Emit(OpCodes.Ldarg_3); constructorGenerator.Emit(OpCodes.Call, BaseConstructor); } protected override AbstractConfigBase ConstructGeneratedType(Type type) { return (AbstractConfigBase)Activator.CreateInstance(type, sectionData.Name, baseConfig, overlay); } public new DictionaryOverlayConfigBase Build() { return (DictionaryOverlayConfigBase)base.Build(); } } public class LocalConfigSectionClassBuilder : ConfigSectionClassBuilder { private readonly ConfigFile configFile; protected override Type ConfigBaseType => typeof(LocalConfigBase); protected override ConstructorInfo BaseConstructor => ConfigBaseType.GetConstructor(new Type[2] { typeof(string), typeof(ConfigFile) }); public LocalConfigSectionClassBuilder(ConfigSectionData section, ConfigFile config) : base(section) { configFile = config; } protected override void AppendBaseConstructorOpcodes() { constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldarg_1); constructorGenerator.Emit(OpCodes.Ldarg_2); constructorGenerator.Emit(OpCodes.Call, BaseConstructor); } protected override AbstractConfigBase ConstructGeneratedType(Type type) { return (AbstractConfigBase)Activator.CreateInstance(type, sectionData.Name, configFile); } public new LocalConfigBase Build() { return (LocalConfigBase)base.Build(); } } } namespace LethalProgression.LessShitConfig.Sources { public abstract class AbstractConfigBase { private string sectionName; protected AbstractConfigBase(string sectionName) { this.sectionName = sectionName; } protected ConfigDefinition GetDefinition(string key) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown return new ConfigDefinition(sectionName, key); } public abstract object GetValue(ConfigDefinition definition); public abstract T GetValue<T>(ConfigDefinition definition); } public abstract class DictionaryOverlayConfigBase : AbstractConfigBase { private readonly AbstractConfigBase baseConfig; private readonly IDictionary<ConfigDefinition, object> overlay; public DictionaryOverlayConfigBase(string sectionName, AbstractConfigBase baseConfig, IDictionary<ConfigDefinition, object> overlay) : base(sectionName) { this.baseConfig = baseConfig; this.overlay = overlay; } public override object GetValue(ConfigDefinition definition) { if (overlay.TryGetValue(definition, out var value)) { return value; } return baseConfig.GetValue(definition); } public override T GetValue<T>(ConfigDefinition definition) { if (overlay.TryGetValue(definition, out var value)) { return (T)value; } return baseConfig.GetValue<T>(definition); } } public abstract class LocalConfigBase : AbstractConfigBase { private readonly ConfigFile configFile; public LocalConfigBase(string sectionName, ConfigFile config) : base(sectionName) { configFile = config; } public override object GetValue(ConfigDefinition definition) { IDictionary<ConfigDefinition, ConfigEntryBase> dictionary = (IDictionary<ConfigDefinition, ConfigEntryBase>)configFile; if (dictionary.TryGetValue(definition, out var value)) { return value.BoxedValue; } throw new ArgumentException($"The config entry {definition} is not registered.", "definition"); } public override T GetValue<T>(ConfigDefinition definition) { ConfigEntry<T> val = default(ConfigEntry<T>); if (configFile.TryGetEntry<T>(definition, ref val)) { return val.Value; } throw new ArgumentException($"The config entry {definition} is not registered.", "definition"); } } } namespace LethalProgression.LessShitConfig.Attributes { [AttributeUsage(AttributeTargets.Property)] public class ConfigDefaultAttribute : Attribute { public object Value; public ConfigDefaultAttribute(object value) { Value = value; } } [AttributeUsage(AttributeTargets.Property)] internal class ConfigDescriptionAttribute : Attribute { public readonly ConfigDescription Description; public ConfigDescriptionAttribute(string description) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown Description = new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()); } } [AttributeUsage(AttributeTargets.Property)] internal class ConfigNameAttribute : Attribute { public readonly string name; public ConfigNameAttribute(string name) { this.name = name; } } [AttributeUsage(AttributeTargets.Interface)] internal class ConfigSectionAttribute : Attribute { public readonly string section; public ConfigSectionAttribute(string section) { this.section = section; } } } namespace LethalProgression.GUI.XPBar { internal class XPBarGUI { [CompilerGenerated] private static class <>O { public static UnityAction <0>__OpenSkillTree; } private GameObject xpBar; private GameObject xpInfoContainer; private GameObject xpBarProgress; private GameObject skillTreeButton; private TextMeshProUGUI xpText; private TextMeshProUGUI xpLevel; private TextMeshProUGUI profit; public void Show() { CreateAllObjectsIfRequired(); xpBar.SetActive(true); xpBarProgress.SetActive(true); } public void Update(bool active) { CreateAllObjectsIfRequired(); LC_XP xpInstance = LP_NetworkManager.xpInstance; xpInfoContainer.SetActive(active); ((TMP_Text)xpText).text = $"{xpInstance.GetXP()} / {xpInstance.teamXPRequired.Value}"; ((TMP_Text)xpLevel).text = $"Level: {xpInstance.GetLevel()}"; ((TMP_Text)profit).text = $"You've made.. {xpInstance.GetProfit()}$"; xpBarProgress.GetComponent<Image>().fillAmount = (float)xpInstance.GetXP() / (float)xpInstance.teamXPRequired.Value; } private void CreateContainer() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)xpInfoContainer)) { GameObject val = GameObject.Find("/Systems/UI/Canvas/QuickMenu"); xpInfoContainer = new GameObject("XpInfoContainer"); xpInfoContainer.transform.SetParent(val.transform, false); xpInfoContainer.transform.localScale = new Vector3(0.75f, 0.75f, 0.75f); xpInfoContainer.transform.Translate(-1.7f, 0.9f, 0f); } } private void CreateXPBar() { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)xpBar)) { GameObject val = GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/LevelUpBox"); GameObject val2 = GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/Total"); xpBar = Object.Instantiate<GameObject>(val); ((Object)xpBar).name = "XPBar"; xpBar.transform.SetParent(xpInfoContainer.transform, false); xpText = Object.Instantiate<GameObject>(val2).GetComponent<TextMeshProUGUI>(); ((Object)xpText).name = "XPText"; ((TMP_Text)xpText).SetText("0/1000", true); ((TMP_Text)xpText).alignment = (TextAlignmentOptions)514; ((Graphic)xpText).color = new Color(1f, 0.6f, 0f, 1f); ((TMP_Text)xpText).transform.SetParent(xpBar.transform, false); ((TMP_Text)xpText).transform.Translate(-0.75f, 0.21f, 0f); xpLevel = Object.Instantiate<GameObject>(val2).GetComponent<TextMeshProUGUI>(); ((Object)xpLevel).name = "XPLevel"; ((TMP_Text)xpLevel).SetText("Level: 0", true); ((TMP_Text)xpLevel).alignment = (TextAlignmentOptions)514; ((Graphic)xpLevel).color = new Color(1f, 0.6f, 0f, 1f); ((TMP_Text)xpLevel).transform.SetParent(xpInfoContainer.transform, false); ((TMP_Text)xpLevel).transform.position = new Vector3(xpBar.transform.position.x, xpBar.transform.position.y, xpBar.transform.position.z); ((TMP_Text)xpLevel).transform.Translate(-0.3f, 0.2f, 0f); profit = Object.Instantiate<GameObject>(val2).GetComponent<TextMeshProUGUI>(); ((Object)profit).name = "XPProfit"; ((TMP_Text)profit).SetText("You've made.. 0$.", true); ((Graphic)profit).color = new Color(1f, 0.6f, 0f, 1f); ((TMP_Text)profit).alignment = (TextAlignmentOptions)514; ((TMP_Text)profit).transform.SetParent(xpInfoContainer.transform, false); ((TMP_Text)profit).transform.position = new Vector3(xpBar.transform.position.x, xpBar.transform.position.y, xpBar.transform.position.z); ((TMP_Text)profit).transform.Translate(-0.1f, -0.2f, 0f); } } private void CreateXPBarProgress() { //IL_009b: Unknown result type (might be due to invalid IL