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 QOL KPX v2.3.0
QOL_KPX.dll
Decompiled 2 days 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.Globalization; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("QOL_KPX")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.3.0.0")] [assembly: AssemblyInformationalVersion("2.3.0+8e1c531dbf9c80d1e61a45420e7a51e511639606")] [assembly: AssemblyProduct("QOL_KPX")] [assembly: AssemblyTitle("QOL_KPX")] [assembly: AssemblyVersion("2.3.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 QolKpx { internal static class Archery { internal static float StaminaReduction = 0.5f; internal static float AccuracyBonus = 1f; internal static bool Enabled = true; private static Player Local => Player.m_localPlayer; private static float Factor => ((Character)Local).GetSkillFactor((SkillType)8); private static bool IsLocalBow(Character c, ItemData weapon) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Invalid comparison between Unknown and I4 if (Enabled && (Object)(object)Local != (Object)null && (Object)(object)c == (Object)(object)Local && weapon != null) { return (int)weapon.m_shared.m_skillType == 8; } return false; } [HarmonyPatch(typeof(ItemData), "GetDrawStaminaDrain")] [HarmonyPostfix] private static void DrawDrain(ItemData __instance, ref float __result) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 try { if (Enabled && !(__result <= 0f) && !((Object)(object)Local == (Object)null) && (int)__instance.m_shared.m_skillType == 8) { __result *= 1f - Factor * StaminaReduction; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha na stamina do arco: " + ex.Message)); } } [HarmonyPatch(typeof(Attack), "GetAttackStamina")] [HarmonyPostfix] private static void ShotStamina(ref float __result, Character ___m_character, ItemData ___m_weapon) { try { if (!(__result <= 0f) && IsLocalBow(___m_character, ___m_weapon)) { __result *= 1f - Factor * StaminaReduction; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha na stamina do disparo: " + ex.Message)); } } [HarmonyPatch(typeof(Attack), "FireProjectileBurst")] [HarmonyPrefix] private static void AimBefore(Character ___m_character, ItemData ___m_weapon, out float __state) { __state = float.NaN; try { if (IsLocalBow(___m_character, ___m_weapon)) { Attack attack = ___m_weapon.m_shared.m_attack; __state = attack.m_projectileAccuracy; attack.m_projectileAccuracy = Mathf.Lerp(attack.m_projectileAccuracy, attack.m_projectileAccuracyMin, Mathf.Clamp01(Factor * AccuracyBonus)); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha na precisão do arco: " + ex.Message)); } } [HarmonyPatch(typeof(Attack), "FireProjectileBurst")] [HarmonyPostfix] private static void AimAfter(ItemData ___m_weapon, float __state) { if (!float.IsNaN(__state) && ___m_weapon != null) { ___m_weapon.m_shared.m_attack.m_projectileAccuracy = __state; } } } internal static class BlastFurnace { internal struct Saved { internal bool active; internal float seconds; internal int fuel; } internal static bool Enabled = true; internal static float Efficiency = 0.5f; private const string Furnace = "blastfurnace"; private const string Smelter = "smelter"; private static readonly HashSet<string> borrowed = new HashSet<string>(); private static readonly Func<Smelter, string> QueuedOre = AccessTools.MethodDelegate<Func<Smelter, string>>(AccessTools.Method(typeof(Smelter), "GetQueuedOre", (Type[])null, (Type[])null), (object)null, true); [HarmonyPatch(typeof(ZNetScene), "Awake")] [HarmonyPostfix] private static void Teach(ZNetScene __instance) { try { if (!Enabled || (Object)(object)__instance == (Object)null) { return; } Smelter val = Component(__instance, "blastfurnace"); Smelter val2 = Component(__instance, "smelter"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } borrowed.Clear(); foreach (ItemConversion item in val2.m_conversion) { if ((Object)(object)item?.m_from != (Object)null && (Object)(object)item.m_to != (Object)null) { borrowed.Add(((Object)((Component)item.m_from).gameObject).name); } } HashSet<string> hashSet = new HashSet<string>(); foreach (ItemConversion item2 in val.m_conversion) { if ((Object)(object)item2?.m_from != (Object)null) { hashSet.Add(((Object)((Component)item2.m_from).gameObject).name); } } int num = 0; foreach (ItemConversion item3 in val2.m_conversion) { if (!((Object)(object)item3?.m_from == (Object)null) && !((Object)(object)item3.m_to == (Object)null) && hashSet.Add(((Object)((Component)item3.m_from).gameObject).name)) { val.m_conversion.Add(item3); num++; } } Debug.Log((object)("[QOL KPX] [BlastFurnace] minérios com desconto: " + borrowed.Count + ", receitas novas: " + num)); } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao ensinar o alto-forno: " + ex.Message)); } } private static Smelter Component(ZNetScene scene, string prefabName) { GameObject prefab = scene.GetPrefab(prefabName); if (!((Object)(object)prefab != (Object)null)) { return null; } return prefab.GetComponent<Smelter>(); } [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] [HarmonyPrefix] private static void Cheaper(Smelter __instance, out Saved __state) { __state = default(Saved); try { if (Enabled && !(Efficiency <= 0f) && !(Efficiency >= 1f) && !((Object)(object)__instance == (Object)null) && borrowed.Count != 0 && !(Utils.GetPrefabName(((Component)__instance).gameObject) != "blastfurnace") && borrowed.Contains(QueuedOre(__instance))) { __state.active = true; __state.seconds = __instance.m_secPerProduct; __state.fuel = __instance.m_fuelPerProduct; __instance.m_secPerProduct *= Efficiency; __instance.m_fuelPerProduct = Mathf.Max(1, Mathf.RoundToInt((float)__state.fuel * Efficiency)); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no desconto do alto-forno: " + ex.Message)); } } [HarmonyPatch(typeof(Smelter), "UpdateSmelter")] [HarmonyFinalizer] private static void Restore(Smelter __instance, Saved __state) { if (__state.active && !((Object)(object)__instance == (Object)null)) { __instance.m_secPerProduct = __state.seconds; __instance.m_fuelPerProduct = __state.fuel; } } } internal static class Bronze { internal static bool Enabled = true; internal static float Ratio = 1f; private const string Item = "Bronze"; [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPostfix] private static void OnDbAwake(ObjectDB __instance) { Rebalance(__instance); } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] [HarmonyPostfix] private static void OnDbCopied(ObjectDB __instance) { Rebalance(__instance); } private static void Rebalance(ObjectDB db) { try { if (!Enabled || db?.m_recipes == null) { return; } foreach (Recipe recipe in db.m_recipes) { if ((Object)(object)recipe?.m_item == (Object)null || ((Object)((Component)recipe.m_item).gameObject).name != "Bronze" || recipe.m_resources == null || recipe.m_resources.Length == 0) { continue; } int num = 0; Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { if ((Object)(object)val?.m_resItem != (Object)null) { num += val.m_amount; } } if (num > 0) { int num2 = Mathf.Max(1, Mathf.RoundToInt((float)num * Ratio)); if (recipe.m_amount != num2) { Debug.Log((object)$"[QOL KPX] bronze: {num} de entrada passa a render {num2} (era {recipe.m_amount})"); recipe.m_amount = num2; } } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao ajustar o bronze: " + ex.Message)); } } } internal static class Building { internal static bool Enabled = true; internal static float Multiplier = 3f; [HarmonyPatch(typeof(WearNTear), "GetMaterialProperties")] [HarmonyPostfix] private static void Reinforce(ref float maxSupport, ref float horizontalLoss, ref float verticalLoss) { try { if (Enabled && !(Multiplier <= 0f)) { maxSupport *= Multiplier; horizontalLoss /= Multiplier; verticalLoss /= Multiplier; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no limite de construção: " + ex.Message)); } } } internal static class BuildTools { internal static bool NoStamina = true; internal static bool NoDurability = true; internal static bool NoMoveStamina = true; private static bool IsLocal(Player p) { if ((Object)(object)p != (Object)null) { return (Object)(object)p == (Object)(object)Player.m_localPlayer; } return false; } [HarmonyPatch(typeof(Player), "UseStamina")] [HarmonyPrefix] private static bool FreeWhileBuilding(Player __instance) { if (!NoMoveStamina || !IsLocal(__instance) || !((Character)__instance).InPlaceMode()) { return true; } return false; } [HarmonyPatch(typeof(Player), "GetBuildStamina")] [HarmonyPostfix] private static void NoBuildStamina(Player __instance, ref float __result) { if (NoStamina && IsLocal(__instance)) { __result = 0f; } } [HarmonyPatch(typeof(Player), "GetPlaceDurability")] [HarmonyPostfix] private static void NoPlaceWear(Player __instance, ref float __result) { if (NoDurability && IsLocal(__instance)) { __result = 0f; } } [HarmonyPatch(typeof(Player), "Repair")] [HarmonyPrefix] private static void KeepWear(ItemData __0, out float __state) { __state = __0?.m_durability ?? (-1f); } [HarmonyPatch(typeof(Player), "Repair")] [HarmonyPostfix] private static void RestoreWear(Player __instance, ItemData __0, float __state) { if (NoDurability && __state >= 0f && __0 != null && IsLocal(__instance)) { __0.m_durability = __state; } } } internal static class Charcoal { internal static bool Enabled = true; internal static int KilnCapacity = 100; internal static string WeightList = "Wood:1,RoundLog:5,FineWood:8,ElderBark:10,YggdrasilWood:15,Blackwood:20,Frostwood:25"; private const string CoalName = "Coal"; private static readonly FieldRef<Smelter, ZNetView> NView = AccessTools.FieldRefAccess<Smelter, ZNetView>("m_nview"); private static readonly Func<Smelter, int> QueueSize = AccessTools.MethodDelegate<Func<Smelter, int>>(AccessTools.Method(typeof(Smelter), "GetQueueSize", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Smelter, Inventory, ItemData> FindCookable = AccessTools.MethodDelegate<Func<Smelter, Inventory, ItemData>>(AccessTools.Method(typeof(Smelter), "FindCookableItem", (Type[])null, (Type[])null), (object)null, true); private static readonly Dictionary<string, int> weights = new Dictionary<string, int>(); private static readonly HashSet<string> warned = new HashSet<string>(); private static string parsedFrom; private static void Parse() { if (parsedFrom == WeightList) { return; } parsedFrom = WeightList; weights.Clear(); warned.Clear(); string[] array = WeightList.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }); if (array2.Length == 2 && int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result > 0) { weights[array2[0].Trim()] = result; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] [HarmonyPostfix] private static void Prepare(ZNetScene __instance) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown try { if (!Enabled || (Object)(object)__instance == (Object)null) { return; } Parse(); int num = 1; foreach (int value in weights.Values) { if (value > num) { num = value; } } foreach (GameObject prefab2 in __instance.m_prefabs) { Smelter val = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Smelter>() : null); if ((Object)(object)val == (Object)null || val.m_conversion == null) { continue; } ItemDrop val2 = CoalFrom(val); if ((Object)(object)val2 == (Object)null) { continue; } int num2 = 0; foreach (KeyValuePair<string, int> weight in weights) { if (!IsInput(val, weight.Key)) { GameObject prefab = __instance.GetPrefab(weight.Key); ItemDrop val3 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null); if (!((Object)(object)val3 == (Object)null)) { val.m_conversion.Add(new ItemConversion { m_from = val3, m_to = val2 }); num2++; } } } int maxOre = val.m_maxOre; val.m_maxOre = Mathf.Max(maxOre, Mathf.Max(KilnCapacity, num)); Debug.Log((object)("[QOL KPX] [Charcoal] " + ((Object)prefab2).name + ": carga " + maxOre + " -> " + val.m_maxOre + ", madeiras novas: " + num2)); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao preparar o forno de carvão: " + ex.Message)); } } private static ItemDrop CoalFrom(Smelter kiln) { foreach (ItemConversion item in kiln.m_conversion) { if ((Object)(object)item?.m_from != (Object)null && (Object)(object)item.m_to != (Object)null && Utils.GetPrefabName(((Component)item.m_to).gameObject) == "Coal") { return item.m_to; } } return null; } private static bool MakesCoal(Smelter smelter, string prefab) { foreach (ItemConversion item in smelter.m_conversion) { if (!((Object)(object)item?.m_from == (Object)null) && !((Object)(object)item.m_to == (Object)null) && !(Utils.GetPrefabName(((Component)item.m_from).gameObject) != prefab)) { return Utils.GetPrefabName(((Component)item.m_to).gameObject) == "Coal"; } } return false; } internal static int Weight(Smelter smelter, string prefab) { if (!Enabled || (Object)(object)smelter == (Object)null || string.IsNullOrEmpty(prefab)) { return 1; } Parse(); if (!weights.TryGetValue(prefab, out var value) || value <= 1) { return 1; } if (!MakesCoal(smelter, prefab)) { return 1; } if (value > smelter.m_maxOre && warned.Add(prefab)) { Debug.LogWarning((object)("[QOL KPX] [Charcoal] " + prefab + " pesa " + value + ", mas o forno só cabe " + smelter.m_maxOre + ": nunca vai entrar")); } return value; } internal static bool Fits(Smelter smelter, string prefab) { if ((Object)(object)smelter == (Object)null) { return false; } return QueueSize(smelter) + Weight(smelter, prefab) <= smelter.m_maxOre; } [HarmonyPatch(typeof(Smelter), "OnAddOre")] [HarmonyPrefix] private static bool OnlyWhatFits(Smelter __instance, Humanoid user, ref ItemData item, ref bool __result) { try { if (!Enabled || (Object)(object)__instance == (Object)null || (Object)(object)user == (Object)null) { return true; } Inventory inventory = user.GetInventory(); bool flag = item != null; ItemData val = item ?? FindCookable(__instance, inventory); string text = (((Object)(object)val?.m_dropPrefab != (Object)null) ? ((Object)val.m_dropPrefab).name : null); if (text == null) { return true; } if (Fits(__instance, text)) { return true; } if (!flag) { ItemData val2 = BestFit(__instance, inventory); if (val2 != null) { item = val2; return true; } } ((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null, false); __result = false; return false; } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao conferir a carga do forno: " + ex.Message)); } return true; } internal static ItemData BestFit(Smelter smelter, Inventory inv) { if ((Object)(object)smelter == (Object)null || inv == null) { return null; } ItemData result = null; int num = 0; foreach (ItemData allItem in inv.GetAllItems()) { string text = (((Object)(object)allItem?.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : null); if (text != null && IsInput(smelter, text) && Fits(smelter, text)) { int num2 = Weight(smelter, text); if (num2 > num) { result = allItem; num = num2; } } } return result; } internal static bool IsInput(Smelter smelter, string prefab) { foreach (ItemConversion item in smelter.m_conversion) { if ((Object)(object)item?.m_from != (Object)null && Utils.GetPrefabName(((Component)item.m_from).gameObject) == prefab) { return true; } } return false; } [HarmonyPatch(typeof(Smelter), "QueueOre")] [HarmonyPostfix] private static void Weigh(Smelter __instance, string name, bool cheated) { try { if (!Enabled || (Object)(object)__instance == (Object)null || string.IsNullOrEmpty(name)) { return; } int num = Weight(__instance, name); if (num <= 1) { return; } ZNetView obj = NView.Invoke(__instance); ZDO val = ((obj != null) ? obj.GetZDO() : null); if (val == null) { return; } for (int i = 1; i < num; i++) { int num2 = val.GetInt(ZDOVars.s_queued, 0); if (num2 < __instance.m_maxOre) { val.Set("item" + num2, name); val.Set(ZDOVars.s_queued, num2 + 1, false); val.Set(ZDOVars.s_cheatedQueued, cheated); continue; } break; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no peso da madeira: " + ex.Message)); } } } internal static class ChestCrafting { private class Request { internal Container Chest; internal string Name; internal int Amount; internal int Quality; internal int Tries; internal bool ForCredit; internal bool Replied; internal uint Revision; internal float Time; } internal static bool Enabled = true; private const string RpcTake = "QolKpx_ChestTake"; private const string RpcTook = "QolKpx_ChestTook"; private const float ReplyTimeout = 5f; private const int MaxTries = 3; private static readonly FieldRef<Container, ZNetView> View = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview"); private static readonly FieldRef<Container, uint> LoadedRevision = AccessTools.FieldRefAccess<Container, uint>("m_lastRevision"); private static readonly FieldRef<InventoryGui, float> CraftTimer = AccessTools.FieldRefAccess<InventoryGui, float>("m_craftTimer"); private static readonly FieldRef<InventoryGui, Recipe> CraftRecipe = AccessTools.FieldRefAccess<InventoryGui, Recipe>("m_craftRecipe"); private static readonly FieldRef<InventoryGui, ItemData> CraftUpgradeItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_craftUpgradeItem"); private static readonly FieldRef<InventoryGui, bool> MultiCrafting = AccessTools.FieldRefAccess<InventoryGui, bool>("m_multiCrafting"); private static readonly FieldRef<InventoryGui, ItemData> DragItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_dragItem"); private static readonly FieldRef<InventoryGui, ItemData> SplitItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_splitItem"); private static readonly FieldInfo Stations = AccessTools.Field(typeof(CraftingStation), "m_allStations"); private static readonly HashSet<Container> all = new HashSet<Container>(); private static readonly List<Container> nearby = new List<Container>(); private static readonly List<CraftingStation> covering = new List<CraftingStation>(); private static float nearbyAt = -10f; private const float Refresh = 0.5f; private static readonly Dictionary<string, int> counts = new Dictionary<string, int>(); private static int countsFrame = -1; private static int depth; private static readonly Dictionary<string, int> credit = new Dictionary<string, int>(); private static readonly Dictionary<string, ItemDrop> prefabs = new Dictionary<string, ItemDrop>(); private static readonly Dictionary<int, Request> requests = new Dictionary<int, Request>(); private static readonly List<int> finished = new List<int>(); private static int nextId; private static Player Local => Player.m_localPlayer; [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPostfix] private static void Track(Container __instance) { try { if ((Object)(object)__instance == (Object)null || __instance.GetInventory() == null) { return; } all.Add(__instance); ZNetView val = View.Invoke(__instance); if (!((Object)(object)val == (Object)null)) { Container chest = __instance; val.Register<string, int, int, int>("QolKpx_ChestTake", (Method<string, int, int, int>)delegate(long sender, string name, int amount, int quality, int id) { OnTake(chest, sender, name, amount, quality, id); }); val.Register<int, int, bool>("QolKpx_ChestTook", (Action<long, int, int, bool>)OnTook); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao registrar baú: " + ex.Message)); } } [HarmonyPatch(typeof(Player), "HaveRequirementItems")] [HarmonyPrefix] private static void EnterRecipe(Player __instance, Recipe piece, bool discover, out bool __state) { __state = Enabled && (Object)(object)__instance == (Object)(object)Local && !discover && (Object)(object)piece != (Object)null && !piece.m_requireOnlyOneIngredient; if (__state) { depth++; } } [HarmonyPatch(typeof(Player), "HaveRequirementItems")] [HarmonyFinalizer] private static void LeaveRecipe(bool __state) { if (__state) { depth--; } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyPrefix] private static void EnterBuild(Player __instance, RequirementMode mode, out bool __state) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 __state = Enabled && (Object)(object)__instance == (Object)(object)Local && ((int)mode == 0 || (int)mode == 2); if (__state) { depth++; } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyFinalizer] private static void LeaveBuild(bool __state) { if (__state) { depth--; } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] [HarmonyPrefix] private static void EnterPanel(Player player, out bool __state) { __state = Enabled && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Local; if (__state) { depth++; } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] [HarmonyFinalizer] private static void LeavePanel(bool __state) { if (__state) { depth--; } } [HarmonyPatch(typeof(Inventory), "CountItems")] [HarmonyPostfix] private static void AddStock(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result) { try { if (depth > 0 && name != null && !((Object)(object)Local == (Object)null) && __instance == ((Humanoid)Local).GetInventory()) { __result += Stock(name, quality, matchWorldLevel); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao contar os baús: " + ex.Message)); } } [HarmonyPatch(typeof(Inventory), "HaveItem", new Type[] { typeof(string), typeof(bool) })] [HarmonyPostfix] private static void HaveStock(Inventory __instance, string name, bool matchWorldLevel, ref bool __result) { try { if (!__result && depth > 0 && name != null && !((Object)(object)Local == (Object)null) && __instance == ((Humanoid)Local).GetInventory()) { __result = Stock(name, -1, matchWorldLevel) > 0; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao contar os baús: " + ex.Message)); } } internal static int Reachable(string name) { try { return (Enabled && name != null && (Object)(object)Local != (Object)null) ? Stock(name, -1, matchWorldLevel: true) : 0; } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao ler o estoque dos baús: " + ex.Message)); return 0; } } private static int Stock(string name, int quality, bool matchWorldLevel) { if (countsFrame != Time.frameCount) { counts.Clear(); countsFrame = Time.frameCount; } string key = name + "|" + quality + (matchWorldLevel ? "|1" : "|0"); if (counts.TryGetValue(key, out var value)) { return value; } value = ((quality <= 1 && credit.TryGetValue(name, out var value2)) ? value2 : 0); foreach (Container item in Nearby(force: false)) { if (Valid(item)) { value += Available(item, name, quality, matchWorldLevel); } } counts[key] = value; return value; } private static int Available(Container c, string name, int quality, bool matchWorldLevel) { int num = c.GetInventory().CountItems(name, quality, matchWorldLevel); foreach (Request value in requests.Values) { if ((Object)(object)value.Chest == (Object)(object)c && value.Name == name) { num -= value.Amount; } } return Mathf.Max(0, num); } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] [HarmonyPostfix] private static void PayOnClick(InventoryGui __instance) { try { Player local = Local; if (Enabled && !((Object)(object)local == (Object)null) && CraftTimer.Invoke(__instance) == 0f) { Recipe val = CraftRecipe.Invoke(__instance); if (!((Object)(object)val == (Object)null) && !val.m_requireOnlyOneIngredient && !local.NoCostCheat() && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)25)) { ItemData val2 = CraftUpgradeItem.Invoke(__instance); int qualityLevel = ((val2 == null) ? 1 : (val2.m_quality + 1)); int multiplier = ((!MultiCrafting.Invoke(__instance)) ? 1 : __instance.m_multiCraftAmount); Pay(local, val.m_resources, qualityLevel, -1, multiplier, toCredit: true); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao pagar a fabricação: " + ex.Message)); } } [HarmonyPatch(typeof(InventoryGui), "Update")] [HarmonyPostfix] private static void Settle(InventoryGui __instance) { try { Expire(); if (credit.Count == 0 || CraftTimer.Invoke(__instance) >= 0f) { return; } foreach (Request value in requests.Values) { if (value.ForCredit && !value.Replied) { return; } } Refund(); } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao devolver material: " + ex.Message)); } } private static void Refund() { Player local = Local; if ((Object)(object)local != (Object)null) { foreach (KeyValuePair<string, int> item in credit) { if (item.Value > 0 && prefabs.TryGetValue(item.Key, out var value) && !((Object)(object)value == (Object)null)) { ((Humanoid)local).GetInventory().AddItem(((Object)((Component)value).gameObject).name, item.Value, 1, 0, 0L, "", false, false); } } } credit.Clear(); countsFrame = -1; } [HarmonyPatch(typeof(Player), "ConsumeResources")] [HarmonyPrefix] private static bool Consume(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier) { try { if (!Enabled || (Object)(object)__instance != (Object)(object)Local || requirements == null) { return true; } Pay(__instance, requirements, qualityLevel, itemQuality, multiplier, toCredit: false); return false; } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao tirar recursos dos baús: " + ex.Message)); return true; } } private static void Pay(Player player, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier, bool toCredit) { CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); Inventory inventory = ((Humanoid)player).GetInventory(); List<Container> list = null; foreach (Requirement val in requirements) { if (val == null || !Object.op_Implicit((Object)(object)val.m_resItem) || (((Object)(object)currentCraftingStation != (Object)null) ? (currentCraftingStation.m_upgrader != val.m_upgraderResource) : val.m_upgraderResource)) { continue; } int num = val.GetAmount(qualityLevel) * multiplier; if (num <= 0) { continue; } string name = val.m_resItem.m_itemData.m_shared.m_name; prefabs[name] = val.m_resItem; if (!toCredit && credit.TryGetValue(name, out var value)) { int num2 = Mathf.Min(value, num); credit[name] = value - num2; num -= num2; } int num3 = Mathf.Min(num, inventory.CountItems(name, itemQuality, true)); if (num3 > 0) { inventory.RemoveItem(name, num3, itemQuality, true); num -= num3; if (toCredit) { AddCredit(name, num3); } } if (num <= 0) { continue; } if (list == null) { list = Nearby(force: true); } foreach (Container item in list) { if (num <= 0) { break; } num -= Withdraw(item, name, num, itemQuality, toCredit); } } countsFrame = -1; } private static void AddCredit(string name, int amount) { credit.TryGetValue(name, out var value); credit[name] = value + amount; } private static int Withdraw(Container c, string name, int amount, int quality, bool toCredit) { if (!Valid(c)) { return 0; } int num = Mathf.Min(amount, Available(c, name, quality, matchWorldLevel: true)); if (num <= 0) { return 0; } ZNetView val = View.Invoke(c); if (!val.GetZDO().HasOwner()) { val.ClaimOwnership(); } if (val.IsOwner()) { num = TakeFrom(c, name, num, quality); if (toCredit) { AddCredit(name, num); } return num; } Send(new Request { Chest = c, Name = name, Amount = num, Quality = quality, ForCredit = toCredit, Revision = LoadedRevision.Invoke(c), Time = Time.time }); if (toCredit) { AddCredit(name, num); } return num; } private static void Send(Request r) { int num = ++nextId; r.Tries++; r.Time = Time.time; requests[num] = r; View.Invoke(r.Chest).InvokeRPC("QolKpx_ChestTake", new object[4] { r.Name, r.Amount, r.Quality, num }); } private static void OnTake(Container c, long sender, string name, int amount, int quality, int id) { int num = 0; bool flag = false; try { ZNetView val = View.Invoke(c); if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner()) { flag = true; } else { num = TakeFrom(c, name, amount, quality); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao atender pedido de baú: " + ex.Message)); } try { ZNetView obj = View.Invoke(c); if (obj != null) { obj.InvokeRPC(sender, "QolKpx_ChestTook", new object[3] { id, num, flag }); } } catch (Exception ex2) { Debug.LogWarning((object)("[QOL KPX] falha ao responder pedido de baú: " + ex2.Message)); } } private static int TakeFrom(Container c, string name, int amount, int quality) { Inventory inventory = c.GetInventory(); InventoryGui instance = InventoryGui.instance; ItemData val = (((Object)(object)instance != (Object)null) ? DragItem.Invoke(instance) : null); ItemData val2 = (((Object)(object)instance != (Object)null) ? SplitItem.Invoke(instance) : null); int num = 0; ItemData[] array = inventory.GetAllItems().ToArray(); foreach (ItemData val3 in array) { if (num >= amount) { break; } if (val3 != val && val3 != val2 && !(val3.m_shared.m_name != name) && (quality < 0 || val3.m_quality == quality) && val3.m_worldLevel >= Game.m_worldLevel) { int num2 = Mathf.Min(val3.m_stack, amount - num); if (inventory.RemoveItem(val3, num2)) { num += num2; } } } return num; } private static void OnTook(long sender, int id, int removed, bool notOwner) { try { if (!requests.TryGetValue(id, out var value)) { return; } if (notOwner && value.Tries < 3 && Valid(value.Chest)) { requests.Remove(id); Send(value); return; } if (removed < value.Amount) { if (value.ForCredit) { AddCredit(value.Name, removed - value.Amount); } else { Debug.LogWarning((object)$"[QOL KPX] baú entregou {removed} de {value.Amount} {value.Name}"); } } value.Amount = removed; value.Replied = true; countsFrame = -1; } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao ler resposta de baú: " + ex.Message)); } } private static void Expire() { if (requests.Count == 0) { return; } finished.Clear(); foreach (KeyValuePair<int, Request> request in requests) { Request value = request.Value; if ((Object)(object)value.Chest == (Object)null) { finished.Add(request.Key); } else if (value.Replied) { if (value.Amount <= 0 || LoadedRevision.Invoke(value.Chest) != value.Revision || Time.time - value.Time > 5f) { finished.Add(request.Key); } } else if (Time.time - value.Time > 5f) { if (value.ForCredit) { AddCredit(value.Name, -value.Amount); } Debug.LogWarning((object)$"[QOL KPX] baú não respondeu ao pedido de {value.Amount} {value.Name}"); finished.Add(request.Key); } } foreach (int item in finished) { requests.Remove(item); } if (finished.Count > 0) { countsFrame = -1; } } private static List<Container> Nearby(bool force) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) if (!force && Time.time - nearbyAt < 0.5f) { return nearby; } nearbyAt = Time.time; nearby.Clear(); Player local = Local; List<CraftingStation> list = Stations?.GetValue(null) as List<CraftingStation>; if ((Object)(object)local == (Object)null || list == null) { return nearby; } Vector3 position = ((Component)local).transform.position; covering.Clear(); foreach (CraftingStation item in list) { if ((Object)(object)item != (Object)null && Flat(((Component)item).transform.position, position) < item.GetStationBuildRange()) { covering.Add(item); } } if (covering.Count == 0) { return nearby; } all.RemoveWhere((Container c) => (Object)(object)c == (Object)null); foreach (Container item2 in all) { if (!Allowed(item2)) { continue; } Vector3 position2 = ((Component)item2).transform.position; foreach (CraftingStation item3 in covering) { if (Flat(((Component)item3).transform.position, position2) < item3.GetStationBuildRange()) { nearby.Add(item2); break; } } } return nearby; } private static float Flat(Vector3 a, Vector3 b) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) a.y = b.y; return Vector3.Distance(a, b); } private static bool Allowed(Container c) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 if (c.GetInventory() == null) { return false; } if (Object.op_Implicit((Object)(object)((Component)c).GetComponent<TombStone>()) || Object.op_Implicit((Object)(object)((Component)c).GetComponent<Smelter>())) { return false; } if (c.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false)) { return false; } PrivacySetting privacy = c.m_privacy; if ((int)privacy != 0) { if ((int)privacy == 2) { return true; } return false; } Piece component = ((Component)c).GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { return component.GetCreator() == Game.instance.GetPlayerProfile().GetPlayerID(); } return false; } private static bool Valid(Container c) { if ((Object)(object)c == (Object)null) { return false; } ZNetView val = View.Invoke(c); if ((Object)(object)val != (Object)null) { return val.IsValid(); } return false; } } internal static class CookTime { internal static bool Enabled = true; private const int NotDone = 0; private const int Done = 1; private const int Burnt = 2; private static readonly FieldRef<CookingStation, ZNetView> CookView = AccessTools.FieldRefAccess<CookingStation, ZNetView>("m_nview"); private static readonly FieldRef<Fermenter, ZNetView> BarrelView = AccessTools.FieldRefAccess<Fermenter, ZNetView>("m_nview"); [HarmonyPatch(typeof(CookingStation), "GetHoverText")] [HarmonyPostfix] private static void CookingLeft(CookingStation __instance, ref string __result) { try { if (!Enabled || string.IsNullOrEmpty(__result) || (Object)(object)__instance == (Object)null) { return; } ZNetView val = CookView.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsValid()) { return; } ZDO zDO = val.GetZDO(); string text = ""; for (int i = 0; i < __instance.m_slots.Length; i++) { string text2 = zDO.GetString("slot" + i, ""); if (string.IsNullOrEmpty(text2)) { continue; } int num = zDO.GetInt("slotstatus" + i, 0); string text3 = Name(text2); switch (num) { case 2: text = text + "\n" + text3 + ": burnt"; continue; case 1: text = text + "\n" + text3 + ": ready"; continue; } ItemConversion val2 = Conversion(__instance, text2); if (val2 != null) { float seconds = val2.m_cookTime - zDO.GetFloat("slot" + i, 0f); text = text + "\n" + text3 + ": ready in " + Spell(seconds); } } if (text.Length > 0) { __result = Insert(__result, text); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no tempo da fogueira: " + ex.Message)); } } [HarmonyPatch(typeof(Fermenter), "GetHoverText")] [HarmonyPostfix] private static void FermentingLeft(Fermenter __instance, ref string __result) { try { if (!Enabled || string.IsNullOrEmpty(__result) || (Object)(object)__instance == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } ZNetView val = BarrelView.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsValid()) { return; } long num = val.GetZDO().GetLong(ZDOVars.s_startTime, 0L); if (num != 0L) { double totalSeconds = (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds; float num2 = __instance.m_fermentationDuration - (float)totalSeconds; if (!(num2 <= 0f)) { __result = Insert(__result, "\nReady in " + Spell(num2)); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no tempo do fermentador: " + ex.Message)); } } private static string Insert(string hover, string lines) { int num = hover.IndexOf("\n["); if (num >= 0) { return hover.Substring(0, num) + lines + hover.Substring(num); } return hover + lines; } private static ItemConversion Conversion(CookingStation station, string itemName) { foreach (ItemConversion item in station.m_conversion) { if ((Object)(object)item?.m_from != (Object)null && ((Object)item.m_from).name == itemName) { return item; } } return null; } private static string Name(string prefab) { GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if (!((Object)(object)val2 != (Object)null)) { return prefab; } return Localization.instance.Localize(val2.m_itemData.m_shared.m_name); } private static string Spell(float seconds) { int num = Mathf.Max(0, Mathf.CeilToInt(seconds)); int num2 = num / 3600; int num3 = num % 3600 / 60; int num4 = num % 60; if (num2 > 0) { if (num3 <= 0) { return num2 + "h"; } return num2 + "h " + num3 + "m"; } if (num3 > 0) { if (num4 <= 0) { return num3 + "m"; } return num3 + "m " + num4 + "s"; } return num4 + "s"; } } internal static class Crafting { internal static SkillType Skill; internal static float MaxDiscount = 0.25f; internal static float XpPerCraft = 0.2f; internal static bool Enabled = true; private static Requirement[] lowered; private static int[] originalAmounts; private static Player Local => Player.m_localPlayer; [HarmonyPatch(typeof(Requirement), "GetAmount")] [HarmonyPostfix] private static void Discount(ref int __result) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) try { if (Enabled && __result > 1 && !((Object)(object)Local == (Object)null)) { float num = 1f - ((Character)Local).GetSkillFactor(Skill) * MaxDiscount; __result = Round((float)__result * num); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no desconto de criação: " + ex.Message)); } } private static int Discounted(int amount) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (amount <= 1 || (Object)(object)Local == (Object)null) { return amount; } float num = 1f - ((Character)Local).GetSkillFactor(Skill) * MaxDiscount; return Round((float)amount * num); } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyPrefix] private static void DiscountBuildCheck(Player __instance, Piece piece, RequirementMode mode) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) lowered = null; try { if (!Enabled || (Object)(object)__instance != (Object)(object)Local || (int)mode != 0) { return; } Requirement[] array = piece?.m_resources; if (array != null && array.Length != 0) { lowered = array; originalAmounts = new int[array.Length]; for (int i = 0; i < array.Length; i++) { originalAmounts[i] = array[i].m_amount; array[i].m_amount = Discounted(array[i].m_amount); } } } catch (Exception ex) { lowered = null; Debug.LogWarning((object)("[QOL KPX] falha no desconto da checagem de construção: " + ex.Message)); } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyFinalizer] private static void RestoreBuildCheck() { Requirement[] array = lowered; lowered = null; if (array != null) { for (int i = 0; i < array.Length && i < originalAmounts.Length; i++) { array[i].m_amount = originalAmounts[i]; } } } private static int Round(float value) { return Mathf.Max(1, Mathf.FloorToInt(value + 0.5f)); } private static void Gain() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (Enabled && !((Object)(object)Local == (Object)null)) { ((Character)Local).RaiseSkill(Skill, XpPerCraft); } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPostfix] private static void CraftXp(Player player) { try { if ((Object)(object)player == (Object)(object)Local) { Gain(); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no XP de criação: " + ex.Message)); } } [HarmonyPatch(typeof(Player), "GetBuildStamina")] [HarmonyPostfix] private static void HammerXp(Player __instance) { try { if ((Object)(object)__instance == (Object)(object)Local) { Gain(); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no XP de martelo: " + ex.Message)); } } } internal static class Equipment { internal static readonly ItemType[] Types; internal const int Width = 10; internal const int Row = 4; internal const int FoodCount = 3; private static readonly FieldRef<Inventory, int> HeightRef; private static readonly FieldRef<Inventory, int> WidthRef; private static readonly FieldRef<InventoryGrid, List<InventoryElement>> ElementsRef; private static readonly MethodInfo Changed; private static readonly object[] ChangedArgs; private static bool enabled; private static float basePanelWidth; private static Vector2 basePanelPos; private static bool logged; private static readonly Vector3[] PanelCorners; private static readonly Vector3[] CellCorners; internal static bool Active => enabled; internal static int FoodColumn(int i) { return Types.Length + i; } private static string IconKey(int k) { if (k >= Types.Length) { return "Food"; } return ((object)Unsafe.As<ItemType, ItemType>(ref Types[k])/*cast due to .constrained prefix*/).ToString(); } private static bool IsPlayerInv(Inventory inv) { if ((Object)(object)Player.m_localPlayer != (Object)null && inv != null) { return ((Humanoid)Player.m_localPlayer).GetInventory() == inv; } return false; } private static int SlotFor(ItemData item) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return Array.IndexOf(Types, item.m_shared.m_itemType); } internal static bool IsFood(ItemData item) { SharedData val = item?.m_shared; if (val != null) { if (!(val.m_food > 0f) && !(val.m_foodStamina > 0f)) { return val.m_foodEitr > 0f; } return true; } return false; } internal static void EnsureSize(Inventory inv, bool on) { enabled = on; if (inv != null) { int num = (on ? 10 : 8); int num2 = (on ? 5 : 4); if (num < WidthRef.Invoke(inv)) { VacateColumns(inv, num); } if (WidthRef.Invoke(inv) != num) { WidthRef.Invoke(inv) = num; } if (HeightRef.Invoke(inv) != num2) { HeightRef.Invoke(inv) = num2; } } } private static void VacateColumns(Inventory inv, int keep) { try { int num = 0; foreach (ItemData item in new List<ItemData>(inv.GetAllItems())) { if (item.m_gridPos.x >= keep && MoveToFreeSlot(inv, item, keep)) { num++; } } if (num > 0) { Changed?.Invoke(inv, ChangedArgs); Debug.Log((object)$"[QOL KPX] {num} item(ns) tirado(s) das colunas que seriam removidas"); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao esvaziar colunas: " + ex.Message)); } } [HarmonyPatch(typeof(Player), "Load", new Type[] { typeof(ZPackage) })] [HarmonyPrefix] private static void GrowBeforeLoad(Player __instance) { try { if ((Object)(object)__instance != (Object)null) { EnsureSize(((Humanoid)__instance).GetInventory(), enabled); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao preparar a mochila antes do load: " + ex.Message)); } } internal static void EnsurePanel(bool on, float gap) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_playerGrid == (Object)null) { return; } RectTransform player = instance.m_player; InventoryGrid playerGrid = instance.m_playerGrid; if ((Object)(object)player == (Object)null) { return; } if (basePanelWidth <= 0f) { basePanelWidth = player.sizeDelta.x; basePanelPos = player.anchoredPosition; } List<InventoryElement> list = ElementsRef.Invoke(playerGrid); Inventory inventory = playerGrid.GetInventory(); int num = ((inventory != null) ? inventory.GetWidth() : 0); if (!on || list == null || num == 0 || list.Count < 5 * num) { instance.SetInventorySize(4); player.sizeDelta = new Vector2(basePanelWidth, player.sizeDelta.y); player.anchoredPosition = basePanelPos; return; } float elementSpace = playerGrid.m_elementSpace; float num2 = (float)(num - 8) * elementSpace; instance.SetInventorySize(5); player.sizeDelta = new Vector2(basePanelWidth + num2, player.sizeDelta.y + gap); for (int i = 0; i < num; i++) { InventoryElement val = list[4 * num + i]; InventoryElement val2 = list[3 * num + i]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { continue; } Transform transform = ((Component)val).transform; RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null); Transform transform2 = ((Component)val2).transform; RectTransform val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null)) { val3.anchoredPosition = new Vector2(val4.anchoredPosition.x, val4.anchoredPosition.y - elementSpace - gap); if (i < Types.Length + 3) { SlotIcons.Apply((Transform)(object)val3, IconKey(i)); } } } if (num >= 10) { InventoryElement obj = list[9]; object obj2; if (obj == null) { obj2 = null; } else { Transform obj3 = ((Component)obj).transform.Find("binding"); obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null); } TMP_Text val5 = (TMP_Text)obj2; if ((Object)(object)val5 != (Object)null && val5.text != "0") { val5.text = "0"; } } InventoryElement obj4 = list[0]; Transform obj5 = ((obj4 != null) ? ((Component)obj4).transform : null); RectTransform val6 = (RectTransform)(object)((obj5 is RectTransform) ? obj5 : null); InventoryElement obj6 = list[num - 1]; Transform obj7 = ((obj6 != null) ? ((Component)obj6).transform : null); RectTransform val7 = (RectTransform)(object)((obj7 is RectTransform) ? obj7 : null); Transform obj8 = ((val6 != null) ? ((Transform)val6).parent : null); RectTransform val8 = (RectTransform)(object)((obj8 is RectTransform) ? obj8 : null); if ((Object)(object)val6 == (Object)null || (Object)(object)val7 == (Object)null || (Object)(object)val8 == (Object)null) { return; } player.GetWorldCorners(PanelCorners); float x = PanelCorners[0].x; float x2 = PanelCorners[2].x; val6.GetWorldCorners(CellCorners); float x3 = CellCorners[0].x; val7.GetWorldCorners(CellCorners); float x4 = CellCorners[2].x; float num3 = (x + x2) * 0.5f - (x3 + x4) * 0.5f; float x5 = ((Transform)val8).InverseTransformVector(new Vector3(num3, 0f, 0f)).x; if (Mathf.Abs(x5) > 0.5f) { foreach (InventoryElement item in list) { Transform obj9 = ((item != null) ? ((Component)item).transform : null); RectTransform val9 = (RectTransform)(object)((obj9 is RectTransform) ? obj9 : null); if ((Object)(object)val9 != (Object)null) { val9.anchoredPosition += new Vector2(x5, 0f); } } } if (!logged) { logged = true; Debug.Log((object)($"[QOL KPX-UI] painel=[{x:F1}..{x2:F1}] " + $"grid=[{x3:F1}..{x4:F1}] dx={x5:F1} " + $"tam={player.sizeDelta} space={elementSpace} pivoCelula={val6.pivot}")); } } [HarmonyPatch(typeof(Humanoid), "DropInvalidItems")] [HarmonyPrefix] private static void GrowBeforeValidation(Humanoid __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { Inventory inventory = __instance.GetInventory(); EnsureSize(inventory, enabled); Rescue(inventory); } } private static void Rescue(Inventory inv) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) try { if (inv == null) { return; } int width = inv.GetWidth(); int height = inv.GetHeight(); int num = 0; foreach (ItemData item in new List<ItemData>(inv.GetAllItems())) { Vector2i gridPos = item.m_gridPos; if ((gridPos.x < 0 || gridPos.y < 0 || gridPos.x >= width || gridPos.y >= height) && MoveToFreeSlot(inv, item)) { num++; } } if (num > 0) { Changed?.Invoke(inv, ChangedArgs); Debug.Log((object)$"[QOL KPX] {num} item(ns) fora da grade devolvido(s) à mochila"); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao resgatar itens fora da grade: " + ex.Message)); } } private static bool MoveToFreeSlot(Inventory inv, ItemData item, int maxWidth = int.MaxValue) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Min(inv.GetWidth(), maxWidth); for (int i = 0; i < 4; i++) { for (int j = 0; j < num; j++) { if (inv.GetItemAt(j, i) == null) { item.m_gridPos = new Vector2i(j, i); return true; } } } return false; } [HarmonyPatch(typeof(Inventory), "FindEmptySlot")] [HarmonyPostfix] private static void KeepRowFree(Inventory __instance, bool __0, ref Vector2i __result) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!IsPlayerInv(__instance) || (__result.x >= 0 && __result.y < 4)) { return; } __result = new Vector2i(-1, -1); int width = __instance.GetWidth(); for (int i = 0; i < 4; i++) { int num = (__0 ? i : (3 - i)); for (int j = 0; j < width; j++) { if (__instance.GetItemAt(j, num) == null) { __result = new Vector2i(j, num); return; } } } } [HarmonyPatch(typeof(Inventory), "GetEmptySlots")] [HarmonyPostfix] private static void FreeSlots(Inventory __instance, ref int __result) { if (!IsPlayerInv(__instance)) { return; } for (int i = 0; i < __instance.GetWidth(); i++) { if (__instance.GetItemAt(i, 4) == null) { __result--; } } } [HarmonyPatch(typeof(Inventory), "HaveEmptySlot")] [HarmonyPostfix] private static void HaveSlot(Inventory __instance, ref bool __result) { if (!__result || !IsPlayerInv(__instance)) { return; } __result = false; for (int i = 0; i < 4; i++) { if (__result) { break; } for (int j = 0; j < __instance.GetWidth(); j++) { if (__result) { break; } if (__instance.GetItemAt(j, i) == null) { __result = true; } } } } [HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[] { typeof(ItemData), typeof(int) })] [HarmonyPostfix] private static void CanAdd(Inventory __instance, ItemData __0, int __1, ref bool __result) { if (!__result || __0 == null || !IsPlayerInv(__instance)) { return; } int num = ((__1 > 0) ? __1 : __0.m_stack); int num2 = 0; int width = __instance.GetWidth(); for (int i = 0; i < 4; i++) { for (int j = 0; j < width; j++) { if (__instance.GetItemAt(j, i) == null) { num2++; } } } __result = __instance.FindFreeStackSpace(__0.m_shared.m_name, (float)__0.m_worldLevel) + num2 * __0.m_shared.m_maxStackSize >= num; } [HarmonyPatch(typeof(InventoryGrid), "DropItem")] [HarmonyPrefix] private static bool GuardDrop(InventoryGrid __instance, ItemData __1, Vector2i __3, ref bool __result) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!IsPlayerInv(__instance.GetInventory()) || __3.y != 4) { return true; } if ((__3.x < Types.Length) ? (SlotFor(__1) == __3.x) : IsFood(__1)) { return true; } __result = false; return false; } [HarmonyPatch(typeof(Humanoid), "EquipItem")] [HarmonyPostfix] private static void MoveToSlot(Humanoid __instance, ItemData __0, bool __result) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) try { if (!__result || !enabled || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } int num = SlotFor(__0); if (num >= 0) { Inventory inventory = __instance.GetInventory(); EnsureSize(inventory, enabled); if (inventory.GetItemAt(num, 4) == null) { __0.m_gridPos = new Vector2i(num, 4); Changed?.Invoke(inventory, ChangedArgs); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao mover para o slot: " + ex.Message)); } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] [HarmonyPostfix] private static void BackToBag(Humanoid __instance, ItemData __0) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) try { if (!enabled || __0 == null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || __0.m_gridPos.y != 4) { return; } Inventory inventory = __instance.GetInventory(); for (int i = 0; i < 4; i++) { for (int j = 0; j < inventory.GetWidth(); j++) { if (inventory.GetItemAt(j, i) == null) { __0.m_gridPos = new Vector2i(j, i); Changed?.Invoke(inventory, ChangedArgs); return; } } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao devolver a peça: " + ex.Message)); } } static Equipment() { ItemType[] array = new ItemType[7]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Types = (ItemType[])(object)array; HeightRef = AccessTools.FieldRefAccess<Inventory, int>("m_height"); WidthRef = AccessTools.FieldRefAccess<Inventory, int>("m_width"); ElementsRef = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements"); Changed = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null); ChangedArgs = new object[2] { false, false }; enabled = true; PanelCorners = (Vector3[])(object)new Vector3[4]; CellCorners = (Vector3[])(object)new Vector3[4]; } } internal static class Exploration { internal static int NewPixels; [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(int), typeof(int) })] [HarmonyPostfix] private static void Count(bool __result) { if (__result) { NewPixels++; } } } internal static class ExtraSlots { internal static bool Enabled = true; private static Player Local => Player.m_localPlayer; internal static bool CanTakeInput() { if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return false; } if (Console.IsVisible() || TextInput.IsVisible()) { return false; } if (InventoryGui.IsVisible() || Menu.IsVisible()) { return false; } return true; } internal static void Tick() { try { if (Enabled && !((Object)(object)Local == (Object)null) && CanTakeInput()) { if (Input.GetKeyDown((KeyCode)57)) { Local.UseHotbarItem(9); } else if (Input.GetKeyDown((KeyCode)48)) { Local.UseHotbarItem(10); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no atalho de poção: " + ex.Message)); } } } internal static class Fires { internal static bool Enabled = true; [HarmonyPatch(typeof(Fireplace), "UpdateFireplace")] [HarmonyPrefix] private static void NeverRunOut(Fireplace __instance) { try { if (Enabled && (Object)(object)__instance != (Object)null) { __instance.m_infiniteFuel = true; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no combustível infinito: " + ex.Message)); } } } internal static class FoodDecay { internal static bool Enabled = true; private static readonly FieldRef<Player, List<Food>> FoodsRef = AccessTools.FieldRefAccess<Player, List<Food>>("m_foods"); private static readonly FieldRef<Player, float> BaseHpRef = AccessTools.FieldRefAccess<Player, float>("m_baseHP"); private static readonly FieldRef<Player, float> BaseStaminaRef = AccessTools.FieldRefAccess<Player, float>("m_baseStamina"); private static readonly MethodInfo SetMaxEitrMethod = AccessTools.Method(typeof(Player), "SetMaxEitr", new Type[2] { typeof(float), typeof(bool) }, (Type[])null); [HarmonyPatch(typeof(Hud), "UpdateFood")] [HarmonyPostfix] private static void SolidFoodIcons(Hud __instance) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) try { if (!Enabled || (Object)(object)__instance == (Object)null || __instance.m_foodIcons == null) { return; } Image[] foodIcons = __instance.m_foodIcons; foreach (Image val in foodIcons) { if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf) { ((Graphic)val).color = Color.white; } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao fixar o ícone da comida: " + ex.Message)); } } [HarmonyPatch(typeof(Player), "UpdateFood")] [HarmonyPrefix] private static void SaveCurrent(Player __instance, out float[] __state) { __state = ((!((Object)(object)__instance == (Object)(object)Player.m_localPlayer)) ? null : new float[2] { ((Character)__instance).GetHealth(), __instance.GetStamina() }); } [HarmonyPatch(typeof(Player), "UpdateFood")] [HarmonyPostfix] private static void KeepFull(Player __instance, float[] __state) { try { if (!Enabled || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } List<Food> list = FoodsRef.Invoke(__instance); if (list == null || list.Count == 0) { return; } float num = BaseHpRef.Invoke(__instance); float num2 = BaseStaminaRef.Invoke(__instance); float num3 = 0f; foreach (Food item in list) { SharedData shared = item.m_item.m_shared; item.m_health = shared.m_food; item.m_stamina = shared.m_foodStamina; item.m_eitr = shared.m_foodEitr; num += item.m_health; num2 += item.m_stamina; num3 += item.m_eitr; } __instance.SetMaxHealth(num, false); __instance.SetMaxStamina(num2, false); SetMaxEitrMethod?.Invoke(__instance, new object[2] { num3, false }); if (__state != null) { float num4 = Mathf.Min(__state[0], ((Character)__instance).GetMaxHealth()); if (((Character)__instance).GetHealth() < num4) { ((Character)__instance).SetHealth(num4); } float num5 = Mathf.Min(__state[1], ((Character)__instance).GetMaxStamina()) - __instance.GetStamina(); if (num5 > 0f) { ((Character)__instance).AddStamina(num5); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no efeito da comida: " + ex.Message)); } } } internal static class FoodSlots { internal static bool Enabled = true; private static readonly FieldRef<Player, List<Food>> FoodsRef = AccessTools.FieldRefAccess<Player, List<Food>>("m_foods"); private static float timer; private static bool IsActive(List<Food> foods, ItemData item) { foreach (Food food in foods) { if (food.m_item.m_shared.m_name == item.m_shared.m_name) { return true; } } return false; } internal static void Tick(float dt) { try { Player localPlayer = Player.m_localPlayer; if (!Enabled || (Object)(object)localPlayer == (Object)null) { return; } timer += dt; if (timer < 0.5f) { return; } timer = 0f; Inventory inventory = ((Humanoid)localPlayer).GetInventory(); List<Food> list = FoodsRef.Invoke(localPlayer); if (inventory == null || list == null) { return; } for (int i = 0; i < 3; i++) { ItemData itemAt = inventory.GetItemAt(Equipment.FoodColumn(i), 4); if (itemAt != null && Equipment.IsFood(itemAt) && !IsActive(list, itemAt) && localPlayer.CanEat(itemAt, false)) { ((Humanoid)localPlayer).ConsumeItem(inventory, itemAt, false); break; } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao comer automaticamente: " + ex.Message)); } } } internal static class Grave { internal static bool Enabled = true; [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPrefix] private static void Enlarge(Container __instance) { try { if (Enabled && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<TombStone>() == (Object)null)) { if (__instance.m_width < 10) { __instance.m_width = 10; } if (__instance.m_height < 5) { __instance.m_height = 5; } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao dimensionar a lápide: " + ex.Message)); } } } internal static class Hotbar { [HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")] [HarmonyPostfix] private static void TenthKeyIsZero(HotkeyBar __instance) { try { if (!Equipment.Active || (Object)(object)__instance == (Object)null) { return; } Transform transform = ((Component)__instance).transform; if (transform.childCount >= 10) { Transform obj = transform.GetChild(9).Find("binding"); TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null); if ((Object)(object)val != (Object)null && val.text == "10") { val.text = "0"; } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no número do atalho: " + ex.Message)); } } } internal static class Signs { internal static bool Enabled = true; [HarmonyPatch(typeof(Sign), "GetHoverText")] [HarmonyPostfix] private static void ShowShift(ref string __result) { try { if (Enabled && !string.IsNullOrEmpty(__result) && __result.Contains("$KEY_Use")) { __result = __result.Replace("$KEY_Use", "Shift + $KEY_Use"); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no texto da placa: " + ex.Message)); } } [HarmonyPatch(typeof(Sign), "Interact")] [HarmonyPrefix] private static bool RequireShift(bool __2, ref bool __result) { try { if (!Enabled || __2) { return true; } __result = false; return false; } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no atalho da placa: " + ex.Message)); return true; } } } internal static class HammerHover { internal static bool Enabled = true; private static bool inHoverCheck; [HarmonyPatch(typeof(Player), "UpdateHover")] [HarmonyPrefix] private static void OpenWindow() { inHoverCheck = Enabled; } [HarmonyPatch(typeof(Player), "UpdateHover")] [HarmonyPostfix] private static void CloseWindow() { inHoverCheck = false; } [HarmonyPatch(typeof(Player), "InPlaceMode")] [HarmonyPostfix] private static void PretendNotBuilding(ref bool __result) { if (inHoverCheck) { __result = false; } } } internal static class Intro { internal static bool Enabled = true; [HarmonyPatch(typeof(CinematicsManager), "Awake")] [HarmonyPostfix] private static void SkipStartupVideo(CinematicsManager __instance) { try { if (Enabled && (Object)(object)__instance != (Object)null) { __instance.m_introOnStartup = false; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao pular o vídeo de abertura: " + ex.Message)); } } } internal static class KeepAchievements { internal static bool Enabled = true; private static bool restore; [HarmonyPatch(typeof(Achievements), "IsCheatedAtAll")] [HarmonyPrefix] private static void HideModdedFlag() { restore = false; try { if (Enabled && Game.isModded) { Game.isModded = false; restore = true; } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao manter achievements: " + ex.Message)); } } [HarmonyPatch(typeof(Achievements), "IsCheatedAtAll")] [HarmonyFinalizer] private static void RestoreModdedFlag() { if (restore) { Game.isModded = true; } restore = false; } } internal static class MapShare { internal static bool Enabled = true; private const string RpcCells = "QolKpx_MapCells"; private const string RpcFull = "QolKpx_MapFull"; private const string RpcAsk = "QolKpx_MapAsk"; private const float SendInterval = 2f; private const float JoinDelay = 5f; private const float SaveInterval = 30f; private static readonly FieldRef<Minimap, BitArray> ExploredRef = AccessTools.FieldRefAccess<Minimap, BitArray>("m_explored"); private static readonly FieldRef<Minimap, BitArray> OthersRef = AccessTools.FieldRefAccess<Minimap, BitArray>("m_exploredOthers"); private static readonly FieldRef<Minimap, Texture2D> FogRef = AccessTools.FieldRefAccess<Minimap, Texture2D>("m_fogTexture"); private static readonly Func<Minimap, int, int, bool> ExploreOthers = AccessTools.MethodDelegate<Func<Minimap, int, int, bool>>(AccessTools.Method(typeof(Minimap), "ExploreOthers", new Type[2] { typeof(int), typeof(int) }, (Type[])null), (object)null, true); private static BitArray world; private static int worldSize; private static bool worldDirty; private static float saveTimer; private static string tag; private static readonly List<int> pending = new List<int>(); private static bool live; private static float sendTimer; private static float joinTimer; private static ZRoutedRpc registeredOn; private static Player announcedFor; private static string WorldFile => Path.Combine(Paths.ConfigPath, "qol.kpx." + tag + ".map"); private static bool OnServer { get { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } internal static string WorldTag() { ZNet instance = ZNet.instance; long num = (((Object)(object)instance != (Object)null) ? instance.GetWorldUID() : 0); if (num == 0L) { return "unknown"; } return num.ToString(); } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(Vector3), typeof(float) })] [HarmonyPrefix] private static void OpenWindow() { live = Enabled; } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(Vector3), typeof(float) })] [HarmonyFinalizer] private static void CloseWindow() { live = false; } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(int), typeof(int) })] [HarmonyPostfix] private static void Record(Minimap __instance, int __0, int __1, bool __result) { if (live && __result) { pending.Add(__1 * __instance.m_textureSize + __0); } } internal static void Tick(float dt) { //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Expected O, but got Unknown try { ZRoutedRpc instance = ZRoutedRpc.instance; if (!Enabled || instance == null) { return; } if (registeredOn != instance) { instance.Register<ZPackage>("QolKpx_MapCells", (Action<long, ZPackage>)OnCells); instance.Register<ZPackage>("QolKpx_MapFull", (Action<long, ZPackage>)OnFull); instance.Register("QolKpx_MapAsk", (Action<long>)OnAsk); registeredOn = instance; PortalPins.Register(instance); } string text = WorldTag(); if (tag != text) { if (tag != null && worldDirty && world != null) { SaveWorld(); } tag = text; world = null; worldSize = 0; worldDirty = false; live = false; pending.Clear(); announcedFor = null; joinTimer = 0f; if (OnServer) { LoadWorld(); } PortalPins.NewWorld(text); } if (OnServer) { saveTimer += dt; if (saveTimer >= 30f) { if (worldDirty) { SaveWorld(); } PortalPins.Tick(); } } Minimap instance2 = Minimap.instance; if ((Object)(object)instance2 == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { announcedFor = null; joinTimer = 0f; pending.Clear(); return; } if ((Object)(object)announcedFor != (Object)(object)Player.m_localPlayer) { joinTimer += dt; if (joinTimer < 5f) { return; } announcedFor = Player.m_localPlayer; joinTimer = 0f; instance.InvokeRoutedRPC(0L, "QolKpx_MapFull", new object[1] { PackFull(instance2) }); instance.InvokeRoutedRPC(0L, "QolKpx_MapAsk", Array.Empty<object>()); } sendTimer += dt; if (sendTimer < 2f || pending.Count == 0) { return; } sendTimer = 0f; ZPackage val = new ZPackage(); val.Write(instance2.m_textureSize); val.Write(pending.Count); foreach (int item in pending) { val.Write(item); } if (OnServer) { MergeWorld(instance2.m_textureSize, pending); } pending.Clear(); instance.InvokeRoutedRPC(0L, "QolKpx_MapCells", new object[1] { val }); } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao compartilhar o mapa: " + ex.Message)); } } private static void OnAsk(long sender) { try { if (!Enabled || ZRoutedRpc.instance == null) { return; } if (OnServer) { if (world != null) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "QolKpx_MapFull", new object[1] { PackRuns(world, worldSize) }); } PortalPins.SendAllTo(sender); } else if ((Object)(object)Minimap.instance != (Object)null) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "QolKpx_MapFull", new object[1] { PackFull(Minimap.instance) }); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao responder o mapa: " + ex.Message)); } } private static void OnCells(long sender, ZPackage pkg) { try { if (Enabled) { int num = pkg.ReadInt(); int num2 = pkg.ReadInt(); List<int> list = new List<int>(num2); for (int i = 0; i < num2; i++) { list.Add(pkg.ReadInt()); } if (OnServer) { MergeWorld(num, list); } Minimap instance = Minimap.instance; if ((Object)(object)instance != (Object)null && num == instance.m_textureSize) { Apply(instance, list); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao receber células do mapa: " + ex.Message)); } } private static void OnFull(long sender, ZPackage pkg) { try { if (Enabled) { int num = pkg.ReadInt(); List<int> cells = new List<int>(UnpackRuns(pkg)); if (OnServer) { MergeWorld(num, cells); } Minimap instance = Minimap.instance; if ((Object)(object)instance != (Object)null && num == instance.m_textureSize) { Apply(instance, cells); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao receber o mapa: " + ex.Message)); } } private static void Apply(Minimap map, IEnumerable<int> cells) { BitArray bitArray = ExploredRef.Invoke(map); BitArray bitArray2 = OthersRef.Invoke(map); if (bitArray == null || bitArray2 == null) { return; } int textureSize = map.m_textureSize; bool flag = false; foreach (int cell in cells) { if (cell >= 0 && cell < bitArray.Length && !bitArray[cell] && !bitArray2[cell] && ExploreOthers(map, cell % textureSize, cell / textureSize)) { flag = true; } } if (flag) { FogRef.Invoke(map).Apply(); } } private static ZPackage PackFull(Minimap map) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown BitArray bitArray = ExploredRef.Invoke(map); BitArray bitArray2 = OthersRef.Invoke(map); List<int> list = new List<int>(); bool flag = false; int num = 0; for (int i = 0; i < bitArray.Length; i++) { bool flag2 = bitArray[i] || bitArray2[i]; if (flag2 == flag) { num++; continue; } list.Add(num); flag = flag2; num = 1; } list.Add(num); ZPackage val = new ZPackage(); val.Write(map.m_textureSize); val.Write(list.Count); foreach (int item in list) { val.Write(item); } return val; } private static ZPackage PackRuns(BitArray bits, int size) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown List<int> list = new List<int>(); bool flag = false; int num = 0; for (int i = 0; i < bits.Length; i++) { if (bits[i] == flag) { num++; continue; } list.Add(num); flag = bits[i]; num = 1; } list.Add(num); ZPackage val = new ZPackage(); val.Write(size); val.Write(list.Count); foreach (int item in list) { val.Write(item); } return val; } private static void MergeWorld(int size, IEnumerable<int> cells) { if (size <= 0 || size > 8192) { return; } if (world == null) { world = new BitArray(size * size); worldSize = size; } if (size != worldSize) { return; } foreach (int cell in cells) { if (cell >= 0 && cell < world.Length && !world[cell]) { world[cell] = true; worldDirty = true; } } } private static void LoadWorld() { try { if (File.Exists(WorldFile)) { byte[] array = File.ReadAllBytes(WorldFile); if (array.Length >= 4) { worldSize = BitConverter.ToInt32(array, 0); byte[] array2 = new byte[array.Length - 4]; Array.Copy(array, 4, array2, 0, array2.Length); world = new BitArray(array2) { Length = worldSize * worldSize }; Debug.Log((object)$"[QOL KPX] mapa do mundo {tag} carregado ({worldSize}x{worldSize})"); } } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao ler o mapa do mundo: " + ex.Message)); } } private static void SaveWorld() { try { saveTimer = 0f; worldDirty = false; if (world != null) { byte[] array = new byte[(world.Length + 7) / 8]; world.CopyTo(array, 0); byte[] array2 = new byte[array.Length + 4]; Buffer.BlockCopy(BitConverter.GetBytes(worldSize), 0, array2, 0, 4); Buffer.BlockCopy(array, 0, array2, 4, array.Length); File.WriteAllBytes(WorldFile, array2); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao gravar o mapa do mundo: " + ex.Message)); } } private static IEnumerable<int> UnpackRuns(ZPackage pkg) { int count = pkg.ReadInt(); int pos = 0; for (int k = 0; k < count; k++) { int run = pkg.ReadInt(); if (k % 2 == 1) { for (int j = 0; j < run; j++) { yield return pos + j; } } pos += run; } } } internal static class Mining { internal static SkillType Skill; internal static float MaxDamageBonus = 1f; internal static float TierWeight = 0.25f; internal static float XpPerHit = 1f; internal static bool Enabled = true; private static Player Local => Player.m_localPlayer; internal static float OneShotChance(float factor) { return factor * 0.1f + factor * factor * factor * 0.05f; } private static void Boost(HitData hit, int minToolTier, bool supportsRadius) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || hit == null || (Object)(object)Local == (Object)null || (Object)(object)hit.GetAttacker() != (Object)(object)Local || hit.m_damage.m_pickaxe <= 0f || !hit.CheckToolTier(minToolTier, false)) { return; } float skillFactor = ((Character)Local).GetSkillFactor(Skill); hit.m_damage.m_pickaxe *= 1f + skillFactor * MaxDamageBonus * (1f + (float)hit.m_toolTier * TierWeight); if (Random.value < OneShotChance(skillFactor)) { hit.m_damage.m_pickaxe *= 1000f; if (supportsRadius) { hit.m_radius = Mathf.Max(hit.m_radius, 8f); } ((Character)Local).Message((MessageType)1, "Vein shattered!", 0, (Sprite)null, false); } ((Character)Local).RaiseSkill(Skill, XpPerHit); Strength.Effort(); } [HarmonyPatch(typeof(MineRock5), "Damage")] [HarmonyPrefix] private static void Rock5(MineRock5 __instance, HitData __0) { Safe(delegate { Boost(__0, __instance.m_minToolTier, supportsRadius: true); }); } [HarmonyPatch(typeof(MineRock), "Damage")] [HarmonyPrefix] private static void Rock(MineRock __instance, HitData __0) { Safe(delegate { Boost(__0, __instance.m_minToolTier, supportsRadius: false); }); } private static void Safe(Action a) { try { a(); } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no bônus de mineração: " + ex.Message)); } } } internal static class PingText { internal static string Pending; internal static bool Beam = true; internal static float BeamHeight = 500f; internal static float BeamSeconds = 0f; internal static float BeamWidth = 0.3f; private static bool warned; [HarmonyPatch(typeof(Chat), "AddInworldText")] [HarmonyPostfix] private static void OnPing(Chat __instance, object[] __args) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) try { if (__args == null || __args.Length < 4 || !(__args[3] is Type val) || (int)val != 3) { return; } if (!string.IsNullOrEmpty(Pending)) { List<WorldTextInstance> worldTexts = __instance.WorldTexts; if (worldTexts != null && worldTexts.Count > 0) { WorldTextInstance val2 = worldTexts[worldTexts.Count - 1]; val2.m_text = Pending; if ((Object)(object)val2.m_textMeshField != (Object)null) { ((TMP_Text)val2.m_textMeshField).text = val2.m_name + ": " + Pending; } } Pending = null; } if (__args[2] is Vector3 position) { ShowBeam(position); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no texto do ping: " + ex.Message)); } } internal static void ShowBeam(Vector3 position) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) try { if (Beam && !((Object)(object)Plugin.Host == (Object)null)) { Plugin.Host.StartCoroutine(BeamRoutine(position)); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha no feixe do ping: " + ex.Message)); } } private static IEnumerator BeamRoutine(Vector3 position) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("UI/Default") ?? Shader.Find("Particles/Standard Unlit"); if ((Object)(object)val == (Object)null) { if (!warned) { warned = true; Debug.LogWarning((object)"[QOL KPX] nenhum shader para o feixe do ping"); } yield break; } float life = ((BeamSeconds > 0f) ? BeamSeconds : (((Object)(object)Chat.instance != (Object)null) ? Chat.instance.m_worldTextTTL : 5f)); GameObject go = new GameObject("qolkpx_ping_beam"); go.transform.position = position; LineRenderer line = go.AddComponent<LineRenderer>(); line.useWorldSpace = true; line.positionCount = 2; line.SetPosition(0, position); line.SetPosition(1, position + Vector3.up * BeamHeight); line.startWidth = BeamWidth; line.endWidth = BeamWidth; ((Renderer)line).material = new Material(val); ((Renderer)line).material.color = Color.white; line.startColor = new Color(1f, 1f, 1f, 0.9f); line.endColor = new Color(1f, 1f, 1f, 0.1f); float total = life; while (life > 0f && (Object)(object)go != (Object)null) { life -= Time.deltaTime; if ((Object)(object)line != (Object)null && (Object)(object)((Renderer)line).material != (Object)null) { ((Renderer)line).material.color = new Color(1f, 1f, 1f, Mathf.Clamp01(life / total)); } yield return null; } if ((Object)(object)go != (Object)null) { Object.Destroy((Object)(object)go); } } } [BepInPlugin("qol.kpx", "QOL KPX", "2.3.0")] public class Plugin : BaseUnityPlugin { private static class Repair { internal static readonly MethodInfo RepairOne = AccessTools.Method(typeof(InventoryGui), "RepairOneItem", (Type[])null, (Type[])null); internal static readonly MethodInfo HaveRepairable = AccessTools.Method(typeof(InventoryGui), "HaveRepairableItems", (Type[])null, (Type[])null); [HarmonyPatch(typeof(InventoryGui), "UpdateRepair")] [HarmonyPostfix] private static void RepairAll(InventoryGui __instance) { if (!autoRepair.Value) { return; } for (int i = 0; i < 64; i++) { if (!(bool)HaveRepairable.Invoke(__instance, null)) { break; } RepairOne.Invoke(__instance, null); } } } private static class Float { private static int added; [HarmonyPatch(typeof(ObjectDB), "Awake")] [HarmonyPostfix] [HarmonyPriority(200)] private static void OnDbAwake(ObjectDB __instance) { ApplyAll(__instance); } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] [HarmonyPostfix] [HarmonyPriority(200)] private static void OnDbCopied(ObjectDB __instance) { ApplyAll(__instance); } private static void ApplyAll(ObjectDB db) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) try { if (!floatItems.Value || db?.m_items == null) { return; } added = 0; foreach (GameObject item in db.m_items) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item.GetComponent<Floating>() != (Object)null)) { Rigidbody component = item.GetComponent<Rigidbody>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)item.GetComponentInChildren<Collider>() == (Object)null)) { item.AddComponent<Floating>().m_waterLevelOffset = 0.7f; component.centerOfMass = Normalize(component.centerOfMass); added++; } } } if (added > 0) { Debug.Log((object)$"[QOL KPX] {added} itens passam a boiar"); } } catch (Exception ex) { Debug.LogWarning((object)("[QOL KPX] falha ao fazer os itens boiarem: " + ex.Message)); } } private static Vector3 Normalize(Vector3 mass) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (mass.x < -1f) { mass.x = 0f; } if (mass.y < -1f) { mass.y = 0f; } if (mass.z < -1f) { mass.z = 0f; } return mass; } } private const SkillType Skill = (SkillType)715293104; private const SkillType ExploreSkill = (SkillType)715293105; private const SkillType MiningSkill = (SkillType)715293106; private const SkillType VitalitySkill = (SkillType)715293107; private const SkillType WoodSkill = (SkillType)715293108; private const SkillType CraftSkill = (SkillType)715293109; private const SkillType StrengthSkill = (SkillType)715293110; private static ConfigEntry<float> xpRate; private static ConfigEntry<float> maxSpeed; private static ConfigEntry<float> maxJump; private static ConfigEntry<float> maxFall; private static ConfigEntry<bool> autoRepair; private static ConfigEntry<bool> clockEnabled; private static ConfigEntry<bool> floatItems; private static ConfigEntry<bool> equipSlots; private static ConfigEntry<bool> exploreEnabled; private static ConfigEntry<bool> miningEnabled; private static ConfigEntry<int> portalPinIcon; private static ConfigEntry<string> charcoalWeights; private static ConfigEntry<int> kilnCapacity; private static ConfigEntry<float> shipPerPlayer; private static ConfigEntry<float> furnaceEfficiency; private static ConfigEntry<float> bronzeRatio; private static ConfigEntry<int> smelterWidth; private static ConfigEntry<int> smelterRows; private static ConfigEntry<int> capeLevel; private static ConfigEntry<int> capeResin; private static ConfigEntry<float> clockOffset; private static ConfigEntry<float> clockSize; private static ConfigEntry<float> maxRadius; private static ConfigEntry<float> xpPerPixel; private static ConfigEntry<float> foodGap; private static ConfigEntry<float> slotIconAlpha; private static ConfigEntry<float> miningBonus; private static ConfigEntry<float> miningTierWeight; private static ConfigEntry<float> miningXp; private static ConfigEntry<bool> vitalityEnabled; private static ConfigEntry<bool> buildNoStamina; private static ConfigEntry<bool> buildNoWear; private static ConfigEntry<bool> woodEnabled; private static ConfigEntry<bool> buildNoMoveStamina; private static ConfigEntry<float> woodBonus; private static ConfigEntry<float> woodTierWeight; private static ConfigEntry<float> woodXp; private static ConfigEntry<bool> archeryEnabled; private static ConfigEntry<bool> craftEnabled; private static ConfigEntry<bool> strengthEnabled; private static ConfigEntry<bool> foodNoDecay; private static ConfigEntry<bool> foodAutoEat; private static ConfigEntry<bool> restedEnabled; private static ConfigEntry<bool> firesEnabled; private static ConfigEntry<bool> extraSlots; private static ConfigEntry<bool> teleportAll; private static ConfigEntry<bool> introSkip; private static ConfigEntry<bool> shipEnabled; private static ConfigEntry<bool> furnaceEnabled; private static ConfigEntry<bool> signShift; private static ConfigEntry<bool> hoverBuildTool; private static ConfigEntry<bool> swimKeepGear; private static ConfigEntry<bool> slotIcons; private static ConfigEntry<bool> keepAchievements; private static ConfigEntry<bool> pingEnabled; private static ConfigEntry<bool> mapShare; private static ConfigEntry<bool> serverConfig; private static ConfigEntry<bool> portalPins; private static ConfigEntry<bool> charcoal; private static ConfigEntry<bool> smelterBox; private static ConfigEntry<bool> trollCape; private static ConfigEntry<bool> bronze; private static ConfigEntry<KeyboardShortcut> pingKey; private static ConfigEntry<KeyboardShortcut> pingForceKey; private static ConfigEntry<bool> pingShowName; private static ConfigEntry<bool> pingBeam; private static ConfigEntry<bool> freeMovement; private static ConfigEntry<float> terrainLimit; private static ConfigEntry<float> buildSupport; private static ConfigEntry<float> stubHealth; private static ConfigEntry<bool> stubsEnabled; private static ConfigEntry<bool> quickStack; private static ConfigEntry<bool> quickStackMerge; private static ConfigEntry<bool> showStock; private static ConfigEntry<bool> cookTime; private static ConfigEntry<bool> tarEnabled; private static ConfigEntry<bool> buildEnabled; private static ConfigEntry<bool> chestCrafting; private static ConfigEntry<float> pingBeamHeight; private static ConfigEntry<float> pingBeamSeconds; private static ConfigEntry<float> pingPinRange; private static ConfigEntry<float> pingDistance; private static ConfigEntry<float> restedMinutes; private static ConfigEntry<float> strengthBonus; private static ConfigEntry<float> strengthXpEffort; private static ConfigEntry<float> strengthXpLoad; private static ConfigEntry<float> strengthLoad; private static ConfigEntry<float> craftDiscount; private static ConfigEntry<float> craftXp; private static ConfigEntry<float> archeryStamina; private static ConfigEntry<float> archeryAccuracy; private static ConfigEntry<float> vitalityBonus; private static ConfigEntry<float> vitalityXp; private static ConfigEntry<float> vitalityStamina; internal static ConfigFile Cfg; internal static MonoBehaviour Host; private Player player; private float walk; private float jog; private float run; private float jump; private float baseRadius; private TMP_Text clock; internal static Action ApplyConfig; private void ApplyConfigValues() { ExtraSlots.Enabled = extraSlots.Value; SlotIcons.Enabled = slotIcons.Value; SlotIcons.Alpha = slotIconAlpha.Value; Mining.Enabled = miningEnabled.Value; Mining.MaxDamageBonus = miningBonus.Value; Mining.TierWeight = miningTierWeight.Value; Mining.XpPerHit = miningXp.Value; Vitality.Enabled = vitalityEnabled.Value; Vitality.MaxHealthBonus = vitalityBonus.Value; Vitality.MaxStaminaBonus = vitalityStamina.Value; Vitality.XpPerHealth = vitalityXp.Value; Strength.Enabled = strengthEnabled.Value; Strength.MaxBonus = strengthBonus.Value; Strength.XpPerEffort = strengthXpEffort.Value; Strength.XpPerSecond = strengthXpLoad.Value; Strength.LoadThreshold = strengthLoad.Value; Crafting.Enabled = craftEnabled.Value; Crafting.MaxDiscount = craftDiscount.Value; Crafting.XpPerCraft = craftXp.Value; Rested.Enabled = restedEnabled.Value; Rested.MinutesPerLevel = restedMinutes.Value; Fires.Enabled = firesEnabled.Value; Teleport.Enabled = teleportAll.Value; Intro.Enabled = introSkip.Value; Signs.Enabled = signShift.Value; HammerHover.Enabled = hoverBuildTool.Value; Swim.Enabled = swimKeepGear.Value; KeepAchievements.Enabled = keepAchievements.Value; QuickPing.Enabled = pingEnabled.Value; QuickPing.MaxDistance = pingDistance.Value; QuickPing.ShowName = pingShowName.Value; Building.Enabled = buildEnabled.Value; Building.Multiplier = buildSupport.Value; ChestCrafting.Enabled = chestCrafting.Value; Terrain.Limit = terrainLimit.Value; Stubs.Enabled = stubsEnabled.Value; Tar.Enabled = tarEnabled.Value; Stubs.Health = stubHealth.Value; QuickStack.Enabled = quickStack.Value; QuickStack.Merge = quickStackMerge.Value; Requirements.Enabled = showStock.Value; CookTime.Enabled = cookTime.Value; Stamina.FreeMovement = freeMovement.Value; PingText.Beam = pingBeam.Value; PingText.BeamHeight = pingBeamHeight.Value; PingText.BeamSeconds = pingBeamSeconds.Value; QuickPing.PinRange = pingPinRange.Value; MapShare.Enabled = mapShare.Value; Bronze.Enabled = bronze.Value; Bronze.Ratio = bronzeRatio.Value; TrollCape.Enabled = trollCape.Value; TrollCape.Level = capeLevel.Value; TrollCape.ResinCost = capeResin.Value; SmelterBox.Enabled = smelterBox.Value; SmelterBox.Width = smelterWid