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 FurtherUpgrades v1.2.0
plugins/FurtherUpgrades.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("FurtherUpgrades")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("FurtherUpgrades")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] namespace FurtherUpgrades; internal static class CoinCosts { [HarmonyPatch(typeof(Requirement), "GetAmount")] private static class GetAmountPatch { [HarmonyPriority(0)] private static void Postfix(Requirement __instance, int qualityLevel, ref int __result) { if (trackedRequirements.TryGetValue(__instance, out var value)) { __result = (int)Math.Min(2147483647L, (long)__result + (long)GetCost(value, qualityLevel)); } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] private static class UpdateRecipeListPatch { private static void Prefix(List<Recipe> recipes) { RegisterRecipes(recipes); } } private static readonly ConditionalWeakTable<Requirement, Recipe> trackedRequirements = new ConditionalWeakTable<Requirement, Recipe>(); private static readonly Dictionary<ConfigEntry<string>, int[]> costs = new Dictionary<ConfigEntry<string>, int[]>(); private static bool refreshPending; public static void Initialize() { ConfigEntry<string>[] array = new ConfigEntry<string>[5] { Configs.ArmorCoinCosts, Configs.GlobalCoinCosts, Configs.ShieldCoinCosts, Configs.ToolCoinCosts, Configs.WeaponCoinCosts }; foreach (ConfigEntry<string> val in array) { costs[val] = null; LoadCosts(val); val.SettingChanged += OnCostsChanged; } _ = ItemManager.Instance; ItemManager.OnItemsRegistered += RegisterRecipes; Configs.EnableCoinCosts.SettingChanged += OnEnabledChanged; } public static void Shutdown() { ItemManager.OnItemsRegistered -= RegisterRecipes; Configs.EnableCoinCosts.SettingChanged -= OnEnabledChanged; foreach (ConfigEntry<string> key in costs.Keys) { key.SettingChanged -= OnCostsChanged; } costs.Clear(); } public static void Update() { if (refreshPending && (Object)(object)InventoryGui.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null && InventoryGui.IsVisible()) { refreshPending = false; InventoryGui.instance.UpdateCraftingPanel(false); } } private static void OnEnabledChanged(object sender, EventArgs args) { refreshPending = true; } private static void OnCostsChanged(object sender, EventArgs args) { LoadCosts((ConfigEntry<string>)sender); refreshPending = true; } private static void LoadCosts(ConfigEntry<string> entry) { if (string.IsNullOrWhiteSpace(entry.Value)) { costs[entry] = null; return; } string[] array = entry.Value.Split(new char[1] { ',' }); int[] array2 = new int[array.Length]; for (int i = 0; i < array.Length; i++) { if (!int.TryParse(array[i].Trim(), NumberStyles.None, CultureInfo.InvariantCulture, out array2[i])) { Logger.LogWarning((object)(((ConfigEntryBase)entry).Definition.Key + " must contain comma-separated nonnegative integers. Keeping the previous valid costs.")); return; } } costs[entry] = array2; } private static void RegisterRecipes() { if ((Object)(object)ObjectDB.instance != (Object)null) { RegisterRecipes(ObjectDB.instance.m_recipes); } } private static void RegisterRecipes(List<Recipe> recipes) { if ((Object)(object)ObjectDB.instance == (Object)null || recipes == null) { return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins"); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { return; } foreach (Recipe recipe in recipes) { if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && recipe.m_resources != null && !recipe.m_requireOnlyOneIngredient) { RegisterRequirement(recipe, val, upgraderResource: false); if (recipe.m_resources.Any((Requirement x) => x.m_upgraderResource)) { RegisterRequirement(recipe, val, upgraderResource: true); } } } } private static void RegisterRequirement(Recipe recipe, ItemDrop coins, bool upgraderResource) { //IL_002f: 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_0040: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown Requirement val = ((IEnumerable<Requirement>)recipe.m_resources).FirstOrDefault((Func<Requirement, bool>)((Requirement x) => x.m_upgraderResource == upgraderResource && (Object)(object)x.m_resItem != (Object)null && x.m_resItem.m_itemData.m_shared.m_name == coins.m_itemData.m_shared.m_name)); if (val == null) { val = new Requirement { m_resItem = coins, m_amount = 0, m_amountPerLevel = 0, m_recover = false, m_upgraderResource = upgraderResource }; recipe.m_resources = recipe.m_resources.Concat((IEnumerable<Requirement>)(object)new Requirement[1] { val }).ToArray(); } if (!trackedRequirements.TryGetValue(val, out var _)) { trackedRequirements.Add(val, recipe); } } private static ConfigEntry<string> GetCategory(Recipe recipe) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected I4, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Invalid comparison between Unknown and I4 SharedData shared = recipe.m_item.m_itemData.m_shared; if ((int)shared.m_skillType == 12 || (int)shared.m_itemType == 19) { return Configs.ToolCoinCosts; } ItemType itemType = shared.m_itemType; switch (itemType - 3) { default: if ((int)itemType != 22) { break; } goto case 0; case 3: case 4: case 8: case 14: return Configs.ArmorCoinCosts; case 2: return Configs.ShieldCoinCosts; case 0: case 1: case 11: case 12: return Configs.WeaponCoinCosts; case 5: case 6: case 7: case 9: case 10: case 13: break; } return Configs.GlobalCoinCosts; } private static int GetCost(Recipe recipe, int qualityLevel) { if (!Configs.EnableCoinCosts.Value || qualityLevel <= 1 || (Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || recipe.m_requireOnlyOneIngredient) { return 0; } int[] array = costs[GetCategory(recipe)] ?? costs[Configs.GlobalCoinCosts]; if (array != null) { return array[Math.Min(qualityLevel - 2, array.Length - 1)]; } return 0; } } public static class Configs { public static ConfigEntry<bool> EnableCompatibilityWithWarfareMods; public static ConfigEntry<int> ArmorChests; public static ConfigEntry<int> ArmorHelmets; public static ConfigEntry<int> ArmorLegs; public static ConfigEntry<int> ArmorShoulders; public static ConfigEntry<int> Axes; public static ConfigEntry<int> Bows; public static ConfigEntry<int> Clubs; public static ConfigEntry<int> Crossbows; public static ConfigEntry<int> Knives; public static ConfigEntry<int> Pickaxes; public static ConfigEntry<int> Polearms; public static ConfigEntry<int> Shields; public static ConfigEntry<int> Spears; public static ConfigEntry<int> StavesBlood; public static ConfigEntry<int> StavesElemental; public static ConfigEntry<int> Swords; public static ConfigEntry<int> Tools; public static ConfigEntry<int> Unarmed; public static ConfigEntry<string> CustomItemList; public static ConfigEntry<string> IgnoreItemList; public static ConfigEntry<int> UpgradeRequiredLevelDivisor; public static ConfigEntry<int> BlackForge; public static ConfigEntry<int> Forge; public static ConfigEntry<int> GaldrTable; public static ConfigEntry<int> Workbench; public static ConfigEntry<string> CustomStations; public static ConfigEntry<int> MaterialsRequiredPerLevel; public static ConfigEntry<bool> EnableCoinCosts; public static ConfigEntry<string> GlobalCoinCosts; public static ConfigEntry<string> ArmorCoinCosts; public static ConfigEntry<string> ShieldCoinCosts; public static ConfigEntry<string> ToolCoinCosts; public static ConfigEntry<string> WeaponCoinCosts; public static ConfigEntry<bool> EnableUpgradeModifiers; public static ConfigEntry<int> ArmorUpgradeMultiplier; public static ConfigEntry<int> DamageUpgradeMultiplier; public static ConfigEntry<int> DurabilityUpgradeMultiplier; public static ConfigurationManagerAttributes IsAdminOnly = new ConfigurationManagerAttributes { IsAdminOnly = true }; public static ConfigurationManagerAttributes IsAdminOnlyAndAdvanced = new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = true }; public static void SetupConfigs(ConfigFile config) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Expected O, but got Unknown //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Expected O, but got Unknown //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Expected O, but got Unknown //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Expected O, but got Unknown //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Expected O, but got Unknown //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Expected O, but got Unknown //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Expected O, but got Unknown //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Expected O, but got Unknown //IL_047d: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Unknown result type (might be due to invalid IL or missing references) //IL_04a8: Expected O, but got Unknown //IL_04a8: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Expected O, but got Unknown //IL_04da: Unknown result type (might be due to invalid IL or missing references) //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04f2: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Expected O, but got Unknown //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_050f: Expected O, but got Unknown //IL_0550: Unknown result type (might be due to invalid IL or missing references) //IL_055a: Expected O, but got Unknown //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_058e: Expected O, but got Unknown //IL_05b8: Unknown result type (might be due to invalid IL or missing references) //IL_05c2: Expected O, but got Unknown //IL_05ec: Unknown result type (might be due to invalid IL or missing references) //IL_05f6: Expected O, but got Unknown //IL_0620: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Expected O, but got Unknown //IL_0652: Unknown result type (might be due to invalid IL or missing references) //IL_0657: Unknown result type (might be due to invalid IL or missing references) //IL_065e: Unknown result type (might be due to invalid IL or missing references) //IL_066a: Unknown result type (might be due to invalid IL or missing references) //IL_067d: Expected O, but got Unknown //IL_067d: Unknown result type (might be due to invalid IL or missing references) //IL_0687: Expected O, but got Unknown //IL_06cf: Unknown result type (might be due to invalid IL or missing references) //IL_06d9: Expected O, but got Unknown //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_070f: Expected O, but got Unknown //IL_07c2: Unknown result type (might be due to invalid IL or missing references) //IL_07cc: Expected O, but got Unknown //IL_0806: Unknown result type (might be due to invalid IL or missing references) //IL_0810: Expected O, but got Unknown //IL_084a: Unknown result type (might be due to invalid IL or missing references) //IL_0854: Expected O, but got Unknown //IL_088e: Unknown result type (might be due to invalid IL or missing references) //IL_0898: Expected O, but got Unknown EnableCompatibilityWithWarfareMods = config.Bind<bool>("Compatibility", GenerateConfigKey("EnableCompatibilityWithWarfareMods"), true, new ConfigDescription("Enable compatibility with Warfare mods by replacing their changes to the station level requirements for item upgrades.\nDisable this if you encounter compatibility issues.", (AcceptableValueBase)null, new object[1] { IsAdminOnly })); ArmorChests = config.Bind<int>("Item Levels", GenerateConfigKey("ArmorChests"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); ArmorHelmets = config.Bind<int>("Item Levels", GenerateConfigKey("ArmorHelmets"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); ArmorLegs = config.Bind<int>("Item Levels", GenerateConfigKey("ArmorLegs"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); ArmorShoulders = config.Bind<int>("Item Levels", GenerateConfigKey("ArmorLegs"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Axes = config.Bind<int>("Item Levels", GenerateConfigKey("Axes"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Bows = config.Bind<int>("Item Levels", GenerateConfigKey("Bows"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Clubs = config.Bind<int>("Item Levels", GenerateConfigKey("Clubs"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Crossbows = config.Bind<int>("Item Levels", GenerateConfigKey("Crossbows"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Knives = config.Bind<int>("Item Levels", GenerateConfigKey("Knives"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Pickaxes = config.Bind<int>("Item Levels", GenerateConfigKey("Pickaxes"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Polearms = config.Bind<int>("Item Levels", GenerateConfigKey("Polearms"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Shields = config.Bind<int>("Item Levels", GenerateConfigKey("Shields"), 5, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Spears = config.Bind<int>("Item Levels", GenerateConfigKey("Spears"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); StavesBlood = config.Bind<int>("Item Levels", GenerateConfigKey("StavesBlood"), 0, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); StavesElemental = config.Bind<int>("Item Levels", GenerateConfigKey("StavesElemental"), 0, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Swords = config.Bind<int>("Item Levels", GenerateConfigKey("Swords"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Tools = config.Bind<int>("Item Levels", GenerateConfigKey("Tools"), 5, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); Unarmed = config.Bind<int>("Item Levels", GenerateConfigKey("Unarmed"), 7, new ConfigDescription("Sets the maximum upgrade level for this item category.\nEnter 0 to leave the existing maximum levels unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { IsAdminOnly })); CustomItemList = config.Bind<string>("Item Levels", GenerateConfigKey("CustomItemList"), string.Empty, new ConfigDescription("Sets maximum upgrade levels for specific items, overriding the category settings.\nEnter each item token followed by a colon and its maximum level, separating entries with commas.\nFormat: item_token_1:max_level,item_token_2:max_level.\nUse whole-number levels greater than 0, with no trailing comma.\nExample: $item_spear_bronze:10,$item_bow_finewood:20 allows the bronze spear to reach level 10 and the finewood bow to reach level 20.\nSee https://valheim-modding.github.io/Jotunn/data/objects/item-list.html for a list of item tokens.\nPrefab names can be used instead of tokens.\nUse exact token or prefab names, not translated item names.\nLeave empty to use the category settings for all items.\nItems in Ignore Item List are excluded, even if listed here.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = -1, CustomDrawer = TextAreaDrawer } })); IgnoreItemList = config.Bind<string>("Item Levels", GenerateConfigKey("IgnoreItemList"), string.Empty, new ConfigDescription("Keeps the existing maximum upgrade levels and material costs for the specified items, overriding the category settings and Custom Item List.\nEnter item tokens separated by commas, with no levels or trailing comma.\nFormat: item_token_1,item_token_2.\nExample: $item_spear_bronze,$item_bow_finewood keeps the bronze spear and finewood bow at their original upgrade limits, regardless of the settings for spears and bows.\nSee https://valheim-modding.github.io/Jotunn/data/objects/item-list.html for a list of item tokens.\nPrefab names can be used instead of tokens.\nUse exact token or prefab names, not translated item names.\nLeave empty to exclude no items.\nStation requirements, coin costs and upgrade stat multipliers still apply.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = -1, CustomDrawer = TextAreaDrawer } })); UpgradeRequiredLevelDivisor = config.Bind<int>("Station Requirements", GenerateConfigKey("UpgradeRequiredLevelDivisor"), 1, new ConfigDescription("Determines how many item levels share each required station level.\nA value of 2 increases the station requirement every 2 item levels instead of every level.\nFor example, for a recipe with a minimum station level of 1, item levels 3 and 4 both require station level 2.\nThe recipe's minimum station level is still accounted for, and station level caps still apply.", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[3] { 1, 2, 3 }), new object[1] { SetOrder(1) })); BlackForge = config.Bind<int>("Station Requirements", GenerateConfigKey("BlackForge"), 5, new ConfigDescription("Caps the station level required for item upgrades.\nFor example, if an item can be upgraded to level 10, a value of 5 means that upgrade requires at most station level 5.\nSet this to the highest station level obtainable with the available extensions.\nEnter 0 to disable the cap.", (AcceptableValueBase)null, new object[1] { IsAdminOnlyAndAdvanced })); Forge = config.Bind<int>("Station Requirements", GenerateConfigKey("Forge"), 7, new ConfigDescription("Caps the station level required for item upgrades.\nFor example, if an item can be upgraded to level 10, a value of 5 means that upgrade requires at most station level 5.\nSet this to the highest station level obtainable with the available extensions.\nEnter 0 to disable the cap.", (AcceptableValueBase)null, new object[1] { IsAdminOnlyAndAdvanced })); GaldrTable = config.Bind<int>("Station Requirements", GenerateConfigKey("GaldrTable"), 4, new ConfigDescription("Caps the station level required for item upgrades.\nFor example, if an item can be upgraded to level 10, a value of 5 means that upgrade requires at most station level 5.\nSet this to the highest station level obtainable with the available extensions.\nEnter 0 to disable the cap.", (AcceptableValueBase)null, new object[1] { IsAdminOnlyAndAdvanced })); Workbench = config.Bind<int>("Station Requirements", GenerateConfigKey("Workbench"), 5, new ConfigDescription("Caps the station level required for item upgrades.\nFor example, if an item can be upgraded to level 10, a value of 5 means that upgrade requires at most station level 5.\nSet this to the highest station level obtainable with the available extensions.\nEnter 0 to disable the cap.", (AcceptableValueBase)null, new object[1] { IsAdminOnlyAndAdvanced })); CustomStations = config.Bind<string>("Station Requirements", GenerateConfigKey("CustomStations"), "FletcherTable_TW:5", new ConfigDescription("Sets maximum required station levels for custom or modded crafting stations, allowing further item upgrades without additional extensions.\nEnter each station token followed by a colon and its required level cap, separating entries with commas.\nFormat: station_token_1:max_level,station_token_2:max_level.\nUse whole-number levels greater than 0, with no trailing comma.\nExample: FletcherTable_TW:5 means item upgrades at that station require at most station level 5.\nSet each value to the highest station level obtainable with its available extensions.\nPrefab names can be used instead of station tokens; use exact names, not translated station names.\nLeave empty for no custom station caps.\nThis list does not set maximum item levels.\nThe workbench, forge, black forge and galdr table use their separate settings above.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, Order = -1, CustomDrawer = TextAreaDrawer } })); MaterialsRequiredPerLevel = config.Bind<int>("Upgrade Costs", GenerateConfigKey("MaterialsRequiredPerLevel", "%"), 50, new ConfigDescription("Determines upgrade material costs as a percentage of the normal per-level amounts.\nFor example, 50 uses half the normal amount and 100 keeps it unchanged.\nAmounts are rounded down, with a minimum of 1 for each required material.\nApplies only to items handled by the maximum level settings.\nFor items without existing upgrade costs, the starting amount is half the crafting material cost.\nInitial crafting costs are unchanged.", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[10] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }), new object[1] { SetOrder(4) })); EnableCoinCosts = config.Bind<bool>("Upgrade Costs", GenerateConfigKey("EnableCoinCosts"), false, new ConfigDescription("Enable additional coin costs for item upgrades.\nInitial crafting is unchanged.\nApplies independently of maximum level settings and Ignore Item List.\nRecipes that accept any one of several alternative ingredients are excluded.\nChanges apply without restarting.", (AcceptableValueBase)null, new object[1] { SetOrder(3) })); GlobalCoinCosts = BindCoinCosts(config, "GlobalCoinCosts", "Sets the additional coins required for each upgrade level.\nUsed for all items unless a category list, such as Armor Coin Costs, supplies its own costs.\nAlso covers modded items without a matching category.", "0,0,0,0,0,0", 2); ArmorCoinCosts = BindCoinCosts(config, "ArmorCoinCosts", "Coin cost override for armor, including helmets, chest armor, leg armor and capes.", string.Empty); ShieldCoinCosts = BindCoinCosts(config, "ShieldCoinCosts", "Coin cost override for shields.", string.Empty); ToolCoinCosts = BindCoinCosts(config, "ToolCoinCosts", "Coin cost override for tools, including pickaxes.\nAxes use Weapon Coin Costs.", string.Empty); WeaponCoinCosts = BindCoinCosts(config, "WeaponCoinCosts", "Coin cost override for weapons, including melee weapons, bows, crossbows and magic staves.", string.Empty); EnableUpgradeModifiers = config.Bind<bool>("Upgrade Stats", GenerateConfigKey("EnableUpgradeModifiers"), false, new ConfigDescription("Enable the damage, armor and durability upgrade multipliers.\nOnly stat gains per item level are multiplied; base stats remain unchanged.\nApplies independently of maximum item level settings and Ignore Item List.", (AcceptableValueBase)null, new object[1] { SetOrder(1) })); ArmorUpgradeMultiplier = config.Bind<int>("Upgrade Stats", GenerateConfigKey("ArmorUpgradeMultiplier", "%"), 100, new ConfigDescription("Multiplier for armor gained per upgrade.\nEnter a percentage: 100 keeps the normal gain, 200 doubles it, and 0 removes the gain.\nRequires Enable Upgrade Modifiers.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), new object[1] { IsAdminOnly })); DamageUpgradeMultiplier = config.Bind<int>("Upgrade Stats", GenerateConfigKey("DamageUpgradeMultiplier", "%"), 100, new ConfigDescription("Multiplier for damage gained per upgrade, applied to each damage type.\nEnter a percentage: 100 keeps the normal gain, 200 doubles it, and 0 removes the gain.\nRequires Enable Upgrade Modifiers.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), new object[1] { IsAdminOnly })); DurabilityUpgradeMultiplier = config.Bind<int>("Upgrade Stats", GenerateConfigKey("DurabilityUpgradeMultiplier", "%"), 100, new ConfigDescription("Multiplier for maximum durability gained per upgrade.\nEnter a percentage: 100 keeps the normal gain, 200 doubles it, and 0 removes the gain.\nRequires Enable Upgrade Modifiers.\nExisting items are not automatically repaired.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), new object[1] { IsAdminOnly })); } public static string GenerateConfigKey(string key) { return GenerateConfigKey(key, null); } public static string GenerateConfigKey(string key, string unit) { key = string.Concat(key.Select((char x) => (!char.IsUpper(x)) ? x.ToString() : (" " + x))).TrimStart(new char[1] { ' ' }); if (!string.IsNullOrEmpty(unit)) { key += $" ({unit})"; } return key; } private static ConfigEntry<string> BindCoinCosts(ConfigFile config, string key, string description, string defaultValue, int order = 0) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown ConfigurationManagerAttributes val = SetOrder(order); return config.Bind<string>("Upgrade Costs", GenerateConfigKey(key), defaultValue, new ConfigDescription(description + "\nRequires Enable Coin Costs.\nEnter coin amounts separated by commas: the first value is the cost to upgrade from item level 1 to 2, the second from 2 to 3, and so on.\nExample: 0,0,5,10 makes upgrades to levels 2 and 3 free of additional coin costs, level 4 cost 5 coins, and level 5 or higher cost 10 coins per upgrade.\nThe last value repeats at all higher levels; a single 5 therefore adds 5 coins to every upgrade.\nUse whole numbers of 0 or higher, without a trailing comma.\nEnter 0 for no additional coin cost at any level.\nLeave a category list empty to use Global Coin Costs; leaving Global Coin Costs empty adds no coins unless a category list specifies them.\nInvalid input keeps the previous valid costs active.\nChanges apply without restarting.", (AcceptableValueBase)null, new object[1] { val })); } private static void TextAreaDrawer(ConfigEntryBase entry) { GUILayout.ExpandHeight(true); GUILayout.ExpandWidth(true); entry.BoxedValue = GUILayout.TextArea((string)entry.BoxedValue, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true) }); } public static ConfigurationManagerAttributes SetOrder(int order, bool isAdminOnly = true) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return new ConfigurationManagerAttributes { Order = order, IsAdminOnly = isAdminOnly }; } } [BepInPlugin("FurtherUpgrades", "FurtherUpgrades", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class FurtherUpgrades : BaseUnityPlugin { [HarmonyPatch(typeof(Recipe), "GetRequiredStationLevel")] public class Recipe_GetRequiredStationLevel_Patch { public static bool Prefix(Recipe __instance, int quality, ref int __result) { if (!hasWarfareMod.HasValue) { hasWarfareMod = Harmony.HasAnyPatches("Therzie.Warfare") || Harmony.HasAnyPatches("Therzie.WarfareFireAndIce"); if (hasWarfareMod.Value && Configs.EnableCompatibilityWithWarfareMods.Value) { harmony.Unpatch((MethodBase)AccessTools.Method(typeof(Recipe), "GetRequiredStationLevel", (Type[])null, (Type[])null), (HarmonyPatchType)2, "org.bepinex.helpers.ItemManager"); Logger.LogInfo((object)"Unpatched method 'GetRequiredStationLevel' from 'org.bepinex.helpers.ItemManager' used by mods 'Therzie.Warfare' and 'Therzie.WarfareFireAndIce'."); } } CraftingStation craftingStation = __instance.GetRequiredStation(quality); if ((Object)(object)craftingStation != (Object)null) { int num = Mathf.CeilToInt((float)quality / (float)Configs.UpgradeRequiredLevelDivisor.Value) + (__instance.m_minStationLevel - 1); if (craftingStation.m_name == "$piece_workbench") { if (Configs.Workbench.Value > 0 && num > Configs.Workbench.Value) { __result = Configs.Workbench.Value; return false; } } else if (craftingStation.m_name == "$piece_forge") { if (Configs.Forge.Value > 0 && num > Configs.Forge.Value) { __result = Configs.Forge.Value; return false; } } else if (craftingStation.m_name == "$piece_blackforge") { if (Configs.BlackForge.Value > 0 && num > Configs.BlackForge.Value) { __result = Configs.BlackForge.Value; return false; } } else if (craftingStation.m_name == "$piece_magetable") { if (Configs.GaldrTable.Value > 0 && num > Configs.GaldrTable.Value) { __result = Configs.GaldrTable.Value; return false; } } else { KeyValuePair<string, int> keyValuePair = CustomStations.FirstOrDefault((KeyValuePair<string, int> x) => ((Object)((Component)craftingStation).gameObject).name.StartsWith(x.Key) || craftingStation.m_name == x.Key); if (keyValuePair.Key != null && num > keyValuePair.Value) { __result = keyValuePair.Value; return false; } } __result = num; return false; } return true; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static class ItemDrop_Awake_Patch { private static void Postfix(ItemDrop __instance) { ApplyItemCustomChanges(__instance); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static class ItemDrop_SlowUpdate_Patch { private static void Postfix(ref ItemDrop __instance) { ApplyItemCustomChanges(__instance); } } public const string PluginGUID = "FurtherUpgrades"; public const string PluginName = "FurtherUpgrades"; public const string PluginVersion = "1.2.0"; public static readonly Dictionary<string, int> CustomStations = new Dictionary<string, int>(); public static readonly Dictionary<string, int> CustomItems = new Dictionary<string, int>(); public static readonly List<string> IgnoredItems = new List<string>(); private static readonly List<string> modifiedItems = new List<string>(); private static bool? hasWarfareMod; private static Harmony harmony; private void Awake() { Configs.SetupConfigs(((BaseUnityPlugin)this).Config); CoinCosts.Initialize(); LoadCustomStations(); LoadCustomItemList(); LoadIgnoreItemList(); harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "FurtherUpgrades"); } private void Update() { CoinCosts.Update(); } private void OnDestroy() { CoinCosts.Shutdown(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } public static void LoadCustomStations() { if (string.IsNullOrEmpty(Configs.CustomStations.Value)) { return; } string[] array = Configs.CustomStations.Value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Trim().Split(new char[1] { ':' }); if (array2.Length < 2) { Logger.LogError((object)"Custom Stations not in the expected format. Please see the documentation and adhere to the correct format."); CustomStations.Clear(); return; } string text = array2[0].Trim(); int result; bool flag = int.TryParse(array2[1].Trim(), out result); if (text.Length == 0 || !flag) { Logger.LogError((object)"Custom Stations not in the expected format. Please see the documentation and adhere to the correct format."); CustomStations.Clear(); return; } if (result <= 0) { Logger.LogError((object)"Max Station Level cannot be equal or lower than 0."); CustomStations.Clear(); return; } CustomStations.Add(text, result); } Logger.LogInfo((object)"Custom Stations loaded successfully."); } public static void LoadCustomItemList() { if (string.IsNullOrEmpty(Configs.CustomItemList.Value)) { return; } string[] array = Configs.CustomItemList.Value.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Trim().Split(new char[1] { ':' }); if (array2.Length < 2) { Logger.LogError((object)"Custom Item List not in the expected format. Please see the documentation and adhere to the correct format."); CustomItems.Clear(); return; } string text = array2[0].Trim(); int result; bool flag = int.TryParse(array2[1].Trim(), out result); if (text.Length == 0 || !flag) { Logger.LogError((object)"Custom Item List not in the expected format. Please see the documentation and adhere to the correct format."); CustomItems.Clear(); return; } if (result <= 0) { Logger.LogError((object)"Max Item Level cannot be equal or lower than 0."); CustomItems.Clear(); return; } CustomItems.Add(text, result); } Logger.LogInfo((object)"Custom Item List loaded successfully."); } public static void LoadIgnoreItemList() { if (string.IsNullOrEmpty(Configs.IgnoreItemList.Value)) { return; } string[] array = Configs.IgnoreItemList.Value.Split(new char[1] { ',' }); foreach (string text in array) { if (string.IsNullOrEmpty(text)) { Logger.LogError((object)"Ignore Item List not in the expected format. Please see the documentation and adhere to the correct format."); IgnoredItems.Clear(); return; } IgnoredItems.Add(text.Trim()); } Logger.LogInfo((object)"Ignore Item List loaded successfully."); } private static void ApplyItemCustomChanges(ItemDrop item) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Invalid comparison between Unknown and I4 //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Invalid comparison between Unknown and I4 //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Invalid comparison between Unknown and I4 //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Invalid comparison between Unknown and I4 //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Invalid comparison between Unknown and I4 //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Invalid comparison between Unknown and I4 //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Invalid comparison between Unknown and I4 //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Invalid comparison between Unknown and I4 //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Invalid comparison between Unknown and I4 //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Invalid comparison between Unknown and I4 //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Invalid comparison between Unknown and I4 //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Invalid comparison between Unknown and I4 //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Invalid comparison between Unknown and I4 //IL_0415: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Invalid comparison between Unknown and I4 //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Invalid comparison between Unknown and I4 //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Invalid comparison between Unknown and I4 //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Invalid comparison between Unknown and I4 //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Invalid comparison between Unknown and I4 //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Invalid comparison between Unknown and I4 //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Invalid comparison between Unknown and I4 //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Invalid comparison between Unknown and I4 //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Invalid comparison between Unknown and I4 //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Invalid comparison between Unknown and I4 //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Invalid comparison between Unknown and I4 //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Invalid comparison between Unknown and I4 SharedData info = item.m_itemData.m_shared; if (IgnoredItems.Contains(info.m_name) || ((Object)(object)item.m_itemData.m_dropPrefab != (Object)null && IgnoredItems.Contains(((Object)item.m_itemData.m_dropPrefab).name))) { return; } string text = CustomItems.Keys.FirstOrDefault((string x) => x == info.m_name); if (text == null && (Object)(object)item.m_itemData.m_dropPrefab != (Object)null) { text = CustomItems.Keys.FirstOrDefault((string x) => x == ((Object)item.m_itemData.m_dropPrefab).name); } if (text == null) { if (info.m_maxQuality <= 1) { return; } if ((int)info.m_itemType == 4) { if ((int)info.m_skillType == 8 && Configs.Bows.Value > 0) { UpdateItemData(item, Configs.Bows.Value); return; } if ((int)info.m_skillType == 14 && Configs.Crossbows.Value > 0) { UpdateItemData(item, Configs.Crossbows.Value); return; } } if ((int)info.m_itemType == 3 || (int)info.m_itemType == 14 || (int)info.m_itemType == 22 || (int)info.m_itemType == 15) { if ((int)info.m_skillType == 7 && Configs.Axes.Value > 0) { UpdateItemData(item, Configs.Axes.Value); return; } if ((int)info.m_skillType == 10 && Configs.StavesBlood.Value > 0) { UpdateItemData(item, Configs.StavesBlood.Value); return; } if ((int)info.m_skillType == 8 && Configs.Bows.Value > 0) { UpdateItemData(item, Configs.Bows.Value); return; } if ((int)info.m_skillType == 3 && Configs.Clubs.Value > 0) { UpdateItemData(item, Configs.Clubs.Value); return; } if ((int)info.m_skillType == 14 && Configs.Crossbows.Value > 0) { UpdateItemData(item, Configs.Crossbows.Value); return; } if ((int)info.m_skillType == 9 && Configs.StavesElemental.Value > 0) { UpdateItemData(item, Configs.StavesElemental.Value); return; } if ((int)info.m_skillType == 2 && Configs.Knives.Value > 0) { UpdateItemData(item, Configs.Knives.Value); return; } if ((int)info.m_skillType == 12 && Configs.Pickaxes.Value > 0) { UpdateItemData(item, Configs.Pickaxes.Value); return; } if ((int)info.m_skillType == 4 && Configs.Polearms.Value > 0) { UpdateItemData(item, Configs.Polearms.Value); return; } if ((int)info.m_skillType == 5 && Configs.Spears.Value > 0) { UpdateItemData(item, Configs.Spears.Value); return; } if ((int)info.m_skillType == 1 && Configs.Swords.Value > 0) { UpdateItemData(item, Configs.Swords.Value); return; } if ((int)info.m_skillType == 11 && Configs.Unarmed.Value > 0) { UpdateItemData(item, Configs.Unarmed.Value); return; } } if ((int)info.m_itemType == 7 && Configs.ArmorChests.Value > 0) { UpdateItemData(item, Configs.ArmorChests.Value); } else if ((int)info.m_itemType == 6 && Configs.ArmorHelmets.Value > 0) { UpdateItemData(item, Configs.ArmorHelmets.Value); } else if ((int)info.m_itemType == 11 && Configs.ArmorLegs.Value > 0) { UpdateItemData(item, Configs.ArmorLegs.Value); } else if ((int)info.m_itemType == 5 && Configs.Shields.Value > 0) { UpdateItemData(item, Configs.Shields.Value); } else if ((int)info.m_itemType == 17 && Configs.ArmorShoulders.Value > 0) { UpdateItemData(item, Configs.ArmorShoulders.Value); } else if ((int)info.m_itemType == 19 && Configs.Tools.Value > 0) { UpdateItemData(item, Configs.Tools.Value); } } else { UpdateItemData(item, CustomItems[text]); } } private static void UpdateItemData(ItemDrop item, int maxQuality) { if (!((Object)(object)ObjectDB.instance != (Object)null) || ObjectDB.instance.m_recipes == null || modifiedItems.Contains(item.m_itemData.m_shared.m_name)) { return; } Recipe val = ((IEnumerable<Recipe>)ObjectDB.instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe x) => x.m_item?.m_itemData.m_shared.m_name == item.m_itemData.m_shared.m_name)); if (!((Object)(object)val != (Object)null)) { return; } val.m_item.m_itemData.m_shared.m_maxQuality = (item.m_itemData.m_shared.m_maxQuality = maxQuality); bool flag = false; Requirement[] resources = val.m_resources; foreach (Requirement val2 in resources) { if (val2.m_amountPerLevel > 0) { if (val2.m_amountPerLevel > 1) { val2.m_amountPerLevel = Math.Max(Mathf.FloorToInt((float)val2.m_amountPerLevel * ((float)Configs.MaterialsRequiredPerLevel.Value / 100f)), 1); } flag = true; } } if (!flag) { resources = val.m_resources; foreach (Requirement val3 in resources) { if (val3.m_amount > 1) { val3.m_amountPerLevel = Math.Max(Mathf.FloorToInt((float)val3.m_amount * 0.5f * ((float)Configs.MaterialsRequiredPerLevel.Value / 100f)), 1); } } } modifiedItems.Add(item.m_itemData.m_shared.m_name); } } internal static class UpgradeModifiers { [HarmonyPatch(typeof(ItemData), "GetArmor", new Type[] { typeof(int), typeof(float) })] private static class GetArmorPatch { private static void Postfix(ItemData __instance, int quality, ref float __result) { if (Configs.EnableUpgradeModifiers.Value && Configs.ArmorUpgradeMultiplier.Value != 100) { __result += (float)Mathf.Max(0, quality - 1) * __instance.m_shared.m_armorPerLevel * ((float)Configs.ArmorUpgradeMultiplier.Value / 100f - 1f); } } } [HarmonyPatch(typeof(ItemData), "GetDamage", new Type[] { typeof(int), typeof(float) })] private static class GetDamagePatch { private static void Postfix(ItemData __instance, int quality, ref DamageTypes __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (Configs.EnableUpgradeModifiers.Value && Configs.DamageUpgradeMultiplier.Value != 100 && quality > 1) { DamageTypes damagesPerLevel = __instance.m_shared.m_damagesPerLevel; ((DamageTypes)(ref damagesPerLevel)).Modify((float)Configs.DamageUpgradeMultiplier.Value / 100f - 1f); ((DamageTypes)(ref __result)).Add(damagesPerLevel, quality - 1); } } } [HarmonyPatch(typeof(ItemData), "GetMaxDurability", new Type[] { typeof(int) })] private static class GetMaxDurabilityPatch { private static void Postfix(ItemData __instance, int quality, ref float __result) { if (Configs.EnableUpgradeModifiers.Value && Configs.DurabilityUpgradeMultiplier.Value != 100) { __result += (float)Mathf.Max(0, quality - 1) * __instance.m_shared.m_durabilityPerLevel * ((float)Configs.DurabilityUpgradeMultiplier.Value / 100f - 1f); } } } }