From 3a1450286f97d4187464b4274f1264f01e705c5a Mon Sep 17 00:00:00 2001 From: MagicBot Date: Sat, 24 Oct 2026 11:39:36 -0400 Subject: [PATCH] Take mob scale from the race rune instead of static_npc_mobbase.scale The client builds a mob's scale from its race rune SCALEFACTOR (ArcCharacter_BuildCharFromRune 0x458160) and overwrites the three floats the server sends, so the DB column (always 1) never had a visible effect. MobBase now holds rune_scale_factor (1,1,1 when absent) and the mob message sends it. No client-visible change. The column drop is sql/3.7-mobbase-scale-drop.sql, to run after this build is deployed. Co-Authored-By: Claude Opus 5.5 --- src/engine/objects/Mob.java | 6 +++--- src/engine/objects/MobBase.java | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java index bc9fc53a..3e6fe3c3 100644 --- a/src/engine/objects/Mob.java +++ b/src/engine/objects/Mob.java @@ -227,9 +227,9 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { writer.putInt(mob.currentID); if (mob.mobBase != null) { - writer.putFloat(mob.mobBase.getScale()); - writer.putFloat(mob.mobBase.getScale()); - writer.putFloat(mob.mobBase.getScale()); + writer.putFloat(mob.mobBase.getScale().x); + writer.putFloat(mob.mobBase.getScale().y); + writer.putFloat(mob.mobBase.getScale().z); } else { writer.putFloat(1.0f); writer.putFloat(1.0f); diff --git a/src/engine/objects/MobBase.java b/src/engine/objects/MobBase.java index d948a0ac..244c00f5 100644 --- a/src/engine/objects/MobBase.java +++ b/src/engine/objects/MobBase.java @@ -13,6 +13,7 @@ import engine.gameManager.DbManager; import engine.gameManager.ItemManager; import engine.gameManager.LootManager; import engine.loot.BootySetEntry; +import engine.math.Vector3fImmutable; import engine.mbEnums; import engine.parsers.cache.CacheParserUtil; import engine.parsers.objects.RuneTemplate; @@ -29,7 +30,7 @@ public class MobBase extends AbstractGameObject { private final String firstName; private final byte level; - private final float scale; + private final Vector3fImmutable scale; public final ArrayList effectsList; public int bootySet; public mbEnums.MobBehaviourType fsm; @@ -84,6 +85,7 @@ public class MobBase extends AbstractGameObject { this.walkCombat = rune.rune_speed.getOrDefault(mbEnums.MovementType.COMBATWALK, 0f); this.run = rune.rune_speed.getOrDefault(mbEnums.MovementType.RUN, 0f); this.runCombat = rune.rune_speed.getOrDefault(mbEnums.MovementType.COMBATRUN, 0f); + this.scale = (rune.rune_scale_factor != null) ? rune.rune_scale_factor : new Vector3fImmutable(1, 1, 1); } else { Logger.error("Mobbase " + this.getObjectUUID() + " has no race rune"); this.firstName = ""; @@ -91,6 +93,7 @@ public class MobBase extends AbstractGameObject { this.fsm = mbEnums.MobBehaviourType.None; this.notEnemy = EnumSet.noneOf(mbEnums.MonsterType.class); this.enemy = EnumSet.noneOf(mbEnums.MonsterType.class); + this.scale = new Vector3fImmutable(1, 1, 1); } this.goldMod = rs.getInt("goldMod"); @@ -101,7 +104,6 @@ public class MobBase extends AbstractGameObject { this.flags = mbEnums.fromLong(rs.getLong("flags"), mbEnums.MobFlagType.class); this.seeInvis = rs.getInt("seeInvis"); - this.scale = rs.getFloat("scale"); this.hitBoxRadius = 5f; this.mask = 0; @@ -197,7 +199,8 @@ public class MobBase extends AbstractGameObject { return this.flags; } - public float getScale() { + // Cosmetic only: the client rebuilds a mob's scale from its race rune (ArcCharacter_BuildCharFromRune 0x458160) + public Vector3fImmutable getScale() { return this.scale; }