fix(DB/Gameobject): Recalculate quaternion rotation values from orientation (#24617)

This commit is contained in:
blinkysc
2026-02-06 14:41:08 -06:00
committed by GitHub
parent 653136e311
commit 9b63cde7cb
8 changed files with 105 additions and 41 deletions

View File

@@ -0,0 +1,2 @@
-- Recalculate quaternion rotation from orientation for unverified gameobjects
UPDATE `gameobject` SET `rotation2` = SIN(`orientation` / 2), `rotation3` = COS(`orientation` / 2) WHERE `rotation0` = 0 AND `rotation1` = 0 AND (`VerifiedBuild` IS NULL OR `VerifiedBuild` = 0);

View File

@@ -0,0 +1,67 @@
-- Add transport parent_rotation values (from TrinityCore/UDB)
DELETE FROM `gameobject_addon` WHERE `guid` IN (14139,16760,16761,16871,20505,24055,24074,24075,25138,34057,35693,35694,55230,56744,56937,56954,56961,57132,57133,57140,57141,57799,57992,57993,57994,57995,57996,58299,58304,58305,58306,58310,58782,58824,58935,59160,59328,59336,59343,59350,59386,59762,59763,59764,59765,59766,59779,59780,59781,59782,59783,60421,60463,61053,65435,65436,65438,65439,65520,66717,67873,67874,67875,67876);
INSERT INTO `gameobject_addon` (`guid`,`parent_rotation0`,`parent_rotation1`,`parent_rotation2`,`parent_rotation3`,`invisibilityType`,`invisibilityValue`) VALUES
(14139,0,0,1,-0.0000000437114,0,0),
(16760,0,0,-0.378575,0.92557,0,0),
(16761,0,0,-0.378575,0.92557,0,0),
(16871,0,0,0.694658,0.71934,0,0),
(20505,0,0,-0.694658,0.71934,0,0),
(24055,0,0,-0.526214,0.850352,0,0),
(24074,0,0,-0.526214,0.850352,0,0),
(24075,0,0,-0.526214,0.850352,0,0),
(25138,0,0,0.45399,0.891007,0,0),
(34057,0,0,0.000000325841,1,0,0),
(35693,0,0,0.989651,0.143493,0,0),
(35694,0,0,0.989651,0.143493,0,0),
(55230,0,0,0.999048,0.0436193,0,0),
(56744,0,0,0.951057,0.309017,0,0),
(56937,0,0,0.951057,0.309017,0,0),
(56954,0,0,0.951057,0.309017,0,0),
(56961,0,0,0.999048,0.0436193,0,0),
(57132,-0.00276125,-0.00551835,-0.370553,0.928791,0,0),
(57133,0.00544418,-0.00290476,0.918772,0.394739,0,0),
(57140,-0.00276125,-0.00551835,-0.370553,0.928791,0,0),
(57141,0.00544418,-0.00290476,0.918772,0.394739,0,0),
(57799,0,0,0.999048,0.0436193,0,0),
(57992,0,0,-0.370557,0.92881,0,0),
(57993,0,0,-0.760406,0.649448,0,0),
(57994,0,0,0.915312,0.402747,0,0),
(57995,0,0,-0.748956,0.66262,0,0),
(57996,0,0,0.995805,0.0915015,0,0),
(58299,0,0,0.999048,0.0436193,0,0),
(58304,0,0,-0.263031,0.964787,0,0),
(58305,0,0,0.522499,0.85264,0,0),
(58306,0,0,0.996917,-0.0784592,0,0),
(58310,0,0,0.333807,0.942641,0,0),
(58782,0,0,0.333807,0.942641,0,0),
(58824,0,0,0.333807,0.942641,0,0),
(58935,0,0,0.932008,-0.362438,0,0),
(59160,0,0,0.99999,0.00436324,0,0),
(59328,0,0,0.99999,-0.00436333,0,0),
(59336,0,0,0.99999,-0.00436333,0,0),
(59343,0,0,0.99999,-0.00436333,0,0),
(59350,0,0,0.99999,-0.00436333,0,0),
(59386,0,0,0.99999,-0.00436333,0,0),
(59762,0,0,-0.370557,0.92881,0,0),
(59763,0,0,-0.760406,0.649448,0,0),
(59764,0,0,0.915312,0.402747,0,0),
(59765,0,0,-0.748956,0.66262,0,0),
(59766,0,0,0.995805,0.0915015,0,0),
(59779,0,0,-0.370557,0.92881,0,0),
(59780,0,0,-0.760406,0.649448,0,0),
(59781,0,0,0.915312,0.402747,0,0),
(59782,0,0,-0.748956,0.66262,0,0),
(59783,0,0,0.995805,0.0915015,0,0),
(60421,0,0,0.99999,0.00436324,0,0),
(60463,0,0,0.999048,0.0436193,0,0),
(61053,0,0,0.999048,0.0436193,0,0),
(65435,0,0,0.915312,0.402747,0,0),
(65436,0,0,0.99999,0.00436324,0,0),
(65438,0,0,0.915312,0.402747,0,0),
(65439,0,0,0.915312,0.402747,0,0),
(65520,0,0,0.99999,0.00436324,0,0),
(66717,0,0,0.999657,0.0261769,0,0),
(67873,-0.00276125,-0.00551835,-0.370553,0.928791,0,0),
(67874,0.00544418,-0.00290476,0.918772,0.394739,0,0),
(67875,-0.00276125,-0.00551835,-0.370553,0.928791,0,0),
(67876,0.00544418,-0.00290476,0.918772,0.394739,0,0);

View File

@@ -840,7 +840,8 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z
// Create gameobject
GameObject* go = sObjectMgr->IsGameObjectStaticTransport(entry) ? new StaticTransport() : new GameObject();
if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, x, y, z, o, G3D::Quat(), 100, GO_STATE_READY))
G3D::Quat rotation = G3D::Quat::fromAxisAngleRotation(G3D::Vector3::unitZ(), o);
if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, x, y, z, o, rotation, 100, GO_STATE_READY))
{
LOG_ERROR("sql.sql", "Battlefield::SpawnGameObject: Gameobject template {} not found in database! Battlefield not created!", entry);
LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Cannot create gameobject template {}! Battlefield not created!", entry);

View File

@@ -298,7 +298,7 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
return false;
}
SetLocalRotation(rotation);
SetWorldRotation(rotation);
GameObjectAddon const* gameObjectAddon = sObjectMgr->GetGameObjectAddon(GetSpawnId());
QuaternionData parentRotation;
@@ -1038,7 +1038,7 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool
data.posY = GetPositionY();
data.posZ = GetPositionZ();
data.orientation = GetOrientation();
data.rotation = m_localRotation;
data.rotation = WorldRotation;
data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime;
data.animprogress = GetGoAnimProgress();
data.go_state = GetGoState();
@@ -1064,10 +1064,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool
stmt->SetData(index++, GetPositionY());
stmt->SetData(index++, GetPositionZ());
stmt->SetData(index++, GetOrientation());
stmt->SetData(index++, m_localRotation.x);
stmt->SetData(index++, m_localRotation.y);
stmt->SetData(index++, m_localRotation.z);
stmt->SetData(index++, m_localRotation.w);
stmt->SetData(index++, WorldRotation.x);
stmt->SetData(index++, WorldRotation.y);
stmt->SetData(index++, WorldRotation.z);
stmt->SetData(index++, WorldRotation.w);
stmt->SetData(index++, int32(m_respawnDelayTime));
stmt->SetData(index++, GetGoAnimProgress());
stmt->SetData(index++, uint8(GetGoState()));
@@ -2199,24 +2199,18 @@ void GameObject::UpdatePackedRotation()
static const int32 PACK_X = PACK_YZ << 1;
static const int32 PACK_YZ_MASK = (PACK_YZ << 1) - 1;
static const int32 PACK_X_MASK = (PACK_X << 1) - 1;
int8 w_sign = (m_localRotation.w >= 0.f ? 1 : -1);
int64 x = int32(m_localRotation.x * PACK_X) * w_sign & PACK_X_MASK;
int64 y = int32(m_localRotation.y * PACK_YZ) * w_sign & PACK_YZ_MASK;
int64 z = int32(m_localRotation.z * PACK_YZ) * w_sign & PACK_YZ_MASK;
int8 w_sign = (WorldRotation.w >= 0.f ? 1 : -1);
int64 x = int32(WorldRotation.x * PACK_X) * w_sign & PACK_X_MASK;
int64 y = int32(WorldRotation.y * PACK_YZ) * w_sign & PACK_YZ_MASK;
int64 z = int32(WorldRotation.z * PACK_YZ) * w_sign & PACK_YZ_MASK;
m_packedRotation = z | (y << 21) | (x << 42);
}
void GameObject::SetLocalRotation(G3D::Quat const& rot)
void GameObject::SetWorldRotation(G3D::Quat const& rot)
{
G3D::Quat rotation;
// Temporary solution for gameobjects that have no rotation data in DB:
if (G3D::fuzzyEq(rot.z, 0.f) && G3D::fuzzyEq(rot.w, 0.f))
rotation = G3D::Quat::fromAxisAngleRotation(G3D::Vector3::unitZ(), GetOrientation());
else
rotation = rot;
G3D::Quat rotation = rot;
rotation.unitize();
m_localRotation = rotation;
WorldRotation = rotation;
UpdatePackedRotation();
}
@@ -2228,26 +2222,26 @@ void GameObject::SetTransportPathRotation(float qx, float qy, float qz, float qw
SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, qw);
}
void GameObject::SetLocalRotationAngles(float z_rot, float y_rot, float x_rot)
void GameObject::SetWorldRotationAngles(float z_rot, float y_rot, float x_rot)
{
SetLocalRotation(G3D::Quat(G3D::Matrix3::fromEulerAnglesZYX(z_rot, y_rot, x_rot)));
SetWorldRotation(G3D::Quat(G3D::Matrix3::fromEulerAnglesZYX(z_rot, y_rot, x_rot)));
}
G3D::Quat GameObject::GetWorldRotation() const
G3D::Quat GameObject::GetFinalWorldRotation() const
{
G3D::Quat localRotation = GetLocalRotation();
G3D::Quat worldRotation = GetWorldRotation();
if (Transport* transport = GetTransport())
{
G3D::Quat worldRotation = transport->GetWorldRotation();
G3D::Quat transportRotation = transport->GetWorldRotation();
G3D::Quat transportRotationQuat(transportRotation.x, transportRotation.y, transportRotation.z, transportRotation.w);
G3D::Quat worldRotationQuat(worldRotation.x, worldRotation.y, worldRotation.z, worldRotation.w);
G3D::Quat localRotationQuat(localRotation.x, localRotation.y, localRotation.z, localRotation.w);
G3D::Quat resultRotation = localRotationQuat * worldRotationQuat;
G3D::Quat resultRotation = worldRotationQuat * transportRotationQuat;
return G3D::Quat(resultRotation.x, resultRotation.y, resultRotation.z, resultRotation.w);
}
return localRotation;
return worldRotation;
}
void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= nullptr*/, uint32 spellId /*= 0*/)
@@ -2967,10 +2961,10 @@ bool GameObject::IsAtInteractDistance(Position const& pos, float radius) const
float maxY = displayInfo->maxY * scale + radius;
float maxZ = displayInfo->maxZ * scale + radius;
G3D::Quat worldRotation = GetWorldRotation();
G3D::Quat worldRotationQuat(worldRotation.x, worldRotation.y, worldRotation.z, worldRotation.w);
G3D::Quat finalRotation = GetFinalWorldRotation();
G3D::Quat finalRotationQuat(finalRotation.x, finalRotation.y, finalRotation.z, finalRotation.w);
return G3D::CoordinateFrame {{worldRotationQuat}, {GetPositionX(), GetPositionY(), GetPositionZ()}}.toWorldSpace(G3D::Box {{minX, minY, minZ}, {maxX, maxY, maxZ}}).contains({pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()});
return G3D::CoordinateFrame {{finalRotationQuat}, {GetPositionX(), GetPositionY(), GetPositionZ()}}.toWorldSpace(G3D::Box {{minX, minY, minZ}, {maxX, maxY, maxZ}}).contains({pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()});
}
return GetExactDist(&pos) <= radius;

View File

@@ -144,12 +144,12 @@ public:
[[nodiscard]] ObjectGuid::LowType GetSpawnId() const { return m_spawnId; }
// z_rot, y_rot, x_rot - rotation angles around z, y and x axes
void SetLocalRotationAngles(float z_rot, float y_rot, float x_rot);
void SetLocalRotation(G3D::Quat const& rot);
void SetWorldRotationAngles(float z_rot, float y_rot, float x_rot);
void SetWorldRotation(G3D::Quat const& rot);
void SetTransportPathRotation(float qx, float qy, float qz, float qw);
[[nodiscard]] G3D::Quat const& GetLocalRotation() const { return m_localRotation; }
[[nodiscard]] int64 GetPackedLocalRotation() const { return m_packedRotation; }
[[nodiscard]] G3D::Quat GetWorldRotation() const;
[[nodiscard]] G3D::Quat const& GetWorldRotation() const { return WorldRotation; }
[[nodiscard]] int64 GetPackedWorldRotation() const { return m_packedRotation; }
[[nodiscard]] G3D::Quat GetFinalWorldRotation() const;
// overwrite WorldObject function for proper name localization
[[nodiscard]] std::string const& GetNameForLocaleIdx(LocaleConstant locale_idx) const override;
@@ -394,7 +394,7 @@ protected:
bool m_allowModifyDestructibleBuilding;
int64 m_packedRotation;
G3D::Quat m_localRotation;
G3D::Quat WorldRotation;
Position m_stationaryPosition;
ObjectGuid m_lootRecipient;

View File

@@ -479,7 +479,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
// 0x200
if (flags & UPDATEFLAG_ROTATION)
{
*data << int64(ToGameObject()->GetPackedLocalRotation());
*data << int64(ToGameObject()->GetPackedWorldRotation());
}
}

View File

@@ -99,7 +99,7 @@ bool MotionTransport::CreateMoTrans(ObjectGuid::LowType guidlow, uint32 entry, u
SetName(goinfo->name);
// pussywizard: no WorldRotation for MotionTransports
SetLocalRotation(G3D::Quat());
SetWorldRotation(G3D::Quat());
// pussywizard: no PathRotation for MotionTransports
SetTransportPathRotation(0.0f, 0.0f, 0.0f, 1.0f);
@@ -768,7 +768,7 @@ bool StaticTransport::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* m
// pussywizard: temporarily calculate WorldRotation from orientation, do so until values in db are correct
//SetWorldRotation( /*for StaticTransport we need 2 rotation Quats in db for World- and Path- Rotation*/ );
SetLocalRotationAngles(NormalizeOrientation(GetOrientation()), 0.0f, 0.0f);
SetWorldRotationAngles(NormalizeOrientation(GetOrientation()), 0.0f, 0.0f);
// pussywizard: PathRotation for StaticTransport (only StaticTransports have PathRotation)
SetTransportPathRotation(rotation.x, rotation.y, rotation.z, rotation.w);

View File

@@ -332,7 +332,7 @@ public:
Map* map = object->GetMap();
object->Relocate(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), *oz);
object->SetLocalRotationAngles(*oz, oy.value_or(0.0f), ox.value_or(0.0f));
object->SetWorldRotationAngles(*oz, oy.value_or(0.0f), ox.value_or(0.0f));
object->SaveToDB();
// Generate a completely new spawn with new guid