[11529] Pack and send to client all gameobject's quaternion components which allows place gameobjects cornerwise.

Update '.gobject turn' command, now you have to specify 3 rotations to turn gameobject: rotation angles around z, y and x axes.
Note to DB devs: use QuaternionCompressed::Unpack to extract rotations from the data that came with UPDATEFLAG_ROTATION.
This commit is contained in:
SilverIce 2011-05-24 03:49:13 +03:00
parent ab50a7d3e9
commit 7c86d3f477
8 changed files with 70 additions and 48 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_11523_02_mangos_mangos_string` bit(1) default NULL `required_11529_01_mangos_command` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -587,7 +587,7 @@ INSERT INTO `command` VALUES
('gobject move',2,'Syntax: .gobject move #goguid [#x #y #z]\r\n\r\nMove gameobject #goguid to character coordinates (or to (#x,#y,#z) coordinates if its provide).'), ('gobject move',2,'Syntax: .gobject move #goguid [#x #y #z]\r\n\r\nMove gameobject #goguid to character coordinates (or to (#x,#y,#z) coordinates if its provide).'),
('gobject near',2,'Syntax: .gobject near [#distance]\r\n\r\nOutput gameobjects at distance #distance from player. Output gameobject guids and coordinates sorted by distance from character. If #distance not provided use 10 as default value.'), ('gobject near',2,'Syntax: .gobject near [#distance]\r\n\r\nOutput gameobjects at distance #distance from player. Output gameobject guids and coordinates sorted by distance from character. If #distance not provided use 10 as default value.'),
('gobject setphase',2,'Syntax: .gobject setphase #guid #phasemask\r\n\r\nGameobject with DB guid #guid phasemask changed to #phasemask with related world vision update for players. Gameobject state saved to DB and persistent.'), ('gobject setphase',2,'Syntax: .gobject setphase #guid #phasemask\r\n\r\nGameobject with DB guid #guid phasemask changed to #phasemask with related world vision update for players. Gameobject state saved to DB and persistent.'),
('gobject turn',2,'Syntax: .gobject turn #goguid \r\n\r\nSet for gameobject #goguid orientation same as current character orientation.'), ('gobject turn',2,'Syntax: .gobject turn #goguid [#z_angle]\r\n\r\nChanges gameobject #goguid orientation (rotates gameobject around z axis). Optional parameters are (#y_angle,#x_angle) values that represents rotation angles around y and x axes.'),
('gobject target',2,'Syntax: .gobject target [#go_id|#go_name_part]\r\n\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.'), ('gobject target',2,'Syntax: .gobject target [#go_id|#go_name_part]\r\n\r\nLocate and show position nearest gameobject. If #go_id or #go_name_part provide then locate and show position of nearest gameobject with gameobject template id #go_id or name included #go_name_part as part.'),
('goname',1,'Syntax: .goname [$charactername]\r\n\r\nTeleport to the given character. Either specify the character name or click on the character\'s portrait, e.g. when you are in a group. Character can be offline.'), ('goname',1,'Syntax: .goname [$charactername]\r\n\r\nTeleport to the given character. Either specify the character name or click on the character\'s portrait, e.g. when you are in a group. Character can be offline.'),
('gps',1,'Syntax: .gps [$name|$shift-link]\r\n\r\nDisplay the position information for a selected character or creature (also if player name $name provided then for named player, or if creature/gameobject shift-link provided then pointed creature/gameobject if it loaded). Position information includes X, Y, Z, and orientation, map Id and zone Id'), ('gps',1,'Syntax: .gps [$name|$shift-link]\r\n\r\nDisplay the position information for a selected character or creature (also if player name $name provided then for named player, or if creature/gameobject shift-link provided then pointed creature/gameobject if it loaded). Position information includes X, Y, Z, and orientation, map Id and zone Id'),

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_11523_02_mangos_mangos_string required_11529_01_mangos_command bit;
DELETE FROM command WHERE name = 'gobject turn';
INSERT INTO command (name, security, help) VALUES
('gobject turn',2,'Syntax: .gobject turn #goguid [#z_angle]\r\n\r\nChanges gameobject #goguid orientation (rotates gameobject around z axis). Optional parameters are (#y_angle,#x_angle) values that represents rotation angles around y and x axes.');

View file

@ -38,6 +38,7 @@
#include "BattleGroundAV.h" #include "BattleGroundAV.h"
#include "Util.h" #include "Util.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include <G3D/Quat.h>
GameObject::GameObject() : WorldObject(), GameObject::GameObject() : WorldObject(),
m_goInfo(NULL), m_goInfo(NULL),
@ -128,10 +129,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
SetObjectScale(goinfo->size); SetObjectScale(goinfo->size);
SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0); SetRotationQuat(rotation0,rotation1,rotation2,rotation3);
SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1);
UpdateRotationFields(rotation2,rotation3); // GAMEOBJECT_FACING, GAMEOBJECT_ROTATION, GAMEOBJECT_PARENTROTATION+2/3
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
@ -1632,34 +1630,60 @@ const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const
return GetName(); return GetName();
} }
void GameObject::UpdateRotationFields(float rotation2 /*=0.0f*/, float rotation3 /*=0.0f*/) using G3D::Quat;
struct QuaternionCompressed
{ {
static double const atan_pow = atan(pow(2.0f, -20.0f)); QuaternionCompressed() : m_raw(0) {}
QuaternionCompressed(int64 val) : m_raw(val) {}
QuaternionCompressed(const Quat& quat) { Set(quat); }
double f_rot1 = sin(GetOrientation() / 2.0f); enum{
double f_rot2 = cos(GetOrientation() / 2.0f); PACK_COEFF_YZ = 1 << 20,
PACK_COEFF_X = 1 << 21,
};
int64 i_rot1 = int64(f_rot1 / atan_pow *(f_rot2 >= 0 ? 1.0f : -1.0f)); void Set(const Quat& quat)
int64 rotation = (i_rot1 << 43 >> 43) & 0x00000000001FFFFF;
//float f_rot2 = sin(0.0f / 2.0f);
//int64 i_rot2 = f_rot2 / atan(pow(2.0f, -20.0f));
//rotation |= (((i_rot2 << 22) >> 32) >> 11) & 0x000003FFFFE00000;
//float f_rot3 = sin(0.0f / 2.0f);
//int64 i_rot3 = f_rot3 / atan(pow(2.0f, -21.0f));
//rotation |= (i_rot3 >> 42) & 0x7FFFFC0000000000;
m_rotation = rotation;
if(rotation2==0.0f && rotation3==0.0f)
{ {
rotation2 = (float)f_rot1; int8 w_sign = (quat.w >= 0 ? 1 : -1);
rotation3 = (float)f_rot2; int64 X = int32(quat.x * PACK_COEFF_X) * w_sign & ((1 << 22) - 1);
int64 Y = int32(quat.y * PACK_COEFF_YZ) * w_sign & ((1 << 21) - 1);
int64 Z = int32(quat.z * PACK_COEFF_YZ) * w_sign & ((1 << 21) - 1);
m_raw = Z | (Y << 21) | (X << 42);
} }
SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); Quat Unpack() const
SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); {
double x = (double)(m_raw >> 42) / (double)PACK_COEFF_X;
double y = (double)(m_raw << 22 >> 43) / (double)PACK_COEFF_YZ;
double z = (double)(m_raw << 43 >> 43) / (double)PACK_COEFF_YZ;
double w = 1 - (x * x + y * y + z * z);
MANGOS_ASSERT(w >= 0);
w = sqrt(w);
return Quat(x,y,z,w);
}
int64 m_raw;
};
void GameObject::SetRotationQuat(float qx, float qy, float qz, float qw)
{
Quat quat(qx, qy, qz, qw);
// Temporary solution for gameobjects that has no rotation data in DB:
if (qz == 0 && qw == 0)
quat = Quat::fromAxisAngleRotation(G3D::Vector3::unitZ(), GetOrientation());
m_rotation = QuaternionCompressed(quat).m_raw;
SetFloatValue(GAMEOBJECT_PARENTROTATION+0, quat.x);
SetFloatValue(GAMEOBJECT_PARENTROTATION+1, quat.y);
SetFloatValue(GAMEOBJECT_PARENTROTATION+2, quat.z);
SetFloatValue(GAMEOBJECT_PARENTROTATION+3, quat.w);
}
void GameObject::SetRotationAngles(float z_rot, float y_rot, float x_rot)
{
Quat quat( G3D::Matrix3::fromEulerAnglesZYX(z_rot, y_rot, x_rot) );
SetRotationQuat(quat.x, quat.y, quat.z, quat.w);
} }
bool GameObject::IsHostileTo(Unit const* unit) const bool GameObject::IsHostileTo(Unit const* unit) const

View file

@ -606,7 +606,9 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
bool HasStaticDBSpawnData() const; // listed in `gameobject` table and have fixed in DB guid bool HasStaticDBSpawnData() const; // listed in `gameobject` table and have fixed in DB guid
void UpdateRotationFields(float rotation2 = 0.0f, float rotation3 = 0.0f); // z_rot, y_rot, x_rot - rotation angles around z, y and x axes
void SetRotationAngles(float z_rot, float y_rot, float x_rot);
int64 GetRotation() const { return m_rotation; }
// overwrite WorldObject function for proper name localization // overwrite WorldObject function for proper name localization
const char* GetNameForLocaleIdx(int32 locale_idx) const; const char* GetNameForLocaleIdx(int32 locale_idx) const;
@ -721,7 +723,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
GridReference<GameObject> &GetGridRef() { return m_gridRef; } GridReference<GameObject> &GetGridRef() { return m_gridRef; }
uint64 GetRotation() const { return m_rotation; }
protected: protected:
uint32 m_spellId; uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()), time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
@ -743,9 +744,10 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
GameObjectInfo const* m_goInfo; GameObjectInfo const* m_goInfo;
GameObjectDisplayInfoEntry const* m_displayInfo; GameObjectDisplayInfoEntry const* m_displayInfo;
uint64 m_rotation; int64 m_rotation;
private: private:
void SwitchDoorOrButton(bool activate, bool alternative = false); void SwitchDoorOrButton(bool activate, bool alternative = false);
void SetRotationQuat(float qx, float qy, float qz, float qw);
GridReference<GameObject> m_gridRef; GridReference<GameObject> m_gridRef;
}; };

View file

@ -958,23 +958,13 @@ bool ChatHandler::HandleGameObjectTurnCommand(char* args)
return false; return false;
} }
float o; float z_rot, y_rot, x_rot;
if (!ExtractOptFloat(&args, o, m_session->GetPlayer()->GetOrientation())) if (!ExtractFloat(&args, z_rot) || !ExtractOptFloat(&args, y_rot, 0) || !ExtractOptFloat(&args, x_rot, 0))
return false; return false;
Map* map = obj->GetMap();
map->Remove(obj,false);
obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
obj->UpdateRotationFields();
map->Add(obj);
obj->SetRotationAngles(z_rot, y_rot, x_rot);
obj->SaveToDB(); obj->SaveToDB();
obj->Refresh();
PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow()); PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, obj->GetGUIDLow(), obj->GetGOInfo()->name, obj->GetGUIDLow());
return true; return true;
} }

View file

@ -511,7 +511,7 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
// 0x200 // 0x200
if(updateFlags & UPDATEFLAG_ROTATION) if(updateFlags & UPDATEFLAG_ROTATION)
{ {
*data << uint64(((GameObject*)this)->GetRotation()); *data << int64(((GameObject*)this)->GetRotation());
} }
} }

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "11528" #define REVISION_NR "11529"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_11436_01_characters_character_queststatus" #define REVISION_DB_CHARACTERS "required_11436_01_characters_character_queststatus"
#define REVISION_DB_MANGOS "required_11523_02_mangos_mangos_string" #define REVISION_DB_MANGOS "required_11529_01_mangos_command"
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__