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 AdaptiveCreatureScaling v1.3.1
AdaptiveCreatureScaling.dll
Decompiled a day agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Adaptive Creature Scaling")] [assembly: AssemblyDescription("Scales Valheim creatures against upgraded player equipment.")] [assembly: AssemblyCompany("Adaptive Creature Scaling contributors")] [assembly: AssemblyProduct("Adaptive Creature Scaling")] [assembly: AssemblyCopyright("Copyright © 2026 Adaptive Creature Scaling contributors")] [assembly: AssemblyFileVersion("1.3.1.0")] [assembly: AssemblyVersion("1.3.1.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 AdaptiveCreatureScaling { [BepInPlugin("com.forgepotential.adaptivecreaturescaling", "Adaptive Creature Scaling", "1.3.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class AdaptiveCreatureScalingPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Character), "RPC_Damage")] private static class CreatureDamageScalingPatch { private static void Prefix(Character __instance, HitData hit) { if (!((Object)(object)__instance == (Object)null) && __instance.IsPlayer() && hit != null && IsScalableCreature(hit.GetAttacker())) { float damageMultiplier = GetDamageMultiplier(GetMaximumQuality()); if (damageMultiplier > 1f) { ((DamageTypes)(ref hit.m_damage)).Modify(damageMultiplier); } } } } public const string PluginGuid = "com.forgepotential.adaptivecreaturescaling"; public const string PluginName = "Adaptive Creature Scaling"; public const string PluginVersion = "1.3.1"; private const string PotentialDraughtPluginGuid = "com.forgepotential.potentialdraught"; private const string PotentialDraughtPluginType = "PotentialDraught.PotentialDraughtPlugin, PotentialDraught"; private const int DefaultReferenceQuality = 25; private const string CreatureBaseHealthZdoKey = "ACS_BaseMaxHealth"; private const string CreatureScaledQualityZdoKey = "ACS_ScaledQuality"; private const string BossStarRollCompletedZdoKey = "ACS_BossStarRollCompleted"; private const string BossStarLevelZdoKey = "ACS_BossStarLevel"; private const float UpdateInterval = 2f; private static readonly FieldInfo CharacterNetViewField = AccessTools.Field(typeof(Character), "m_nview"); private static ConfigEntry<int> _baselineQuality; private static ConfigEntry<int> _maximumQuality; private static ConfigEntry<bool> _autoDetectUpgradeCap; private static ConfigEntry<int> _referenceQuality; private static ConfigEntry<float> _maximumHealthMultiplier; private static ConfigEntry<float> _maximumDamageMultiplier; private static ConfigEntry<bool> _scaleBosses; private static ConfigEntry<bool> _enableBossStars; private static ConfigEntry<float> _oneStarBossChance; private static ConfigEntry<float> _twoStarBossChance; private Harmony _harmony; private float _updateTimer; private int _lastReportedMaximumQuality = int.MinValue; private void Awake() { //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown _baselineQuality = ((BaseUnityPlugin)this).Config.Bind<int>("Scaling", "BaselineItemQuality", 4, "The highest item quality that uses unmodified vanilla creature balance."); _maximumQuality = ((BaseUnityPlugin)this).Config.Bind<int>("Scaling", "MaximumItemQuality", 25, "Fallback upgrade ceiling used when automatic Potential Draught cap detection is disabled or unavailable."); _autoDetectUpgradeCap = ((BaseUnityPlugin)this).Config.Bind<bool>("Scaling", "AutoDetectUpgradeCap", true, "Automatically use Potential Draught's compiled Forge upgrade cap when that mod is installed."); _referenceQuality = ((BaseUnityPlugin)this).Config.Bind<int>("Scaling", "ReferenceItemQuality", 25, "The item quality at which MaximumHealthMultiplier and MaximumDamageMultiplier are reached. Higher detected caps extrapolate the same curve."); _maximumHealthMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Scaling", "MaximumHealthMultiplier", 3f, "Creature maximum-health multiplier when nearby equipment reaches MaximumItemQuality."); _maximumDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Scaling", "MaximumDamageMultiplier", 2f, "Creature damage multiplier against a player whose equipment reaches MaximumItemQuality."); _scaleBosses = ((BaseUnityPlugin)this).Config.Bind<bool>("Scaling", "ScaleBosses", true, "Whether bosses use adaptive health and damage scaling."); _enableBossStars = ((BaseUnityPlugin)this).Config.Bind<bool>("Boss Stars", "Enabled", true, "Whether naturally spawned unstarred bosses receive a one-time star roll."); _oneStarBossChance = ((BaseUnityPlugin)this).Config.Bind<float>("Boss Stars", "OneStarChancePercent", 10f, "Chance that a naturally spawned unstarred boss becomes a one-star boss."); _twoStarBossChance = ((BaseUnityPlugin)this).Config.Bind<float>("Boss Stars", "TwoStarChancePercent", 2f, "Chance that a naturally spawned unstarred boss becomes a two-star boss. This roll takes priority over one star."); _harmony = new Harmony("com.forgepotential.adaptivecreaturescaling"); _harmony.PatchAll(Assembly.GetExecutingAssembly()); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Adaptive Creature Scaling 1.3.1 loaded. All hostile creatures use the " + $"quality-{GetMaximumQuality()} difficulty tier ({GetMaximumQualitySource()}).")); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 _updateTimer += Time.unscaledDeltaTime; if (_updateTimer < 2f) { return; } _updateTimer = 0f; if (!((Object)(object)ZNet.instance == (Object)null) && (int)ZNet.GetConnectionStatus() == 2) { ScaleOwnedCreatures(); int maximumQuality = GetMaximumQuality(); if (maximumQuality != _lastReportedMaximumQuality) { _lastReportedMaximumQuality = maximumQuality; ((BaseUnityPlugin)this).Logger.LogInfo((object)($"Creature scaling target is now quality {maximumQuality} " + "(" + GetMaximumQualitySource() + "): " + $"{GetHealthMultiplier(maximumQuality):0.###}x health, " + $"{GetDamageMultiplier(maximumQuality):0.###}x damage.")); } } } private static ZNetView GetNetView(Character character) { if (!((Object)(object)character == (Object)null)) { object? obj = CharacterNetViewField?.GetValue(character); return (ZNetView)((obj is ZNetView) ? obj : null); } return null; } private static int GetMaximumQuality() { int num = Mathf.Max(1, _baselineQuality?.Value ?? 4); ConfigEntry<bool> autoDetectUpgradeCap = _autoDetectUpgradeCap; if ((autoDetectUpgradeCap == null || autoDetectUpgradeCap.Value) && TryGetPotentialDraughtMaximumQuality(out var quality)) { return Mathf.Max(num + 1, quality); } return Mathf.Max(num + 1, _maximumQuality?.Value ?? 25); } private static bool TryGetPotentialDraughtMaximumQuality(out int quality) { quality = 0; Type type = Type.GetType("PotentialDraught.PotentialDraughtPlugin, PotentialDraught", throwOnError: false); if (type == null && Chainloader.PluginInfos.TryGetValue("com.forgepotential.potentialdraught", out var value)) { type = ((object)value.Instance)?.GetType(); } PropertyInfo propertyInfo = type?.GetProperty("MaximumItemQuality", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = null; if (propertyInfo != null) { try { obj = propertyInfo.GetValue(null, null); } catch { } } FieldInfo fieldInfo = type?.GetField("DefaultForgeMaxQuality", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (obj == null && fieldInfo == null) { return false; } if (obj == null) { obj = (fieldInfo.IsLiteral ? fieldInfo.GetRawConstantValue() : fieldInfo.GetValue(null)); } if (!(obj is int num) || num < 1) { return false; } quality = num; return true; } private static string GetMaximumQualitySource() { ConfigEntry<bool> autoDetectUpgradeCap = _autoDetectUpgradeCap; if ((autoDetectUpgradeCap != null && !autoDetectUpgradeCap.Value) || !TryGetPotentialDraughtMaximumQuality(out var _)) { return "MaximumItemQuality fallback"; } return "Potential Draught auto-detection"; } private static float GetProgress(int quality) { int num = Mathf.Max(1, _baselineQuality?.Value ?? 4); int num2 = Mathf.Max(num + 1, _referenceQuality?.Value ?? 25); return Mathf.Max(0f, (float)(quality - num) / (float)(num2 - num)); } private static float GetHealthMultiplier(int quality) { return Mathf.Lerp(1f, Mathf.Max(1f, _maximumHealthMultiplier?.Value ?? 3f), GetProgress(quality)); } private static float GetDamageMultiplier(int quality) { return Mathf.Lerp(1f, Mathf.Max(1f, _maximumDamageMultiplier?.Value ?? 2f), GetProgress(quality)); } private static bool IsMonsterCreature(Character character) { if ((Object)(object)character != (Object)null && !character.IsPlayer() && !character.IsTamed()) { return (Object)(object)character.GetBaseAI() != (Object)null; } return false; } private static bool IsScalableCreature(Character character) { if (IsMonsterCreature(character)) { if (character.IsBoss()) { return _scaleBosses?.Value ?? true; } return true; } return false; } private static void RollBossStars(Character character, ZDO zdo) { if ((Object)(object)character == (Object)null || zdo == null || !character.IsBoss()) { return; } ConfigEntry<bool> enableBossStars = _enableBossStars; if ((enableBossStars != null && !enableBossStars.Value) || zdo.GetBool("ACS_BossStarRollCompleted", false)) { return; } int num = Mathf.Max(1, character.GetLevel()); if (num > 1) { zdo.Set("ACS_BossStarLevel", num); zdo.Set("ACS_BossStarRollCompleted", true); return; } float num2 = Mathf.Clamp(_twoStarBossChance?.Value ?? 2f, 0f, 100f); float num3 = Mathf.Clamp(_oneStarBossChance?.Value ?? 10f, 0f, 100f - num2); float num4 = Random.Range(0f, 100f); int num5 = ((num4 < num2) ? 3 : ((!(num4 < num2 + num3)) ? 1 : 2)); zdo.Set("ACS_BossStarLevel", num5); zdo.Set("ACS_BossStarRollCompleted", true); if (num5 > 1) { character.SetLevel(num5); zdo.Set("ACS_BaseMaxHealth", character.GetMaxHealth()); } } private static void ScaleOwnedCreatures() { foreach (Character allCharacter in Character.GetAllCharacters()) { if (!IsMonsterCreature(allCharacter) || allCharacter.GetHealth() <= 0f) { continue; } ZNetView netView = GetNetView(allCharacter); if ((Object)(object)netView == (Object)null || !netView.IsValid() || !netView.IsOwner()) { continue; } ZDO zDO = netView.GetZDO(); if (zDO == null) { continue; } RollBossStars(allCharacter, zDO); if (IsScalableCreature(allCharacter)) { float num = zDO.GetFloat("ACS_BaseMaxHealth", 0f); if (num <= 0f) { num = Mathf.Max(1f, allCharacter.GetMaxHealth()); zDO.Set("ACS_BaseMaxHealth", num); } int maximumQuality = GetMaximumQuality(); int num2 = zDO.GetInt("ACS_ScaledQuality", int.MinValue); float num3 = num * GetHealthMultiplier(maximumQuality); float num4 = Mathf.Max(1f, allCharacter.GetMaxHealth()); if (num2 != maximumQuality || !(Mathf.Abs(num4 - num3) < 0.05f)) { float num5 = Mathf.Clamp01(allCharacter.GetHealth() / num4); allCharacter.SetMaxHealth(num3); allCharacter.SetHealth(Mathf.Max(1f, num3 * num5)); zDO.Set("ACS_ScaledQuality", maximumQuality); } } } } } }