aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/Object
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2022-01-29 19:44:55 +0100
committerShauren <shauren.trinity@gmail.com>2022-01-29 20:35:25 +0100
commit70442041300bb0a1146717497fd5f771d874befa (patch)
tree04afe7c59fa8e1c1376510930aaf73f322de176c /src/server/game/Entities/Object
parenta5c713eaf21ce086074cf5934d1ee105c2c86922 (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.cpp116
-rw-r--r--src/server/game/Entities/Object/Object.h26
-rw-r--r--src/server/game/Entities/Object/SmoothPhasing.cpp67
-rw-r--r--src/server/game/Entities/Object/SmoothPhasing.h58
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