diff options
-rw-r--r-- | src/server/game/Entities/AreaTrigger/AreaTrigger.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 6 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Grids/ObjectGridLoader.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.cpp | 1 |
7 files changed, 34 insertions, 5 deletions
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h index 5db5409d476..3ba82809ec3 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h @@ -63,7 +63,7 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge bool IsServerSide() const { return _areaTriggerTemplate->Id.IsServerSide; } - bool IsNeverVisibleFor(WorldObject const* /*seer*/) const override { return IsServerSide(); } + bool IsNeverVisibleFor(WorldObject const* seer) const override { return WorldObject::IsNeverVisibleFor(seer) || IsServerSide(); } private: bool Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spell, Position const& pos, int32 duration, SpellCastVisual spellVisual, ObjectGuid const& castId, AuraEffect const* aurEff); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index f07d8f71fb6..e926d7d5aab 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -75,6 +75,7 @@ Object::Object() : m_values(this) m_inWorld = false; m_isNewObject = false; + m_isDestroyedObject = false; m_objectUpdated = false; } @@ -243,6 +244,17 @@ void Object::DestroyForPlayer(Player* target) const target->SendDirectMessage(&packet); } +void Object::SendOutOfRangeForPlayer(Player* target) const +{ + ASSERT(target); + + UpdateData updateData(target->GetMapId()); + BuildOutOfRangeUpdateBlock(&updateData); + WorldPacket packet; + updateData.BuildPacket(&packet); + target->SendDirectMessage(&packet); +} + void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags) const { std::vector<uint32> const* PauseTimes = nullptr; diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 065994344d3..7068f7e73bf 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -180,6 +180,7 @@ class TC_GAME_API Object ByteBuffer PrepareValuesUpdateBuffer() const; virtual void DestroyForPlayer(Player* target) const; + void SendOutOfRangeForPlayer(Player* target) const; virtual void ClearUpdateMask(bool remove); @@ -188,6 +189,8 @@ 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; } + bool IsDestroyedObject() const { return m_isDestroyedObject; } + void SetDestroyedObject(bool destroyed) { m_isDestroyedObject = destroyed; } virtual void BuildUpdate(UpdateDataMapType&) { } void BuildFieldsUpdate(Player*, UpdateDataMapType &) const; @@ -391,6 +394,7 @@ class TC_GAME_API Object ObjectGuid m_guid; bool m_inWorld; bool m_isNewObject; + bool m_isDestroyedObject; Object(Object const& right) = delete; Object& operator=(Object const& right) = delete; @@ -745,7 +749,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; } void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; } - virtual bool IsNeverVisibleFor(WorldObject const* /*seer*/) const { return !IsInWorld(); } + virtual bool IsNeverVisibleFor(WorldObject const* /*seer*/) const { return !IsInWorld() || IsDestroyedObject(); } virtual bool IsAlwaysVisibleFor(WorldObject const* /*seer*/) const { return false; } virtual bool IsInvisibleDueToDespawn() const { return false; } //difference from IsAlwaysVisibleFor: 1. after distance check; 2. use owner or charmer as seer diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index ba43e020d2f..36892a3bd4b 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -24186,7 +24186,11 @@ void Player::UpdateVisibilityOf(WorldObject* target) if (target->GetTypeId() == TYPEID_UNIT) BeforeVisibilityDestroy<Creature>(target->ToCreature(), this); - target->DestroyForPlayer(this); + if (!target->IsDestroyedObject()) + target->SendOutOfRangeForPlayer(this); + else + target->DestroyForPlayer(this); + m_clientGUIDs.erase(target->GetGUID()); #ifdef TRINITY_DEBUG @@ -24273,7 +24277,11 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi { BeforeVisibilityDestroy<T>(target, this); - target->BuildOutOfRangeUpdateBlock(&data); + if (!target->IsDestroyedObject()) + target->BuildOutOfRangeUpdateBlock(&data); + else + target->BuildDestroyUpdateBlock(&data); + m_clientGUIDs.erase(target->GetGUID()); #ifdef TRINITY_DEBUG @@ -24281,7 +24289,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& vi #endif } } - else //if (visibleNow.size() < 30 || target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->IsVehicle()) + else { if (CanSeeOrDetect(target, false, true)) { diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index 666dd0037f3..f110d9b84ea 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -282,7 +282,10 @@ template<class T> void ObjectGridCleaner::Visit(GridRefManager<T> &m) { for (typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter) + { + iter->GetSource()->SetDestroyedObject(true); iter->GetSource()->CleanupsBeforeDelete(); + } } template void ObjectGridUnloader::Visit(CreatureMapType &); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 1b00a50db5a..eb0c6b1a0b8 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3667,6 +3667,7 @@ void Map::AddObjectToRemoveList(WorldObject* obj) { ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId()); + obj->SetDestroyedObject(true); obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links i_objectsToRemove.insert(obj); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 7d06c95b42a..2f71f2c9a45 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -648,6 +648,7 @@ void WorldSession::LogoutPlayer(bool save) // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes + _player->SetDestroyedObject(true); _player->CleanupsBeforeDelete(); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Logout Character:[%s] %s Level: %d, XP: %u/%u (%u left)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), _player->GetLevel(), |