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:
1 parent
2078a5c344
commit
bb76596a9a
11 files changed
+77
-94
No files matched your search
@@ -64,8 +64,8 @@ public class dbBuildingHandler extends dbHandlerBase {
|
||||
preparedStatement.setNull(13, java.sql.Types.DATE);
|
||||
|
||||
preparedStatement.setInt(14, building.getBlueprintUUID());
|
||||
preparedStatement.setFloat(15, building.getw());
|
||||
preparedStatement.setFloat(16, building.getRot().y);
|
||||
preparedStatement.setFloat(15, building.getRotation().w);
|
||||
preparedStatement.setFloat(16, building.getRotation().y);
|
||||
|
||||
ResultSet rs = preparedStatement.executeQuery();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mbEnums.ProtectionState;
|
||||
import engine.objects.*;
|
||||
@@ -54,8 +54,7 @@ public class AddBuildingCmd extends AbstractDevCmd {
|
||||
"Invalid addBuilding Command. Invalid Building ID.");
|
||||
return;
|
||||
}
|
||||
Vector3f rot = new Vector3f(0.0f, 0.0f, 0.0f);
|
||||
float w = 1f;
|
||||
Quaternion rotation = new Quaternion();
|
||||
Zone zone = ZoneManager.findSmallestZone(pc.getLoc());
|
||||
|
||||
if (zone == null) {
|
||||
@@ -73,8 +72,7 @@ public class AddBuildingCmd extends AbstractDevCmd {
|
||||
Building likeBuilding = DbManager.BuildingQueries.GET_BUILDING_BY_MESH(ID);
|
||||
|
||||
if (likeBuilding != null) {
|
||||
rot = likeBuilding.getRot();
|
||||
w = likeBuilding.getw();
|
||||
rotation = likeBuilding.getRotation();
|
||||
}
|
||||
|
||||
String buildingName = "";
|
||||
@@ -93,7 +91,7 @@ public class AddBuildingCmd extends AbstractDevCmd {
|
||||
Building building = Building.persistBuilding(Building.createBuilding(
|
||||
zone, 0, buildingName, ID,
|
||||
localLoc, 1.0f, 0, ProtectionState.PROTECTED, 0, rank,
|
||||
null, blueprintUUID, w, rot.y));
|
||||
null, blueprintUUID, rotation.w, rotation.y));
|
||||
|
||||
|
||||
if (building == null) {
|
||||
@@ -101,9 +99,6 @@ public class AddBuildingCmd extends AbstractDevCmd {
|
||||
return;
|
||||
}
|
||||
|
||||
building.setRot(rot);
|
||||
building.setw(w);
|
||||
|
||||
building.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
|
||||
WorldGrid.addObject(building, pc);
|
||||
ChatManager.chatSayInfo(pc,
|
||||
|
||||
@@ -88,7 +88,7 @@ public class InfoCmd extends AbstractDevCmd {
|
||||
output += newline;
|
||||
output += StringUtils.addWS("Alt: " + targetLoc.y, 20);
|
||||
output += newline;
|
||||
output += "Rot: " + targetAWO.getRot().y;
|
||||
output += "Rot: " + targetAWO.getRotation().y;
|
||||
output += newline;
|
||||
double radian = 0;
|
||||
|
||||
@@ -106,7 +106,7 @@ public class InfoCmd extends AbstractDevCmd {
|
||||
case Building:
|
||||
Building targetBuilding = (Building) target;
|
||||
output += StringUtils.addWS("Lac: "
|
||||
+ targetBuilding.getw(), 20);
|
||||
+ targetBuilding.getRotation().w, 20);
|
||||
output += "Blueprint : ";
|
||||
output += targetBuilding.getBlueprintUUID();
|
||||
output += newline;
|
||||
|
||||
@@ -14,7 +14,7 @@ import engine.devcmd.AbstractDevCmd;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.objects.*;
|
||||
|
||||
@@ -63,14 +63,12 @@ public class RotateCmd extends AbstractDevCmd {
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3f rotation = new Vector3f(0f, rot, 0f);
|
||||
|
||||
if (target instanceof Building)
|
||||
rotateBuilding(pc, (Building) target, rotation, rot, false);
|
||||
rotateBuilding(pc, (Building) target, rot);
|
||||
else if (target instanceof NPC)
|
||||
rotateNPC(pc, (NPC) target, rotation, false);
|
||||
rotateNPC(pc, (NPC) target, rot);
|
||||
else if (target instanceof Mob)
|
||||
rotateMob(pc, (Mob) target, rotation, false);
|
||||
rotateMob(pc, (Mob) target, rot);
|
||||
else
|
||||
throwbackError(pc, "Target " + target.getObjectType()
|
||||
+ " is not a valid object type");
|
||||
@@ -141,15 +139,13 @@ public class RotateCmd extends AbstractDevCmd {
|
||||
}
|
||||
}
|
||||
|
||||
Vector3f rotation = new Vector3f(0f, rot, 0f);
|
||||
|
||||
Building b;
|
||||
if (id != 0)
|
||||
b = BuildingManager.getBuilding(id);
|
||||
else
|
||||
b = getTargetAsBuilding(pc);
|
||||
if (b != null) {
|
||||
rotateBuilding(pc, b, rotation, rot, false);
|
||||
rotateBuilding(pc, b, rot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -160,7 +156,7 @@ public class RotateCmd extends AbstractDevCmd {
|
||||
else
|
||||
npc = getTargetAsNPC(pc);
|
||||
if (npc != null) {
|
||||
rotateNPC(pc, npc, rotation, false);
|
||||
rotateNPC(pc, npc, rot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -171,7 +167,7 @@ public class RotateCmd extends AbstractDevCmd {
|
||||
else
|
||||
mob = getTargetAsMob(pc);
|
||||
if (mob != null) {
|
||||
rotateMob(pc, mob, rotation, false);
|
||||
rotateMob(pc, mob, rot);
|
||||
return;
|
||||
}
|
||||
throwbackError(pc, "Nothing found to rotate.");
|
||||
@@ -188,31 +184,29 @@ public class RotateCmd extends AbstractDevCmd {
|
||||
return "' /rotate [objectID] rotation' || ' /rot [objectID] rotation'";
|
||||
}
|
||||
|
||||
private void rotateBuilding(PlayerCharacter pc, Building building, Vector3f rot, float orig, boolean faceDirection) {
|
||||
if (!faceDirection)
|
||||
rot.set(0.0f, (float) Math.sin(Math.toRadians(orig) / 2), 0.0f);
|
||||
building.setRot(rot);
|
||||
building.setw((float) Math.abs(Math.cos(Math.toRadians(orig) / 2)));
|
||||
private void rotateBuilding(PlayerCharacter pc, Building building, float orig) {
|
||||
building.setRotation(new Quaternion(0f, (float) Math.sin(Math.toRadians(orig) / 2), 0f,
|
||||
(float) Math.abs(Math.cos(Math.toRadians(orig) / 2))));
|
||||
building.getBounds().setBounds(building);
|
||||
WorldGrid.updateObject(building, pc);
|
||||
DbManager.BuildingQueries.SET_PROPERTY(building, "rotY", building.getRot().getY());
|
||||
DbManager.BuildingQueries.SET_PROPERTY(building, "w", building.getw());
|
||||
DbManager.BuildingQueries.SET_PROPERTY(building, "rotY", building.getRotation().y);
|
||||
DbManager.BuildingQueries.SET_PROPERTY(building, "w", building.getRotation().w);
|
||||
ChatManager.chatSayInfo(pc,
|
||||
"Building with ID " + building.getObjectUUID() + " rotated");
|
||||
}
|
||||
|
||||
private void rotateNPC(PlayerCharacter pc, NPC npc, Vector3f rot, boolean faceDirection) {
|
||||
npc.setRot(rot);
|
||||
DbManager.NPCQueries.SET_PROPERTY(npc, "npc_rotation", rot.y);
|
||||
private void rotateNPC(PlayerCharacter pc, NPC npc, float rot) {
|
||||
npc.setRotation(Quaternion.fromYaw((float) Math.acos(rot) * 2));
|
||||
DbManager.NPCQueries.SET_PROPERTY(npc, "npc_rotation", rot);
|
||||
WorldGrid.updateObject(npc, pc);
|
||||
//no rotation for npc's in db currently
|
||||
ChatManager.chatSayInfo(pc,
|
||||
"NPC with ID " + npc.getObjectUUID() + " rotated");
|
||||
}
|
||||
|
||||
private void rotateMob(PlayerCharacter pc, Mob mob, Vector3f rot, boolean faceDirection) {
|
||||
mob.setRot(rot);
|
||||
DbManager.MobQueries.SET_PROPERTY(mob, "mob_rotation", rot.y);
|
||||
private void rotateMob(PlayerCharacter pc, Mob mob, float rot) {
|
||||
mob.setRotation(Quaternion.fromYaw((float) Math.acos(rot) * 2));
|
||||
DbManager.MobQueries.SET_PROPERTY(mob, "mob_rotation", rot);
|
||||
WorldGrid.updateObject(mob, pc);
|
||||
//no rotation for mobs's in db currently
|
||||
ChatManager.chatSayInfo(pc,
|
||||
@@ -235,14 +229,12 @@ public class RotateCmd extends AbstractDevCmd {
|
||||
if (rot > 180)
|
||||
rot *= -1;
|
||||
|
||||
Vector3f buildingrotation = new Vector3f(0f, rot, 0f);
|
||||
Vector3f rotation = new Vector3f(0f, rotangle, 0f);
|
||||
if (target instanceof Building)
|
||||
rotateBuilding(pc, (Building) target, buildingrotation, rot, false);
|
||||
rotateBuilding(pc, (Building) target, rot);
|
||||
else if (target instanceof NPC)
|
||||
rotateNPC(pc, (NPC) target, rotation, true);
|
||||
rotateNPC(pc, (NPC) target, rotangle);
|
||||
else if (target instanceof Mob)
|
||||
rotateMob(pc, (Mob) target, rotation, true);
|
||||
rotateMob(pc, (Mob) target, rotangle);
|
||||
else
|
||||
throwbackError(pc, "Target " + target.getObjectType()
|
||||
+ " is not a valid object type");
|
||||
|
||||
@@ -11,7 +11,6 @@ package engine.gameManager;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.loot.WorkOrder;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mbEnums;
|
||||
import engine.net.Dispatch;
|
||||
@@ -32,8 +31,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static engine.math.FastMath.acos;
|
||||
|
||||
public enum NPCManager {
|
||||
|
||||
NPC_MANAGER;
|
||||
@@ -227,11 +224,12 @@ public enum NPCManager {
|
||||
|
||||
abstractCharacter.loc = new Vector3fImmutable(abstractCharacter.bindLoc);
|
||||
|
||||
// Rotate NPC rotation by the building's rotation
|
||||
// Rotate NPC rotation by the building's rotation.
|
||||
// Kept for wire parity: the product's sin θ/2 is read back as cos θ/2, so the yaw sent is not own + building.
|
||||
|
||||
Quaternion slotRotation = new Quaternion().fromAngles(0, acos(abstractCharacter.getRot().y) * 2, 0);
|
||||
Quaternion slotRotation = new Quaternion().fromAngles(0, abstractCharacter.getRotation().getYaw(), 0);
|
||||
slotRotation = slotRotation.mult(abstractCharacter.building.getBounds().getQuaternion());
|
||||
abstractCharacter.setRot(new Vector3f(0, slotRotation.y, 0));
|
||||
abstractCharacter.setRotation(Quaternion.fromYaw((float) Math.acos(slotRotation.y) * 2));
|
||||
|
||||
// Configure region and floor/level for this NPC
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ public class Bounds {
|
||||
|
||||
blueprint = building.getBlueprint();
|
||||
|
||||
this.quaternion = new Quaternion(building.getRot().x, building.getRot().y, building.getRot().z, building.getw());
|
||||
this.quaternion = new Quaternion(building.getRotation().x, building.getRotation().y, building.getRotation().z, building.getRotation().w);
|
||||
|
||||
// Calculate Bounds for non-blueprint objects
|
||||
|
||||
@@ -437,7 +437,7 @@ public class Bounds {
|
||||
|
||||
// The rotation is reset after the new aabb is calculated.
|
||||
|
||||
this.rotation = building.getRot().y;
|
||||
this.rotation = building.getRotation().y;
|
||||
|
||||
// Caclculate and set the new half halfExtents for the rotated bounding box
|
||||
// and reset the rotation to 0 for this bounds.
|
||||
@@ -451,7 +451,7 @@ public class Bounds {
|
||||
}
|
||||
|
||||
this.origin.set(building.getLoc().x, building.getLoc().z);
|
||||
this.rotation = building.getRot().y;
|
||||
this.rotation = building.getRotation().y;
|
||||
this.halfExtents.set(blueprint.getExtents());
|
||||
this.flipExtents = Bounds.calculateFlipExtents(this);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import engine.jobs.PersistentAoeJob;
|
||||
import engine.jobs.TrackJob;
|
||||
import engine.math.AtomicFloat;
|
||||
import engine.math.Bounds;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mbEnums;
|
||||
import engine.mbEnums.*;
|
||||
@@ -536,6 +537,18 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
|
||||
|
||||
}
|
||||
|
||||
// The one yaw float LOADCHARACTER carries; a character in a building gets the building's yaw added.
|
||||
public float getClientYaw() {
|
||||
|
||||
float yaw = this.getRotation().getYaw();
|
||||
|
||||
if (this.building != null)
|
||||
if (this.building.getBounds() != null && this.building.getBounds().getQuaternion() != null)
|
||||
yaw += this.building.getBounds().getQuaternion().angleY;
|
||||
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public static void teleport(AbstractCharacter abstractCharacter, final Vector3fImmutable targetLoc) {
|
||||
abstractCharacter.locationLock.writeLock().lock();
|
||||
try {
|
||||
|
||||
@@ -18,7 +18,7 @@ import engine.job.JobScheduler;
|
||||
import engine.jobs.NoTimeJob;
|
||||
import engine.math.AtomicFloat;
|
||||
import engine.math.Bounds;
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mbEnums.DispatchChannel;
|
||||
import engine.mbEnums.EffectSourceType;
|
||||
@@ -56,7 +56,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
|
||||
protected boolean movingUp = false;
|
||||
private String name = "";
|
||||
private byte tier = 0;
|
||||
private Vector3f rot = new Vector3f(0.0f, 0.0f, 0.0f);
|
||||
private Quaternion rotation = new Quaternion();
|
||||
private int objectTypeMask = 0;
|
||||
private Bounds bounds;
|
||||
|
||||
@@ -528,13 +528,13 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
|
||||
|
||||
}
|
||||
|
||||
public Vector3f getRot() {
|
||||
return rot;
|
||||
public Quaternion getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public void setRot(Vector3f rotation) {
|
||||
synchronized (this.rot) {
|
||||
this.rot = rotation;
|
||||
public void setRotation(Quaternion rotation) {
|
||||
synchronized (this.rotation) {
|
||||
this.rotation = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
|
||||
}
|
||||
|
||||
public void setTier(byte tier) {
|
||||
synchronized (this.rot) {
|
||||
synchronized (this.rotation) {
|
||||
this.tier = tier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import engine.job.JobScheduler;
|
||||
import engine.jobs.DeferredPowerJob;
|
||||
import engine.jobs.UpgradeNPCJob;
|
||||
import engine.math.Bounds;
|
||||
import engine.math.FastMath;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mbEnums;
|
||||
import engine.mbEnums.*;
|
||||
@@ -80,6 +82,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
|
||||
// PERSIST.
|
||||
public Mob() {
|
||||
super();
|
||||
this.setRotation(Quaternion.fromYaw(FastMath.PI));
|
||||
this.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||||
this.currentID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||||
this.bindLoc = Vector3fImmutable.ZERO;
|
||||
@@ -99,6 +102,9 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
|
||||
float statAlt;
|
||||
float statLon;
|
||||
|
||||
// mob_rotation is not loaded: the old default (cos θ/2 = 0) faced every mob at yaw π.
|
||||
this.setRotation(Quaternion.fromYaw(FastMath.PI));
|
||||
|
||||
try {
|
||||
this.dbID = rs.getInt(1);
|
||||
this.loadID = rs.getInt("mob_mobbaseID");
|
||||
@@ -240,14 +246,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
|
||||
|
||||
writer.putVector3f(mob.getLoc());
|
||||
|
||||
//Rotation
|
||||
float radians = (float) Math.acos(mob.getRot().y) * 2;
|
||||
|
||||
if (mob.building != null)
|
||||
if (mob.building.getBounds() != null && mob.building.getBounds().getQuaternion() != null)
|
||||
radians += (mob.building.getBounds().getQuaternion()).angleY;
|
||||
|
||||
writer.putFloat(radians);
|
||||
writer.putFloat(mob.getClientYaw());
|
||||
|
||||
//Inventory Stuff
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ import engine.job.JobContainer;
|
||||
import engine.job.JobScheduler;
|
||||
import engine.jobs.UpgradeNPCJob;
|
||||
import engine.math.Bounds;
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.FastMath;
|
||||
import engine.math.Quaternion;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.mbEnums;
|
||||
import engine.mbEnums.*;
|
||||
@@ -80,6 +81,7 @@ public class NPC extends AbstractCharacter {
|
||||
public NPC() {
|
||||
|
||||
super();
|
||||
this.setRotation(Quaternion.fromYaw(FastMath.PI));
|
||||
this.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||||
this.currentID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET;
|
||||
}
|
||||
@@ -118,7 +120,8 @@ public class NPC extends AbstractCharacter {
|
||||
this.buyPercent = .33f;
|
||||
this.sellPercent = 1;
|
||||
|
||||
this.setRot(new Vector3f(0, rs.getFloat("npc_rotation"), 0));
|
||||
// npc_rotation holds cos θ/2
|
||||
this.setRotation(Quaternion.fromYaw((float) Math.acos(rs.getFloat("npc_rotation")) * 2));
|
||||
|
||||
this.statLat = rs.getFloat("npc_spawnX");
|
||||
this.statAlt = rs.getFloat("npc_spawnY");
|
||||
@@ -320,14 +323,7 @@ public class NPC extends AbstractCharacter {
|
||||
else
|
||||
writer.putVector3f(npc.getLoc());
|
||||
|
||||
//Rotation
|
||||
float radians = (float) Math.acos(npc.getRot().y) * 2;
|
||||
|
||||
if (npc.building != null)
|
||||
if (npc.building.getBounds() != null && npc.building.getBounds().getQuaternion() != null)
|
||||
radians += (npc.building.getBounds().getQuaternion()).angleY;
|
||||
|
||||
writer.putFloat(radians);
|
||||
writer.putFloat(npc.getClientYaw());
|
||||
|
||||
//Running Speed
|
||||
writer.putInt(0);
|
||||
|
||||
Reference in new issue
Block a user