Revert Visibility Notifier changes (#17682)

* Revert "fix(Core/Grid): Implement missing GridUnload setting (#17569)"

This reverts commit 79b39f9655.

* Revert "fix(Core/Grid): Address bugs and performance issues introduced by visibility notifier implementation (#17480)"

This reverts commit 60e27511c5.

* Revert "fix(Core): GridCleanUpDelay Log (#17436)"

This reverts commit 90b16ca065.

* Revert "feat(Core/Grids): Implement visibility notifier (#15919)"

This reverts commit 2779833768.
This commit is contained in:
Kitzunu 2023-11-12 00:48:49 +01:00 committed by GitHub
parent 4df0ab3427
commit bbadc32bea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 1074 additions and 1764 deletions

View file

@ -301,6 +301,9 @@ void Creature::RemoveFromWorld()
if (m_formation)
sFormationMgr->RemoveCreatureFromGroup(m_formation, this);
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
Unit::RemoveFromWorld();
if (m_spawnId)
@ -362,15 +365,17 @@ void Creature::RemoveCorpse(bool setSpawnTime, bool skipVisibility)
//SaveRespawnTime();
}
float x, y, z, o;
GetRespawnPosition(x, y, z, &o);
SetHomePosition(x, y, z, o);
SetPosition(x, y, z, o);
// xinef: relocate notifier
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
// pussywizard: if corpse was removed during falling then the falling will continue after respawn, so stop falling is such case
if (IsFalling())
StopMoving();
float x, y, z, o;
GetRespawnPosition(x, y, z, &o);
UpdateAllowedPositionZ(x, y, z);
SetHomePosition(x, y, z, o);
GetMap()->CreatureRelocation(this, x, y, z, o);
}
/**
@ -1823,25 +1828,7 @@ void Creature::DeleteFromDB()
return;
}
CreatureData const* data = sObjectMgr->GetCreatureData(m_spawnId);
if (!data)
return;
CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction();
sMapMgr->DoForAllMapsWithMapId(data->mapid,
[this, charTrans](Map* map) -> void
{
// despawn all active creatures, and remove their respawns
std::vector<Creature*> toUnload;
for (auto const& pair : Acore::Containers::MapEqualRange(map->GetCreatureBySpawnIdStore(), m_spawnId))
toUnload.push_back(pair.second);
for (Creature* creature : toUnload)
map->AddObjectToRemoveList(creature);
map->RemoveCreatureRespawnTime(m_spawnId);
}
);
GetMap()->RemoveCreatureRespawnTime(m_spawnId);
sObjectMgr->DeleteCreatureData(m_spawnId);
WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction();
@ -2093,7 +2080,9 @@ void Creature::Respawn(bool force)
m_respawnedTime = GameTime::GetGameTime().count();
}
m_respawnedTime = GameTime::GetGameTime().count();
UpdateObjectVisibility();
// xinef: relocate notifier, fixes npc appearing in corpse position after forced respawn (instead of spawn)
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
UpdateObjectVisibility(false);
}
void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
@ -3075,7 +3064,10 @@ std::string const& Creature::GetNameForLocaleIdx(LocaleConstant loc_idx) const
void Creature::SetPosition(float x, float y, float z, float o)
{
UpdatePosition(x, y, z, o, false);
if (!Acore::IsValidMapCoord(x, y, z, o))
return;
GetMap()->CreatureRelocation(this, x, y, z, o);
}
bool Creature::IsDungeonBoss() const

View file

@ -68,7 +68,6 @@ public:
void Update(uint32 time) override; // overwrited Unit::Update
void GetRespawnPosition(float& x, float& y, float& z, float* ori = nullptr, float* dist = nullptr) const;
bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->mapid != GetMapId(); }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
void SetCorpseRemoveTime(uint32 delay);

View file

@ -47,6 +47,14 @@ DynamicObject::~DynamicObject()
void DynamicObject::CleanupsBeforeDelete(bool finalCleanup /* = true */)
{
if (Transport* transport = GetTransport())
{
transport->RemovePassenger(this);
SetTransport(nullptr);
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
}
WorldObject::CleanupsBeforeDelete(finalCleanup);
}
@ -80,6 +88,9 @@ void DynamicObject::RemoveFromWorld()
UnbindFromCaster();
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
WorldObject::RemoveFromWorld();
GetMap()->GetObjectsStore().Remove<DynamicObject>(GetGUID());
@ -114,15 +125,17 @@ bool DynamicObject::CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caste
SetFloatValue(DYNAMICOBJECT_RADIUS, radius);
SetUInt32Value(DYNAMICOBJECT_CASTTIME, GameTime::GetGameTimeMS().count());
if (IsWorldObject())
setActive(true); //must before add to map to be put in world container
if (!GetMap()->AddToMap(this, true))
{
// Returning false will cause the object to be deleted - remove from transport
return false;
}
if (IsWorldObject())
{
setActive(true);
}
return true;
}

View file

@ -27,7 +27,6 @@
#include "GridNotifiersImpl.h"
#include "Group.h"
#include "GroupMgr.h"
#include "MapMgr.h"
#include "ObjectMgr.h"
#include "OutdoorPvPMgr.h"
#include "PoolMgr.h"
@ -103,9 +102,18 @@ std::string const& GameObject::GetAIName() const
return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName;
}
void GameObject::CleanupsBeforeDelete(bool finalCleanup)
void GameObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
{
WorldObject::CleanupsBeforeDelete(finalCleanup);
if (GetTransport() && !ToTransport())
{
GetTransport()->RemovePassenger(this);
SetTransport(nullptr);
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
}
if (IsInWorld())
RemoveFromWorld();
if (m_uint32Values) // field array can be not exist if GameOBject not loaded
RemoveFromOwner();
@ -174,6 +182,9 @@ void GameObject::RemoveFromWorld()
if (GetMap()->ContainsGameObjectModel(*m_model))
GetMap()->RemoveGameObjectModel(*m_model);
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
// If linked trap exists, despawn it
if (GameObject* linkedTrap = GetLinkedTrap())
{
@ -877,11 +888,7 @@ void GameObject::Update(uint32 diff)
if (!m_spawnedByDefault)
{
m_respawnTime = 0;
if (m_spawnId)
DestroyForNearbyPlayers(); // xinef: old UpdateObjectVisibility();
else
Delete();
DestroyForNearbyPlayers(); // xinef: old UpdateObjectVisibility();
return;
}
@ -1177,31 +1184,7 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, boo
void GameObject::DeleteFromDB()
{
if (!m_spawnId)
{
LOG_ERROR("entities.gameobject", "Trying to delete not saved gameobject: {}", GetGUID().ToString());
return;
}
GameObjectData const* data = sObjectMgr->GetGameObjectData(m_spawnId);
if (!data)
return;
CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction();
sMapMgr->DoForAllMapsWithMapId(data->mapid,
[this, charTrans](Map* map) -> void
{
// despawn all active objects, and remove their respawns
std::vector<GameObject*> toUnload;
for (auto const& pair : Acore::Containers::MapEqualRange(map->GetGameObjectBySpawnIdStore(), m_spawnId))
toUnload.push_back(pair.second);
for (GameObject* obj : toUnload)
map->AddObjectToRemoveList(obj);
map->RemoveGORespawnTime(m_spawnId);
}
);
GetMap()->RemoveGORespawnTime(m_spawnId);
sObjectMgr->DeleteGOData(m_spawnId);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT);
@ -2190,6 +2173,15 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const
&& dz < (info->maxZ * scale) + radius && dz > (info->minZ * scale) - radius;
}
void GameObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const
{
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION * 2.0f; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, dist);
}
void GameObject::EventInform(uint32 eventId)
{
if (!eventId)

View file

@ -289,6 +289,8 @@ public:
void SendCustomAnim(uint32 anim);
[[nodiscard]] bool IsInRange(float x, float y, float z, float radius) const;
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard!
void ModifyHealth(int32 change, Unit* attackerOrHealer = nullptr, uint32 spellId = 0);
void SetDestructibleBuildingModifyState(bool allow) { m_allowModifyDestructibleBuilding = allow; }
// sets GameObject type 33 destruction flags and optionally default health for that state

View file

@ -21,6 +21,7 @@
#include "CellImpl.h"
#include "Chat.h"
#include "Creature.h"
#include "DynamicVisibility.h"
#include "GameObjectAI.h"
#include "GameTime.h"
#include "GridNotifiers.h"
@ -64,7 +65,7 @@ constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max
VISIBILITY_DISTANCE_SMALL,
VISIBILITY_DISTANCE_LARGE,
VISIBILITY_DISTANCE_GIGANTIC,
MAX_VISIBILITY_DISTANCE
VISIBILITY_DISTANCE_INFINITE
};
Object::Object() : m_PackGUID(sizeof(uint64) + 1)
@ -248,10 +249,7 @@ void Object::SendUpdateToPlayer(Player* player)
UpdateData upd;
WorldPacket packet;
if (player->HaveAtClient(this))
BuildValuesUpdateBlockForPlayer(&upd, player);
else
BuildCreateUpdateBlockForPlayer(&upd, player);
BuildCreateUpdateBlockForPlayer(&upd, player);
upd.BuildPacket(&packet);
player->GetSession()->SendPacket(&packet);
}
@ -1050,7 +1048,7 @@ void MovementInfo::OutDebug()
}
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(),
LastUsedScriptID(0), m_name(""), m_isActive(false), m_isFarVisible(false), m_visibilityDistanceOverride(), m_isWorldObject(isWorldObject), m_zoneScript(nullptr),
LastUsedScriptID(0), m_name(""), m_isActive(false), m_visibilityDistanceOverride(), m_isWorldObject(isWorldObject), m_zoneScript(nullptr),
_zoneId(0), _areaId(0), _floorZ(INVALID_HEIGHT), _outdoors(false), _liquidData(), _updatePositionData(false), m_transport(nullptr),
m_currMap(nullptr), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_useCombinedPhases(true), m_notifyflags(0), m_executed_notifies(0)
{
@ -1107,6 +1105,8 @@ void WorldObject::setActive(bool on)
map->AddToActive(this->ToCreature());
else if (GetTypeId() == TYPEID_DYNAMICOBJECT)
map->AddToActive((DynamicObject*)this);
else if (GetTypeId() == TYPEID_GAMEOBJECT)
map->AddToActive((GameObject*)this);
}
else
{
@ -1114,17 +1114,11 @@ void WorldObject::setActive(bool on)
map->RemoveFromActive(this->ToCreature());
else if (GetTypeId() == TYPEID_DYNAMICOBJECT)
map->RemoveFromActive((DynamicObject*)this);
else if (GetTypeId() == TYPEID_GAMEOBJECT)
map->RemoveFromActive((GameObject*)this);
}
}
void WorldObject::SetFarVisible(bool on)
{
if (GetTypeId() == TYPEID_PLAYER)
return;
m_isFarVisible = on;
}
void WorldObject::SetVisibilityDistanceOverride(VisibilityDistanceType type)
{
ASSERT(type < VisibilityDistanceType::Max);
@ -1140,9 +1134,6 @@ void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
{
if (IsInWorld())
RemoveFromWorld();
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
}
void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 phaseMask)
@ -1635,9 +1626,9 @@ float WorldObject::GetGridActivationRange() const
{
if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
{
return std::max(DEFAULT_VISIBILITY_INSTANCE, GetMap()->GetVisibilityRange());
return DEFAULT_VISIBILITY_INSTANCE;
}
return IsInWintergrasp() ? VISIBILITY_DISTANCE_LARGE : GetMap()->GetVisibilityRange();
return IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
}
else if (ToCreature())
{
@ -1653,12 +1644,29 @@ float WorldObject::GetGridActivationRange() const
float WorldObject::GetVisibilityRange() const
{
if (IsVisibilityOverridden() && !ToPlayer())
if (IsVisibilityOverridden() && GetTypeId() == TYPEID_UNIT)
{
return *m_visibilityDistanceOverride;
else if (IsFarVisible() && !ToPlayer())
return MAX_VISIBILITY_DISTANCE;
}
else if (GetTypeId() == TYPEID_GAMEOBJECT)
{
{
if (IsInWintergrasp())
{
return VISIBILITY_DIST_WINTERGRASP + VISIBILITY_INC_FOR_GOBJECTS;
}
else if (IsVisibilityOverridden())
{
return *m_visibilityDistanceOverride;
}
else
{
return GetMap()->GetVisibilityRange() + VISIBILITY_INC_FOR_GOBJECTS;
}
}
}
else
return IsInWintergrasp() ? VISIBILITY_DISTANCE_LARGE : GetMap()->GetVisibilityRange();
return IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
}
float WorldObject::GetSightRange(WorldObject const* target) const
@ -1667,19 +1675,44 @@ float WorldObject::GetSightRange(WorldObject const* target) const
{
if (ToPlayer())
{
if (target && target->IsVisibilityOverridden() && !target->ToPlayer())
return *target->m_visibilityDistanceOverride;
else if (target && target->IsFarVisible() && !target->ToPlayer())
return MAX_VISIBILITY_DISTANCE;
else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
return DEFAULT_VISIBILITY_INSTANCE;
else
return IsInWintergrasp() ? VISIBILITY_DISTANCE_LARGE : GetMap()->GetVisibilityRange();
if (target)
{
if (target->IsVisibilityOverridden() && target->GetTypeId() == TYPEID_UNIT)
{
return *target->m_visibilityDistanceOverride;
}
else if (target->GetTypeId() == TYPEID_GAMEOBJECT)
{
if (IsInWintergrasp() && target->IsInWintergrasp())
{
return VISIBILITY_DIST_WINTERGRASP + VISIBILITY_INC_FOR_GOBJECTS;
}
else if (target->IsVisibilityOverridden())
{
return *target->m_visibilityDistanceOverride;
}
else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
{
return DEFAULT_VISIBILITY_INSTANCE;
}
else
{
return GetMap()->GetVisibilityRange() + VISIBILITY_INC_FOR_GOBJECTS;
}
}
return IsInWintergrasp() && target->IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
}
return IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
}
else if (ToCreature())
{
return ToCreature()->m_SightDistance;
}
else
{
return SIGHT_RANGE_UNIT;
}
}
if (ToDynObject() && isActiveObject())
@ -2044,8 +2077,11 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const
BuildMovementPacket(data);
}
void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, Player const* skipped_rcvr) const
void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const
{
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, dist);
}
@ -2192,8 +2228,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
return nullptr;
}
if (!IsGridLoaded(pos.GetPositionX(), pos.GetPositionY()))
EnsureGridLoaded(Cell(pos.GetPositionX(), pos.GetPositionY()));
EnsureGridLoaded(Cell(pos.GetPositionX(), pos.GetPositionY()));
if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, vehId, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()))
{
delete summon;
@ -2866,8 +2901,8 @@ void WorldObject::DestroyForNearbyPlayers()
return;
std::list<Player*> targets;
Acore::AnyPlayerInObjectRangeCheck check(this, GetVisibilityRange(), false);
Acore::PlayerListSearcher<Acore::AnyPlayerInObjectRangeCheck> searcher(this, targets, check);
Acore::AnyPlayerInObjectRangeCheck check(this, GetVisibilityRange() + VISIBILITY_COMPENSATION, false);
Acore::PlayerListSearcherWithSharedVision<Acore::AnyPlayerInObjectRangeCheck> searcher(this, targets, check);
Cell::VisitWorldObjects(this, searcher, GetVisibilityRange());
for (std::list<Player*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
{
@ -2887,7 +2922,7 @@ void WorldObject::DestroyForNearbyPlayers()
}
}
void WorldObject::UpdateObjectVisibility(bool /*forced*/)
void WorldObject::UpdateObjectVisibility(bool /*forced*/, bool /*fromUpdate*/)
{
//updates object's visibility for nearby players
Acore::VisibleChangesNotifier notifier(*this);
@ -2896,7 +2931,28 @@ void WorldObject::UpdateObjectVisibility(bool /*forced*/)
void WorldObject::AddToNotify(uint16 f)
{
m_notifyflags |= f;
if (!(m_notifyflags & f))
if (Unit* u = ToUnit())
{
if (f & NOTIFY_VISIBILITY_CHANGED)
{
uint32 EVENT_VISIBILITY_DELAY = u->FindMap() ? DynamicVisibilityMgr::GetVisibilityNotifyDelay(u->FindMap()->GetEntry()->map_type) : 1000;
uint32 diff = getMSTimeDiff(u->m_last_notify_mstime, GameTime::GetGameTimeMS().count());
if (diff >= EVENT_VISIBILITY_DELAY / 2)
EVENT_VISIBILITY_DELAY /= 2;
else
EVENT_VISIBILITY_DELAY -= diff;
u->m_delayed_unit_relocation_timer = EVENT_VISIBILITY_DELAY;
u->m_last_notify_mstime = GameTime::GetGameTimeMS().count() + EVENT_VISIBILITY_DELAY - 1;
}
else if (f & NOTIFY_AI_RELOCATION)
{
u->m_delayed_unit_ai_notify_timer = u->FindMap() ? DynamicVisibilityMgr::GetAINotifyDelay(u->FindMap()->GetEntry()->map_type) : 500;
}
m_notifyflags |= f;
}
}
struct WorldObjectChangeAccumulator
@ -2949,7 +3005,7 @@ struct WorldObjectChangeAccumulator
source = iter->GetSource();
ObjectGuid guid = source->GetCasterGUID();
if (guid.IsPlayer())
if (guid)
{
//Caster may be nullptr if DynObj is in removelist
if (Player* caster = ObjectAccessor::FindPlayer(guid))

View file

@ -379,23 +379,14 @@ class MovableMapObject
template<class T> friend class RandomMovementGenerator;
protected:
MovableMapObject() : _moveState(MAP_OBJECT_CELL_MOVE_NONE)
{
_newPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
}
MovableMapObject() = default;
private:
Cell _currentCell;
[[nodiscard]] Cell const& GetCurrentCell() const { return _currentCell; }
void SetCurrentCell(Cell const& cell) { _currentCell = cell; }
MapObjectCellMoveState _moveState;
Position _newPosition;
void SetNewCellPosition(float x, float y, float z, float o)
{
_moveState = MAP_OBJECT_CELL_MOVE_ACTIVE;
_newPosition.Relocate(x, y, z, o);
}
Cell _currentCell;
MapObjectCellMoveState _moveState{MAP_OBJECT_CELL_MOVE_NONE};
};
class WorldObject : public Object, public WorldLocation
@ -488,9 +479,9 @@ public:
virtual void CleanupsBeforeDelete(bool finalCleanup = true); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units
virtual void SendMessageToSet(WorldPacket const* data, bool self) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), self); } // pussywizard!
virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, Player const* skipped_rcvr = nullptr) const; // pussywizard!
virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), false, skipped_rcvr); } // pussywizard!
virtual void SendMessageToSet(WorldPacket const* data, bool self) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard!
virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const; // pussywizard!
virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), false, true, skipped_rcvr); } // pussywizard!
virtual uint8 getLevelForTarget(WorldObject const* /*target*/) const { return 1; }
@ -547,7 +538,7 @@ public:
void GetDeadCreatureListInGrid(std::list<Creature*>& lList, float maxSearchRange, bool alive = false) const;
void DestroyForNearbyPlayers();
virtual void UpdateObjectVisibility(bool forced = true);
virtual void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false);
void BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& player_set) override;
void GetCreaturesWithEntryInRange(std::list<Creature*>& creatureList, float radius, uint32 entry);
@ -569,7 +560,6 @@ public:
[[nodiscard]] bool isActiveObject() const { return m_isActive; }
void setActive(bool isActiveObject);
[[nodiscard]] bool IsFarVisible() const { return m_isFarVisible; }
void SetFarVisible(bool on);
[[nodiscard]] bool IsVisibilityOverridden() const { return m_visibilityDistanceOverride.has_value(); }
void SetVisibilityDistanceOverride(VisibilityDistanceType type);
void SetWorldObject(bool apply);
@ -578,7 +568,7 @@ public:
[[nodiscard]] bool IsInWintergrasp() const
{
return GetMapId() == 571 && GetZoneId() == 4197;
return GetMapId() == 571 && GetPositionX() > 3733.33331f && GetPositionX() < 5866.66663f && GetPositionY() > 1599.99999f && GetPositionY() < 4799.99997f;
}
#ifdef MAP_BASED_RAND_GEN

View file

@ -23,18 +23,23 @@
#define CONTACT_DISTANCE 0.5f
#define INTERACTION_DISTANCE 5.5f
#define ATTACK_DISTANCE 5.0f
#define VISIBILITY_COMPENSATION 15.0f // increase searchers
#define INSPECT_DISTANCE 28.0f
#define VISIBILITY_INC_FOR_GOBJECTS 30.0f // pussywizard
#define SPELL_SEARCHER_COMPENSATION 30.0f // increase searchers size in case we have large npc near cell border
#define TRADE_DISTANCE 11.11f
#define MAX_VISIBILITY_DISTANCE SIZE_OF_GRIDS // max distance for visible objects, experimental
#define MAX_VISIBILITY_DISTANCE 250.0f // max distance for visible objects, experimental
#define SIGHT_RANGE_UNIT 50.0f
#define MAX_SEARCHER_DISTANCE 150.0f // pussywizard: replace the use of MAX_VISIBILITY_DISTANCE in searchers, because MAX_VISIBILITY_DISTANCE is quite too big for this purpose
#define VISIBILITY_DISTANCE_INFINITE 533.0f
#define VISIBILITY_DISTANCE_GIGANTIC 400.0f
#define VISIBILITY_DISTANCE_LARGE 200.0f
#define VISIBILITY_DISTANCE_NORMAL 100.0f
#define VISIBILITY_DISTANCE_SMALL 50.0f
#define VISIBILITY_DISTANCE_TINY 25.0f
#define DEFAULT_VISIBILITY_DISTANCE VISIBILITY_DISTANCE_NORMAL // default visible distance, 100 yards on continents
#define DEFAULT_VISIBILITY_DISTANCE 100.0f // default visible distance, 100 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards
#define VISIBILITY_DIST_WINTERGRASP 175.0f
#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards
#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects

View file

@ -134,7 +134,6 @@ class ObjectGuid
ObjectGuid(HighGuid hi, uint32 entry, LowType counter) : _guid(counter ? uint64(counter) | (uint64(entry) << 24) | (uint64(hi) << 48) : 0) { }
ObjectGuid(HighGuid hi, LowType counter) : _guid(counter ? uint64(counter) | (uint64(hi) << 48) : 0) { }
operator uint64() const { return _guid; }
PackedGuidReader ReadAsPacked() { return PackedGuidReader(*this); }
void Set(uint64 guid) { _guid = guid; }

View file

@ -1353,7 +1353,10 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (GetTransport())
{
m_transport->RemovePassenger(this, true);
m_transport->RemovePassenger(this);
m_transport = nullptr;
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
}
@ -1395,7 +1398,10 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
else
{
m_transport->RemovePassenger(this, true);
m_transport->RemovePassenger(this);
m_transport = nullptr;
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
}
}
@ -5575,11 +5581,14 @@ void Player::SaveRecallPosition()
m_recallO = GetOrientation();
}
void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, Player const* skipped_rcvr) const
void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, Player const* skipped_rcvr) const
{
if (self)
GetSession()->SendPacket(data);
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, dist);
}
@ -11313,7 +11322,7 @@ WorldLocation Player::GetStartPosition() const
return WorldLocation(mapId, info->positionX, info->positionY, info->positionZ, 0);
}
bool Player::HaveAtClient(Object const* u) const
bool Player::HaveAtClient(WorldObject const* u) const
{
if (u == this)
{
@ -13087,11 +13096,14 @@ void Player::SetViewpoint(WorldObject* target, bool apply)
UpdateVisibilityOf(target);
if (target->isType(TYPEMASK_UNIT) && !GetVehicle())
static_cast<Unit*>(target)->AddPlayerToVision(this);
((Unit*)target)->AddPlayerToVision(this);
SetSeer(target);
}
else
{
//must immediately set seer back otherwise may crash
m_seer = this;
LOG_DEBUG("maps", "Player::CreateViewpoint: Player {} remove seer", GetName());
if (!RemoveGuidValue(PLAYER_FARSIGHT, target->GetGUID()))

View file

@ -1986,10 +1986,10 @@ public:
void ProcessTerrainStatusUpdate() override;
void SendMessageToSet(WorldPacket const* data, bool self) const override { SendMessageToSetInRange(data, GetVisibilityRange(), self); } // pussywizard!
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, Player const* skipped_rcvr = nullptr) const override; // pussywizard!
void SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const; // pussywizard!
void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override { SendMessageToSetInRange(data, GetVisibilityRange(), skipped_rcvr != this, skipped_rcvr); } // pussywizard!
void SendMessageToSet(WorldPacket const* data, bool self) const override { SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard!
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard!
void SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const; // pussywizard! param includeMargin not needed here
void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override { SendMessageToSetInRange(data, GetVisibilityRange(), skipped_rcvr != this, true, skipped_rcvr); } // pussywizard!
void SendTeleportAckPacket();
@ -2342,8 +2342,9 @@ public:
// currently visible objects at player client
GuidUnorderedSet m_clientGUIDs;
std::vector<Unit*> m_newVisible; // pussywizard
[[nodiscard]] bool HaveAtClient(Object const* u) const;
[[nodiscard]] bool HaveAtClient(WorldObject const* u) const;
[[nodiscard]] bool HaveAtClient(ObjectGuid guid) const;
[[nodiscard]] bool IsNeverVisible() const override;
@ -2351,13 +2352,13 @@ public:
bool IsVisibleGloballyFor(Player const* player) const;
void GetInitialVisiblePackets(Unit* target);
void UpdateObjectVisibility(bool forced = true) override;
void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false) override;
void UpdateVisibilityForPlayer(bool mapChange = false);
void UpdateVisibilityOf(WorldObject* target);
void UpdateTriggerVisibility();
template<class T>
void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow);
void UpdateVisibilityOf(T* target, UpdateData& data, std::vector<Unit*>& visibleNow);
uint8 m_forced_speed_changes[MAX_MOVE_TYPE];

View file

@ -412,6 +412,14 @@ void Player::Update(uint32 p_time)
SetHasDelayedTeleport(false);
TeleportTo(teleportStore_dest, teleportStore_options);
}
if (!IsBeingTeleported() && bRequestForcedVisibilityUpdate)
{
bRequestForcedVisibilityUpdate = false;
UpdateObjectVisibility(true, true);
m_delayed_unit_relocation_timer = 0;
RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
}
}
void Player::UpdateMirrorTimers()
@ -1521,11 +1529,17 @@ void Player::UpdatePotionCooldown(Spell* spell)
SetLastPotionId(0);
}
template void Player::UpdateVisibilityOf(Player* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(Player* target, UpdateData& data,
std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data,
std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data,
std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data,
std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(DynamicObject* target,
UpdateData& data,
std::vector<Unit*>& visibleNow);
void Player::UpdateVisibilityForPlayer(bool mapChange)
{
@ -1536,13 +1550,23 @@ void Player::UpdateVisibilityForPlayer(bool mapChange)
m_seer = this;
}
// updates visibility of all objects around point of view for current player
Acore::VisibleNotifier notifier(*this);
Cell::VisitAllObjects(m_seer, notifier, GetSightRange());
notifier.SendToSelf(); // send gathered data
Acore::VisibleNotifier notifierNoLarge(
*this, mapChange,
false); // visit only objects which are not large; default distance
Cell::VisitAllObjects(m_seer, notifierNoLarge,
GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
notifierNoLarge.SendToSelf();
Acore::VisibleNotifier notifierLarge(
*this, mapChange, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(m_seer, notifierLarge, GetSightRange());
notifierLarge.SendToSelf();
if (mapChange)
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
}
void Player::UpdateObjectVisibility(bool forced)
void Player::UpdateObjectVisibility(bool forced, bool fromUpdate)
{
// Prevent updating visibility if player is not in world (example: LoadFromDB sets drunkstate which updates invisibility while player is not in map)
if (!IsInWorld())
@ -1552,19 +1576,26 @@ void Player::UpdateObjectVisibility(bool forced)
AddToNotify(NOTIFY_VISIBILITY_CHANGED);
else if (!isBeingLoaded())
{
if (!fromUpdate) // pussywizard:
{
bRequestForcedVisibilityUpdate = true;
return;
}
Unit::UpdateObjectVisibility(true);
UpdateVisibilityForPlayer();
}
}
template <class T>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, T* target, std::set<Unit*>& /*v*/)
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, T* target,
std::vector<Unit*>& /*v*/)
{
s64.insert(target->GetGUID());
}
template <>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target, std::set<Unit*>& /*v*/)
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target,
std::vector<Unit*>& /*v*/)
{
// @HACK: This is to prevent objects like deeprun tram from disappearing
// when player moves far from its spawn point while riding it
@ -1573,17 +1604,19 @@ inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target,
}
template <>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Creature* target, std::set<Unit*>& v)
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Creature* target,
std::vector<Unit*>& v)
{
s64.insert(target->GetGUID());
v.insert(target);
v.push_back(target);
}
template <>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Player* target, std::set<Unit*>& v)
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Player* target,
std::vector<Unit*>& v)
{
s64.insert(target->GetGUID());
v.insert(target);
v.push_back(target);
}
template <class T>
@ -1599,7 +1632,8 @@ inline void BeforeVisibilityDestroy<Creature>(Creature* t, Player* p)
}
template <class T>
void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow)
void Player::UpdateVisibilityOf(T* target, UpdateData& data,
std::vector<Unit*>& visibleNow)
{
if (HaveAtClient(target))
{

View file

@ -32,7 +32,7 @@
#include "World.h"
#include "WorldModel.h"
MotionTransport::MotionTransport() : Transport(), _transportInfo(nullptr), _isMoving(true), _pendingStop(false), _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), _delayedTeleport(false)
MotionTransport::MotionTransport() : Transport(), _transportInfo(nullptr), _isMoving(true), _pendingStop(false), _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), _passengersLoaded(false), _delayedTeleport(false)
{
m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION;
}
@ -230,14 +230,8 @@ void MotionTransport::Update(uint32 diff)
3. transport moves from active to inactive grid
4. the grid that transport is currently in unloads
*/
bool gridActive = GetMap()->IsGridLoaded(GetPositionX(), GetPositionY());
if (_staticPassengers.empty() && gridActive) // 2.
if (_staticPassengers.empty() && GetMap()->IsGridLoaded(GetPositionX(), GetPositionY())) // 2.
LoadStaticPassengers();
else if (!_staticPassengers.empty() && !gridActive)
// 4. - if transports stopped on grid edge, some passengers can remain in active grids
// unload all static passengers otherwise passengers won't load correctly when the grid that transport is currently in becomes active
UnloadStaticPassengers();
}
}
@ -254,27 +248,18 @@ void MotionTransport::DelayedUpdate(uint32 /*diff*/)
void MotionTransport::UpdatePosition(float x, float y, float z, float o)
{
bool newActive = GetMap()->IsGridLoaded(x, y);
Cell oldCell(GetPositionX(), GetPositionY());
if (!GetMap()->IsGridLoaded(x, y)) // pussywizard: should not happen, but just in case
GetMap()->LoadGrid(x, y);
Relocate(x, y, z, o);
UpdateModelPosition();
UpdatePassengerPositions(_passengers);
/* There are four possible scenarios that trigger loading/unloading passengers:
1. transport moves from inactive to active grid
2. the grid that transport is currently in becomes active
3. transport moves from active to inactive grid
4. the grid that transport is currently in unloads
*/
if (_staticPassengers.empty() && newActive) // 1.
if (_staticPassengers.empty())
LoadStaticPassengers();
else if (!_staticPassengers.empty() && !newActive && oldCell.DiffGrid(Cell(GetPositionX(), GetPositionY()))) // 3.
UnloadStaticPassengers();
else
UpdatePassengerPositions(_staticPassengers);
// 4. is handed by grid unload
}
void MotionTransport::AddPassenger(WorldObject* passenger, bool withAll)
@ -321,7 +306,8 @@ void MotionTransport::RemovePassenger(WorldObject* passenger, bool withAll)
{
passenger->SetTransport(nullptr);
passenger->m_movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
passenger->m_movementInfo.transport.Reset();
passenger->m_movementInfo.transport.guid.Clear();
passenger->m_movementInfo.transport.pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
if (passenger->ToUnit())
{
passenger->ToUnit()->ClearUnitState(UNIT_STATE_IGNORE_PATHFINDING);
@ -421,6 +407,9 @@ GameObject* MotionTransport::CreateGOPassenger(ObjectGuid::LowType guid, GameObj
void MotionTransport::LoadStaticPassengers()
{
if (PassengersLoaded())
return;
SetPassengersLoaded(true);
if (uint32 mapId = GetGOInfo()->moTransport.mapID)
{
CellObjectGuidsMap const& cells = sObjectMgr->GetMapObjectGuids(mapId, GetMap()->GetSpawnMode());
@ -442,6 +431,7 @@ void MotionTransport::LoadStaticPassengers()
void MotionTransport::UnloadStaticPassengers()
{
SetPassengersLoaded(false);
while (!_staticPassengers.empty())
{
WorldObject* obj = *_staticPassengers.begin();
@ -552,19 +542,11 @@ void MotionTransport::DelayedTeleportTransport()
_delayedTeleport = false;
uint32 newMapId = _nextFrame->Node->mapid;
Map* newMap = sMapMgr->CreateBaseMap(newMapId);
GetMap()->RemoveFromMap<MotionTransport>(this, false);
float x = _nextFrame->Node->x,
y = _nextFrame->Node->y,
z = _nextFrame->Node->z,
o = _nextFrame->InitialOrientation;
if (!newMap->IsGridLoaded(x, y) && !_passengers.empty())
newMap->LoadGrid(x, y); // xinef: load before adding passengers to new map
SetMap(newMap);
PassengerSet _passengersCopy = _passengers;
for (PassengerSet::iterator itr = _passengersCopy.begin(); itr != _passengersCopy.end(); )
{
@ -610,8 +592,15 @@ void MotionTransport::DelayedTeleportTransport()
}
}
Map* newMap = sMapMgr->CreateBaseMap(newMapId);
GetMap()->RemoveFromMap<MotionTransport>(this, false);
newMap->LoadGrid(x, y); // xinef: load before adding passengers to new map
SetMap(newMap);
Relocate(x, y, z, o);
GetMap()->AddToMap<MotionTransport>(this);
LoadStaticPassengers();
}
void MotionTransport::UpdatePassengerPositions(PassengerSet& passengers)
@ -642,7 +631,7 @@ void MotionTransport::UpdatePassengerPositions(PassengerSet& passengers)
case TYPEID_UNIT:
{
Creature* creature = passenger->ToCreature();
GetMap()->CreatureRelocation(creature, x, y, z, o, false);
GetMap()->CreatureRelocation(creature, x, y, z, o);
creature->GetTransportHomePosition(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
@ -654,7 +643,7 @@ void MotionTransport::UpdatePassengerPositions(PassengerSet& passengers)
GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o);
break;
case TYPEID_GAMEOBJECT:
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false);
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o);
break;
case TYPEID_DYNAMICOBJECT:
GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o);
@ -791,6 +780,7 @@ bool StaticTransport::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* m
LastUsedScriptID = GetGOInfo()->ScriptId;
AIM_Initialize();
this->setActive(true);
return true;
}
@ -925,8 +915,7 @@ void StaticTransport::UpdatePosition(float x, float y, float z, float o)
if (!GetMap()->IsGridLoaded(x, y)) // pussywizard: should not happen, but just in case
GetMap()->LoadGrid(x, y);
Relocate(x, y, z, o);
UpdateModelPosition();
GetMap()->GameObjectRelocation(this, x, y, z, o); // this also relocates the model
UpdatePassengerPositions();
}
@ -953,14 +942,17 @@ void StaticTransport::UpdatePassengerPositions()
switch (passenger->GetTypeId())
{
case TYPEID_UNIT:
GetMap()->CreatureRelocation(passenger->ToCreature(), x, y, z, o, false);
GetMap()->CreatureRelocation(passenger->ToCreature(), x, y, z, o);
break;
case TYPEID_PLAYER:
if (passenger->IsInWorld())
{
GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o);
passenger->ToPlayer()->SetFallInformation(GameTime::GetGameTime().count(), z);
}
break;
case TYPEID_GAMEOBJECT:
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false);
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o);
break;
case TYPEID_DYNAMICOBJECT:
GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o);
@ -1009,7 +1001,8 @@ void StaticTransport::RemovePassenger(WorldObject* passenger, bool withAll)
{
passenger->SetTransport(nullptr);
passenger->m_movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
passenger->m_movementInfo.transport.Reset();
passenger->m_movementInfo.transport.guid.Clear();
passenger->m_movementInfo.transport.pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
}
}
}

View file

@ -68,6 +68,8 @@ public:
PassengerSet const& GetStaticPassengers() const { return _staticPassengers; }
void UnloadStaticPassengers();
void UnloadNonStaticPassengers();
void SetPassengersLoaded(bool loaded) { _passengersLoaded = loaded; }
bool PassengersLoaded() const { return _passengersLoaded; }
KeyFrameVec const& GetKeyFrames() const { return _transportInfo->keyFrames; }
void EnableMovement(bool enabled);
@ -102,6 +104,7 @@ private:
PassengerSet _staticPassengers;
mutable std::mutex Lock;
bool _passengersLoaded;
bool _delayedTeleport;
};

View file

@ -32,6 +32,7 @@
#include "CreatureAIImpl.h"
#include "CreatureGroups.h"
#include "DisableMgr.h"
#include "DynamicVisibility.h"
#include "Formulas.h"
#include "GameObjectAI.h"
#include "GameTime.h"
@ -43,7 +44,6 @@
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "MovementGenerator.h"
#include "MovementPacketBuilder.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
@ -317,6 +317,12 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
m_last_notify_mstime = 0;
m_delayed_unit_relocation_timer = 0;
m_delayed_unit_ai_notify_timer = 0;
bRequestForcedVisibilityUpdate = false;
m_applyResilience = false;
_instantCast = false;
@ -405,6 +411,32 @@ void Unit::Update(uint32 p_time)
if (!IsInWorld())
return;
// pussywizard:
if (GetTypeId() != TYPEID_PLAYER || (!ToPlayer()->IsBeingTeleported() && !bRequestForcedVisibilityUpdate))
{
if (m_delayed_unit_relocation_timer)
{
if (m_delayed_unit_relocation_timer <= p_time)
{
m_delayed_unit_relocation_timer = 0;
//ExecuteDelayedUnitRelocationEvent();
FindMap()->i_objectsForDelayedVisibility.insert(this);
}
else
m_delayed_unit_relocation_timer -= p_time;
}
if (m_delayed_unit_ai_notify_timer)
{
if (m_delayed_unit_ai_notify_timer <= p_time)
{
m_delayed_unit_ai_notify_timer = 0;
ExecuteDelayedUnitAINotifyEvent();
}
else
m_delayed_unit_ai_notify_timer -= p_time;
}
}
_UpdateSpells( p_time );
if (CanHaveThreatList() && GetThreatMgr().isNeedUpdateToClient(p_time))
@ -568,27 +600,14 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
SplineHandler handler(this);
movespline->updateState(t_diff, handler);
// Xinef: Spline was cleared by StopMoving, return
if (!movespline->Initialized()) {
if (!movespline->Initialized())
{
DisableSpline();
return;
}
bool arrived = movespline->Finalized();
if (movespline->isCyclic())
{
m_splineSyncTimer.Update(t_diff);
if (m_splineSyncTimer.Passed())
{
m_splineSyncTimer.Reset(5000); // Retail value, do not change
WorldPacket data(SMSG_FLIGHT_SPLINE_SYNC, 4 + GetPackGUID().size());
Movement::PacketBuilder::WriteSplineSync(*movespline, data);
data.appendPackGUID(GetGUID());
SendMessageToSet(&data, true);
}
}
if (arrived)
{
DisableSpline();
@ -597,11 +616,17 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, movespline->GetAnimationType());
}
// pussywizard: update always! not every 400ms, because movement generators need the actual position
//m_movesplineTimer.Update(t_diff);
//if (m_movesplineTimer.Passed() || arrived)
UpdateSplinePosition();
}
void Unit::UpdateSplinePosition()
{
//static uint32 const positionUpdateDelay = 400;
//m_movesplineTimer.Reset(positionUpdateDelay);
Movement::Location loc = movespline->ComputePosition();
if (movespline->onTransport)
@ -614,14 +639,16 @@ void Unit::UpdateSplinePosition()
if (TransportBase* transport = GetDirectTransport())
transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation);
else
return;
}
if (HasUnitState(UNIT_STATE_CANNOT_TURN))
loc.orientation = GetOrientation();
// Xinef: if we had spline running update orientation along with position
//if (HasUnitState(UNIT_STATE_CANNOT_TURN))
// loc.orientation = GetOrientation();
UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
if (GetTypeId() == TYPEID_PLAYER)
UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
else
ToCreature()->SetPosition(loc.x, loc.y, loc.z, loc.orientation);
}
void Unit::DisableSpline()
@ -15714,9 +15741,15 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
void Unit::CleanupsBeforeDelete(bool finalCleanup)
{
CleanupBeforeRemoveFromMap(finalCleanup);
if (GetTransport())
{
GetTransport()->RemovePassenger(this);
SetTransport(nullptr);
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
}
WorldObject::CleanupsBeforeDelete(finalCleanup);
CleanupBeforeRemoveFromMap(finalCleanup);
}
void Unit::UpdateCharmAI()
@ -17489,17 +17522,13 @@ void Unit::SetContestedPvP(Player* attackedPlayer, bool lookForNearContestedGuar
player->AddUnitState(UNIT_STATE_ATTACK_PLAYER);
player->SetPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP);
// call MoveInLineOfSight for nearby contested guards
Acore::AIRelocationNotifier notifier(*this);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
AddToNotify(NOTIFY_AI_RELOCATION);
}
for (Unit* unit : m_Controlled)
if (!HasUnitState(UNIT_STATE_ATTACK_PLAYER))
{
if (!unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER))
{
unit->AddUnitState(UNIT_STATE_ATTACK_PLAYER);
Acore::AIRelocationNotifier notifier(*unit);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
}
AddUnitState(UNIT_STATE_ATTACK_PLAYER);
// call MoveInLineOfSight for nearby contested guards
AddToNotify(NOTIFY_AI_RELOCATION);
}
}
@ -19346,7 +19375,7 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
}
}
void Unit::UpdateObjectVisibility(bool forced)
void Unit::UpdateObjectVisibility(bool forced, bool /*fromUpdate*/)
{
if (!forced)
AddToNotify(NOTIFY_VISIBILITY_CHANGED);
@ -19354,7 +19383,8 @@ void Unit::UpdateObjectVisibility(bool forced)
{
WorldObject::UpdateObjectVisibility(true);
Acore::AIRelocationNotifier notifier(*this);
Cell::VisitAllObjects(this, notifier, GetVisibilityRange());
float radius = 60.0f;
Cell::VisitAllObjects(this, notifier, radius);
}
}
@ -20252,14 +20282,10 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
if (!Acore::IsValidMapCoord(x, y, z, orientation))
return false;
// Check if angular distance changed
bool const turn = G3D::fuzzyGt(M_PI - fabs(fabs(GetOrientation() - orientation) - M_PI), 0.0f);
// G3D::fuzzyEq won't help here, in some cases magnitudes differ by a little more than G3D::eps, but should be considered equal
bool const relocated = (teleport ||
std::fabs(GetPositionX() - x) > 0.001f ||
std::fabs(GetPositionY() - y) > 0.001f ||
std::fabs(GetPositionZ() - z) > 0.001f);
float old_orientation = GetOrientation();
float current_z = GetPositionZ();
bool turn = (old_orientation != orientation);
bool relocated = (teleport || GetPositionX() != x || GetPositionY() != y || current_z != z);
if (!GetVehicle())
{
@ -20285,8 +20311,6 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
UpdateObjectVisibility(false);
}
UpdatePositionData();
return (relocated || turn);
}
@ -20717,6 +20741,124 @@ bool ConflagrateAuraStateDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time
return true;
}
void Unit::ExecuteDelayedUnitRelocationEvent()
{
this->RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
return;
if (this->HasSharedVision())
for (SharedVisionList::const_iterator itr = this->GetSharedVisionList().begin(); itr != this->GetSharedVisionList().end(); ++itr)
if (Player* player = (*itr))
{
if (player->IsOnVehicle(this) || !player->IsInWorld() || player->IsDuringRemoveFromWorld()) // players on vehicles have their own event executed (due to passenger relocation)
continue;
WorldObject* viewPoint = player;
if (player->m_seer && player->m_seer->IsInWorld())
viewPoint = player->m_seer;
if (!viewPoint->IsPositionValid() || !player->IsPositionValid())
continue;
if (Unit* active = viewPoint->ToUnit())
{
//if (active->IsVehicle()) // always check original unit here, last notify position is not relocated
// active = player;
float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
continue;
// this will be relocated below sharedvision!
//active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
}
Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance
Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
relocateNoLarge.SendToSelf();
Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
relocateLarge.SendToSelf();
}
if (Player* player = this->ToPlayer())
{
WorldObject* viewPoint = player;
if (player->m_seer && player->m_seer->IsInWorld())
viewPoint = player->m_seer;
if (viewPoint->GetMapId() != player->GetMapId() || !viewPoint->IsPositionValid() || !player->IsPositionValid())
return;
if (Unit* active = viewPoint->ToUnit())
{
if (active->IsVehicle())
active = player;
if (!player->GetFarSightDistance())
{
float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
return;
active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
}
}
Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance
Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
relocateNoLarge.SendToSelf();
if (!player->GetFarSightDistance())
{
Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
relocateLarge.SendToSelf();
}
this->AddToNotify(NOTIFY_AI_RELOCATION);
}
else if (Creature* unit = this->ToCreature())
{
if (!unit->IsPositionValid())
return;
float dx = unit->m_last_notify_position.GetPositionX() - unit->GetPositionX();
float dy = unit->m_last_notify_position.GetPositionY() - unit->GetPositionY();
float dz = unit->m_last_notify_position.GetPositionZ() - unit->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(unit->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
return;
unit->m_last_notify_position.Relocate(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ());
Acore::CreatureRelocationNotifier relocate(*unit);
Cell::VisitAllObjects(unit, relocate, unit->GetVisibilityRange() + VISIBILITY_COMPENSATION);
this->AddToNotify(NOTIFY_AI_RELOCATION);
}
}
void Unit::ExecuteDelayedUnitAINotifyEvent()
{
this->RemoveFromNotify(NOTIFY_AI_RELOCATION);
if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
return;
Acore::AIRelocationNotifier notifier(*this);
float radius = 60.0f;
Cell::VisitAllObjects(this, notifier, radius);
}
void Unit::SetInFront(WorldObject const* target)
{
if (!HasUnitState(UNIT_STATE_CANNOT_TURN))

View file

@ -2145,7 +2145,7 @@ public:
// common function for visibility checks for player/creatures with detection code
[[nodiscard]] uint32 GetPhaseByAuras() const;
void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite WorldObject::SetPhaseMask
void UpdateObjectVisibility(bool forced = true) override;
void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false) override;
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
uint32 m_lastSanctuaryTime;
@ -2419,6 +2419,14 @@ public:
void AddPointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.insert(sup); }
void RemovePointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.erase(sup); }
static void HandleSafeUnitPointersOnDelete(Unit* thisUnit);
// Relocation Nofier optimization
Position m_last_notify_position;
uint32 m_last_notify_mstime;
uint16 m_delayed_unit_relocation_timer;
uint16 m_delayed_unit_ai_notify_timer;
bool bRequestForcedVisibilityUpdate;
void ExecuteDelayedUnitRelocationEvent();
void ExecuteDelayedUnitAINotifyEvent();
// cooldowns
[[nodiscard]] virtual bool HasSpellCooldown(uint32 /*spell_id*/) const { return false; }
@ -2577,7 +2585,7 @@ private:
uint32 m_state; // Even derived shouldn't modify
uint32 m_CombatTimer;
uint32 m_lastManaUse; // msecs
TimeTrackerSmall m_splineSyncTimer;
//TimeTrackerSmall m_movesplineTimer;
Diminishing m_Diminishing;
// Manage all Units that are threatened by us

View file

@ -545,8 +545,7 @@ bool Vehicle::IsVehicleInUse()
void Vehicle::TeleportVehicle(float x, float y, float z, float ang)
{
if (!_me->GetMap()->IsGridLoaded(x, y))
_me->GetMap()->LoadGrid(x, y);
_me->GetMap()->LoadGrid(x, y);
_me->NearTeleportTo(x, y, z, ang, true);
for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)