diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/Entities/Creature/TemporarySummon.cpp | 38 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/TemporarySummon.h | 1 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 116 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.h | 26 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/SmoothPhasing.cpp | 67 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/SmoothPhasing.h | 58 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 39 | ||||
| -rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.cpp | 27 | ||||
| -rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.h | 4 | ||||
| -rw-r--r-- | src/server/game/Maps/Map.h | 3 | ||||
| -rw-r--r-- | src/server/game/Phasing/PhasingHandler.cpp | 14 | ||||
| -rw-r--r-- | src/server/game/Phasing/PhasingHandler.h | 2 | ||||
| -rw-r--r-- | src/server/scripts/Commands/cs_debug.cpp | 14 |
13 files changed, 263 insertions, 146 deletions
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index eaa07869ecd..ca465aba8fc 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.cpp +++ b/src/server/game/Entities/Creature/TemporarySummon.cpp @@ -20,11 +20,14 @@ #include "DB2Structure.h" #include "GameObject.h" #include "GameObjectAI.h" +#include "GridNotifiers.h" #include "Log.h" #include "Map.h" #include "ObjectAccessor.h" #include "Pet.h" #include "Player.h" +#include "SmoothPhasing.h" +#include <boost/container/small_vector.hpp> #include <sstream> TempSummon::TempSummon(SummonPropertiesEntry const* properties, WorldObject* owner, bool isWorldObject) : @@ -244,7 +247,40 @@ void TempSummon::InitSummon() void TempSummon::UpdateObjectVisibilityOnCreate() { - WorldObject::UpdateObjectVisibility(true); + boost::container::small_vector<WorldObject*, 2> objectsToUpdate; + objectsToUpdate.push_back(this); + + SmoothPhasing const* smoothPhasing = GetSmoothPhasing(); + if (WorldObject* original = GetSummoner()) + if (smoothPhasing && smoothPhasing->IsReplacing(original->GetGUID())) + objectsToUpdate.push_back(original); + + Trinity::VisibleChangesNotifier notifier({ objectsToUpdate.data(), objectsToUpdate.data() + objectsToUpdate.size() }); + Cell::VisitWorldObjects(this, notifier, GetVisibilityRange()); +} + +void TempSummon::UpdateObjectVisibilityOnDestroy() +{ + boost::container::small_vector<WorldObject*, 2> objectsToUpdate; + objectsToUpdate.push_back(this); + + WorldObject* original = GetSummoner(); + SmoothPhasing const* smoothPhasing = GetSmoothPhasing(); + if (original && smoothPhasing && smoothPhasing->IsReplacing(original->GetGUID())) + { + objectsToUpdate.push_back(original); + + // disable replacement without removing - it is still needed for next step (visibility update) + if (SmoothPhasing* originalSmoothPhasing = original->GetSmoothPhasing()) + originalSmoothPhasing->DisableReplacementForSeer(GetDemonCreatorGUID()); + } + + Trinity::VisibleChangesNotifier notifier({ objectsToUpdate.data(), objectsToUpdate.data() + objectsToUpdate.size() }); + Cell::VisitWorldObjects(this, notifier, GetVisibilityRange()); + + if (original && smoothPhasing && smoothPhasing->IsReplacing(original->GetGUID())) + if (SmoothPhasing* originalSmoothPhasing = original->GetSmoothPhasing()) + originalSmoothPhasing->ClearViewerDependentInfo(GetDemonCreatorGUID()); } void TempSummon::SetTempSummonType(TempSummonType type) diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index 04ca319f1dd..d9501cce342 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -49,6 +49,7 @@ class TC_GAME_API TempSummon : public Creature virtual void InitStats(uint32 lifetime); virtual void InitSummon(); void UpdateObjectVisibilityOnCreate() override; + void UpdateObjectVisibilityOnDestroy() override; virtual void UnSummon(uint32 msTime = 0); void RemoveFromWorld() override; void SetTempSummonType(TempSummonType type); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 7236a02718c..fe8e65b22d2 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -41,6 +41,7 @@ #include "PhasingHandler.h" #include "Player.h" #include "ReputationMgr.h" +#include "SmoothPhasing.h" #include "SpellAuraEffects.h" #include "SpellMgr.h" #include "SpellPackets.h" @@ -164,7 +165,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c if (worldObject->GetAIAnimKitId() || worldObject->GetMovementAnimKitId() || worldObject->GetMeleeAnimKitId()) flags.AnimKit = true; - if (worldObject->IsReplacingObjectFor(target)) + if (worldObject->GetSmoothPhasing() && worldObject->GetSmoothPhasing()->GetInfoForSeer(target->GetGUID())) flags.SmoothPhasing = true; } @@ -564,14 +565,15 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe if (flags.SmoothPhasing) { - ReplaceObjectInfo const* replacedObjectInfo = static_cast<WorldObject const*>(this)->GetReplacedObjectFor(target); - ASSERT(replacedObjectInfo); + SmoothPhasingInfo const* smoothPhasingInfo = static_cast<WorldObject const*>(this)->GetSmoothPhasing()->GetInfoForSeer(target->GetGUID()); + ASSERT(smoothPhasingInfo); - data->WriteBit(true); // ReplaceActive - data->WriteBit(replacedObjectInfo->StopAnimKits); - data->WriteBit(true); + data->WriteBit(smoothPhasingInfo->ReplaceActive); + data->WriteBit(smoothPhasingInfo->StopAnimKits); + data->WriteBit(smoothPhasingInfo->ReplaceObject.has_value()); data->FlushBits(); - *data << ObjectGuid(replacedObjectInfo->ReplaceObject); + if (smoothPhasingInfo->ReplaceObject) + *data << *smoothPhasingInfo->ReplaceObject; } if (flags.SceneObject) @@ -927,8 +929,6 @@ void WorldObject::RemoveFromWorld() if (!IsInWorld()) return; - RestoreReplacedObject(); - UpdateObjectVisibilityOnDestroy(); Object::RemoveFromWorld(); @@ -1409,71 +1409,12 @@ bool WorldObject::CheckPrivateObjectOwnerVisibility(WorldObject const* seer) con return false; } -void WorldObject::SetReplacedObject(ObjectGuid const& seer, ObjectGuid const& replacedObject, bool stopAnimKits) -{ - ReplaceObjectInfo replaceObjectInfo; - replaceObjectInfo.ReplaceObject = replacedObject; - replaceObjectInfo.StopAnimKits = stopAnimKits; - _replacedObjects[seer] = replaceObjectInfo; -} - -void WorldObject::ReplaceWith(WorldObject const* seer, WorldObject* replaceWithObject, bool stopAnimKits) -{ - _objectsWhichReplaceMeForSeer[seer->GetGUID()] = replaceWithObject->GetGUID(); - replaceWithObject->SetReplacedObject(seer->GetGUID(), GetGUID(), stopAnimKits); -} - -void WorldObject::ReplaceWith(ObjectGuid const& seerGuid, ObjectGuid const& replaceWithObjectGuid, bool stopAnimKits /*=true*/) -{ - WorldObject* replaceWithObject = ObjectAccessor::GetWorldObject(*this, replaceWithObjectGuid); - if (!replaceWithObject) - return; - - _objectsWhichReplaceMeForSeer[seerGuid] = replaceWithObjectGuid; - replaceWithObject->SetReplacedObject(seerGuid, GetGUID(), stopAnimKits); -} - -void WorldObject::RestoreReplacedObject() -{ - if (_replacedObjects.empty() || !IsPrivateObject()) - return; - - std::unordered_map<ObjectGuid, ReplaceObjectInfo>::iterator itr = _replacedObjects.begin(); - WorldObject* replacedObject = ObjectAccessor::GetWorldObject(*this, itr->second.ReplaceObject); - if (!replacedObject) - return; - - ReplaceWith(itr->first, itr->second.ReplaceObject, itr->second.StopAnimKits); - replacedObject->RemoveObjectWhichReplacesMe(itr->first); - _replacedObjects.erase(itr->first); - - Player* player = ObjectAccessor::FindPlayer(itr->first); - if (!player) - return; - - WorldObject* targets[] = { replacedObject, this }; - player->UpdateVisibilityOf({ std::begin(targets), std::end(targets) }); -} - -ReplaceObjectInfo const* WorldObject::GetReplacedObjectFor(WorldObject const* seer) const -{ - auto itr = _replacedObjects.find(seer->GetGUID()); - if (itr != _replacedObjects.end()) - return &itr->second; - - return nullptr; -} - -bool WorldObject::CheckReplacedObjectVisibility(WorldObject const* seer) const +SmoothPhasing* WorldObject::GetOrCreateSmoothPhasing() { - if (Creature const* creature = ToCreature()) - { - Player const* player = seer->ToPlayer(); - if (player && IsBeingReplacedFor(player)) - return false; - } + if (!_smoothPhasing) + _smoothPhasing = std::make_unique<SmoothPhasing>(); - return true; + return _smoothPhasing.get(); } bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, bool distanceCheck, bool checkAlert) const @@ -1490,8 +1431,9 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo if (!obj->CheckPrivateObjectOwnerVisibility(this)) return false; - if (!obj->CheckReplacedObjectVisibility(this)) - return false; + if (SmoothPhasing const* smoothPhasing = obj->GetSmoothPhasing()) + if (smoothPhasing->IsBeingReplacedForSeer(GetGUID())) + return false; if (!sConditionMgr->IsObjectMeetingVisibilityByObjectIdConditions(obj->GetTypeId(), obj->GetEntry(), const_cast<WorldObject*>(this))) return false; @@ -1789,7 +1731,7 @@ void WorldObject::AddObjectToRemoveList() map->AddObjectToRemoveList(this); } -TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, WorldObject* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, ObjectGuid privateObjectOwner /*= ObjectGuid::Empty*/, ObjectGuid replaceObject /* = ObjectGuid::Empty */) +TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, WorldObject* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, ObjectGuid privateObjectOwner /*= ObjectGuid::Empty*/, SmoothPhasingInfo const* smoothPhasingInfo /* = nullptr*/) { uint32 mask = UNIT_MASK_SUMMON; if (properties) @@ -1839,9 +1781,6 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert } } - if (WorldObject* objectOwner = ObjectAccessor::GetWorldObject(*summoner, privateObjectOwner)) - summoner = objectOwner; - Unit* summonerUnit = summoner ? summoner->ToUnit() : nullptr; TempSummon* summon = nullptr; @@ -1881,8 +1820,19 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert summon->SetPrivateObjectOwner(privateObjectOwner); - if (summoner && !replaceObject.IsEmpty()) - PhasingHandler::ReplaceObject(summoner, summon, replaceObject); + if (smoothPhasingInfo) + { + if (summoner && smoothPhasingInfo->ReplaceObject) + { + SmoothPhasingInfo originalSmoothPhasingInfo = *smoothPhasingInfo; + originalSmoothPhasingInfo.ReplaceObject = summon->GetGUID(); + summoner->GetOrCreateSmoothPhasing()->SetViewerDependentInfo(privateObjectOwner, originalSmoothPhasingInfo); + + summon->SetDemonCreatorGUID(privateObjectOwner); + } + + summon->GetOrCreateSmoothPhasing()->SetSingleInfo(*smoothPhasingInfo); + } if (!AddToMap(summon->ToCreature())) { @@ -1970,7 +1920,8 @@ TempSummon* WorldObject::SummonPersonalClone(Position const& pos, TempSummonType { if (Map* map = FindMap()) { - if (TempSummon* summon = map->SummonCreature(GetEntry(), pos, nullptr, despawnTime.count(), this, spellId, vehId, privateObjectOwner, GetGUID())) + SmoothPhasingInfo smoothPhasingInfo{GetGUID(), true, true}; + if (TempSummon* summon = map->SummonCreature(GetEntry(), pos, nullptr, despawnTime.count(), this, spellId, vehId, privateObjectOwner, &smoothPhasingInfo)) { summon->SetTempSummonType(despawnType); return summon; @@ -3473,7 +3424,8 @@ void WorldObject::DestroyForNearbyPlayers() void WorldObject::UpdateObjectVisibility(bool /*forced*/) { //updates object's visibility for nearby players - Trinity::VisibleChangesNotifier notifier(*this); + WorldObject* objects[] = { this }; + Trinity::VisibleChangesNotifier notifier({ std::begin(objects), std::end(objects) }); Cell::VisitWorldObjects(this, notifier, GetVisibilityRange()); } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index a71bb7b5e75..948c29a87e8 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -49,6 +49,7 @@ class Object; class Player; class Scenario; class SceneObject; +class SmoothPhasing; class Spell; class SpellCastTargets; class SpellEffectInfo; @@ -438,12 +439,6 @@ class FlaggedValuesArray32 T_FLAGS m_flags; }; -struct TC_GAME_API ReplaceObjectInfo -{ - ObjectGuid ReplaceObject; - bool StopAnimKits = true; -}; - class TC_GAME_API WorldObject : public Object, public WorldLocation { protected: @@ -732,19 +727,9 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation bool CheckPrivateObjectOwnerVisibility(WorldObject const* seer) const; // Smooth Phasing - void ReplaceWith(ObjectGuid const& seerGuid, ObjectGuid const& replaceWithObjectGuid, bool stopAnimKits = true); - void ReplaceWith(WorldObject const* seer, WorldObject* replaceWithObject, bool stopAnimKits = true); - void SetReplacedObject(ObjectGuid const& seer, ObjectGuid const& replacedObject, bool stopAnimKits = true); - void RestoreReplacedObject(); - void RemoveObjectWhichReplacesMe(WorldObject const* seer) { RemoveObjectWhichReplacesMe(seer->GetGUID()); } - void RemoveObjectWhichReplacesMe(ObjectGuid const& seerGuid) { _objectsWhichReplaceMeForSeer.erase(seerGuid); } - // If Me is replacing any other creature - ReplaceObjectInfo const* GetReplacedObjectFor(WorldObject const* seer) const; - bool IsReplacingObjectFor(WorldObject const* seer) const { return GetReplacedObjectFor(seer) != nullptr; } - // If Me is replaced for player x by any other creature - bool IsBeingReplacedFor(WorldObject const* seer) const { return _objectsWhichReplaceMeForSeer.find(seer->GetGUID()) != _objectsWhichReplaceMeForSeer.end(); } - - bool CheckReplacedObjectVisibility(WorldObject const* seer) const; + SmoothPhasing* GetOrCreateSmoothPhasing(); + SmoothPhasing* GetSmoothPhasing() { return _smoothPhasing.get(); } + SmoothPhasing const* GetSmoothPhasing() const { return _smoothPhasing.get(); } protected: std::string m_name; @@ -787,8 +772,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation ObjectGuid _privateObjectOwner; - std::unordered_map<ObjectGuid /* Seer */, ReplaceObjectInfo> _replacedObjects; - std::unordered_map<ObjectGuid /* Seer */, ObjectGuid /* Object which is replacing me */> _objectsWhichReplaceMeForSeer; + std::unique_ptr<SmoothPhasing> _smoothPhasing; virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius = true, bool incTargetRadius = true) const; diff --git a/src/server/game/Entities/Object/SmoothPhasing.cpp b/src/server/game/Entities/Object/SmoothPhasing.cpp new file mode 100644 index 00000000000..d578df24f2b --- /dev/null +++ b/src/server/game/Entities/Object/SmoothPhasing.cpp @@ -0,0 +1,67 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "SmoothPhasing.h" +#include "Containers.h" + +void SmoothPhasing::SetViewerDependentInfo(ObjectGuid seer, SmoothPhasingInfo const& info) +{ + if (!std::holds_alternative<SmoothPhasingInfoViewerDependent>(_storage)) + _storage.emplace<SmoothPhasingInfoViewerDependent>(); + + std::get<SmoothPhasingInfoViewerDependent>(_storage)[seer] = info; +} + +void SmoothPhasing::ClearViewerDependentInfo(ObjectGuid seer) +{ + if (std::holds_alternative<SmoothPhasingInfoViewerDependent>(_storage)) + std::get<SmoothPhasingInfoViewerDependent>(_storage).erase(seer); +} + +void SmoothPhasing::SetSingleInfo(SmoothPhasingInfo const& info) +{ + _storage.emplace<SmoothPhasingInfoSingle>() = info; +} + +bool SmoothPhasing::IsReplacing(ObjectGuid guid) const +{ + return std::holds_alternative<SmoothPhasingInfoSingle>(_storage) && std::get<SmoothPhasingInfoSingle>(_storage).ReplaceObject == guid; +} + +bool SmoothPhasing::IsBeingReplacedForSeer(ObjectGuid seer) const +{ + if (std::holds_alternative<SmoothPhasingInfoViewerDependent>(_storage)) + if (SmoothPhasingInfo const* smoothPhasingInfo = Trinity::Containers::MapGetValuePtr(std::get<SmoothPhasingInfoViewerDependent>(_storage), seer)) + return !smoothPhasingInfo->Disabled; + + return false; +} + +SmoothPhasingInfo const* SmoothPhasing::GetInfoForSeer(ObjectGuid seer) const +{ + if (std::holds_alternative<SmoothPhasingInfoViewerDependent>(_storage)) + return Trinity::Containers::MapGetValuePtr(std::get<SmoothPhasingInfoViewerDependent>(_storage), seer); + + return &std::get<SmoothPhasingInfoSingle>(_storage); +} + +void SmoothPhasing::DisableReplacementForSeer(ObjectGuid seer) +{ + if (std::holds_alternative<SmoothPhasingInfoViewerDependent>(_storage)) + if (SmoothPhasingInfo* smoothPhasingInfo = Trinity::Containers::MapGetValuePtr(std::get<SmoothPhasingInfoViewerDependent>(_storage), seer)) + smoothPhasingInfo->Disabled = true; +} diff --git a/src/server/game/Entities/Object/SmoothPhasing.h b/src/server/game/Entities/Object/SmoothPhasing.h new file mode 100644 index 00000000000..6d211e8da28 --- /dev/null +++ b/src/server/game/Entities/Object/SmoothPhasing.h @@ -0,0 +1,58 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TRINITYCORE_SMOOTHPHASING_H +#define TRINITYCORE_SMOOTHPHASING_H + +#include "ObjectGuid.h" +#include "Optional.h" +#include <unordered_map> +#include <variant> + +struct SmoothPhasingInfo +{ + // Fields visible on client + Optional<ObjectGuid> ReplaceObject; + bool ReplaceActive = true; + bool StopAnimKits = true; + + // Serverside fields + bool Disabled = false; +}; + +class TC_GAME_API SmoothPhasing +{ +public: + void SetViewerDependentInfo(ObjectGuid seer, SmoothPhasingInfo const& info); + void ClearViewerDependentInfo(ObjectGuid seer); + + void SetSingleInfo(SmoothPhasingInfo const& info); + + bool IsReplacing(ObjectGuid guid) const; + + bool IsBeingReplacedForSeer(ObjectGuid seer) const; + SmoothPhasingInfo const* GetInfoForSeer(ObjectGuid seer) const; + void DisableReplacementForSeer(ObjectGuid seer); + +private: + using SmoothPhasingInfoViewerDependent = std::unordered_map<ObjectGuid /* Seer */, SmoothPhasingInfo>; + using SmoothPhasingInfoSingle = SmoothPhasingInfo; + + std::variant<SmoothPhasingInfoSingle, SmoothPhasingInfoViewerDependent> _storage; +}; + +#endif // TRINITYCORE_SMOOTHPHASING_H diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 85cadfbc429..d50efffe822 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -24183,11 +24183,42 @@ void Player::UpdateVisibilityOf(Trinity::IteratorPair<WorldObject**> targets) return; UpdateData udata(GetMapId()); - std::set<Unit*> visibleNow; + std::set<Unit*> newVisibleUnits; for (WorldObject* target : targets) { - UpdateVisibilityOf(target, udata, visibleNow); + if (target == this) + continue; + + switch (target->GetTypeId()) + { + case TYPEID_UNIT: + UpdateVisibilityOf(target->ToCreature(), udata, newVisibleUnits); + break; + case TYPEID_PLAYER: + UpdateVisibilityOf(target->ToPlayer(), udata, newVisibleUnits); + break; + case TYPEID_GAMEOBJECT: + UpdateVisibilityOf(target->ToGameObject(), udata, newVisibleUnits); + break; + case TYPEID_DYNAMICOBJECT: + UpdateVisibilityOf(target->ToDynObject(), udata, newVisibleUnits); + break; + case TYPEID_CORPSE: + UpdateVisibilityOf(target->ToCorpse(), udata, newVisibleUnits); + break; + case TYPEID_AREATRIGGER: + UpdateVisibilityOf(target->ToAreaTrigger(), udata, newVisibleUnits); + break; + case TYPEID_SCENEOBJECT: + UpdateVisibilityOf(target->ToSceneObject(), udata, newVisibleUnits); + break; + case TYPEID_CONVERSATION: + UpdateVisibilityOf(target->ToConversation(), udata, newVisibleUnits); + break; + default: + break; + } } if (!udata.HasData()) @@ -24197,8 +24228,8 @@ void Player::UpdateVisibilityOf(Trinity::IteratorPair<WorldObject**> targets) udata.BuildPacket(&packet); SendDirectMessage(&packet); - for (std::set<Unit*>::const_iterator it = visibleNow.begin(); it != visibleNow.end(); ++it) - SendInitialVisiblePackets(*it); + for (Unit* visibleUnit : newVisibleUnits) + SendInitialVisiblePackets(visibleUnit); } void Player::UpdateVisibilityOf(WorldObject* target) diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index a223e55f0ac..fcfea53e891 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -89,31 +89,22 @@ void VisibleChangesNotifier::Visit(PlayerMapType &m) { for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { - if (iter->GetSource() == &i_object) - continue; - - iter->GetSource()->UpdateVisibilityOf(&i_object); + iter->GetSource()->UpdateVisibilityOf(i_objects); - if (iter->GetSource()->HasSharedVision()) - { - for (SharedVisionList::const_iterator i = iter->GetSource()->GetSharedVisionList().begin(); - i != iter->GetSource()->GetSharedVisionList().end(); ++i) - { + for (SharedVisionList::const_iterator i = iter->GetSource()->GetSharedVisionList().begin(); + i != iter->GetSource()->GetSharedVisionList().end(); ++i) if ((*i)->m_seer == iter->GetSource()) - (*i)->UpdateVisibilityOf(&i_object); - } - } + (*i)->UpdateVisibilityOf(i_objects); } } void VisibleChangesNotifier::Visit(CreatureMapType &m) { for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (iter->GetSource()->HasSharedVision()) - for (SharedVisionList::const_iterator i = iter->GetSource()->GetSharedVisionList().begin(); - i != iter->GetSource()->GetSharedVisionList().end(); ++i) - if ((*i)->m_seer == iter->GetSource()) - (*i)->UpdateVisibilityOf(&i_object); + for (SharedVisionList::const_iterator i = iter->GetSource()->GetSharedVisionList().begin(); + i != iter->GetSource()->GetSharedVisionList().end(); ++i) + if ((*i)->m_seer == iter->GetSource()) + (*i)->UpdateVisibilityOf(i_objects); } void VisibleChangesNotifier::Visit(DynamicObjectMapType &m) @@ -122,7 +113,7 @@ void VisibleChangesNotifier::Visit(DynamicObjectMapType &m) if (Unit* caster = iter->GetSource()->GetCaster()) if (Player* player = caster->ToPlayer()) if (player->m_seer == iter->GetSource()) - player->UpdateVisibilityOf(&i_object); + player->UpdateVisibilityOf(i_objects); } inline void CreatureUnitRelocationWorker(Creature* c, Unit* u) diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index a73a7e5dd61..08165b08934 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -49,9 +49,9 @@ namespace Trinity struct VisibleChangesNotifier { - WorldObject &i_object; + IteratorPair<WorldObject**> i_objects; - explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) { } + explicit VisibleChangesNotifier(IteratorPair<WorldObject**> objects) : i_objects(objects) { } template<class T> void Visit(GridRefManager<T> &) { } void Visit(PlayerMapType &); void Visit(CreatureMapType &); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 470a4a16464..d044190fd4f 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -65,6 +65,7 @@ struct MapEntry; struct Position; struct ScriptAction; struct ScriptInfo; +struct SmoothPhasingInfo; struct SummonPropertiesEntry; class Transport; enum Difficulty : uint8; @@ -448,7 +449,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType> void UpdateIteratorBack(Player* player); - TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = nullptr, uint32 duration = 0, WorldObject* summoner = nullptr, uint32 spellId = 0, uint32 vehId = 0, ObjectGuid privateObjectOwner = ObjectGuid::Empty, ObjectGuid replaceObject = ObjectGuid::Empty); + TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = nullptr, uint32 duration = 0, WorldObject* summoner = nullptr, uint32 spellId = 0, uint32 vehId = 0, ObjectGuid privateObjectOwner = ObjectGuid::Empty, SmoothPhasingInfo const* smoothPhasingInfo = nullptr); void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = nullptr); AreaTrigger* GetAreaTrigger(ObjectGuid const& guid); SceneObject* GetSceneObject(ObjectGuid const& guid); diff --git a/src/server/game/Phasing/PhasingHandler.cpp b/src/server/game/Phasing/PhasingHandler.cpp index 974461141a3..50e7afe586f 100644 --- a/src/server/game/Phasing/PhasingHandler.cpp +++ b/src/server/game/Phasing/PhasingHandler.cpp @@ -670,20 +670,6 @@ bool PhasingHandler::IsPersonalPhase(uint32 phaseId) return false; } -void PhasingHandler::ReplaceObject(WorldObject* object, WorldObject* newObject, ObjectGuid const& replacedObjectGuid, bool stopAnimKits /*= true*/) -{ - WorldObject* replacedObject = ObjectAccessor::GetWorldObject(*object, replacedObjectGuid); - if (!replacedObject) - return; - - replacedObject->ReplaceWith(object, newObject, stopAnimKits); - if (Player* player = object->ToPlayer()) - { - WorldObject* targets[] = { newObject, replacedObject }; - player->UpdateVisibilityOf({ std::begin(targets), std::end(targets) }); - } -} - void PhasingHandler::UpdateVisibilityIfNeeded(WorldObject* object, bool updateVisibility, bool changed) { if (changed && object->IsInWorld()) diff --git a/src/server/game/Phasing/PhasingHandler.h b/src/server/game/Phasing/PhasingHandler.h index bace95c9fa4..dfb8eb7aa94 100644 --- a/src/server/game/Phasing/PhasingHandler.h +++ b/src/server/game/Phasing/PhasingHandler.h @@ -74,8 +74,6 @@ public: static bool IsPersonalPhase(uint32 phaseId); - static void ReplaceObject(WorldObject* object, WorldObject* newObject, ObjectGuid const& replacedObjectGuid, bool stopAnimKits = true); - private: class ControlledUnitVisitor; friend ControlledUnitVisitor; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index f7029874f34..ed6cd8c005a 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -133,7 +133,8 @@ public: { "asan", rbac::RBAC_PERM_COMMAND_DEBUG_ASAN, true, nullptr, "", debugAsanCommandTable }, { "guidlimits", rbac::RBAC_PERM_COMMAND_DEBUG, true, &HandleDebugGuidLimitsCommand, "" }, { "objectcount", rbac::RBAC_PERM_COMMAND_DEBUG, true, &HandleDebugObjectCountCommand, "" }, - { "questreset", rbac::RBAC_PERM_COMMAND_DEBUG_QUESTRESET, true, &HandleDebugQuestResetCommand, "" } + { "questreset", rbac::RBAC_PERM_COMMAND_DEBUG_QUESTRESET, true, &HandleDebugQuestResetCommand, "" }, + { "personalclone", rbac::RBAC_PERM_COMMAND_DEBUG, false, &HandleDebugBecomePersonalClone, "" } }; static std::vector<ChatCommand> commandTable = { @@ -1925,6 +1926,17 @@ public: handler->PSendSysMessage("Entry: %u Count: %u", p.first, p.second); } + static bool HandleDebugBecomePersonalClone(ChatHandler* handler) + { + Creature* selection = handler->getSelectedCreature(); + if (!selection) + return false; + + Player* player = handler->GetSession()->GetPlayer(); + selection->SummonPersonalClone(player->GetPosition(), TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, player->GetGUID()); + return true; + } + static bool HandleDebugDummyCommand(ChatHandler* handler, CommandArgs* /*args*/) { handler->SendSysMessage("This command does nothing right now. Edit your local core (cs_debug.cpp) to make it do whatever you need for testing."); |
