diff options
| author | Shauren <shauren.trinity@gmail.com> | 2022-01-29 19:44:55 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2022-01-29 20:35:25 +0100 |
| commit | 70442041300bb0a1146717497fd5f771d874befa (patch) | |
| tree | 04afe7c59fa8e1c1376510930aaf73f322de176c /src/server/game/Entities/Object | |
| parent | a5c713eaf21ce086074cf5934d1ee105c2c86922 (diff) | |
Core/Objects: Cleanup SmoothPhasing code - move to separate files and better integrate it with visibility system
Diffstat (limited to 'src/server/game/Entities/Object')
| -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 |
4 files changed, 164 insertions, 103 deletions
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 |
