[7335] Implement active objects support.

Active objects triggrering grid loading and updating around self like players.
It can be used for event long run movements or escoring quest travels.
Also can be used for proper implementation far vision spells.
Currently only creatures can be activated by function call (from script) cr->SetActiveObjectState(true);
Please avoid lot amount active objects in same time use. Existance active objects support isn't meaning
that each rabbit must be active creature.

Also added independent grid unloading locks for explicit unloading lock,
lock for used by instance copied grids, lock counter for actiove object spawn grids locks.
Last case required for prevent double spawn active creature walk far away from spawn point.
This commit is contained in:
VladimirMangos 2009-02-25 13:27:13 +03:00
parent dd06340d6c
commit 872d791ca6
15 changed files with 282 additions and 51 deletions

View file

@ -103,7 +103,7 @@ class MANGOS_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
*/
@ -112,11 +112,21 @@ class MANGOS_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);
}
private:
@ -125,5 +135,7 @@ class MANGOS_DLL_DECL Grid
TypeMapContainer<GRID_OBJECT_TYPES> i_container;
TypeMapContainer<WORLD_OBJECT_TYPES> i_objects;
typedef std::set<void*> ActiveGridObjects;
ActiveGridObjects m_activeGridObjects;
};
#endif

View file

@ -30,17 +30,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
@ -90,8 +96,11 @@ class MANGOS_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); }

View file

@ -86,6 +86,8 @@ class Corpse : public WorldObject
void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); }
GridReference<Corpse> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
private:
GridReference<Corpse> m_gridRef;

View file

@ -114,7 +114,7 @@ m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_resp
m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isVehicle(false), m_isTotem(false),
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_creatureInfo(NULL)
m_creatureInfo(NULL), m_isActiveObject(false)
{
m_regenTimer = 200;
m_valuesCount = UNIT_END;
@ -2098,3 +2098,23 @@ const char* Creature::GetNameForLocaleIdx(int32 loc_idx) const
return GetName();
}
void Creature::SetActiveObjectState( bool on )
{
if(m_isActiveObject==on)
return;
bool world = IsInWorld();
Map* map;
if(world)
{
map = GetMap();
map->Remove(this,false);
}
m_isActiveObject = on;
if(world)
map->Add(this);
}

View file

@ -609,7 +609,10 @@ class MANGOS_DLL_SPEC Creature : public Unit
uint32 GetGlobalCooldown() const { return m_GlobalCooldown; }
void SetDeadByDefault (bool death_state) {m_isDeadByDefault = death_state;}
void SetDeadByDefault (bool death_state) { m_isDeadByDefault = death_state; }
bool isActiveObject() const { return m_isActiveObject; }
void SetActiveObjectState(bool on);
protected:
bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
@ -661,6 +664,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
private:
GridReference<Creature> m_gridRef;
CreatureInfo const* m_creatureInfo; // in heroic mode can different from ObjMgr::GetCreatureTemplate(GetEntry())
bool m_isActiveObject;
};
class AssistDelayEvent : public BasicEvent

View file

@ -54,6 +54,8 @@ class DynamicObject : public WorldObject
void Whisper(int32 textId,uint64 receiver) { MonsterWhisper(textId,receiver); }
GridReference<DynamicObject> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
protected:
uint64 m_casterGuid;
uint32 m_spellId;

View file

@ -575,6 +575,8 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
GameObject* LookupFishingHoleAround(float range);
GridReference<GameObject> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
protected:
uint32 m_charges; // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
uint32 m_spellId;

View file

@ -34,7 +34,7 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, c
info.UpdateTimeTracker(t_diff);
if( info.getTimeTracker().Passed() )
{
if( grid.ActiveObjectsInGrid() == 0 && !m.PlayersNearGrid(x, y) )
if( grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y) )
{
ObjectGridStoper stoper(grid);
stoper.StopN();
@ -58,14 +58,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);
}
}

View file

@ -138,7 +138,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;
}
@ -209,7 +208,8 @@ void Map::DeleteStateMachine()
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode)
: i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode),
i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), i_gridExpiry(expiry)
i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), i_gridExpiry(expiry),
m_activeNonPlayersIter(m_activeNonPlayers.end())
{
for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
{
@ -360,22 +360,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);
@ -387,11 +387,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);
}
@ -412,7 +410,7 @@ Map::LoadGrid(const Cell& cell, bool no_unload)
setGridObjectDataLoaded(true,cell.GridX(), cell.GridY());
if(no_unload)
getNGrid(cell.GridX(), cell.GridY())->setUnloadFlag(false);
getNGrid(cell.GridX(), cell.GridY())->setUnloadExplicitLock(true);
}
LoadVMap(63-cell.GridX(),63-cell.GridY());
}
@ -426,7 +424,7 @@ bool Map::Add(Player *player)
// update player state for other player and visa-versa
CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
Cell cell(p);
EnsureGridLoadedForPlayer(cell, player, true);
EnsureGridLoaded(cell, player);
player->AddToWorld();
SendInitSelf(player);
@ -454,13 +452,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();
AddToActive(obj);
DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());
UpdateObjectVisibility(obj,cell,p);
@ -616,6 +620,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(MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->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)
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);
}
}
}
}
}
// Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load !
// This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
if (IsBattleGroundOrArena())
@ -708,6 +762,8 @@ Map::Remove(T *obj, bool remove)
NGridType *grid = getNGrid(cell.GridX(), cell.GridY());
assert( grid != NULL );
RemoveFromActive(obj);
obj->RemoveFromWorld();
RemoveFromGrid(obj,grid,cell);
@ -749,9 +805,8 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati
RemoveFromGrid(player, oldGrid,old_cell);
if( !old_cell.DiffGrid(new_cell) )
AddToGrid(player, oldGrid,new_cell);
if( old_cell.DiffGrid(new_cell) )
EnsureGridLoadedForPlayer(new_cell, player, true);
else
EnsureGridLoaded(new_cell, player);
}
// if move then update what player see and who seen
@ -868,8 +923,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 MANGOS_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 MANGOS_DEBUG
@ -882,17 +956,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 MANGOS_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 MANGOS_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)
@ -929,7 +1002,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
assert( grid != NULL);
{
if(!pForce && PlayersNearGrid(x, y) )
if(!pForce && ActiveObjectsNearGrid(x, y) )
return false;
DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id);
@ -1513,7 +1586,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);
@ -1532,9 +1605,61 @@ bool Map::PlayersNearGrid(uint32 x, uint32 y) const
return true;
}
for(ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter)
{
WorldObject* obj = *iter;
CellPair p = MaNGOS::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;
}
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())
{
float x,y,z;
c->GetRespawnCoord(x,y,z);
GridPair p = MaNGOS::ComputeGridPair(x, y);
if(getNGrid(p.x_coord, p.y_coord))
getNGrid(p.x_coord, p.y_coord)->incUnloadActiveLock();
else
{
GridPair p2 = MaNGOS::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);
}
}
}
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 = MaNGOS::ComputeGridPair(x, y);
if(getNGrid(p.x_coord, p.y_coord))
getNGrid(p.x_coord, p.y_coord)->decUnloadActiveLock();
else
{
GridPair p2 = MaNGOS::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 *);
template void Map::Add(Creature *);
template void Map::Add(GameObject *);

View file

@ -164,8 +164,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
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(const Cell& cell, bool no_unload = false);
bool UnloadGrid(const uint32 &x, const uint32 &y, bool pForce);
virtual void UnloadAll(bool pForce);
@ -256,12 +256,24 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
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 SendToPlayers(WorldPacket const* data) const;
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);
private:
void LoadVMap(int pX, int pY);
void LoadMap(uint32 mapid, uint32 instanceid, int x,int y);
@ -283,7 +295,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
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); }
@ -302,6 +314,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void setNGrid(NGridType* grid, uint32 x, uint32 y);
protected:
void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
typedef MaNGOS::ObjectLevelLockable<Map, ZThread::Mutex>::Lock Guard;
MapEntry const* i_mapEntry;
@ -312,6 +326,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
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;
@ -336,6 +354,31 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
template<class T>
void DeleteFromWorld(T*);
template<class T>
void AddToActiveHelper(T* obj)
{
if(obj->isActiveObject())
m_activeNonPlayers.insert(obj);
}
template<class T>
void RemoveFromActiveHelper(T* obj)
{
if(obj->isActiveObject())
{
// 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
@ -408,7 +451,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);
}

View file

@ -42,11 +42,18 @@ class MANGOS_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; }

View file

@ -125,6 +125,8 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
addUnitState(obj,cell);
obj->AddToWorld();
map->AddToActive(obj);
++count;
}
@ -150,6 +152,8 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType
addUnitState(obj,cell);
obj->AddToWorld();
map->AddToActive(obj);
++count;
}
}

View file

@ -2142,6 +2142,7 @@ class MANGOS_DLL_SPEC Player : public Unit
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title);
bool isActiveObject() const { return true; }
protected:
/*********************************************************/

View file

@ -62,7 +62,7 @@ template<class T>
inline uint32 Traveller<T>::GetTotalTrevelTimeTo(float x, float y, float z)
{
float dist = GetMoveDestinationTo(x,y,z);
float speed = Speed();
double speed = Speed();
speed *= 0.001f; // speed is in seconds so convert from second to millisecond
return static_cast<uint32>(dist/speed);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "7334"
#define REVISION_NR "7335"
#endif // __REVISION_NR_H__