aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.h2
-rw-r--r--src/server/game/Entities/Object/Object.cpp12
-rw-r--r--src/server/game/Entities/Object/Object.h6
-rw-r--r--src/server/game/Entities/Player/Player.cpp14
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp3
-rw-r--r--src/server/game/Maps/Map.cpp1
-rw-r--r--src/server/game/Server/WorldSession.cpp1
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(),