mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Objects: Cleanup SmoothPhasing code - move to separate files and better integrate it with visibility system
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
SmoothPhasing* WorldObject::GetOrCreateSmoothPhasing()
|
||||
{
|
||||
ReplaceObjectInfo replaceObjectInfo;
|
||||
replaceObjectInfo.ReplaceObject = replacedObject;
|
||||
replaceObjectInfo.StopAnimKits = stopAnimKits;
|
||||
_replacedObjects[seer] = replaceObjectInfo;
|
||||
}
|
||||
if (!_smoothPhasing)
|
||||
_smoothPhasing = std::make_unique<SmoothPhasing>();
|
||||
|
||||
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
|
||||
{
|
||||
if (Creature const* creature = ToCreature())
|
||||
{
|
||||
Player const* player = seer->ToPlayer();
|
||||
if (player && IsBeingReplacedFor(player))
|
||||
return false;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
67
src/server/game/Entities/Object/SmoothPhasing.cpp
Normal file
67
src/server/game/Entities/Object/SmoothPhasing.cpp
Normal file
@@ -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;
|
||||
}
|
||||
58
src/server/game/Entities/Object/SmoothPhasing.h
Normal file
58
src/server/game/Entities/Object/SmoothPhasing.h
Normal file
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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_objects);
|
||||
|
||||
iter->GetSource()->UpdateVisibilityOf(&i_object);
|
||||
|
||||
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)
|
||||
|
||||
@@ -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 &);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
|
||||
Reference in New Issue
Block a user