mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 17:19:07 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -80,6 +80,7 @@ Map::Map(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent) :
|
||||
m_parentMap = (_parent ? _parent : this);
|
||||
|
||||
_zonePlayerCountMap.clear();
|
||||
_updatableObjectListRecheckTimer.SetInterval(UPDATABLE_OBJECT_LIST_RECHECK_TIMER);
|
||||
|
||||
//lets initialize visibility distance for map
|
||||
Map::InitVisibilityDistance();
|
||||
@@ -492,45 +493,7 @@ bool Map::AddToMap(MotionTransport* obj, bool /*checkTransport*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Map::VisitNearbyCellsOfPlayer(Player* player, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor)
|
||||
{
|
||||
// check for valid position
|
||||
if (!player->IsPositionValid())
|
||||
return;
|
||||
|
||||
// check normal grid activation range of the player
|
||||
VisitNearbyCellsOf(player, gridVisitor, worldVisitor, largeGridVisitor, largeWorldVisitor);
|
||||
|
||||
// check maximum visibility distance for large creatures
|
||||
CellArea area = Cell::CalculateCellArea(player->GetPositionX(), player->GetPositionY(), MAX_VISIBILITY_DISTANCE);
|
||||
|
||||
for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
|
||||
{
|
||||
for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
|
||||
{
|
||||
// marked cells are those that have been visited
|
||||
// don't visit the same cell twice
|
||||
uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
|
||||
if (isCellMarkedLarge(cell_id))
|
||||
continue;
|
||||
|
||||
markCellLarge(cell_id);
|
||||
CellCoord pair(x, y);
|
||||
Cell cell(pair);
|
||||
|
||||
Visit(cell, largeGridVisitor);
|
||||
Visit(cell, largeWorldVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor)
|
||||
void Map::MarkNearbyCellsOf(WorldObject* obj)
|
||||
{
|
||||
// Check for valid position
|
||||
if (!obj->IsPositionValid())
|
||||
@@ -538,30 +501,13 @@ void Map::VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::Objec
|
||||
|
||||
// Update mobs/objects in ALL visible cells around object!
|
||||
CellArea area = Cell::CalculateCellArea(obj->GetPositionX(), obj->GetPositionY(), obj->GetGridActivationRange());
|
||||
|
||||
for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
|
||||
{
|
||||
for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
|
||||
{
|
||||
// marked cells are those that have been visited
|
||||
// don't visit the same cell twice
|
||||
uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
|
||||
if (isCellMarked(cell_id))
|
||||
continue;
|
||||
|
||||
markCell(cell_id);
|
||||
CellCoord pair(x, y);
|
||||
Cell cell(pair);
|
||||
|
||||
Visit(cell, gridVisitor);
|
||||
Visit(cell, worldVisitor);
|
||||
|
||||
if (!isCellMarkedLarge(cell_id))
|
||||
{
|
||||
markCellLarge(cell_id);
|
||||
Visit(cell, largeGridVisitor);
|
||||
Visit(cell, largeWorldVisitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -613,39 +559,10 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
return;
|
||||
}
|
||||
|
||||
/// update active cells around players and active objects
|
||||
_updatableObjectListRecheckTimer.Update(t_diff);
|
||||
resetMarkedCells();
|
||||
resetMarkedCellsLarge();
|
||||
|
||||
// Prepare object updaters
|
||||
Acore::ObjectUpdater updater(t_diff, false);
|
||||
|
||||
// For creature
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer> grid_object_update(updater);
|
||||
|
||||
// For pets
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer> world_object_update(updater);
|
||||
|
||||
// For large creatures
|
||||
Acore::ObjectUpdater largeObjectUpdater(t_diff, true);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer> grid_large_object_update(largeObjectUpdater);
|
||||
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer> world_large_object_update(largeObjectUpdater);
|
||||
|
||||
// pussywizard: container for far creatures in combat with players
|
||||
std::vector<Creature*> updateList;
|
||||
updateList.reserve(10);
|
||||
|
||||
// Update non-player active objects
|
||||
for (m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end();)
|
||||
{
|
||||
WorldObject* obj = *m_activeNonPlayersIter;
|
||||
++m_activeNonPlayersIter;
|
||||
|
||||
if (obj && obj->IsInWorld())
|
||||
VisitNearbyCellsOf(obj, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
|
||||
// Update players and their associated objects
|
||||
// Update players
|
||||
for (m_mapRefIter = m_mapRefMgr.begin(); m_mapRefIter != m_mapRefMgr.end(); ++m_mapRefIter)
|
||||
{
|
||||
Player* player = m_mapRefIter->GetSource();
|
||||
@@ -654,53 +571,37 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
continue;
|
||||
|
||||
player->Update(s_diff);
|
||||
VisitNearbyCellsOfPlayer(player, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
|
||||
// If player is using far sight, update viewpoint
|
||||
if (WorldObject* viewPoint = player->GetViewpoint())
|
||||
if (_updatableObjectListRecheckTimer.Passed())
|
||||
{
|
||||
if (Creature* viewCreature = viewPoint->ToCreature())
|
||||
{
|
||||
VisitNearbyCellsOf(viewCreature, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
else if (DynamicObject* viewObject = viewPoint->ToDynObject())
|
||||
{
|
||||
VisitNearbyCellsOf(viewObject, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
}
|
||||
MarkNearbyCellsOf(player);
|
||||
|
||||
// handle updates for creatures in combat with player and are more than X yards away
|
||||
if (player->IsInCombat())
|
||||
{
|
||||
updateList.clear();
|
||||
float rangeSq = player->GetGridActivationRange() - 1.0f;
|
||||
rangeSq *= rangeSq;
|
||||
|
||||
HostileReference* ref = player->getHostileRefMgr().getFirst();
|
||||
while (ref)
|
||||
// If player is using far sight, update viewpoint
|
||||
if (WorldObject* viewPoint = player->GetViewpoint())
|
||||
{
|
||||
if (Unit* unit = ref->GetSource()->GetOwner())
|
||||
if (Creature* cre = unit->ToCreature())
|
||||
if (cre->FindMap() == player->FindMap() && cre->GetExactDist2dSq(player) > rangeSq)
|
||||
updateList.push_back(cre);
|
||||
ref = ref->next();
|
||||
if (Creature* viewCreature = viewPoint->ToCreature())
|
||||
MarkNearbyCellsOf(viewCreature);
|
||||
else if (DynamicObject* viewObject = viewPoint->ToDynObject())
|
||||
MarkNearbyCellsOf(viewObject);
|
||||
}
|
||||
|
||||
for (Creature* cre : updateList)
|
||||
VisitNearbyCellsOf(cre, grid_object_update, world_object_update, grid_large_object_update, world_large_object_update);
|
||||
}
|
||||
}
|
||||
|
||||
// Update transports - pussywizard: transports updated after VisitNearbyCellsOf, grids around are loaded, everything ok
|
||||
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
|
||||
if (_updatableObjectListRecheckTimer.Passed())
|
||||
{
|
||||
MotionTransport* transport = *_transportsUpdateIter;
|
||||
++_transportsUpdateIter;
|
||||
// Mark all cells near active objects
|
||||
for (m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end(); ++m_activeNonPlayersIter)
|
||||
{
|
||||
WorldObject* obj = *m_activeNonPlayersIter;
|
||||
if (!obj || !obj->IsInWorld())
|
||||
continue;
|
||||
|
||||
if (transport->IsInWorld())
|
||||
transport->Update(t_diff);
|
||||
MarkNearbyCellsOf(obj);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateNonPlayerObjects(t_diff);
|
||||
|
||||
SendObjectUpdates();
|
||||
|
||||
///- Process necessary scripts
|
||||
@@ -728,6 +629,101 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
|
||||
METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
|
||||
}
|
||||
|
||||
void Map::UpdateNonPlayerObjects(uint32 const diff)
|
||||
{
|
||||
for (WorldObject* obj : _pendingAddUpdatableObjectList)
|
||||
_AddObjectToUpdateList(obj);
|
||||
_pendingAddUpdatableObjectList.clear();
|
||||
|
||||
if (_updatableObjectListRecheckTimer.Passed())
|
||||
{
|
||||
for (uint32 i = 0; i < _updatableObjectList.size();)
|
||||
{
|
||||
WorldObject* obj = _updatableObjectList[i];
|
||||
if (!obj->IsInWorld())
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
obj->Update(diff);
|
||||
|
||||
if (!obj->IsUpdateNeeded())
|
||||
{
|
||||
_RemoveObjectFromUpdateList(obj);
|
||||
// Intentional no iteration here, obj is swapped with last element in
|
||||
// _updatableObjectList so next loop will update that object at the same index
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
_updatableObjectListRecheckTimer.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = 0; i < _updatableObjectList.size(); ++i)
|
||||
{
|
||||
WorldObject* obj = _updatableObjectList[i];
|
||||
if (!obj->IsInWorld())
|
||||
continue;
|
||||
|
||||
obj->Update(diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::AddObjectToPendingUpdateList(WorldObject* obj)
|
||||
{
|
||||
if (!obj->CanBeAddedToMapUpdateList())
|
||||
return;
|
||||
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
if (mapUpdatableObject->GetUpdateState() != UpdatableMapObject::UpdateState::NotUpdating)
|
||||
return;
|
||||
|
||||
_pendingAddUpdatableObjectList.insert(obj);
|
||||
mapUpdatableObject->SetUpdateState(UpdatableMapObject::UpdateState::PendingAdd);
|
||||
}
|
||||
|
||||
// Internal use only
|
||||
void Map::_AddObjectToUpdateList(WorldObject* obj)
|
||||
{
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
ASSERT(mapUpdatableObject && mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::PendingAdd);
|
||||
|
||||
mapUpdatableObject->SetUpdateState(UpdatableMapObject::UpdateState::Updating);
|
||||
mapUpdatableObject->SetMapUpdateListOffset(_updatableObjectList.size());
|
||||
_updatableObjectList.push_back(obj);
|
||||
}
|
||||
|
||||
// Internal use only
|
||||
void Map::_RemoveObjectFromUpdateList(WorldObject* obj)
|
||||
{
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
ASSERT(mapUpdatableObject && mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::Updating);
|
||||
|
||||
if (obj != _updatableObjectList.back())
|
||||
{
|
||||
dynamic_cast<UpdatableMapObject*>(_updatableObjectList.back())->SetMapUpdateListOffset(mapUpdatableObject->GetMapUpdateListOffset());
|
||||
std::swap(_updatableObjectList[mapUpdatableObject->GetMapUpdateListOffset()], _updatableObjectList.back());
|
||||
}
|
||||
|
||||
_updatableObjectList.pop_back();
|
||||
mapUpdatableObject->SetUpdateState(UpdatableMapObject::UpdateState::NotUpdating);
|
||||
}
|
||||
|
||||
void Map::RemoveObjectFromMapUpdateList(WorldObject* obj)
|
||||
{
|
||||
if (!obj->CanBeAddedToMapUpdateList())
|
||||
return;
|
||||
|
||||
UpdatableMapObject* mapUpdatableObject = dynamic_cast<UpdatableMapObject*>(obj);
|
||||
if (mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::PendingAdd)
|
||||
_pendingAddUpdatableObjectList.erase(obj);
|
||||
else if (mapUpdatableObject->GetUpdateState() == UpdatableMapObject::UpdateState::Updating)
|
||||
_RemoveObjectFromUpdateList(obj);
|
||||
}
|
||||
|
||||
void Map::HandleDelayedVisibility()
|
||||
{
|
||||
if (i_objectsForDelayedVisibility.empty())
|
||||
@@ -795,7 +791,10 @@ void Map::RemoveFromMap(T* obj, bool remove)
|
||||
obj->ResetMap();
|
||||
|
||||
if (remove)
|
||||
{
|
||||
RemoveObjectFromMapUpdateList(obj);
|
||||
DeleteFromWorld(obj);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -831,6 +830,10 @@ void Map::RemoveFromMap(MotionTransport* obj, bool remove)
|
||||
|
||||
obj->ResetMap();
|
||||
|
||||
// Transports are never actually deleted, but it *should* be safe to clear
|
||||
// from update list when removing from world
|
||||
RemoveObjectFromMapUpdateList(obj);
|
||||
|
||||
if (remove)
|
||||
{
|
||||
// if option set then object already saved at this moment
|
||||
|
||||
Reference in New Issue
Block a user