mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Objects: Implement SmoothPhasing part of CreateObject and replacing visible objects
This commit is contained in:
@@ -163,6 +163,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
|
||||
|
||||
if (worldObject->GetAIAnimKitId() || worldObject->GetMovementAnimKitId() || worldObject->GetMeleeAnimKitId())
|
||||
flags.AnimKit = true;
|
||||
|
||||
if (worldObject->IsReplacingObjectFor(target))
|
||||
flags.SmoothPhasing = true;
|
||||
}
|
||||
|
||||
if (Unit const* unit = ToUnit())
|
||||
@@ -178,7 +181,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
|
||||
buf << GetGUID();
|
||||
buf << uint8(objectType);
|
||||
|
||||
BuildMovementUpdate(&buf, flags);
|
||||
BuildMovementUpdate(&buf, flags, target);
|
||||
BuildValuesCreate(&buf, target);
|
||||
data->AddUpdateBlock(buf);
|
||||
}
|
||||
@@ -255,7 +258,7 @@ void Object::SendOutOfRangeForPlayer(Player* target) const
|
||||
target->SendDirectMessage(&packet);
|
||||
}
|
||||
|
||||
void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags) const
|
||||
void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Player* target) const
|
||||
{
|
||||
std::vector<uint32> const* PauseTimes = nullptr;
|
||||
uint32 PauseTimesCount = 0;
|
||||
@@ -559,15 +562,17 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags) const
|
||||
*data << uint32(Int1);
|
||||
}
|
||||
|
||||
//if (flags.SmoothPhasing)
|
||||
//{
|
||||
// data->WriteBit(ReplaceActive);
|
||||
// data->WriteBit(StopAnimKits);
|
||||
// data->WriteBit(HasReplaceObject);
|
||||
// data->FlushBits();
|
||||
// if (HasReplaceObject)
|
||||
// *data << ObjectGuid(ReplaceObject);
|
||||
//}
|
||||
if (flags.SmoothPhasing)
|
||||
{
|
||||
ReplaceObjectInfo const* replacedObjectInfo = static_cast<WorldObject const*>(this)->GetReplacedObjectFor(target);
|
||||
ASSERT(replacedObjectInfo);
|
||||
|
||||
data->WriteBit(true); // ReplaceActive
|
||||
data->WriteBit(replacedObjectInfo->StopAnimKits);
|
||||
data->WriteBit(true);
|
||||
data->FlushBits();
|
||||
*data << ObjectGuid(replacedObjectInfo->ReplaceObject);
|
||||
}
|
||||
|
||||
if (flags.SceneObject)
|
||||
{
|
||||
@@ -922,6 +927,8 @@ void WorldObject::RemoveFromWorld()
|
||||
if (!IsInWorld())
|
||||
return;
|
||||
|
||||
RestoreReplacedObject();
|
||||
|
||||
UpdateObjectVisibilityOnDestroy();
|
||||
|
||||
Object::RemoveFromWorld();
|
||||
@@ -1402,6 +1409,73 @@ 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
|
||||
{
|
||||
if (Creature const* creature = ToCreature())
|
||||
{
|
||||
Player const* player = seer->ToPlayer();
|
||||
if (player && IsBeingReplacedFor(player))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, bool distanceCheck, bool checkAlert) const
|
||||
{
|
||||
if (this == obj)
|
||||
@@ -1416,6 +1490,9 @@ bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, boo
|
||||
if (!obj->CheckPrivateObjectOwnerVisibility(this))
|
||||
return false;
|
||||
|
||||
if (!obj->CheckReplacedObjectVisibility(this))
|
||||
return false;
|
||||
|
||||
if (!sConditionMgr->IsObjectMeetingVisibilityByObjectIdConditions(obj->GetTypeId(), obj->GetEntry(), const_cast<WorldObject*>(this)))
|
||||
return false;
|
||||
|
||||
@@ -1712,7 +1789,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*/)
|
||||
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 */)
|
||||
{
|
||||
uint32 mask = UNIT_MASK_SUMMON;
|
||||
if (properties)
|
||||
@@ -1762,6 +1839,9 @@ 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;
|
||||
@@ -1801,7 +1881,15 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
|
||||
|
||||
summon->SetPrivateObjectOwner(privateObjectOwner);
|
||||
|
||||
AddToMap(summon->ToCreature());
|
||||
if (summoner && !replaceObject.IsEmpty())
|
||||
PhasingHandler::ReplaceObject(summoner, summon, replaceObject);
|
||||
|
||||
if (!AddToMap(summon->ToCreature()))
|
||||
{
|
||||
delete summon;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
summon->InitSummon();
|
||||
|
||||
// call MoveInLineOfSight for nearby creatures
|
||||
@@ -1882,7 +1970,7 @@ 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))
|
||||
if (TempSummon* summon = map->SummonCreature(GetEntry(), pos, nullptr, despawnTime.count(), this, spellId, vehId, privateObjectOwner, GetGUID()))
|
||||
{
|
||||
summon->SetTempSummonType(despawnType);
|
||||
return summon;
|
||||
|
||||
@@ -370,7 +370,7 @@ class TC_GAME_API Object
|
||||
}
|
||||
}
|
||||
|
||||
void BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags) const;
|
||||
void BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Player* target) const;
|
||||
virtual UF::UpdateFieldFlag GetUpdateFieldFlagsFor(Player const* target) const;
|
||||
virtual void BuildValuesCreate(ByteBuffer* data, Player const* target) const = 0;
|
||||
virtual void BuildValuesUpdate(ByteBuffer* data, Player const* target) const = 0;
|
||||
@@ -438,6 +438,12 @@ 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:
|
||||
@@ -725,6 +731,21 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
|
||||
void SetPrivateObjectOwner(ObjectGuid const& owner) { _privateObjectOwner = owner; }
|
||||
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;
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
bool m_isActive;
|
||||
@@ -766,6 +787,9 @@ 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;
|
||||
|
||||
virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius = true, bool incTargetRadius = true) const;
|
||||
|
||||
bool CanNeverSee(WorldObject const* obj) const;
|
||||
|
||||
@@ -24177,6 +24177,30 @@ inline void BeforeVisibilityDestroy<Creature>(Creature* t, Player* p)
|
||||
t->ToPet()->Remove(PET_SAVE_NOT_IN_SLOT, true);
|
||||
}
|
||||
|
||||
void Player::UpdateVisibilityOf(Trinity::IteratorPair<WorldObject**> targets)
|
||||
{
|
||||
if (targets.begin() == targets.end())
|
||||
return;
|
||||
|
||||
UpdateData udata(GetMapId());
|
||||
std::set<Unit*> visibleNow;
|
||||
|
||||
for (WorldObject* target : targets)
|
||||
{
|
||||
UpdateVisibilityOf(target, udata, visibleNow);
|
||||
}
|
||||
|
||||
if (!udata.HasData())
|
||||
return;
|
||||
|
||||
WorldPacket packet;
|
||||
udata.BuildPacket(&packet);
|
||||
SendDirectMessage(&packet);
|
||||
|
||||
for (std::set<Unit*>::const_iterator it = visibleNow.begin(); it != visibleNow.end(); ++it)
|
||||
SendInitialVisiblePackets(*it);
|
||||
}
|
||||
|
||||
void Player::UpdateVisibilityOf(WorldObject* target)
|
||||
{
|
||||
if (HaveAtClient(target))
|
||||
|
||||
@@ -2426,6 +2426,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
void UpdateObjectVisibility(bool forced = true) override;
|
||||
void UpdateVisibilityForPlayer();
|
||||
void UpdateVisibilityOf(WorldObject* target);
|
||||
void UpdateVisibilityOf(Trinity::IteratorPair<WorldObject**> targets);
|
||||
void UpdateTriggerVisibility();
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -448,7 +448,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);
|
||||
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);
|
||||
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = nullptr);
|
||||
AreaTrigger* GetAreaTrigger(ObjectGuid const& guid);
|
||||
SceneObject* GetSceneObject(ObjectGuid const& guid);
|
||||
|
||||
@@ -670,6 +670,20 @@ 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,6 +74,8 @@ public:
|
||||
|
||||
static bool IsPersonalPhase(uint32 phaseId);
|
||||
|
||||
static void ReplaceObject(WorldObject* object, WorldObject* newObject, ObjectGuid const& replacedObjectGuid, bool stopAnimKits = true);
|
||||
|
||||
private:
|
||||
class ControlledUnitVisitor;
|
||||
friend ControlledUnitVisitor;
|
||||
|
||||
Reference in New Issue
Block a user