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 Vandi v1.0.0
plugins/Vandi/Vandi.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.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Ezomic.Core; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("Thijssen Software")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 Robbin Thijssen")] [assembly: AssemblyDescription("Creatures wear more stars in a biome whose boss you keep killing, and that boss comes back harder.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c3426a349408d26e412e86b6145825d15e3266db")] [assembly: AssemblyProduct("Vandi")] [assembly: AssemblyTitle("Vandi")] [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 Vandi { internal static class Bosses { private static Dictionary<Biome, List<string>> _byBiome; private static string _parsedFrom; internal static List<string> For(Biome biome) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Parse(); if (!_byBiome.TryGetValue(biome, out var value)) { return null; } return value; } internal static bool IsBossKey(string key) { if (string.IsNullOrEmpty(key)) { return false; } Parse(); foreach (KeyValuePair<Biome, List<string>> item in _byBiome) { if (item.Value.Contains(key)) { return true; } } return false; } internal static string KeyOf(Character character) { if ((Object)(object)character == (Object)null) { return null; } string defeatSetGlobalKey = character.m_defeatSetGlobalKey; if (!string.IsNullOrEmpty(defeatSetGlobalKey)) { return defeatSetGlobalKey.ToLowerInvariant(); } return null; } internal static string KeyOf(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return null; } Character component = prefab.GetComponent<Character>(); if (!((Object)(object)component == (Object)null)) { return KeyOf(component); } return null; } private static void Parse() { //IL_00ad: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) string text = VandiConfig.BossBiomes.Value ?? ""; if (_byBiome != null && text == _parsedFrom) { return; } _parsedFrom = text; _byBiome = new Dictionary<Biome, List<string>>(); string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }); if (array2.Length != 2) { continue; } string text2 = array2[0].Trim().ToLowerInvariant(); string text3 = array2[1].Trim(); if (text2.Length != 0 && text3.Length != 0) { Biome key; try { key = (Biome)Enum.Parse(typeof(Biome), text3, ignoreCase: true); } catch (Exception) { VandiPlugin.LogOnce("BossBiomes names a biome this game does not have: '" + text3 + "'. That pair is skipped; the rest of the line still counts."); continue; } if (!_byBiome.TryGetValue(key, out var value)) { value = new List<string>(); _byBiome[key] = value; } if (!value.Contains(text2)) { value.Add(text2); } } } } } internal static class Kills { [HarmonyPatch] internal static class Readout { private static readonly Biome[] Biomes; private static bool _registered; [HarmonyPostfix] [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static void Register() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!_registered) { _registered = true; new ConsoleCommand("vandi", "the boss kills this world has credited to you, per boss Vandi counts, and the star roll where you stand", new ConsoleEvent(OnCommand), false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } private static void OnCommand(ConsoleEventArgs args) { Terminal context = args.Context; if ((Object)(object)context == (Object)null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { context.AddString("vandi: no character in a world yet"); return; } long playerID = localPlayer.GetPlayerID(); context.AddString("vandi: " + localPlayer.GetPlayerName() + ", id " + playerID.ToString(CultureInfo.InvariantCulture) + ", enabled=" + (VandiConfig.Enabled.Value ? "yes" : "no") + " (kills of a boss you summoned at an altar, as this world has recorded them)"); HashSet<string> hashSet = new HashSet<string>(); Biome[] biomes = Biomes; for (int i = 0; i < biomes.Length; i++) { List<string> list = Bosses.For(biomes[i]); if (list == null) { continue; } foreach (string item in list) { if (hashSet.Add(item)) { context.AddString("vandi " + item + "=" + Count(playerID, item).ToString(CultureInfo.InvariantCulture)); } } } context.AddString(StarLine(localPlayer)); } private static string StarLine(Player player) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) WorldGenerator instance = WorldGenerator.instance; if (instance == null) { return "vandi starchance: no world generator yet"; } Vector3 position = ((Component)player).transform.position; float levelUpChance = SpawnSystem.GetLevelUpChance(position, 0f); float num = Stars.Share(position); float levelUpChanceMultiplier = instance.GetBiomeSector(position, false).GetLevelUpChanceMultiplier(); return "vandi starchance=" + Number(levelUpChance) + " here (" + ((object)instance.GetBiome(position)/*cast due to .constrained prefix*/).ToString() + ", sector x" + Number(levelUpChanceMultiplier) + "): the game's " + Number(levelUpChance - num) + ", Vandi's +" + Number(num); } private static string Number(float value) { return value.ToString("0.##", CultureInfo.InvariantCulture); } static Readout() { Biome[] array = new Biome[9]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Biomes = (Biome[])(object)array; } } private const string Prefix = "vandi_p_"; internal static int Count(long playerId, string bossKey) { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null || string.IsNullOrEmpty(bossKey)) { return 0; } string s = default(string); if (!instance.GetGlobalKey(Key(playerId, bossKey), ref s)) { return 0; } if (!int.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return 0; } if (result >= 0) { return result; } return 0; } internal static int LocalCount(string bossKey) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { return Count(localPlayer.GetPlayerID(), bossKey); } return 0; } internal static int Add(long playerId, string bossKey) { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null || string.IsNullOrEmpty(bossKey)) { return 0; } int result = Count(playerId, bossKey) + 1; instance.SetGlobalKey(Key(playerId, bossKey) + " " + result.ToString(CultureInfo.InvariantCulture)); return result; } private static string Key(long playerId, string bossKey) { return ("vandi_p_" + playerId + "_" + bossKey).ToLowerInvariant(); } } [HarmonyPatch(typeof(SpawnSystem))] internal static class Stars { [HarmonyPostfix] [HarmonyPatch("GetLevelUpChance", new Type[] { typeof(Vector3), typeof(float) })] private unsafe static void Raise(Vector3 position, ref float __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) float num = Share(position); if (!(num <= 0f)) { float num2 = __result; __result += num; if (VandiConfig.Verbose.Value) { ManualLogSource log = VandiPlugin.Log; string[] obj = new string[9] { "Star chance at ", null, null, null, null, null, null, null, null }; Vector3 val = position; obj[1] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = ": "; obj[3] = num2.ToString("0.#"); obj[4] = " + "; obj[5] = num.ToString("0.#"); obj[6] = " = "; obj[7] = __result.ToString("0.#"); obj[8] = "."; log.LogInfo((object)string.Concat(obj)); } } } internal static float Share(Vector3 position) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!VandiConfig.Enabled.Value) { return 0f; } return Boost(position); } private static float Boost(Vector3 position) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return 0f; } WorldGenerator instance = WorldGenerator.instance; if (instance == null) { return 0f; } List<string> list = Bosses.For(instance.GetBiome(position)); if (list == null || list.Count == 0) { return 0f; } int num = 0; for (int i = 0; i < list.Count; i++) { int num2 = Kills.LocalCount(list[i]); if (num2 > num) { num = num2; } } if (num <= 0) { return 0f; } float num3 = (float)num * VandiConfig.StarChancePerKill.Value; float value = VandiConfig.StarChanceCap.Value; if (!(value > 0f) || !(num3 > value)) { return num3; } return value; } } internal static class Summon { private struct Death { internal bool Owner; internal string Boss; internal long Summoner; } private const string SummonPrefix = "vandi_summon_"; private static readonly int SummonerKey = StringExtensionMethods.GetStableHashCode("vandi_summoner"); private const float SpawnSearchRadius = 8f; [HarmonyPatch(typeof(OfferingBowl), "InitiateSpawnBoss")] [HarmonyPostfix] private static void Offered(OfferingBowl __instance, bool __runOriginal) { if (!__runOriginal || !VandiConfig.Enabled.Value || (Object)(object)Player.m_localPlayer == (Object)null) { return; } string text = Bosses.KeyOf(((Object)(object)__instance == (Object)null) ? null : __instance.m_bossPrefab); if (text == null) { return; } ZoneSystem instance = ZoneSystem.instance; if (!((Object)(object)instance == (Object)null)) { long playerID = Player.m_localPlayer.GetPlayerID(); instance.SetGlobalKey(("vandi_summon_" + text).ToLowerInvariant() + " " + playerID.ToString(CultureInfo.InvariantCulture)); if (VandiConfig.Verbose.Value) { VandiPlugin.Log.LogInfo((object)("Offering made for " + text + " by " + playerID + ".")); } } } [HarmonyPatch(typeof(OfferingBowl), "DelayedSpawnBoss")] [HarmonyPostfix] private static void Spawned(OfferingBowl __instance, Vector3 ___m_bossSpawnPoint) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!VandiConfig.Enabled.Value || (Object)(object)__instance == (Object)null) { return; } string text = Bosses.KeyOf(__instance.m_bossPrefab); if (text == null) { return; } long num = Summoner(text); if (num == 0L) { return; } Character val = JustSpawned(___m_bossSpawnPoint, text); if ((Object)(object)val == (Object)null) { return; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return; } component.GetZDO().Set(SummonerKey, num); if (!VandiConfig.HarderBosses.Value) { return; } int num2 = Kills.Count(num, text); if (num2 > 0) { int value = VandiConfig.BossStarCap.Value; int num3 = ((num2 > value) ? value : num2); if (num3 > 0) { val.SetLevel(num3 + 1); VandiPlugin.Log.LogInfo((object)("Summoned " + text + " at " + num3 + " star(s) for player " + num + ", who has killed it " + num2 + " time(s).")); } } } [HarmonyPatch(typeof(Character), "OnDeath")] [HarmonyPrefix] private static void Dying(Character __instance, out Death __state) { __state = default(Death); if (!VandiConfig.Enabled.Value || (Object)(object)__instance == (Object)null) { return; } string text = Bosses.KeyOf(__instance); if (Bosses.IsBossKey(text)) { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner()) { __state.Owner = true; __state.Boss = text; __state.Summoner = component.GetZDO().GetLong(SummonerKey, 0L); } } } [HarmonyPatch(typeof(Character), "OnDeath")] [HarmonyPostfix] private static void Died(bool __runOriginal, Death __state) { if (!__runOriginal || !__state.Owner) { return; } string boss = __state.Boss; long summoner = __state.Summoner; if (summoner == 0L) { if (VandiConfig.Verbose.Value) { VandiPlugin.Log.LogInfo((object)(boss + " died with no summoner on it, so nobody is credited.")); } return; } int num = Kills.Add(summoner, boss); VandiPlugin.Log.LogInfo((object)(boss + " credited to player " + summoner + ", now " + num + " kill(s).")); } private static long Summoner(string boss) { ZoneSystem instance = ZoneSystem.instance; if ((Object)(object)instance == (Object)null) { return 0L; } string s = default(string); if (!instance.GetGlobalKey(("vandi_summon_" + boss).ToLowerInvariant(), ref s)) { return 0L; } if (!long.TryParse(s, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return 0L; } return result; } private static Character JustSpawned(Vector3 point, string boss) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) List<Character> allCharacters = Character.GetAllCharacters(); if (allCharacters == null) { return null; } Character result = null; float num = 64f; for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if ((Object)(object)val == (Object)null || Bosses.KeyOf(val) != boss) { continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.GetZDO().GetLong(SummonerKey, 0L) == 0L) { Vector3 val2 = ((Component)val).transform.position - point; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num)) { num = sqrMagnitude; result = val; } } } return result; } } public static class VandiApi { public static int BossKills(long playerId, string bossKey) { return Kills.Count(playerId, bossKey); } public static int LocalBossKills(string bossKey) { return Kills.LocalCount(bossKey); } public static bool CountsKillsOf(string bossKey) { if (string.IsNullOrEmpty(bossKey)) { return false; } return Bosses.IsBossKey(bossKey.Trim().ToLowerInvariant()); } } internal static class VandiConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> Verbose; internal static ConfigEntry<float> StarChancePerKill; internal static ConfigEntry<float> StarChanceCap; internal static ConfigEntry<string> BossBiomes; internal static ConfigEntry<bool> HarderBosses; internal static ConfigEntry<int> BossStarCap; internal static void Bind(ConfigFile cfg) { Enabled = cfg.Bind<bool>("Vandi", "Enabled", true, "Off leaves the plugin loaded and changing nothing."); Verbose = cfg.Bind<bool>("Vandi", "Verbose", false, "Write every star roll this changes, and every kill it credits, to BepInEx/LogOutput.log. Off unless something looks wrong; a busy zone rolls this many times a second."); StarChancePerKill = cfg.Bind<float>("Stars", "StarChancePerKill", 5f, "Percentage points added to a creature's star chance for each time you have killed that biome's boss. They go on top of whatever the game already rolls where the creature spawns: 10 in an ordinary stretch of a default world, higher in parts of the world far from the centre, lower on a world set to fewer stars. It is the chance of gaining a star that moves, never the number a creature can have, so two stars stays the ceiling."); StarChanceCap = cfg.Bind<float>("Stars", "StarChanceCap", 25f, "The most that can be added, however many times you kill the boss. At the default five a kill this is reached at five kills, and a fully farmed biome then sits 25 points above the game's own roll there: 35 where the game rolls 10, more where the land already raises it. Past that the biome stops being a place you visit and becomes a place you avoid, which is the opposite of the point."); BossBiomes = cfg.Bind<string>("Stars", "BossBiomes", "defeated_eikthyr:meadows, defeated_gdking:blackforest, defeated_bonemass:swamp, defeated_bonemass:ocean, defeated_dragon:mountain, defeated_goblinking:plains, defeated_queen:mistlands, defeated_fader:ashlands, defeated_fader:deepnorth", "boss:biome, comma separated. Killing that boss raises the star chance in that biome and nowhere else, so a biome whose boss you have never beaten is exactly as the game ships it. A boss may own more than one biome, which is how Bonemass covers the Ocean and Fader the Deep North - the same pairing Utangard gates with."); HarderBosses = cfg.Bind<bool>("Bosses", "HarderBosses", true, "A boss you have killed before comes back with stars on it when you summon it again. Off leaves bosses exactly as the game makes them and keeps the star half of the mod, which is the half the biome feels."); BossStarCap = cfg.Bind<int>("Bosses", "BossStarCap", 2, "The most stars a summoned boss can gain, at one star per repeat kill. Two is what a creature can reach in vanilla, and a two star boss hits hard enough that a third would be asking for a different party rather than a better one."); } } [BepInPlugin("ezomic.valheim.vandi", "Vandi", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class VandiPlugin : BaseUnityPlugin { public const string PluginGuid = "ezomic.valheim.vandi"; public const string PluginName = "Vandi"; public const string PluginVersion = "1.0.0"; public const string PluginAuthor = "Robbin Thijssen"; private const string CoreGuid = "ezomic.valheim.core"; internal static ManualLogSource Log; private static readonly HashSet<string> _said = new HashSet<string>(); internal static bool CorePresent; private Harmony _harmony; internal static void LogOnce(string message) { if (message != null && _said.Add(message)) { Log.LogWarning((object)message); } } private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; VandiConfig.Bind(((BaseUnityPlugin)this).Config); TryRegisterWithCore(); _harmony = new Harmony("ezomic.valheim.vandi"); _harmony.PatchAll(typeof(Stars)); _harmony.PatchAll(typeof(Summon)); _harmony.PatchAll(typeof(Kills.Readout)); Log.LogInfo((object)"Vandi 1.0.0 by Robbin Thijssen - ready."); } private void TryRegisterWithCore() { CorePresent = Chainloader.PluginInfos.ContainsKey("ezomic.valheim.core"); if (!CorePresent) { Log.LogInfo((object)"Core not installed - running standalone, without the version gate."); } else { RegisterWithCore(); } } [MethodImpl(MethodImplOptions.NoInlining)] private void RegisterWithCore() { Suite.Register("ezomic.valheim.vandi", "Vandi", "1.0.0", ((BaseUnityPlugin)this).Config, (Requirement)0, (Assembly)null); Suite.Sync((ConfigEntryBase)(object)VandiConfig.Enabled); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } } } }