aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormegamage <none@none>2009-02-25 20:52:20 -0600
committermegamage <none@none>2009-02-25 20:52:20 -0600
commitbf66375bc73c2b9dd7c2d26d7af25b111734c622 (patch)
tree67c3cf601faf32a03d16dfe7b02b2a938ec76ae7
parentccde296fd3822898e8959c009211fe880a0429f7 (diff)
*Update active object code. By VladimirMangos.
--HG-- branch : trunk
-rw-r--r--src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp2
-rw-r--r--src/framework/GameSystem/Grid.h18
-rw-r--r--src/framework/GameSystem/NGrid.h21
-rw-r--r--src/game/DynamicObject.cpp2
-rw-r--r--src/game/GridStates.cpp4
-rw-r--r--src/game/Map.cpp242
-rw-r--r--src/game/Map.h52
-rw-r--r--src/game/MapInstanced.h11
-rw-r--r--src/game/Object.cpp30
-rw-r--r--src/game/Object.h4
-rw-r--r--src/game/ObjectGridLoader.cpp6
-rw-r--r--src/game/Player.cpp2
-rw-r--r--src/game/SpellEffects.cpp2
-rw-r--r--src/game/Unit.cpp2
14 files changed, 277 insertions, 121 deletions
diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
index 15fcd871740..94e94c9be50 100644
--- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
+++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp
@@ -129,7 +129,7 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance
break;
case 184956:
StrangePool = go->GetGUID();
- if(go->isActive())
+ if(go->isActiveObject())
SetData(DATA_STRANGE_POOL, DONE);
}
}
diff --git a/src/framework/GameSystem/Grid.h b/src/framework/GameSystem/Grid.h
index fffa8120883..24d7634154d 100644
--- a/src/framework/GameSystem/Grid.h
+++ b/src/framework/GameSystem/Grid.h
@@ -105,7 +105,7 @@ class TRINITY_DLL_DECL Grid
/** Returns the number of object within the grid.
*/
- unsigned int ActiveObjectsInGrid(void) const { return i_objects.template Count<ACTIVE_OBJECT>(); }
+ unsigned int ActiveObjectsInGrid(void) const { return m_activeGridObjects.size()+i_objects.template Count<ACTIVE_OBJECT>(); }
/** Accessors: Returns a specific type of object in the GRID_OBJECT_TYPES
*/
@@ -114,11 +114,21 @@ class TRINITY_DLL_DECL Grid
/** Inserts a container type object into the grid.
*/
- template<class SPECIFIC_OBJECT> bool AddGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) { return i_container.template insert<SPECIFIC_OBJECT>(hdl, obj); }
+ template<class SPECIFIC_OBJECT> bool AddGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
+ {
+ if(obj->isActiveObject())
+ m_activeGridObjects.insert(obj);
+ return i_container.template insert<SPECIFIC_OBJECT>(hdl, obj);
+ }
/** Removes a containter type object from the grid
*/
- template<class SPECIFIC_OBJECT> bool RemoveGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl) { return i_container.template remove<SPECIFIC_OBJECT>(obj, hdl); }
+ template<class SPECIFIC_OBJECT> bool RemoveGridObject(SPECIFIC_OBJECT *obj, OBJECT_HANDLE hdl)
+ {
+ if(obj->isActiveObject())
+ m_activeGridObjects.erase(obj);
+ return i_container.template remove<SPECIFIC_OBJECT>(obj, hdl);
+ }
bool NoWorldObjectInGrid() const
{
@@ -136,6 +146,8 @@ class TRINITY_DLL_DECL Grid
TypeMapContainer<GRID_OBJECT_TYPES> i_container;
TypeMapContainer<WORLD_OBJECT_TYPES> i_objects;
+ typedef std::set<void*> ActiveGridObjects;
+ ActiveGridObjects m_activeGridObjects;
};
#endif
diff --git a/src/framework/GameSystem/NGrid.h b/src/framework/GameSystem/NGrid.h
index 617c85d735d..ec5edfe1fb2 100644
--- a/src/framework/GameSystem/NGrid.h
+++ b/src/framework/GameSystem/NGrid.h
@@ -32,17 +32,23 @@ class GridInfo
{
public:
GridInfo() : i_timer(0) {}
- GridInfo(time_t expiry, bool unload = true ) : i_timer(expiry), i_unloadflag(unload) {}
+ GridInfo(time_t expiry, bool unload = true ) : i_timer(expiry), i_unloadExplicitLock(!unload) {}
const TimeTracker& getTimeTracker() const { return i_timer; }
- bool getUnloadFlag() const { return i_unloadflag; }
- void setUnloadFlag( bool pFlag) { i_unloadflag = pFlag; }
+ bool getUnloadLock() const { return i_unloadActiveLockCount || i_unloadExplicitLock || i_unloadReferenceLock; }
+ void setUnloadExplicitLock( bool on ) { i_unloadExplicitLock = on; }
+ void setUnloadReferenceLock( bool on ) { i_unloadReferenceLock = on; }
+ void incUnloadActiveLock() { ++i_unloadActiveLockCount; }
+ void decUnloadActiveLock() { if(i_unloadActiveLockCount) --i_unloadActiveLockCount; }
+
void setTimer(const TimeTracker& pTimer) { i_timer = pTimer; }
void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); }
void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); }
private:
TimeTracker i_timer;
- bool i_unloadflag;
+ uint16 i_unloadActiveLockCount : 16; // lock from active object spawn points (prevent clone loading)
+ bool i_unloadExplicitLock : 1; // explicit manual lock or config setting
+ bool i_unloadReferenceLock : 1; // lock from instance map copy
};
typedef enum
@@ -92,8 +98,11 @@ class TRINITY_DLL_DECL NGrid
GridInfo* getGridInfoRef() { return &i_GridInfo; }
const TimeTracker& getTimeTracker() const { return i_GridInfo.getTimeTracker(); }
- bool getUnloadFlag() const { return i_GridInfo.getUnloadFlag(); }
- void setUnloadFlag( bool pFlag) { i_GridInfo.setUnloadFlag(pFlag); }
+ bool getUnloadLock() const { return i_GridInfo.getUnloadLock(); }
+ void setUnloadExplicitLock( bool on ) { i_GridInfo.setUnloadExplicitLock(on); }
+ void setUnloadReferenceLock( bool on ) { i_GridInfo.setUnloadReferenceLock(on); }
+ void incUnloadActiveLock() { i_GridInfo.incUnloadActiveLock(); }
+ void decUnloadActiveLock() { i_GridInfo.decUnloadActiveLock(); }
void ResetTimeTracker(time_t interval) { i_GridInfo.ResetTimeTracker(interval); }
void UpdateTimeTracker(time_t diff) { i_GridInfo.UpdateTimeTracker(diff); }
diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp
index 12a9cd67500..de8d0eb2c6d 100644
--- a/src/game/DynamicObject.cpp
+++ b/src/game/DynamicObject.cpp
@@ -57,7 +57,7 @@ void DynamicObject::RemoveFromWorld()
{
// Make sure the object is back to grid container for removal as farsight targets
// are switched to world container on creation and they are also set to active
- if (isActive())
+ if (isActiveObject())
{
GetMap()->SwitchGridContainers(this, false);
setActive(false);
diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp
index d38cd922537..bb47428553c 100644
--- a/src/game/GridStates.cpp
+++ b/src/game/GridStates.cpp
@@ -60,14 +60,14 @@ IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 &x, const ui
void
RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const
{
- if(info.getUnloadFlag())
+ if(!info.getUnloadLock())
{
info.UpdateTimeTracker(t_diff);
if( info.getTimeTracker().Passed() )
{
if( !m.UnloadGrid(x, y, false) )
{
- sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players nearby", x, y, m.GetId());
+ sLog.outDebug("Grid[%u,%u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId());
m.ResetGridExpiry(grid);
}
}
diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index 12003134b1c..6934bcf3df1 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ * Copyright (C) 2005-2008 Trinity <http://www.mangosproject.org/>
*
* Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
*
@@ -140,7 +140,6 @@ void Map::LoadMap(uint32 mapid, uint32 instanceid, int x,int y)
// return;
((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(x,y));
- baseMap->SetUnloadFlag(GridPair(63-x,63-y), false);
GridMaps[x][y] = baseMap->GridMaps[x][y];
return;
}
@@ -210,9 +209,10 @@ void Map::DeleteStateMachine()
}
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode)
- : i_id(id), i_gridExpiry(expiry), i_mapEntry (sMapStore.LookupEntry(id)),
- i_InstanceId(InstanceId), i_spawnMode(SpawnMode), m_unloadTimer(0)
- , i_lock(false)
+ : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode),
+ i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), i_gridExpiry(expiry),
+ m_activeNonPlayersIter(m_activeNonPlayers.end())
+ , i_lock(false)
{
for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
{
@@ -391,22 +391,22 @@ Map::EnsureGridCreated(const GridPair &p)
}
void
-Map::EnsureGridLoadedForPlayer(const Cell &cell, Player *player, bool add_player)
+Map::EnsureGridLoaded(const Cell &cell, Player *player)
{
EnsureGridCreated(GridPair(cell.GridX(), cell.GridY()));
NGridType *grid = getNGrid(cell.GridX(), cell.GridY());
assert(grid != NULL);
- if( !isGridObjectDataLoaded(cell.GridX(), cell.GridY()) )
+ if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY()))
{
- if( player != NULL )
+ if (player)
{
player->SendDelayResponse(MAX_GRID_LOAD_TIME);
DEBUG_LOG("Player %s enter cell[%u,%u] triggers of loading grid[%u,%u] on map %u", player->GetName(), cell.CellX(), cell.CellY(), cell.GridX(), cell.GridY(), i_id);
}
else
{
- DEBUG_LOG("Player nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), i_id);
+ DEBUG_LOG("Active object nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), i_id);
}
ObjectGridLoader loader(*grid, this, cell);
@@ -418,11 +418,9 @@ Map::EnsureGridLoadedForPlayer(const Cell &cell, Player *player, bool add_player
ResetGridExpiry(*getNGrid(cell.GridX(), cell.GridY()), 0.1f);
grid->SetGridState(GRID_STATE_ACTIVE);
-
- if( add_player && player != NULL )
- (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(player, player->GetGUID());
}
- else if( player && add_player )
+
+ if(player)
AddToGrid(player,grid,cell);
}
@@ -430,7 +428,7 @@ void Map::LoadGrid(float x, float y)
{
CellPair pair = Trinity::ComputeCellPair(x, y);
Cell cell(pair);
- EnsureGridLoadedForPlayer(cell, NULL, false);
+ EnsureGridLoaded(cell, NULL);
}
bool Map::Add(Player *player)
@@ -442,7 +440,7 @@ bool Map::Add(Player *player)
// update player state for other player and visa-versa
CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
Cell cell(p);
- EnsureGridLoadedForPlayer(cell, player, true);
+ EnsureGridLoaded(cell, player);
player->AddToWorld();
SendInitSelf(player);
@@ -468,14 +466,19 @@ Map::Add(T *obj)
}
Cell cell(p);
- EnsureGridCreated(GridPair(cell.GridX(), cell.GridY()));
+ if(obj->isActiveObject())
+ EnsureGridLoaded(cell);
+ else
+ EnsureGridCreated(GridPair(cell.GridX(), cell.GridY()));
+
NGridType *grid = getNGrid(cell.GridX(), cell.GridY());
assert( grid != NULL );
AddToGrid(obj,grid,cell);
obj->AddToWorld();
- if(obj->isActive())
- AddActiveObject(obj);
+
+ if(obj->isActiveObject())
+ AddToActive(obj);
DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());
@@ -646,29 +649,22 @@ void Map::Update(const uint32 &t_diff)
{
resetMarkedCells();
- //TODO: is there a better way to update activeobjects?
- std::vector<WorldObject*> activeObjects;
- for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
- {
- Player* plr = iter->getSource();
- if(plr->IsInWorld())
- activeObjects.push_back(plr);
- }
- for(std::set<WorldObject *>::iterator iter = i_activeObjects.begin(); iter != i_activeObjects.end(); ++iter)
- {
- if((*iter)->IsInWorld())
- activeObjects.push_back(*iter);
- }
-
Trinity::ObjectUpdater updater(t_diff);
// for creature
TypeContainerVisitor<Trinity::ObjectUpdater, GridTypeMapContainer > grid_object_update(updater);
// for pets
TypeContainerVisitor<Trinity::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater);
- for(std::vector<WorldObject*>::iterator iter = activeObjects.begin(); iter != activeObjects.end(); ++iter)
+ // the player iterator is stored in the map object
+ // to make sure calls to Map::Remove don't invalidate it
+ for(m_mapRefIter = m_mapRefManager.begin(); m_mapRefIter != m_mapRefManager.end(); ++m_mapRefIter)
{
- CellPair standing_cell(Trinity::ComputeCellPair((*iter)->GetPositionX(), (*iter)->GetPositionY()));
+ Player* plr = m_mapRefIter->getSource();
+
+ if(!plr->IsInWorld())
+ continue;
+
+ CellPair standing_cell(Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY()));
// Check for correctness of standing_cell, it also avoids problems with update_cell
if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
@@ -700,8 +696,56 @@ void Map::Update(const uint32 &t_diff)
}
}
}
+ }
+
+ // non-player active objects
+ if(!m_activeNonPlayers.empty())
+ {
+ for(m_activeNonPlayersIter = m_activeNonPlayers.begin(); m_activeNonPlayersIter != m_activeNonPlayers.end(); )
+ {
+ // skip not in world
+ WorldObject* obj = *m_activeNonPlayersIter;
+
+ // step before processing, in this case if Map::Remove remove next object we correctly
+ // step to next-next, and if we step to end() then newly added objects can wait next update.
+ ++m_activeNonPlayersIter;
+
+ if(!obj->IsInWorld())
+ continue;
+
+ CellPair standing_cell(Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()));
- // UpdateActiveCells((*iter)->GetPositionX(), (*iter)->GetPositionY(), t_diff);
+ // Check for correctness of standing_cell, it also avoids problems with update_cell
+ if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
+ continue;
+
+ // the overloaded operators handle range checking
+ // so ther's no need for range checking inside the loop
+ CellPair begin_cell(standing_cell), end_cell(standing_cell);
+ begin_cell << 1; begin_cell -= 1; // upper left
+ end_cell >> 1; end_cell += 1; // lower right
+
+ for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x)
+ {
+ for(uint32 y = begin_cell.y_coord; y <= end_cell.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))
+ {
+ markCell(cell_id);
+ CellPair pair(x,y);
+ Cell cell(pair);
+ cell.data.Part.reserved = CENTER_DISTRICT;
+ //cell.SetNoCreate();
+ CellLock<NullGuard> cell_lock(cell, pair);
+ cell_lock->Visit(cell_lock, grid_object_update, *this);
+ cell_lock->Visit(cell_lock, world_object_update, *this);
+ }
+ }
+ }
+ }
}
RelocationNotify();
@@ -800,9 +844,10 @@ Map::Remove(T *obj, bool remove)
NGridType *grid = getNGrid(cell.GridX(), cell.GridY());
assert( grid != NULL );
+ if(obj->isActiveObject())
+ RemoveFromActive(obj);
+
obj->RemoveFromWorld();
- if(obj->isActive())
- RemoveActiveObject(obj);
RemoveFromGrid(obj,grid,cell);
UpdateObjectVisibility(obj,cell,p);
@@ -844,7 +889,7 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati
if( !old_cell.DiffGrid(new_cell) )
AddToGrid(player, oldGrid,new_cell);
else
- EnsureGridLoadedForPlayer(new_cell, player, true);
+ EnsureGridLoaded(new_cell, player);
}
AddUnitToNotify(player);
@@ -876,13 +921,6 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang
#endif
AddCreatureToMoveList(creature,x,y,z,ang);
// in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList
- if(creature->isActive())
- {
- if(creature->isPossessedByPlayer())
- EnsureGridLoadedForPlayer(new_cell, (Player*)creature->GetCharmer(), false);
- else
- EnsureGridLoadedForPlayer(new_cell, NULL, false);
- }
}
else
{
@@ -955,6 +993,7 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
+ c->SetCurrentCell(new_cell);
}
else
{
@@ -963,8 +1002,27 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
sLog.outDebug("Creature (GUID: %u Entry: %u) move in same grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
#endif
}
+
+ return true;
}
- else // in diff. grids
+
+ // in diff. grids but active creature
+ if(c->isActiveObject())
+ {
+ EnsureGridLoaded(new_cell);
+
+ #ifdef TRINITY_DEBUG
+ if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0)
+ sLog.outDebug("Active creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ #endif
+
+ RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
+ AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
+
+ return true;
+ }
+
+ // in diff. loaded grid normal creature
if(loaded(GridPair(new_cell.GridX(), new_cell.GridY())))
{
#ifdef TRINITY_DEBUG
@@ -977,17 +1035,16 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY()));
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
}
- }
- else
- {
- #ifdef TRINITY_DEBUG
- if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0)
- sLog.outDebug("Creature (GUID: %u Entry: %u) attempt move from grid[%u,%u]cell[%u,%u] to unloaded grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
- #endif
- return false;
+
+ return true;
}
- return true;
+ // fail to move: normal creature attempt move to unloaded grid
+ #ifdef TRINITY_DEBUG
+ if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0)
+ sLog.outDebug("Creature (GUID: %u Entry: %u) attempt move from grid[%u,%u]cell[%u,%u] to unloaded grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
+ #endif
+ return false;
}
bool Map::CreatureRespawnRelocation(Creature *c)
@@ -1025,13 +1082,8 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll)
assert( grid != NULL);
{
- if(!unloadAll)
- {
- if(ActiveObjectsNearGrid(x, y))
- return false;
- }
- else
- assert(!PlayersNearGrid(x, y));
+ if(!unloadAll && ActiveObjectsNearGrid(x, y) )
+ return false;
DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id);
ObjectGridUnloader unloader(*grid);
@@ -1577,7 +1629,7 @@ void Map::SendToPlayers(WorldPacket const* data) const
itr->getSource()->GetSession()->SendPacket(data);
}
-bool Map::PlayersNearGrid(uint32 x, uint32 y) const
+bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const
{
CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS);
CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
@@ -1596,37 +1648,59 @@ bool Map::PlayersNearGrid(uint32 x, uint32 y) const
return true;
}
- return false;
-}
-
-bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const
-{
- CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS);
- CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
- cell_min << 2;
- cell_min -= 2;
- cell_max >> 2;
- cell_max += 2;
-
- for(MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
+ for(ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter)
{
- Player* plr = iter->getSource();
+ WorldObject* obj = *iter;
- CellPair p = Trinity::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY());
+ CellPair p = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
(cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) )
return true;
}
- for(std::set<WorldObject*>::const_iterator itr = i_activeObjects.begin(); itr != i_activeObjects.end(); ++itr)
+ return false;
+}
+
+void Map::AddToActive( Creature* c )
+{
+ AddToActiveHelper(c);
+
+ // also not allow unloading spawn grid to prevent creating creature clone at load
+ if(c->GetDBTableGUIDLow())
{
- CellPair p = Trinity::ComputeCellPair((*itr)->GetPositionX(), (*itr)->GetPositionY());
- if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
- (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) )
- return true;
+ float x,y,z;
+ c->GetRespawnCoord(x,y,z);
+ GridPair p = Trinity::ComputeGridPair(x, y);
+ if(getNGrid(p.x_coord, p.y_coord))
+ getNGrid(p.x_coord, p.y_coord)->incUnloadActiveLock();
+ else
+ {
+ GridPair p2 = Trinity::ComputeGridPair(c->GetPositionX(), c->GetPositionY());
+ sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] not loaded.",
+ c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
+ }
}
+}
- return false;
+void Map::RemoveFromActive( Creature* c )
+{
+ RemoveFromActiveHelper(c);
+
+ // also allow unloading spawn grid
+ if(c->GetDBTableGUIDLow())
+ {
+ float x,y,z;
+ c->GetRespawnCoord(x,y,z);
+ GridPair p = Trinity::ComputeGridPair(x, y);
+ if(getNGrid(p.x_coord, p.y_coord))
+ getNGrid(p.x_coord, p.y_coord)->decUnloadActiveLock();
+ else
+ {
+ GridPair p2 = Trinity::ComputeGridPair(c->GetPositionX(), c->GetPositionY());
+ sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] not loaded.",
+ c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
+ }
+ }
}
template void Map::Add(Corpse *);
diff --git a/src/game/Map.h b/src/game/Map.h
index 820971dae49..5f052c8806c 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -168,8 +168,8 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL );
}
- bool GetUnloadFlag(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadFlag(); }
- void SetUnloadFlag(const GridPair &p, bool unload) { getNGrid(p.x_coord, p.y_coord)->setUnloadFlag(unload); }
+ bool GetUnloadLock(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
+ void SetUnloadLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(float x, float y);
bool UnloadGrid(const uint32 &x, const uint32 &y, bool pForce);
virtual void UnloadAll();
@@ -250,11 +250,8 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
uint32 GetPlayersCountExceptGMs() const;
- bool PlayersNearGrid(uint32 x,uint32 y) const;
bool ActiveObjectsNearGrid(uint32 x, uint32 y) const;
- void AddActiveObject(WorldObject* obj) { i_activeObjects.insert(obj); }
- void RemoveActiveObject(WorldObject* obj) { i_activeObjects.erase(obj); }
void AddUnitToNotify(Unit* unit);
void RelocationNotify();
@@ -262,6 +259,19 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
typedef MapRefManager PlayerList;
PlayerList const& GetPlayers() const { return m_mapRefManager; }
+
+ // must called with AddToWorld
+ template<class T>
+ void AddToActive(T* obj) { AddToActiveHelper(obj); }
+
+ void AddToActive(Creature* obj);
+
+ // must called with RemoveFromWorld
+ template<class T>
+ void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); }
+
+ void RemoveFromActive(Creature* obj);
+
template<class T> void SwitchGridContainers(T* obj, bool active);
template<class NOTIFIER> void VisitAll(const float &x, const float &y, float radius, NOTIFIER &notifier);
template<class NOTIFIER> void VisitWorld(const float &x, const float &y, float radius, NOTIFIER &notifier);
@@ -284,7 +294,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
CreatureMoveList i_creaturesToMove;
bool loaded(const GridPair &) const;
- void EnsureGridLoadedForPlayer(const Cell&, Player*, bool add_player);
+ void EnsureGridLoaded(const Cell&, Player* player = NULL);
void EnsureGridCreated(const GridPair &);
void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); }
@@ -304,6 +314,8 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff);
protected:
+ void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
+
typedef Trinity::ObjectLevelLockable<Map, ZThread::Mutex>::Lock Guard;
MapEntry const* i_mapEntry;
@@ -314,6 +326,10 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
MapRefManager m_mapRefManager;
MapRefManager::iterator m_mapRefIter;
+
+ typedef std::set<WorldObject*> ActiveNonPlayers;
+ ActiveNonPlayers m_activeNonPlayers;
+ ActiveNonPlayers::iterator m_activeNonPlayersIter;
private:
typedef GridReadGuard ReadGuard;
typedef GridWriteGuard WriteGuard;
@@ -325,7 +341,6 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
time_t i_gridExpiry;
bool i_lock;
- std::set<WorldObject *> i_activeObjects;
std::vector<uint64> i_unitsToNotify;
std::set<WorldObject *> i_objectsToRemove;
@@ -341,6 +356,27 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
template<class T>
void DeleteFromWorld(T*);
+
+ template<class T>
+ void AddToActiveHelper(T* obj)
+ {
+ m_activeNonPlayers.insert(obj);
+ }
+
+ template<class T>
+ void RemoveFromActiveHelper(T* obj)
+ {
+ // Map::Update for active object in proccess
+ if(m_activeNonPlayersIter != m_activeNonPlayers.end())
+ {
+ ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj);
+ if(itr==m_activeNonPlayersIter)
+ ++m_activeNonPlayersIter;
+ m_activeNonPlayers.erase(itr);
+ }
+ else
+ m_activeNonPlayers.erase(obj);
+ }
};
enum InstanceResetMethod
@@ -412,7 +448,7 @@ Map::Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &
if( !cell->NoCreate() || loaded(GridPair(x,y)) )
{
- EnsureGridLoadedForPlayer(cell, NULL, false);
+ EnsureGridLoaded(cell);
//LOCK_TYPE guard(i_info[x][y]->i_lock);
getNGrid(x, y)->Visit(cell_x, cell_y, visitor);
}
diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h
index 830f7967d10..d34a5cf2dfb 100644
--- a/src/game/MapInstanced.h
+++ b/src/game/MapInstanced.h
@@ -45,11 +45,18 @@ class TRINITY_DLL_DECL MapInstanced : public Map
Map* FindMap(uint32 InstanceId) { return _FindMap(InstanceId); }
void DestroyInstance(uint32 InstanceId);
void DestroyInstance(InstancedMaps::iterator &itr);
- void AddGridMapReference(const GridPair &p) { ++GridMapReference[p.x_coord][p.y_coord]; }
+
+ void AddGridMapReference(const GridPair &p)
+ {
+ ++GridMapReference[p.x_coord][p.y_coord];
+ SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), true);
+ }
+
void RemoveGridMapReference(const GridPair &p)
{
--GridMapReference[p.x_coord][p.y_coord];
- if (!GridMapReference[p.x_coord][p.y_coord]) { SetUnloadFlag(GridPair(63-p.x_coord,63-p.y_coord), true); }
+ if (!GridMapReference[p.x_coord][p.y_coord])
+ SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), false);
}
InstancedMaps &GetInstancedMaps() { return m_InstancedMaps; }
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index 2d19e51e76e..5551f844376 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -1070,19 +1070,31 @@ WorldObject::WorldObject()
m_isActive = false;
}
-void WorldObject::setActive(bool isActive)
+void WorldObject::setActive( bool on )
{
- // if already in the same activity state as we try to set, do nothing
- if(isActive == m_isActive || isType(TYPEMASK_PLAYER))
+ if(m_isActive==on)
return;
- m_isActive = isActive;
- if(IsInWorld())
+ bool world = IsInWorld();
+
+ Map* map;
+ if(world)
{
- if(isActive)
- GetMap()->AddActiveObject(this);
- else
- GetMap()->RemoveActiveObject(this);
+ map = GetMap();
+ if(GetTypeId() == TYPEID_UNIT)
+ map->Remove((Creature*)this,false);
+ else if(GetTypeId() == TYPEID_DYNAMICOBJECT)
+ map->Remove((DynamicObject*)this,false);
+ }
+
+ m_isActive = on;
+
+ if(world)
+ {
+ if(GetTypeId() == TYPEID_UNIT)
+ map->Add((Creature*)this);
+ else if(GetTypeId() == TYPEID_DYNAMICOBJECT)
+ map->Add((DynamicObject*)this);
}
}
diff --git a/src/game/Object.h b/src/game/Object.h
index 0dfb63e5997..ab3e49721b3 100644
--- a/src/game/Object.h
+++ b/src/game/Object.h
@@ -484,8 +484,8 @@ class TRINITY_DLL_SPEC WorldObject : public Object
Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime);
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
- bool isActive() const { return m_isActive; }
- void setActive(bool isActive);
+ bool isActiveObject() const { return m_isActive; }
+ void setActive(bool isActiveObject);
template<class NOTIFIER> void VisitNearbyObject(const float &radius, NOTIFIER &notifier) const { GetMap()->VisitAll(GetPositionX(), GetPositionY(), radius, notifier); }
template<class NOTIFIER> void VisitNearbyGridObject(const float &radius, NOTIFIER &notifier) const { GetMap()->VisitGrid(GetPositionX(), GetPositionY(), radius, notifier); }
template<class NOTIFIER> void VisitNearbyWorldObject(const float &radius, NOTIFIER &notifier) const { GetMap()->VisitWorld(GetPositionX(), GetPositionY(), radius, notifier); }
diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp
index 2d6d0e7c7a0..14b1865cfa7 100644
--- a/src/game/ObjectGridLoader.cpp
+++ b/src/game/ObjectGridLoader.cpp
@@ -127,6 +127,9 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
addUnitState(obj,cell);
obj->AddToWorld();
+ if(obj->isActiveObject())
+ map->AddToActive(obj);
+
++count;
}
@@ -152,6 +155,9 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType
addUnitState(obj,cell);
obj->AddToWorld();
+ if(obj->isActiveObject())
+ map->AddToActive(obj);
+
++count;
}
}
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index efa414fbfaf..4114f4da4ac 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -17578,7 +17578,7 @@ bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bool
{
// Units far than max visible distance for creature or not in our map are not visible too
if (!target->IsWithinDistInMap(u
- , u->isActive() ? (MAX_VISIBILITY_DISTANCE - (inVisibleList ? 0.0f : World::GetVisibleUnitGreyDistance()))
+ , u->isActiveObject() ? (MAX_VISIBILITY_DISTANCE - (inVisibleList ? 0.0f : World::GetVisibleUnitGreyDistance()))
: (World::GetMaxVisibleDistanceForCreature() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))
, is3dDistance))
return false;
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 066252c6de8..846ab8ddf13 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -3500,8 +3500,8 @@ void Spell::EffectAddFarsight(uint32 i)
Map* map = dynObj->GetMap();
map->LoadGrid(dynObj->GetPositionX(), dynObj->GetPositionY()); // In case the spell is casted into a different grid by player
map->Add(dynObj);
- map->SwitchGridContainers(dynObj, true); // Needed for forwarding player packets
dynObj->setActive(true); // Keep the grid updated even if there are no players in it
+ map->SwitchGridContainers(dynObj, true); // Needed for forwarding player packets
// Need to update visibility of object for client to accept farsight guid
((Player*)m_caster)->UpdateVisibilityOf(dynObj);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 3d3c4874b20..0a6cf93be76 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -8518,8 +8518,8 @@ void Unit::RemovePlayerFromVision(Player* plr)
if (m_sharedVision.empty() && GetTypeId() == TYPEID_UNIT
&& !((Creature*)this)->isPet())
{
- setActive(false);
GetMap()->SwitchGridContainers((Creature*)this, false);
+ setActive(false);
}
plr->ClearFarsight();
}