Please disclose if your mod was created primarily 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 KillCountEvolution v1.0.0
KillCountEvolution.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using KillCountEvolution.Config; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("KillCountEvolution")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MobLevelSystem")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b0de67da-3bbf-4641-bf42-71bdb5d846ed")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [HarmonyPatch(typeof(EnemyHud), "UpdateHuds")] internal class EnemyHudPatch { private static void Postfix(EnemyHud __instance) { if (!(AccessTools.Field(typeof(EnemyHud), "m_huds").GetValue(__instance) is IDictionary dictionary)) { return; } foreach (DictionaryEntry item in dictionary) { object key = item.Key; Character val = (Character)((key is Character) ? key : null); if ((Object)(object)val == (Object)null) { continue; } int level = val.GetLevel(); if (level <= 3) { continue; } object value = item.Value; if (value == null) { continue; } FieldInfo fieldInfo = AccessTools.Field(value.GetType(), "m_name"); if (!(fieldInfo == null)) { object? value2 = fieldInfo.GetValue(value); TMP_Text val2 = (TMP_Text)((value2 is TMP_Text) ? value2 : null); if (!((Object)(object)val2 == (Object)null) && !val2.text.Contains("★")) { int count = level - 1; string text = new string('★', count); val2.text = val2.text + " <color=#FFD700>" + text + "</color>"; } } } } } namespace KillCountEvolution { [BepInPlugin("com.basicMods.KillCountEvolution", "Kill Count Evolution", "1.0.0")] public class KillCountEvolution : BaseUnityPlugin { public static KillCountEvolution Instance; public MobSpawnConfig mobConfig; public PlayerData localPlayerData; private string saveFolder; private Dictionary<long, int> onlinePeerContributions = new Dictionary<long, int>(); private int globalTotalKills; private void Awake() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) Instance = this; saveFolder = Path.Combine(Paths.BepInExRootPath, "plugins", "KillCountEvolution"); Directory.CreateDirectory(saveFolder); mobConfig = new MobSpawnConfig((BaseUnityPlugin)(object)this); new Harmony("com.basicMods.KillCountEvolution").PatchAll(); } public void SetupRPCs() { ZRoutedRpc.instance.Register<int>("RPC_SubmitInitialKills", (Action<long, int>)RPC_SubmitInitialKills); ZRoutedRpc.instance.Register<int>("RPC_SyncGlobalKills", (Action<long, int>)RPC_SyncGlobalKills); ZRoutedRpc.instance.Register("RPC_AddOneKill", (Action<long>)RPC_AddOneKill); } private void RPC_SubmitInitialKills(long sender, int kills) { if (ZNet.instance.IsServer()) { onlinePeerContributions[sender] = kills; UpdateGlobalTotal(); } } private void RPC_AddOneKill(long sender) { if (ZNet.instance.IsServer()) { if (onlinePeerContributions.ContainsKey(sender)) { onlinePeerContributions[sender]++; } else { onlinePeerContributions[sender] = 1; } UpdateGlobalTotal(); } } private void RPC_SyncGlobalKills(long sender, int total) { globalTotalKills = total; } private void UpdateGlobalTotal() { globalTotalKills = onlinePeerContributions.Values.Sum(); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_SyncGlobalKills", new object[1] { globalTotalKills }); SaveMasterJson(); } public void OnPlayerDisconnect(long peerID) { if (ZNet.instance.IsServer() && onlinePeerContributions.ContainsKey(peerID)) { onlinePeerContributions.Remove(peerID); UpdateGlobalTotal(); } } public void LoadLocalData() { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { string worldName = ZNet.instance.GetWorldName(); string playerName = Player.m_localPlayer.GetPlayerName(); string path = Path.Combine(saveFolder, worldName + "_" + playerName + ".json"); if (File.Exists(path)) { string text = File.ReadAllText(path); localPlayerData = JsonUtility.FromJson<PlayerData>(text); Debug.Log((object)$"[KillCountEvolution] Betöltve: {playerName} - {localPlayerData.TotalKills} ölés."); } else { localPlayerData = new PlayerData { PlayerName = playerName, TotalKills = 0 }; Debug.Log((object)"[KillCountEvolution] Új player adat létrehozva."); } ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_SubmitInitialKills", new object[1] { localPlayerData.TotalKills }); } } public void RegisterLocalKill() { localPlayerData.TotalKills++; SaveLocalJson(); ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_AddOneKill", Array.Empty<object>()); } private void SaveLocalJson() { string worldName = ZNet.instance.GetWorldName(); File.WriteAllText(Path.Combine(saveFolder, worldName + "_" + localPlayerData.PlayerName + ".json"), JsonUtility.ToJson((object)localPlayerData, true)); } public void SaveMasterJson(bool forceZero = false) { if (!((Object)(object)ZNet.instance == (Object)null)) { int num = ((!forceZero) ? globalTotalKills : 0); File.WriteAllText(Path.Combine(saveFolder, ZNet.instance.GetWorldName() + "_MASTER.json"), "{\"GlobalOnlineKills\": " + num + "}"); } } public int GetTotalKills() { return globalTotalKills; } public void ClearGlobalData() { onlinePeerContributions.Clear(); globalTotalKills = 0; } } [Serializable] public class PlayerData { public string PlayerName; public int TotalKills; } [HarmonyPatch(typeof(ZNet), "Awake")] internal class ZNet_Awake_Patch { private static void Postfix() { KillCountEvolution.Instance.SetupRPCs(); } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal class Player_Spawn_Patch { private static void Postfix() { KillCountEvolution.Instance.LoadLocalData(); } } [HarmonyPatch(typeof(ZNet), "Shutdown")] internal class ZNet_Shutdown_Patch { private static void Prefix() { if ((Object)(object)KillCountEvolution.Instance != (Object)null && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { KillCountEvolution.Instance.ClearGlobalData(); KillCountEvolution.Instance.SaveMasterJson(forceZero: true); } } } [HarmonyPatch(typeof(Character), "Damage")] internal class Damage_Patch { private static void Postfix(Character __instance, HitData hit) { if (__instance.GetHealth() <= 0f && !__instance.IsPlayer()) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)Player.m_localPlayer) { KillCountEvolution.Instance.RegisterLocalKill(); } } } } public static class RankManager { public static int RollCustomLevel(int originalLevel) { MobSpawnConfig mobConfig = KillCountEvolution.Instance.mobConfig; int totalKills = KillCountEvolution.Instance.GetTotalKills(); float num = mobConfig.Chance5Star.Value + Mathf.Min((float)totalKills * mobConfig.BonusPerKill5Star.Value, mobConfig.MaxBonus5Star.Value); float num2 = mobConfig.Chance4Star.Value + Mathf.Min((float)totalKills * mobConfig.BonusPerKill4Star.Value, mobConfig.MaxBonus4Star.Value); float num3 = mobConfig.Chance3Star.Value + Mathf.Min((float)totalKills * mobConfig.BonusPerKill3Star.Value, mobConfig.MaxBonus3Star.Value); float num4 = num + num2 + num3; float num5 = Mathf.Clamp(mobConfig.VanillaMinSpawnRate.Value, 0f, 100f); float num6 = 100f - num5; float num7; if (num5 <= 0f) { num7 = num4; } else { if (num4 > num6) { float num8 = num6 / num4; num *= num8; num2 *= num8; num3 *= num8; num4 = num6; } num7 = 100f; } if (num7 <= 0f) { return originalLevel; } float num9 = Random.Range(0f, num7); if (num9 < num) { return 6; } if (num9 < num + num2) { return 5; } if (num9 < num + num2 + num3) { return 4; } return originalLevel; } } [HarmonyPatch(typeof(Character), "SetLevel")] public static class SetLevelOverridePatch { private static void Prefix(Character __instance, ref int level) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Invalid comparison between Unknown and I4 if ((Object)(object)__instance == (Object)null || __instance.IsPlayer() || (Object)(object)KillCountEvolution.Instance == (Object)null || KillCountEvolution.Instance.mobConfig == null) { return; } string prefabName = ((Object)__instance).name.Replace("(Clone)", "").Trim(); if (KillCountEvolution.Instance.mobConfig.IsPrefabExcluded(prefabName)) { return; } Biome currentBiome = Heightmap.FindBiome(((Component)__instance).transform.position); if (!KillCountEvolution.Instance.mobConfig.IsBiomeExcluded(currentBiome) && (int)__instance.m_faction != 1 && level <= 3) { int num = level; int num2 = RankManager.RollCustomLevel(num); if (num2 > num) { level = num2; } } } } [HarmonyPatch(typeof(Character), "Awake")] internal class CharacterAwakePatch { private static void Postfix(Character __instance) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Invalid comparison between Unknown and I4 if ((Object)(object)__instance == (Object)null || __instance.IsPlayer() || (Object)(object)KillCountEvolution.Instance == (Object)null || KillCountEvolution.Instance.mobConfig == null) { return; } string prefabName = ((Object)__instance).name.Replace("(Clone)", "").Trim(); if (!KillCountEvolution.Instance.mobConfig.IsPrefabExcluded(prefabName)) { Biome currentBiome = Heightmap.FindBiome(((Component)__instance).transform.position); if (!KillCountEvolution.Instance.mobConfig.IsBiomeExcluded(currentBiome) && (int)__instance.m_faction != 1 && __instance.GetLevel() == 1) { __instance.SetLevel(1); } } } } } namespace KillCountEvolution.Config { public class MobSpawnConfig { public ConfigEntry<float> Chance3Star; public ConfigEntry<float> Chance4Star; public ConfigEntry<float> Chance5Star; public ConfigEntry<string> ExcludedBiomes; public ConfigEntry<string> ExcludedPrefabsConfig; public ConfigEntry<float> BonusPerKill3Star; public ConfigEntry<float> BonusPerKill4Star; public ConfigEntry<float> BonusPerKill5Star; public ConfigEntry<float> MaxBonus3Star; public ConfigEntry<float> MaxBonus4Star; public ConfigEntry<float> MaxBonus5Star; public ConfigEntry<float> VanillaMinSpawnRate; public ConfigEntry<string> LootBonusBlacklist; private HashSet<string> excludedPrefabsSet = new HashSet<string>(); private HashSet<string> lootBlacklistSet = new HashSet<string>(); private static readonly string[] InternalBlacklist = new string[41] { "Eikthyr", "gd_king", "Bonemass", "Dragon", "GoblinKing", "SeekerQueen", "Fader", "Brenna", "Geirrhafa", "GoblinBrute_Hildir", "GoblinShaman_Hildir", "Skeleton_Hildir", "Fenring_Cultist_Hildir", "Goblin_Hildir", "Charred_Melee_Dyrnwyn", "Haldor", "Hildir", "BogWitch", "Hugin", "Munin", "Odin", "Dverger", "DvergerMage", "DvergerMageFire", "DvergerMageIce", "DvergerMageSupport", "DvergerAshlands", "Boar", "Wolf", "Lox", "Asksvin", "Hen", "Chicken", "Deer", "Hare", "Neck", "Seagal", "Crow", "AshCrow", "Leviathan", "Bat" }; public MobSpawnConfig(BaseUnityPlugin plugin) { Chance3Star = plugin.Config.Bind<float>("Rates", "BaseChance3Star", 5f, "Base chance for 3-star (Level 4) spawn (%). Calculated 3-star bonus rates adds to this base."); Chance4Star = plugin.Config.Bind<float>("Rates", "BaseChance4Star", 2f, "Base chance for 4-star (Level 5) spawn (%). Calculated 4-star bonus rates adds to this base."); Chance5Star = plugin.Config.Bind<float>("Rates", "BaseChance5Star", 0.5f, "Base chance for 5-star (Level 6) spawn (%). Calculated 5-star bonus rates adds to this base."); BonusPerKill3Star = plugin.Config.Bind<float>("Progression", "BonusPerKill3Star", 0.02f, "Bonus % added to 3-star chance per kill."); BonusPerKill4Star = plugin.Config.Bind<float>("Progression", "BonusPerKill4Star", 0.01f, "Bonus % added to 4-star chance per kill."); BonusPerKill5Star = plugin.Config.Bind<float>("Progression", "BonusPerKill5Star", 0.005f, "Bonus % added to 5-star chance per kill."); MaxBonus3Star = plugin.Config.Bind<float>("Progression", "MaxBonus3Star", 20f, "Maximum total bonus % for 3-star chance."); MaxBonus4Star = plugin.Config.Bind<float>("Progression", "MaxBonus4Star", 18f, "Maximum total bonus % for 4-star chance."); MaxBonus5Star = plugin.Config.Bind<float>("Progression", "MaxBonus5Star", 9.5f, "Maximum total bonus % for 5-star chance."); VanillaMinSpawnRate = plugin.Config.Bind<float>("Balance", "VanillaMinSpawnRate", 30f, "Minimum % of spawns that must remain vanilla (Level 1-3). If total custom chances exceed the remaining space, they will be scaled down proportionally. Set to 100 to disable custom spawns. Set to 0 to disable vanilla spawns"); ExcludedBiomes = plugin.Config.Bind<string>("General", "ExcludedBiomes", "Mistlands,Ashlands", "Comma-separated list of biomes where the mod is inactive."); string text = "Deathsquito,Blob,BlobElite,BlobTar,FrostBlob,LavaBlob,Serpent,BonemawSerpent,Vulture,Skugg"; ExcludedPrefabsConfig = plugin.Config.Bind<string>("General", "ExcludedPrefabs", text, "Comma-separated list of additional prefabs to exclude (Bosses and pets are excluded by default)."); LootBonusBlacklist = plugin.Config.Bind<string>("Loot", "BonusBlacklist", "Coin,Stone,Resin,Wood", "Comma-separated list of item prefab names that should NEVER drop as an extra bonus item. Trophy is also excluded."); ParseConfig(); } public void ParseConfig() { excludedPrefabsSet.Clear(); string[] internalBlacklist = InternalBlacklist; foreach (string item in internalBlacklist) { excludedPrefabsSet.Add(item); } foreach (string item2 in from p in ExcludedPrefabsConfig.Value.Split(new char[1] { ',' }) select p.Trim() into p where !string.IsNullOrEmpty(p) select p) { excludedPrefabsSet.Add(item2); } lootBlacklistSet.Clear(); foreach (string item3 in from p in LootBonusBlacklist.Value.Split(new char[1] { ',' }) select p.Trim().ToLower() into p where !string.IsNullOrEmpty(p) select p) { lootBlacklistSet.Add(item3); } } public bool IsPrefabExcluded(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } if (prefabName.StartsWith("Fish")) { return true; } return excludedPrefabsSet.Contains(prefabName); } public bool IsItemBlacklisted(string itemName) { if (string.IsNullOrEmpty(itemName)) { return false; } string lowerName = itemName.ToLower(); return lootBlacklistSet.Any((string b) => lowerName.Contains(b)); } public bool IsBiomeExcluded(Biome currentBiome) { string biomeStr = ((object)(Biome)(ref currentBiome)).ToString(); return ExcludedBiomes.Value.Split(new char[1] { ',' }).Any((string b) => b.Trim().Equals(biomeStr, StringComparison.OrdinalIgnoreCase)); } } } namespace KillCountEvolution.Patches { [HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")] public static class DropPatch { private static bool Prefix(CharacterDrop __instance, ref List<KeyValuePair<GameObject, int>> __result) { Character component = ((Component)__instance).GetComponent<Character>(); if ((Object)(object)component == (Object)null) { return true; } int level = component.GetLevel(); if (level < 4) { return true; } MobSpawnConfig config = KillCountEvolution.Instance.mobConfig; List<KeyValuePair<GameObject, int>> list = new List<KeyValuePair<GameObject, int>>(); foreach (Drop drop in __instance.m_drops) { if ((Object)(object)drop.m_prefab == (Object)null || 1 == 0) { continue; } int num = Random.Range(drop.m_amountMin, drop.m_amountMax + 1); if (num <= 0) { continue; } if (((Object)drop.m_prefab).name.ToLower().Contains("trophy")) { if (Random.value <= drop.m_chance) { list.Add(new KeyValuePair<GameObject, int>(drop.m_prefab, num)); } } else { list.Add(new KeyValuePair<GameObject, int>(drop.m_prefab, num * 4)); } } int num2 = level switch { 6 => 2, 5 => 1, _ => 0, }; if (num2 > 0) { List<GameObject> list2 = (from d in __instance.m_drops where (Object)(object)d.m_prefab != (Object)null select d.m_prefab into p where !((Object)p).name.ToLower().Contains("trophy") && !config.IsItemBlacklisted(((Object)p).name) select p).ToList(); if (list2.Count > 0) { GameObject key = list2[Random.Range(0, list2.Count)]; list.Add(new KeyValuePair<GameObject, int>(key, num2)); } } __result = list; return false; } } }