aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/GameObject
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Entities/GameObject')
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp94
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h25
2 files changed, 101 insertions, 18 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index eef416b339d..9829b6019de 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <G3D/Quat.h>
#include "GameObjectAI.h"
#include "Battleground.h"
#include "CellImpl.h"
@@ -32,8 +33,10 @@
#include "SpellMgr.h"
#include "UpdateFieldFlags.h"
#include "World.h"
+#include "Transport.h"
-GameObject::GameObject(): WorldObject(false), m_model(NULL), m_goValue(), m_AI(NULL)
+GameObject::GameObject() : WorldObject(false), MapObject(),
+ m_model(NULL), m_goValue(), m_AI(NULL)
{
m_objectType |= TYPEMASK_GAMEOBJECT;
m_objectTypeId = TYPEID_GAMEOBJECT;
@@ -100,6 +103,9 @@ void GameObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
if (m_uint32Values) // field array can be not exist if GameOBject not loaded
RemoveFromOwner();
+
+ if (GetTransport() && !ToTransport())
+ GetTransport()->RemovePassenger(this);
}
void GameObject::RemoveFromOwner()
@@ -169,6 +175,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
SetMap(map);
Relocate(x, y, z, ang);
+ m_stationaryPosition.Relocate(x, y, z, ang);
if (!IsPositionValid())
{
TC_LOG_ERROR(LOG_FILTER_GENERAL, "Gameobject (GUID: %u Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", guidlow, name_id, x, y);
@@ -192,6 +199,9 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
return false;
}
+ if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
+ m_updateFlag = (m_updateFlag | UPDATEFLAG_TRANSPORT) & ~UPDATEFLAG_POSITION;
+
Object::_Create(guidlow, goinfo->entry, HIGHGUID_GAMEOBJECT);
m_goInfo = goinfo;
@@ -238,9 +248,11 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
break;
case GAMEOBJECT_TYPE_TRANSPORT:
SetUInt32Value(GAMEOBJECT_LEVEL, goinfo->transport.pause);
- if (goinfo->transport.startOpen)
- SetGoState(GO_STATE_ACTIVE);
+ SetGoState(goinfo->transport.startOpen ? GO_STATE_ACTIVE : GO_STATE_READY);
SetGoAnimProgress(animprogress);
+ m_goValue.Transport.PathProgress = 0;
+ m_goValue.Transport.AnimationInfo = sTransportMgr->GetTransportAnimInfo(goinfo->entry);
+ m_goValue.Transport.CurrentSeg = 0;
break;
case GAMEOBJECT_TYPE_FISHINGNODE:
SetGoAnimProgress(0);
@@ -274,18 +286,10 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa
void GameObject::Update(uint32 diff)
{
- if (!AI())
- {
- if (!AIM_Initialize())
- TC_LOG_ERROR(LOG_FILTER_GENERAL, "Could not initialize GameObjectAI");
- } else
+ if (AI())
AI()->UpdateAI(diff);
-
- if (IS_MO_TRANSPORT_GUID(GetGUID()))
- {
- //((Transport*)this)->Update(p_time);
- return;
- }
+ else if (!AIM_Initialize())
+ TC_LOG_ERROR(LOG_FILTER_GENERAL, "Could not initialize GameObjectAI");
switch (m_lootState)
{
@@ -308,6 +312,38 @@ void GameObject::Update(uint32 diff)
m_lootState = GO_READY;
break;
}
+ /* TODO: Fix movement in unloaded grid - currently GO will just disappear
+ case GAMEOBJECT_TYPE_TRANSPORT:
+ {
+ if (!m_goValue.Transport.AnimationInfo)
+ break;
+
+ if (GetGoState() == GO_STATE_READY)
+ {
+ m_goValue.Transport.PathProgress += diff;
+ uint32 timer = m_goValue.Transport.PathProgress % m_goValue.Transport.AnimationInfo->TotalTime;
+ TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo->GetAnimNode(timer);
+ if (node && m_goValue.Transport.CurrentSeg != node->TimeSeg)
+ {
+ m_goValue.Transport.CurrentSeg = node->TimeSeg;
+
+ G3D::Quat rotation = m_goValue.Transport.AnimationInfo->GetAnimRotation(timer);
+ G3D::Vector3 pos = rotation.toRotationMatrix()
+ * G3D::Matrix3::fromEulerAnglesZYX(GetOrientation(), 0.0f, 0.0f)
+ * G3D::Vector3(node->X, node->Y, node->Z);
+
+ pos += G3D::Vector3(GetStationaryX(), GetStationaryY(), GetStationaryZ());
+
+ G3D::Vector3 src(GetPositionX(), GetPositionY(), GetPositionZ());
+
+ sLog->outInfo(LOG_FILTER_GENERAL, "Src: %s Dest: %s", src.toString().c_str(), pos.toString().c_str());
+
+ GetMap()->GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation());
+ }
+ }
+ break;
+ }
+ */
case GAMEOBJECT_TYPE_FISHINGNODE:
{
// fishing code (bobber ready)
@@ -1182,10 +1218,12 @@ void GameObject::Use(Unit* user)
if (itr->second)
{
if (Player* ChairUser = ObjectAccessor::FindPlayer(itr->second))
+ {
if (ChairUser->IsSitState() && ChairUser->getStandState() != UNIT_STAND_STATE_SIT && ChairUser->GetExactDist2d(x_i, y_i) < 0.1f)
continue; // This seat is already occupied by ChairUser. NOTE: Not sure if the ChairUser->getStandState() != UNIT_STAND_STATE_SIT check is required.
else
itr->second = 0; // This seat is unoccupied.
+ }
else
itr->second = 0; // The seat may of had an occupant, but they're offline.
}
@@ -2102,6 +2140,7 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
if (index == GAMEOBJECT_DYNAMIC)
{
uint16 dynFlags = 0;
+ int16 pathProgress = -1;
switch (GetGoType())
{
case GAMEOBJECT_TYPE_CHEST:
@@ -2115,12 +2154,13 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
if (ActivateToQuest(target))
dynFlags |= GO_DYNFLAG_LO_SPARKLE;
break;
- default:
+ case GAMEOBJECT_TYPE_MO_TRANSPORT:
+ pathProgress = int16(float(m_goValue.Transport.PathProgress) / float(GetUInt32Value(GAMEOBJECT_LEVEL)) * 65535.0f);
break;
}
fieldBuffer << uint16(dynFlags);
- fieldBuffer << uint16(-1);
+ fieldBuffer << int16(pathProgress);
}
else if (index == GAMEOBJECT_FLAGS)
{
@@ -2140,3 +2180,25 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
updateMask.AppendToPacket(data);
data->append(fieldBuffer);
}
+
+void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* = NULL*/) const
+{
+ if (m_DBTableGuid)
+ {
+ if (GameObjectData const* data = sObjectMgr->GetGOData(GetDBTableGUIDLow()))
+ {
+ x = data->posX;
+ y = data->posY;
+ z = data->posZ;
+ if (ori)
+ *ori = data->orientation;
+ return;
+ }
+ }
+
+ x = GetPositionX();
+ y = GetPositionY();
+ z = GetPositionZ();
+ if (ori)
+ *ori = GetOrientation();
+}
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 3bddac81ee9..de92257893b 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -28,6 +28,7 @@
class GameObjectAI;
class Group;
+class Transport;
#define MAX_GAMEOBJECT_QUEST_ITEMS 6
@@ -229,6 +230,7 @@ struct GameObjectTemplate
uint32 transportPhysics; //5
uint32 mapID; //6
uint32 worldState1; //7
+ uint32 canBeStopped; //8
} moTransport;
//16 GAMEOBJECT_TYPE_DUELFLAG - empty
//17 GAMEOBJECT_TYPE_FISHINGNODE - empty
@@ -539,9 +541,17 @@ struct GameObjectTemplate
typedef UNORDERED_MAP<uint32, GameObjectTemplate> GameObjectTemplateContainer;
class OPvPCapturePoint;
+struct TransportAnimation;
union GameObjectValue
{
+ //11 GAMEOBJECT_TYPE_TRANSPORT
+ struct
+ {
+ uint32 PathProgress;
+ TransportAnimation const* AnimationInfo;
+ uint32 CurrentSeg;
+ } Transport;
//25 GAMEOBJECT_TYPE_FISHINGHOLE
struct
{
@@ -617,7 +627,7 @@ class GameObjectModel;
// 5 sec for bobber catch
#define FISHING_BOBBER_READY_TIME 5
-class GameObject : public WorldObject, public GridObject<GameObject>
+class GameObject : public WorldObject, public GridObject<GameObject>, public MapObject
{
public:
explicit GameObject();
@@ -811,8 +821,19 @@ class GameObject : public WorldObject, public GridObject<GameObject>
uint32 GetDisplayId() const { return GetUInt32Value(GAMEOBJECT_DISPLAYID); }
GameObjectModel* m_model;
+ void GetRespawnPosition(float &x, float &y, float &z, float* ori = NULL) const;
+
+ Transport* ToTransport() { if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) return reinterpret_cast<Transport*>(this); else return NULL; }
+ Transport const* ToTransport() const { if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) return reinterpret_cast<Transport const*>(this); else return NULL; }
+
+ float GetStationaryX() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionX(); return GetPositionX(); }
+ float GetStationaryY() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionY(); return GetPositionY(); }
+ float GetStationaryZ() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionZ(); return GetPositionZ(); }
+ float GetStationaryO() const { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetOrientation(); return GetOrientation(); }
+
protected:
bool AIM_Initialize();
+ void UpdateModel(); // updates model in case displayId were changed
uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
@@ -835,6 +856,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>
GameObjectValue m_goValue;
uint64 m_rotation;
+ Position m_stationaryPosition;
uint64 m_lootRecipient;
uint32 m_lootRecipientGroup;
@@ -842,7 +864,6 @@ class GameObject : public WorldObject, public GridObject<GameObject>
private:
void RemoveFromOwner();
void SwitchDoorOrButton(bool activate, bool alternative = false);
- void UpdateModel(); // updates model in case displayId were changed
//! Object distance/size - overridden from Object::_IsWithinDist. Needs to take in account proper GO size.
bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool /*is3D*/) const