Store Building, Mob and NPC rotation as a client-order quaternion

AbstractWorldObject.rot (a Vector3f holding one quaternion part) becomes a
Quaternion. Building drops its separate w field; Mob and NPC serialize
through AbstractCharacter.getClientYaw. DB columns are unchanged and are
converted at load and save: building (w, rotY) map to the quaternion's w and
y, npc_rotation (cos of half the yaw) becomes fromYaw(2 acos(value)).

Wire values are meant to be unchanged; a parity run follows. Behaviour kept
on purpose:
- mob_rotation is still not loaded, so every mob defaults to yaw pi as before
- the slot rotation still reads the product's sin as a cos
- /rotate on NPCs and mobs still treats its input as cos of half the yaw

Value changes: building serializer writes the quaternion's x and z instead
of literal zeros (both are 0 for every building); /info "Rot" for NPCs and
mobs prints the quaternion y (sin of half the yaw) instead of the stored cos.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MagicBotandClaude Opus 5.5 committed 2026-10-27 06:40:59 -04:00
1 parent 2078a5c344
commit bb76596a9a
11 files changed
+77 -94

No files matched your search

+7 -17
View File
@@ -24,6 +24,7 @@ import engine.job.JobScheduler;
import engine.jobs.DoorCloseJob;
import engine.jobs.SiegeSpireWithdrawlJob;
import engine.math.Bounds;
import engine.math.Quaternion;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
@@ -85,7 +86,6 @@ public class Building extends AbstractWorldObject {
public ArrayList<Vector3fImmutable> patrolPoints;
public ProtectionState protectionState = ProtectionState.NONE;
protected Resists resists;
private float w = 1.0f;
private Vector3f meshScale = new Vector3f(1.0f, 1.0f, 1.0f);
private int doorState = 0;
private int ownerUUID = 0; //NPC or Character--check ownerIsNPC flag
@@ -128,8 +128,7 @@ public class Building extends AbstractWorldObject {
this.ownerUUID = rs.getInt("ownerUUID");
this.doorState = rs.getInt("doorState");
this.setHealth(rs.getInt("currentHP"));
this.w = rs.getFloat("w");
this.setRot(new Vector3f(0f, rs.getFloat("rotY"), 0f));
this.setRotation(new Quaternion(0f, rs.getFloat("rotY"), 0f, rs.getFloat("w")));
this.reverseKOS = rs.getByte("reverseKOS") == 1;
this.statLat = rs.getFloat("locationX");
this.statAlt = rs.getFloat("locationY");
@@ -207,8 +206,7 @@ public class Building extends AbstractWorldObject {
building._strongboxValue = currentGold;
building.maxGold = 15000000;
building.rank = rank;
building.w = w;
building.setRot(new Vector3f(0f, rotY, 0f));
building.setRotation(new Quaternion(0f, rotY, 0f, w));
building.parentBuildingID = 0;
building.floor = -1;
building.level = -1;
@@ -261,11 +259,11 @@ public class Building extends AbstractWorldObject {
writer.putFloat(building.getLoc().getZ());
}
writer.putFloat(building.w);
writer.putFloat(0f);
writer.putFloat(building.getRot().y);
writer.putFloat(building.getRotation().w);
writer.putFloat(building.getRotation().x);
writer.putFloat(building.getRotation().y);
writer.putFloat(building.getRotation().z);
writer.putFloat(0f);
writer.putFloat(building.meshScale.getX());
writer.putFloat(building.meshScale.getY());
writer.putFloat(building.meshScale.getZ());
@@ -752,14 +750,6 @@ public class Building extends AbstractWorldObject {
this.healthMax = maxHealth;
}
public final void setw(float value) {
this.w = value;
}
public final float getw() {
return this.w;
}
public final Vector3f getMeshScale() {
return this.meshScale;
}