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 BalancedIdolRefinement v1.0.0
BalancedIdolRefinement.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BalancedIdolRefinement")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BalancedIdolRefinement")] [assembly: AssemblyTitle("BalancedIdolRefinement")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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 BalancedIdolRefinement { [BepInPlugin("com.valheim.balancedidolrefinement", "BalancedIdolRefinement", "1.0.0")] public class BalancedIdolRefinementPlugin : BaseUnityPlugin { internal sealed class IdolRecipeSpec { public readonly string IdolPrefab; public readonly string[] StationCandidates; public readonly int MinStationLevel; public readonly (string[] MaterialCandidates, int Amount)[] Ingredients; public IdolRecipeSpec(string idolPrefab, string[] stationCandidates, int minStationLevel, params (string[] MaterialCandidates, int Amount)[] ingredients) { IdolPrefab = idolPrefab; StationCandidates = stationCandidates; MinStationLevel = minStationLevel; Ingredients = ingredients; } } public const string PluginGuid = "com.valheim.balancedidolrefinement"; public const string PluginName = "BalancedIdolRefinement"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private Harmony _harmony; private static readonly string[] WorkbenchStations = new string[2] { "piece_workbench", "$piece_workbench" }; private static readonly string[] ForgeStations = new string[3] { "forge", "piece_forge", "$piece_forge" }; private static readonly string[] BlackForgeStations = new string[3] { "piece_blackforge", "blackforge", "$piece_blackforge" }; internal static readonly IdolRecipeSpec[] IdolSpecs = new IdolRecipeSpec[16] { new IdolRecipeSpec("Upgrader0Weapon", WorkbenchStations, 1, (new string[1] { "Wood" }, 30), (new string[1] { "Flint" }, 20), (new string[1] { "Resin" }, 15)), new IdolRecipeSpec("Upgrader0Armor", WorkbenchStations, 1, (new string[1] { "Wood" }, 30), (new string[1] { "LeatherScraps" }, 20), (new string[1] { "DeerHide" }, 10)), new IdolRecipeSpec("Upgrader1Weapon", ForgeStations, 1, (new string[1] { "Bronze" }, 20), (new string[1] { "RoundLog" }, 15), (new string[1] { "GreydwarfEye" }, 15)), new IdolRecipeSpec("Upgrader1Armor", ForgeStations, 1, (new string[1] { "Bronze" }, 20), (new string[1] { "TrollHide" }, 10), (new string[1] { "GreydwarfEye" }, 15)), new IdolRecipeSpec("Upgrader2Weapon", ForgeStations, 2, (new string[1] { "Iron" }, 20), (new string[1] { "ElderBark" }, 15), (new string[1] { "Guck" }, 10)), new IdolRecipeSpec("Upgrader2Armor", ForgeStations, 2, (new string[1] { "Iron" }, 20), (new string[1] { "Root" }, 8), (new string[1] { "Bloodbag" }, 15)), new IdolRecipeSpec("Upgrader3Weapon", ForgeStations, 3, (new string[1] { "Silver" }, 20), (new string[1] { "WolfFang" }, 12), (new string[1] { "FreezeGland" }, 8)), new IdolRecipeSpec("Upgrader3Armor", ForgeStations, 3, (new string[1] { "Silver" }, 20), (new string[1] { "WolfPelt" }, 12), (new string[1] { "Crystal" }, 8)), new IdolRecipeSpec("Upgrader4Weapon", ForgeStations, 4, (new string[1] { "BlackMetal" }, 20), (new string[1] { "Needle" }, 15), (new string[1] { "LinenThread" }, 15)), new IdolRecipeSpec("Upgrader4Armor", ForgeStations, 4, (new string[1] { "BlackMetal" }, 20), (new string[1] { "LoxPelt" }, 10), (new string[1] { "LinenThread" }, 15)), new IdolRecipeSpec("Upgrader5Weapon", BlackForgeStations, 1, (new string[1] { "BlackMarble" }, 30), (new string[1] { "Eitr" }, 15), (new string[1] { "Carapace" }, 15)), new IdolRecipeSpec("Upgrader5Armor", BlackForgeStations, 1, (new string[1] { "BlackMarble" }, 30), (new string[1] { "Eitr" }, 15), (new string[1] { "ScaleHide" }, 15)), new IdolRecipeSpec("Upgrader6Weapon", BlackForgeStations, 2, (new string[2] { "FlametalNew", "Flametal" }, 20), (new string[1] { "CharredBone" }, 15), (new string[1] { "ProustitePowder" }, 10)), new IdolRecipeSpec("Upgrader6Armor", BlackForgeStations, 2, (new string[2] { "FlametalNew", "Flametal" }, 20), (new string[1] { "AskHide" }, 12), (new string[1] { "CelestialFeather" }, 8)), new IdolRecipeSpec("Upgrader7Weapon", BlackForgeStations, 3, (new string[1] { "Gold" }, 20), (new string[1] { "Frostwood" }, 20), (new string[1] { "WolfClaw" }, 10)), new IdolRecipeSpec("Upgrader7Armor", BlackForgeStations, 3, (new string[1] { "Gold" }, 20), (new string[1] { "MooseHide" }, 12), (new string[1] { "Voidplasm" }, 10)) }; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("com.valheim.balancedidolrefinement"); _harmony.PatchAll(typeof(BalancedIdolRefinementPlugin).Assembly); Log.LogInfo((object)"BalancedIdolRefinement 1.0.0 loaded."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } internal static void ConfigureIdolsAndRecipes(ObjectDB db) { if ((Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0 || db.m_recipes == null) { return; } int num = 0; int num2 = 0; IdolRecipeSpec[] idolSpecs = IdolSpecs; foreach (IdolRecipeSpec idolRecipeSpec in idolSpecs) { GameObject itemPrefab = db.GetItemPrefab(idolRecipeSpec.IdolPrefab); if ((Object)(object)itemPrefab == (Object)null) { continue; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { continue; } SharedData shared = component.m_itemData.m_shared; shared.m_upgradeChance = 0.65f; shared.m_breakChance = 0f; shared.m_breakReturnIngreientsAmount = 0f; num++; string recipeName = "Recipe_" + idolRecipeSpec.IdolPrefab; Recipe val = FindExistingIdolRecipe(db, recipeName, component); CraftingStation station = FindCraftingStation(db, idolRecipeSpec.StationCandidates); Requirement[] array = BuildRequirements(db, idolRecipeSpec.Ingredients); if (array.Length != 0) { if ((Object)(object)val != (Object)null) { PopulateRecipe(val, recipeName, component, station, idolRecipeSpec.MinStationLevel, array); continue; } Recipe val2 = ScriptableObject.CreateInstance<Recipe>(); PopulateRecipe(val2, recipeName, component, station, idolRecipeSpec.MinStationLevel, array); db.m_recipes.Add(val2); num2++; } } foreach (Recipe recipe in db.m_recipes) { if ((Object)(object)recipe == (Object)null || recipe.m_resources == null) { continue; } Requirement[] resources = recipe.m_resources; foreach (Requirement val3 in resources) { if (val3 != null && val3.m_upgraderResource && (Object)(object)val3.m_resItem != (Object)null && val3.m_resItem.m_itemData?.m_shared != null) { val3.m_resItem.m_itemData.m_shared.m_breakChance = 0f; val3.m_resItem.m_itemData.m_shared.m_breakReturnIngreientsAmount = 0f; } } } if (num > 0 || num2 > 0) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"Configured {num} Idols (0% equipment break, downgrade by 1 level on fail, 0% scrap refund) and registered {num2} Idol recipes."); } } } private static void PopulateRecipe(Recipe recipe, string recipeName, ItemDrop idolDrop, CraftingStation station, int minStationLevel, Requirement[] requirements) { ((Object)recipe).name = recipeName; recipe.m_item = idolDrop; recipe.m_amount = 1; recipe.m_enabled = true; recipe.m_qualityResultAmountMultiplier = 1f; recipe.m_listSortWeight = 100; recipe.m_noCraftOnlyUpgrade = false; recipe.m_craftingStation = station; recipe.m_repairStation = station; recipe.m_minStationLevel = minStationLevel; recipe.m_requireOnlyOneIngredient = false; recipe.m_resources = requirements; } private static Recipe FindExistingIdolRecipe(ObjectDB db, string recipeName, ItemDrop idolDrop) { foreach (Recipe recipe in db.m_recipes) { if (!((Object)(object)recipe == (Object)null) && (string.Equals(((Object)recipe).name, recipeName, StringComparison.Ordinal) || ((Object)(object)recipe.m_item != (Object)null && recipe.m_item.m_itemData?.m_shared != null && idolDrop.m_itemData?.m_shared != null && string.Equals(((Object)recipe.m_item).name, ((Object)idolDrop).name, StringComparison.Ordinal) && !recipe.m_noCraftOnlyUpgrade))) { return recipe; } } return null; } private static Requirement[] BuildRequirements(ObjectDB db, (string[] MaterialCandidates, int Amount)[] ingredients) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown List<Requirement> list = new List<Requirement>(ingredients.Length); for (int i = 0; i < ingredients.Length; i++) { (string[] MaterialCandidates, int Amount) tuple = ingredients[i]; string[] item = tuple.MaterialCandidates; int item2 = tuple.Amount; ItemDrop val = null; string[] array = item; foreach (string text in array) { GameObject itemPrefab = db.GetItemPrefab(text); if ((Object)(object)itemPrefab != (Object)null) { val = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)val != (Object)null) { break; } } } if ((Object)(object)val == (Object)null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Could not find material prefab (" + string.Join("/", item) + ") in ObjectDB.")); } } else { list.Add(new Requirement { m_resItem = val, m_amount = item2, m_amountPerLevel = 0, m_extraAmountOnlyOneIngredient = 0, m_upgraderResource = false, m_recover = true }); } } return list.ToArray(); } private static CraftingStation FindCraftingStation(ObjectDB db, string[] candidates) { foreach (Recipe recipe in db.m_recipes) { if ((Object)(object)recipe?.m_craftingStation != (Object)null && MatchesStation(recipe.m_craftingStation, candidates)) { return recipe.m_craftingStation; } } GameObject itemPrefab = db.GetItemPrefab("Hammer"); PieceTable val = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces); if (val?.m_pieces != null) { foreach (GameObject piece in val.m_pieces) { if (!((Object)(object)piece == (Object)null)) { CraftingStation component = piece.GetComponent<CraftingStation>(); if ((Object)(object)component != (Object)null && MatchesStation(component, candidates)) { return component; } } } } CraftingStation[] array = Resources.FindObjectsOfTypeAll<CraftingStation>(); foreach (CraftingStation val2 in array) { if ((Object)(object)val2 != (Object)null && MatchesStation(val2, candidates)) { return val2; } } return null; } private static bool MatchesStation(CraftingStation station, string[] candidates) { foreach (string b in candidates) { if (string.Equals(((Object)station).name, b, StringComparison.OrdinalIgnoreCase) || string.Equals(station.m_name, b, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } [HarmonyPatch(typeof(ObjectDB))] internal static class ObjectDBPatches { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void AwakePostfix(ObjectDB __instance) { BalancedIdolRefinementPlugin.ConfigureIdolsAndRecipes(__instance); } [HarmonyPatch("CopyOtherDB")] [HarmonyPostfix] private static void CopyOtherDBPostfix(ObjectDB __instance) { BalancedIdolRefinementPlugin.ConfigureIdolsAndRecipes(__instance); } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] internal static class InventoryGuiDoCraftingPatch { internal sealed class RefinementSnapshot { public ItemData OriginalItem; public int OriginalQuality; public float OriginalDurability; public Vector2i OriginalGridPos; public int OriginalVariant; public long OriginalCrafterId; public string OriginalCrafterName; public Dictionary<string, string> OriginalCustomData; } [HarmonyPrefix] private static void Prefix(Player player, Recipe ___m_craftRecipe, ItemData ___m_craftUpgradeItem, out RefinementSnapshot __state) { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) __state = null; if ((Object)(object)player == (Object)null || (Object)(object)___m_craftRecipe == (Object)null || ___m_craftUpgradeItem == null) { return; } CraftingStation val = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetCurrentCraftingStation() : player.GetCurrentCraftingStation()); if ((Object)(object)val == (Object)null || !val.m_upgrader) { return; } if (___m_craftRecipe.m_resources != null) { Requirement[] resources = ___m_craftRecipe.m_resources; foreach (Requirement val2 in resources) { if (val2 != null && val2.m_upgraderResource && val2.m_resItem?.m_itemData?.m_shared != null) { val2.m_resItem.m_itemData.m_shared.m_breakChance = 0f; val2.m_resItem.m_itemData.m_shared.m_breakReturnIngreientsAmount = 0f; } } } __state = new RefinementSnapshot { OriginalItem = ___m_craftUpgradeItem, OriginalQuality = ___m_craftUpgradeItem.m_quality, OriginalDurability = ___m_craftUpgradeItem.m_durability, OriginalGridPos = ___m_craftUpgradeItem.m_gridPos, OriginalVariant = ___m_craftUpgradeItem.m_variant, OriginalCrafterId = ___m_craftUpgradeItem.m_crafterID, OriginalCrafterName = ___m_craftUpgradeItem.m_crafterName, OriginalCustomData = ((___m_craftUpgradeItem.m_customData != null) ? new Dictionary<string, string>(___m_craftUpgradeItem.m_customData) : null) }; } [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); FieldInfo fieldInfo = AccessTools.Field(typeof(SharedData), "m_breakChance"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(SharedData), "m_breakReturnIngreientsAmount"); for (int i = 0; i < list.Count; i++) { if (fieldInfo != null && CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false)) { list.Insert(i + 1, new CodeInstruction(OpCodes.Pop, (object)null)); list.Insert(i + 2, new CodeInstruction(OpCodes.Ldc_R4, (object)(-1f))); i += 2; } else if (fieldInfo2 != null && CodeInstructionExtensions.LoadsField(list[i], fieldInfo2, false)) { list.Insert(i + 1, new CodeInstruction(OpCodes.Pop, (object)null)); list.Insert(i + 2, new CodeInstruction(OpCodes.Ldc_R4, (object)0f)); i += 2; } else if (list[i].opcode == OpCodes.Ldstr && object.Equals(list[i].operand, "$msg_upgrader_failed")) { list[i].operand = "$msg_upgrader_fail"; } } return list; } [HarmonyPostfix] private static void Postfix(InventoryGui __instance, Player player, RefinementSnapshot __state) { //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if (__state == null || (Object)(object)player == (Object)null) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } int num = Math.Max(1, __state.OriginalQuality - 1); ItemData val = inventory.GetItemAt(__state.OriginalGridPos.x, __state.OriginalGridPos.y); if (val == null && __state.OriginalItem?.m_shared != null) { val = inventory.GetItem(__state.OriginalItem.m_shared.m_name, num, false) ?? inventory.GetItem(__state.OriginalItem.m_shared.m_name, __state.OriginalQuality + 1, false); } if (val == null && __state.OriginalItem != null) { __state.OriginalItem.m_quality = num; __state.OriginalItem.m_durability = Mathf.Min(__state.OriginalDurability, __state.OriginalItem.GetMaxDurability()); __state.OriginalItem.m_gridPos = __state.OriginalGridPos; inventory.AddItem(__state.OriginalItem); AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", (Type[])null, (Type[])null)?.Invoke(__instance, new object[1] { false }); } else if (val != null && val.m_quality <= __state.OriginalQuality) { val.m_quality = num; val.m_durability = Mathf.Min(__state.OriginalDurability, val.GetMaxDurability()); val.m_variant = __state.OriginalVariant; val.m_crafterID = __state.OriginalCrafterId; val.m_crafterName = __state.OriginalCrafterName; if (__state.OriginalCustomData != null) { val.m_customData = new Dictionary<string, string>(__state.OriginalCustomData); } } } } }