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 ArmorMouldDropRates v1.0.0
BepInEx/plugins/ArmorMouldDropRates/ArmorMouldDropRates.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; 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("ArmorMouldDropRates")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ArmorMouldDropRates")] [assembly: AssemblyTitle("ArmorMouldDropRates")] [assembly: AssemblyVersion("1.0.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 ArmorMouldDropRates { public enum DropRateMode { Fixed, Multiplier } internal sealed class ChanceSettings { internal readonly DropRateMode Mode; internal readonly float FixedChance; internal readonly float Multiplier; internal ChanceSettings(string mode, float fixedChance, float multiplier, Action<string> warn) { if (string.Equals(mode?.Trim(), "Fixed", StringComparison.OrdinalIgnoreCase)) { Mode = DropRateMode.Fixed; } else { Mode = DropRateMode.Multiplier; if (!string.Equals(mode?.Trim(), "Multiplier", StringComparison.OrdinalIgnoreCase)) { warn("Invalid Mode; falling back to Multiplier."); } } FixedChance = Validate(fixedChance, 0.1f, 1f, "FixedChance", warn); Multiplier = Validate(multiplier, 3f, float.MaxValue, "Multiplier", warn); } private static float Validate(float value, float fallback, float max, string key, Action<string> warn) { if (float.IsNaN(value) || float.IsInfinity(value)) { warn(key + " must be finite; using " + fallback + "."); return fallback; } float num = Math.Max(0f, Math.Min(max, value)); if (num != value) { warn(key + " is outside its allowed range; clamped to " + num + "."); } return num; } internal float Apply(float original) { if (Mode != DropRateMode.Fixed) { return (float)Math.Max(0.0, Math.Min(1.0, (double)original * (double)Multiplier)); } return FixedChance; } } internal sealed class DropProcessor { private sealed class Baseline { internal readonly float Chance; internal Baseline(float chance) { Chance = chance; } } internal static readonly string[] KrigenMoulds = new string[6] { "MoldArmorGoldChest", "MoldArmorGoldHelmet", "MoldArmorGoldLegs", "MoldArmormediumChest", "MoldArmorMediumHelmet", "MoldArmorMediumLegs" }; internal static readonly string[] HexenMoulds = new string[3] { "MoldArmorMageChest", "MoldArmorMageHelmet", "MoldArmorMageLegs" }; private readonly ConditionalWeakTable<Drop, Baseline> originals = new ConditionalWeakTable<Drop, Baseline>(); internal void Process(IEnumerable<GameObject> prefabs, ChanceSettings settings, Action<string> info, Action<string> warn, Action<string> debug) { int num = 0; int num2 = 0; HashSet<GameObject> hashSet = new HashSet<GameObject>(); HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal); string[] array2; foreach (GameObject prefab in prefabs) { if (!Object.op_Implicit((Object)(object)prefab) || !hashSet.Add(prefab)) { continue; } string[] array; if (((Object)prefab).name == "JotunWarrior") { array = KrigenMoulds; } else { if (!(((Object)prefab).name == "JotunWitch")) { continue; } array = HexenMoulds; } hashSet2.Add(((Object)prefab).name); info(((Object)prefab).name + " found."); HashSet<string> hashSet3 = new HashSet<string>(array, StringComparer.Ordinal); HashSet<string> hashSet4 = new HashSet<string>(StringComparer.Ordinal); CharacterDrop component = prefab.GetComponent<CharacterDrop>(); int num3 = 0; int num4 = 0; if (!Object.op_Implicit((Object)(object)component) || component.m_drops == null) { warn(((Object)prefab).name + " has no CharacterDrop table."); } else { foreach (Drop drop in component.m_drops) { if (drop == null || !Object.op_Implicit((Object)(object)drop.m_prefab)) { continue; } string name = ((Object)drop.m_prefab).name; if (!hashSet3.Contains(name)) { debug?.Invoke($"Unchanged {((Object)prefab).name} -> {name}: chance={drop.m_chance:G6}, amount={drop.m_amountMin}..{drop.m_amountMax}, levelMultiplier={drop.m_levelMultiplier}, onePerPlayer={drop.m_onePerPlayer}, dontScale={drop.m_dontScale}"); continue; } num3++; if (!hashSet4.Add(name)) { warn("Duplicate expected drop " + name + " on " + ((Object)prefab).name + "."); } Baseline value = originals.GetValue(drop, (Drop d) => new Baseline(d.m_chance)); if (float.IsNaN(value.Chance) || float.IsInfinity(value.Chance)) { warn("Invalid original chance for " + ((Object)prefab).name + " -> " + name + "; skipped."); continue; } float num5 = settings.Apply(value.Chance); if (drop.m_chance != num5) { num4++; } drop.m_chance = num5; debug?.Invoke($"{((Object)prefab).name} -> {name}: {value.Chance:G6} -> {num5:G6}"); if (num5 == 0f) { warn(((Object)prefab).name + " -> " + name + ": base chance set to zero. Valheim 1.0.17 pseudo drops divide by chance without a zero guard; zero is not a verified disable switch."); } } } array2 = array; foreach (string text in array2) { if (!hashSet4.Contains(text)) { warn("Expected drop " + text + " was not found on " + ((Object)prefab).name + "."); } } if (num3 != array.Length) { warn($"Expected {array.Length} armour mould entries on {((Object)prefab).name} but found {num3}."); } num += num3; num2 += num4; info($"{((Object)prefab).name}: {num3} target mould entries; {num4} entries modified."); } array2 = new string[2] { "JotunWarrior", "JotunWitch" }; foreach (string text2 in array2) { if (!hashSet2.Contains(text2)) { warn("Expected creature prefab " + text2 + " was not found."); } } info($"Found {num} armour mould drop entries (expected 9)."); info($"Modified {num2} armour mould drop entries."); if (num != 9) { warn($"Expected 9 armour mould entries but found {num}. A Valheim update or another mod may have changed the drop tables."); } } } [BepInPlugin("com.weizhexu.armormoulddroprates", "ArmorMouldDropRates", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class SceneAwakePatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(ZNetScene __instance) { if ((Object)(object)instance != (Object)null) { instance.Apply(__instance); } } } public const string Guid = "com.weizhexu.armormoulddroprates"; private static Plugin instance; private Harmony harmony; private ChanceSettings settings; private bool debugLogging; private readonly DropProcessor processor = new DropProcessor(); private readonly ConditionalWeakTable<ZNetScene, object> scenes = new ConditionalWeakTable<ZNetScene, object>(); private void Awake() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown instance = this; ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Mode", "Multiplier", "Fixed or Multiplier (case-insensitive). Invalid values use Multiplier. Restart after editing."); ConfigEntry<float> val2 = ((BaseUnityPlugin)this).Config.Bind<float>("General", "FixedChance", 0.1f, "Used in Fixed mode. 0 = 0%, 0.5 = 50%, 1 = 100%. Clamped to [0,1]."); ConfigEntry<float> val3 = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Multiplier", 3f, "Used in Multiplier mode. 2 doubles the existing base mould chance, capped at 100%. Negative values clamp to zero."); debugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Log target changes and unchanged entries with their metadata.").Value; settings = new ChanceSettings(val.Value, val2.Value, val3.Value, delegate(string s) { ((BaseUnityPlugin)this).Logger.LogWarning((object)s); }); harmony = new Harmony("com.weizhexu.armormoulddroprates"); harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Initialized."); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Mode: {settings.Mode}, FixedChance: {settings.FixedChance}, Multiplier: {settings.Multiplier}"); } private void Apply(ZNetScene scene) { if (!scenes.TryGetValue(scene, out var _)) { List<GameObject> list = new List<GameObject>(scene.m_prefabs); list.AddRange(scene.m_nonNetViewPrefabs); processor.Process(list, settings, delegate(string s) { ((BaseUnityPlugin)this).Logger.LogInfo((object)s); }, delegate(string s) { ((BaseUnityPlugin)this).Logger.LogWarning((object)s); }, debugLogging ? ((Action<string>)delegate(string s) { ((BaseUnityPlugin)this).Logger.LogInfo((object)s); }) : null); scenes.Add(scene, new object()); } } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } }