diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 9d7ce11f510..85211e77aa3 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -308,6 +308,20 @@ void Creature::RemoveCorpse(bool setSpawnTime) float x, y, z, o; GetRespawnPosition(x, y, z, &o); + + // We were spawned on transport, calculate real position + if (IsSpawnedOnTransport()) + { + Position& pos = m_movementInfo.transport.pos; + pos.m_positionX = x; + pos.m_positionY = y; + pos.m_positionZ = z; + pos.SetOrientation(o); + + if (TransportBase* transport = GetDirectTransport()) + transport->CalculatePassengerPosition(x, y, z, &o); + } + SetHomePosition(x, y, z, o); GetMap()->CreatureRelocation(this, x, y, z, o); } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 4e6bc789894..b51a0a66d04 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -83,6 +83,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma void Update(uint32 time) override; // overwrited Unit::Update void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr, float* dist =nullptr) const; + bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->spawnPoint.GetMapId() != GetMapId(); } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } uint32 GetCorpseDelay() const { return m_corpseDelay; } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index c7b43b99d53..e0789a231f1 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -67,6 +67,7 @@ Object::Object() : m_PackGUID(sizeof(uint64)+1) _fieldNotifyFlags = UF_FLAG_DYNAMIC; m_inWorld = false; + m_isNewObject = false; m_objectUpdated = false; } @@ -170,32 +171,32 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c if (target == this) // building packet for yourself flags |= UPDATEFLAG_SELF; - switch (GetGUID().GetHigh()) + if (m_isNewObject) { - case HighGuid::Player: - case HighGuid::Pet: - case HighGuid::Corpse: - case HighGuid::DynamicObject: - case HighGuid::AreaTrigger: - updateType = UPDATETYPE_CREATE_OBJECT2; - break; - case HighGuid::Unit: - case HighGuid::Vehicle: + switch (GetGUID().GetHigh()) { - if (TempSummon const* summon = ToUnit()->ToTempSummon()) - if (summon->GetSummonerGUID().IsPlayer()) - updateType = UPDATETYPE_CREATE_OBJECT2; - - break; - } - case HighGuid::GameObject: - { - if (ToGameObject()->GetOwnerGUID().IsPlayer()) + case HighGuid::Player: + case HighGuid::Pet: + case HighGuid::Corpse: + case HighGuid::DynamicObject: updateType = UPDATETYPE_CREATE_OBJECT2; - break; + break; + case HighGuid::Unit: + case HighGuid::Vehicle: + { + if (ToUnit()->IsSummon()) + updateType = UPDATETYPE_CREATE_OBJECT2; + break; + } + case HighGuid::GameObject: + { + if (ToGameObject()->GetOwnerGUID().IsPlayer()) + updateType = UPDATETYPE_CREATE_OBJECT2; + break; + } + default: + break; } - default: - break; } if (WorldObject const* worldObject = dynamic_cast(this)) @@ -210,6 +211,14 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c if (flags & UPDATEFLAG_STATIONARY_POSITION) { + // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses... + if (isType(TYPEMASK_DYNAMICOBJECT | TYPEMASK_CORPSE | TYPEMASK_PLAYER)) + updateType = UPDATETYPE_CREATE_OBJECT2; + + // UPDATETYPE_CREATE_OBJECT2 for pets... + if (target->GetPetGUID() == GetGUID()) + updateType = UPDATETYPE_CREATE_OBJECT2; + // UPDATETYPE_CREATE_OBJECT2 for some gameobject types... if (isType(TYPEMASK_GAMEOBJECT)) { @@ -221,15 +230,20 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c case GAMEOBJECT_TYPE_FLAGDROP: updateType = UPDATETYPE_CREATE_OBJECT2; break; + case GAMEOBJECT_TYPE_TRANSPORT: + flags |= UPDATEFLAG_TRANSPORT; + break; default: break; } } - } - if (Unit const* unit = ToUnit()) - if (unit->GetVictim()) - flags |= UPDATEFLAG_HAS_TARGET; + if (isType(TYPEMASK_UNIT)) + { + if (ToUnit()->GetVictim()) + flags |= UPDATEFLAG_HAS_TARGET; + } + } ByteBuffer buf(500); buf << uint8(updateType); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 084db44ac8a..ffcf4be74a7 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -141,6 +141,7 @@ class TC_GAME_API Object virtual bool hasQuest(uint32 /* quest_id */) const { return false; } virtual bool hasInvolvedQuest(uint32 /* quest_id */) const { return false; } + void SetIsNewObject(bool enable) { m_isNewObject = enable; } virtual void BuildUpdate(UpdateDataMapType&) { } void BuildFieldsUpdate(Player*, UpdateDataMapType &) const; @@ -210,6 +211,7 @@ class TC_GAME_API Object private: bool m_inWorld; + bool m_isNewObject; PackedGuid m_PackGUID; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index c6efbed5bc9..d9acc07834a 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -680,7 +680,9 @@ bool Map::AddToMap(T* obj) //something, such as vehicle, needs to be update immediately //also, trigger needs to cast spell, if not update, cannot see visual + obj->SetIsNewObject(true); obj->UpdateObjectVisibilityOnCreate(); + obj->SetIsNewObject(false); return true; }