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 ConfigurableHaldorSellList v1.2.1
plugins\MG-HaldorSellPatch.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("MG-HaldorSellPatch")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MG-HaldorSellPatch")] [assembly: AssemblyTitle("MG-HaldorSellPatch")] [assembly: AssemblyVersion("1.0.0.0")] [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 MG.HaldorSellPatch { [BepInPlugin("mg.haldorsellpatch", "MG Haldor Sell Patch", "1.2.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class HaldorSellPatchPlugin : BaseUnityPlugin { private readonly struct ItemConfig { public string PrefabName { get; } public int SellPrice { get; } public int BuyQuantity { get; } public int BuyPrice { get; } public bool BuyOnly { get; } public bool HasBuy => BuyQuantity > 0; public ItemConfig(string prefabName, int sellPrice, int buyQuantity = 0, int buyPrice = 0, bool buyOnly = false) { PrefabName = prefabName; SellPrice = sellPrice; BuyQuantity = buyQuantity; BuyPrice = ((buyPrice > 0) ? buyPrice : (sellPrice * buyQuantity * 2)); BuyOnly = buyOnly; } } private sealed class BuyConfig { public ConfigEntry<int> Quantity; public int FixedQuantity; public ConfigEntry<int> Price; } private readonly struct BuyEntry { public string PrefabName { get; } public int Quantity { get; } public int Price { get; } public bool Remove { get; } public BuyEntry(string prefabName, int quantity, int price) { PrefabName = prefabName; Quantity = quantity; Price = price; Remove = false; } private BuyEntry(string prefabName) { PrefabName = prefabName; Quantity = 0; Price = 0; Remove = true; } public static BuyEntry Disabled(string prefabName) { return new BuyEntry(prefabName); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDBAwakePatch { private static void Postfix(ObjectDB __instance) { ApplySellValues(__instance); } } [HarmonyPatch(typeof(StoreGui), "Show")] private static class StoreGuiShowPatch { private static void Prefix(Trader trader) { ApplyBuyItems(trader); } } public const string ModGuid = "mg.haldorsellpatch"; public const string ModName = "MG Haldor Sell Patch"; public const string ModVersion = "1.2.1"; private const int TrophyItemType = 13; private static readonly List<ItemConfig> Items = new List<ItemConfig>(); private static readonly string[] RemovedOriginalBuyItems = new string[2] { "Ashwood", "CharredWood" }; private static readonly Dictionary<string, ConfigEntry<int>> SellPrices = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, BuyConfig> BuyItems = new Dictionary<string, BuyConfig>(StringComparer.OrdinalIgnoreCase); private static ConfigEntry<bool> EnableExtraBuyItemsConfig; private static ConfigEntry<string> CustomBuyItemsConfig; private static ConfigEntry<bool> EnableExtraSellItemsConfig; private static ConfigEntry<string> CustomSellItemsConfig; private static ConfigEntry<bool> EnableTrophySellingConfig; private static ConfigEntry<int> DefaultTrophyPriceConfig; private static ConfigEntry<string> TrophyPriceOverridesConfig; private static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; BuildItemList(); BindConfig(); PatchHaldorExpansionSellLists(); harmony = new Harmony("mg.haldorsellpatch"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded configurable Haldor buy/sell list."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private static void BuildItemList() { Items.Clear(); Add("Stone", 1, 50); Add("Wood", 1, 50); Add("Resin", 1, 50); Add("Feathers", 1, 50); Add("BoneFragments", 1, 50); Add("LeatherScraps", 1, 50); Add("DeerHide", 1, 50); Add("RoundLog", 2, 50); Add("Grausten", 2, 50); Add("GreydwarfEye", 2, 50); Add("Needle", 2, 50); Add("Flint", 2, 30); Add("Coal", 2, 50); Add("TrollHide", 2, 20); Add("WolfPelt", 2, 50); Add("FreezeGland", 2, 50); Add("FineWood", 3, 50); Add("Guck", 3, 50); Add("LoxPelt", 3, 50); Add("ElderBark", 4, 50); Add("BlackMarble", 4, 50); Add("Copper", 4, 30); Add("JuteRed", 4, 50); Add("JuteBlue", 4, 50); Add("YggdrasilWood", 4, 50); Add("Chitin", 4, 50); Add("Root", 4, 50); Add("WolfFang", 4, 50); Add("Carapace", 4, 50); Add("BloodClot", 4, 50); Add("Obsidian", 5, 50); Add("Tin", 5, 30); Add("Tar", 5, 50); Add("Blackwood", 5, 50); Add("Crystal", 5, 50); Add("Chain", 5, 50); Add("Mandible", 5, 50); Add("Bilebag", 5, 50); Add("Bronze", 6, 30); Add("SoftTissue", 6, 40); Add("RoyalJelly", 6, 50); Add("Iron", 7, 30); Add("Silver", 7, 30); Add("RefinedEitr", 7, 30); Add("BlackMetal", 8, 30); Add("Flametal", 10, 30); Add("SurtlingCore", 30, 10); Add("BlackCore", 80, 20); Add("MoltenCore", 130, 20); AddUniqueBuy("BrisingamenRing", 1, 1600); AddUniqueBuy("CapeWoundedBeast", 1, 2500); AddUniqueBuy("CapeFracturedBreath", 1, 2500); AddUniqueBuy("CrossbowSilentHunt", 1, 2500); AddUniqueBuy("Bone_crushers", 1, 2500); AddUniqueBuy("ArmorDelayedDoomChest", 1, 4000); AddUniqueBuy("ArmorPitKingChest", 1, 4000); } private static void Add(string prefabName, int sellPrice, int buyQuantity = 0) { Items.Add(new ItemConfig(prefabName, sellPrice, buyQuantity)); } private static void AddUniqueBuy(string prefabName, int quantity, int price) { Items.Add(new ItemConfig(prefabName, 0, quantity, price, buyOnly: true)); } private void BindConfig() { EnableExtraBuyItemsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Buy - General", "Enable Extra Buy Items", true, "If false, this add-on removes all extra buy items it controls and leaves Haldor's normal vanilla shop alone."); CustomBuyItemsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("1 - Buy - General", "Custom Buy Items", "", "Extra items Haldor sells. Format: PrefabName:Quantity:Price. Example: Coal:50:100."); foreach (ItemConfig item in Items) { if (item.HasBuy) { BuyConfig buyConfig = new BuyConfig { FixedQuantity = item.BuyQuantity, Price = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Buy - Items", item.PrefabName + " - Price", item.BuyPrice, "Coin cost for buying " + item.PrefabName + ". Set to 0 to remove this item from Haldor's shop.") }; if (!item.BuyOnly) { buyConfig.Quantity = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Buy - Items", item.PrefabName + " - Quantity", item.BuyQuantity, "How many " + item.PrefabName + " Haldor sells at once."); } BuyItems[item.PrefabName] = buyConfig; } } EnableExtraSellItemsConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Sell - General", "Enable Extra Sell Items", true, "If false, this add-on disables all extra non-trophy sell items it controls."); CustomSellItemsConfig = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Sell - General", "Custom Sell Items", "", "Extra items players can sell to Haldor. Format: PrefabName:Price,PrefabName:Price. Example: Coal:2,Flint:2. Set a price to 0 to disable selling that item."); foreach (ItemConfig item2 in Items) { if (!item2.BuyOnly) { SellPrices[item2.PrefabName] = ((BaseUnityPlugin)this).Config.Bind<int>("4 - Sell - Items", item2.PrefabName + " - Price", item2.SellPrice, "Coins paid for selling one " + item2.PrefabName + ". Set to 0 to disable selling this item."); } } EnableTrophySellingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Sell - Trophies", "Enable Trophy Selling", true, "If false, all trophy sell values are set to 0."); DefaultTrophyPriceConfig = ((BaseUnityPlugin)this).Config.Bind<int>("5 - Sell - Trophies", "Default Trophy Price", 10, "Sell price for trophy items not listed in Trophy Price Overrides."); TrophyPriceOverridesConfig = ((BaseUnityPlugin)this).Config.Bind<string>("5 - Sell - Trophies", "Trophy Price Overrides", "TrophyDeer:15,TrophyBoar:15,TrophyNeck:25,TrophyEikthyr:70,TrophyGreydwarf:15,TrophySkeleton:15,TrophyGreydwarfShaman:20,TrophyGhost:25,TrophyGreydwarfBrute:20,TrophyBjorn:50,TrophyFrostTroll:50,TrophySkeletonPoison:50,TrophySkeletonHildir:80,TrophyTheElder:100,TrophySerpent:500,TrophyBonemawSerpent:500,TrophyBlob:15,TrophyDraugr:15,TrophyLeech:15,TrophySurtling:15,TrophyDraugrElite:30,TrophyWraith:35,TrophyAbomination:75,TrophyKvastur:80,TrophyBonemass:150,TrophyWolf:15,TrophyHatchling:15,TrophyUlv:20,TrophyFenring:25,TrophyCultist:40,TrophySGolem:70,TrophyCultist_Hildir:80,TrophyDragonQueen:200,TrophyDeathsquito:15,TrophyGoblin:15,TrophyGrowth:15,TrophyBjornUndead:50,TrophyLox:35,TrophyGoblinShaman:30,TrophyGoblinBrute:70,TrophyGoblinBruteBrosShaman:80,TrophyGoblinBruteBrosBrute:80,TrophyGoblinKing:350,TrophySeeker:20,TrophyTick:20,TrophyDvergr:20,TrophyHare:20,TrophyGjall:70,TrophySeekerBrute:80,TrophySeekerQueen:500,TrophyCharredArcher:20,TrophyVolture:20,TrophyAsksvin:20,TrophyCharredMage:25,TrophyCharredMelee:25,TrophyMorgen:100,TrophyFallenValkyrie:120,TrophyFader:1000", "Specific trophy prices. Format: TrophyPrefab:Price,TrophyPrefab:Price. Set a price to 0 to disable that trophy."); } private static void PatchHaldorExpansionSellLists() { PatchDictionary("ExtraSellableItems", GetConfiguredSellItems()); PatchDictionary("TrophyValueOverrides", ParsePriceList(TrophyPriceOverridesConfig.Value)); } private static void PatchDictionary(string fieldName, Dictionary<string, int> values) { object obj = Type.GetType("HaldorExpansion.HaldorExpansionPlugin, HaldorExpansion")?.GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null); PropertyInfo propertyInfo = obj?.GetType().GetProperty("Item"); MethodInfo methodInfo = obj?.GetType().GetMethod("Remove", new Type[1] { typeof(string) }); if (propertyInfo == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Could not find HaldorExpansion " + fieldName + "; direct ObjectDB patch will still run.")); } return; } foreach (KeyValuePair<string, int> value in values) { if (value.Value > 0) { propertyInfo.SetValue(obj, value.Value, new object[1] { value.Key }); } else { methodInfo?.Invoke(obj, new object[1] { value.Key }); } } } internal static void ApplySellValues(ObjectDB db) { if ((Object)(object)db == (Object)null) { return; } PatchHaldorExpansionSellLists(); foreach (KeyValuePair<string, int> configuredSellItem in GetConfiguredSellItems()) { SetItemValue(db, configuredSellItem.Key, configuredSellItem.Value); } ApplyTrophySellValues(db); } private static Dictionary<string, int> GetConfiguredSellItems() { Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, ConfigEntry<int>> sellPrice in SellPrices) { dictionary[sellPrice.Key] = (EnableExtraSellItemsConfig.Value ? Math.Max(0, sellPrice.Value.Value) : 0); } if (EnableExtraSellItemsConfig.Value) { foreach (KeyValuePair<string, int> item in ParsePriceList(CustomSellItemsConfig.Value)) { dictionary[item.Key] = item.Value; } } return dictionary; } private static Dictionary<string, int> ParsePriceList(string value) { Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); if (string.IsNullOrWhiteSpace(value)) { return dictionary; } string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); string[] array2 = text.Split(new char[2] { ':', '=' }, 2); if (array2.Length != 2 || string.IsNullOrWhiteSpace(array2[0]) || !int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Ignored invalid sell config entry: " + text)); } } else { dictionary[array2[0].Trim()] = Math.Max(0, result); } } return dictionary; } private static IEnumerable<BuyEntry> GetConfiguredBuyItems() { foreach (KeyValuePair<string, BuyConfig> buyItem in BuyItems) { BuyConfig value = buyItem.Value; int num = ((value.Quantity != null) ? value.Quantity.Value : value.FixedQuantity); if (!EnableExtraBuyItemsConfig.Value || value.Price.Value <= 0 || num <= 0) { yield return BuyEntry.Disabled(buyItem.Key); } else { yield return new BuyEntry(buyItem.Key, num, value.Price.Value); } } if (!EnableExtraBuyItemsConfig.Value) { yield break; } foreach (BuyEntry item in ParseBuyList(CustomBuyItemsConfig.Value)) { yield return item; } } private static IEnumerable<BuyEntry> ParseBuyList(string value) { if (string.IsNullOrWhiteSpace(value)) { yield break; } string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length != 3 || string.IsNullOrWhiteSpace(array2[0]) || !int.TryParse(array2[2].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Ignored invalid buy config entry: " + text)); } continue; } int result2; if (array2[1].Trim().Equals("MaxStack", StringComparison.OrdinalIgnoreCase)) { result2 = 0; } else if (!int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result2)) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("Ignored invalid buy quantity: " + text)); } continue; } yield return new BuyEntry(array2[0].Trim(), result2, Math.Max(0, result)); } } private static void ApplyTrophySellValues(ObjectDB db) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 Dictionary<string, int> dictionary = ParsePriceList(TrophyPriceOverridesConfig.Value); foreach (GameObject item in db.m_items) { SharedData val = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared; if (val != null && (int)val.m_itemType == 13) { int val2 = 0; if (EnableTrophySellingConfig.Value) { val2 = (dictionary.TryGetValue(((Object)item).name, out var value) ? value : Math.Max(0, DefaultTrophyPriceConfig.Value)); } val.m_value = Math.Max(0, val2); } } } private static void SetItemValue(ObjectDB db, string prefabName, int price) { GameObject itemPrefab = db.GetItemPrefab(prefabName); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (val?.m_itemData?.m_shared == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Could not find item prefab for sell value: " + prefabName)); } } else { val.m_itemData.m_shared.m_value = Math.Max(0, price); } } private static void ApplyBuyItems(Trader trader) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown if ((Object)(object)trader == (Object)null || !IsHaldor(trader)) { return; } if (trader.m_items == null) { trader.m_items = new List<TradeItem>(); } foreach (BuyEntry configuredBuyItem in GetConfiguredBuyItems()) { RemoveTradeItem(trader, configuredBuyItem.PrefabName); if (configuredBuyItem.Remove || configuredBuyItem.Price <= 0) { continue; } ItemDrop itemDrop = GetItemDrop(configuredBuyItem.PrefabName); if ((Object)(object)itemDrop == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Could not find item prefab for buy list: " + configuredBuyItem.PrefabName)); } continue; } int num = ResolveQuantity(itemDrop, configuredBuyItem.Quantity); if (num > 0) { trader.m_items.Add(new TradeItem { m_prefab = itemDrop, m_stack = num, m_price = configuredBuyItem.Price, m_requiredGlobalKey = string.Empty }); } } string[] removedOriginalBuyItems = RemovedOriginalBuyItems; foreach (string prefabName in removedOriginalBuyItems) { RemoveTradeItem(trader, prefabName); } } private static bool IsHaldor(Trader trader) { if ((Object)(object)trader != (Object)null && (Object)(object)((Component)trader).gameObject != (Object)null) { return ((Object)((Component)trader).gameObject).name.StartsWith("Haldor", StringComparison.Ordinal); } return false; } private static ItemDrop GetItemDrop(string prefabName) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefabName) : null); if ((Object)(object)val != (Object)null) { return val.GetComponent<ItemDrop>(); } GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefabName) : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.GetComponent<ItemDrop>(); } private static int ResolveQuantity(ItemDrop itemDrop, int configuredQuantity) { if (configuredQuantity > 0) { return configuredQuantity; } return Math.Max(1, (itemDrop.m_itemData?.m_shared?.m_maxStackSize).GetValueOrDefault(1)); } private static void RemoveTradeItem(Trader trader, string prefabName) { trader.m_items.RemoveAll((TradeItem item) => (Object)(object)item?.m_prefab != (Object)null && NormalizePrefabName(((Object)((Component)item.m_prefab).gameObject).name) == prefabName); } private static string NormalizePrefabName(string name) { if (!string.IsNullOrWhiteSpace(name)) { return name.Replace("(Clone)", string.Empty).Trim(); } return string.Empty; } } }