diff options
Diffstat (limited to 'src/game/Map.h')
-rw-r--r-- | src/game/Map.h | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/game/Map.h b/src/game/Map.h index 8ab318cc2c4..a8d94d350e7 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -17,12 +17,15 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef TRINITY_MAP_H #define TRINITY_MAP_H + #include "Platform/Define.h" #include "Policies/ThreadingModel.h" #include "ace/RW_Thread_Mutex.h" #include "ace/Thread_Mutex.h" + #include "DBCStructure.h" #include "GridDefines.h" #include "Cell.h" @@ -31,8 +34,10 @@ #include "GameSystem/GridRefManager.h" #include "MapRefManager.h" #include "mersennetwister/MersenneTwister.h" + #include <bitset> #include <list> + class Unit; class WorldPacket; class InstanceData; @@ -47,22 +52,27 @@ struct ScriptInfo; struct ScriptAction; struct Position; + typedef ACE_RW_Thread_Mutex GridRWLock; + template<class MUTEX, class LOCK_TYPE> struct RGuard { RGuard(MUTEX &l) : i_lock(l.getReadLock()) {} Trinity::GeneralLock<LOCK_TYPE> i_lock; }; + template<class MUTEX, class LOCK_TYPE> struct WGuard { WGuard(MUTEX &l) : i_lock(l.getWriteLock()) {} Trinity::GeneralLock<LOCK_TYPE> i_lock; }; + typedef RGuard<GridRWLock, ACE_Thread_Mutex> GridReadGuard; typedef WGuard<GridRWLock, ACE_Thread_Mutex> GridWriteGuard; typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard; + //****************************************** // Map file format defines //****************************************** @@ -71,6 +81,7 @@ typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard; #define MAP_AREA_MAGIC 'AERA' #define MAP_HEIGHT_MAGIC 'TGHM' #define MAP_LIQUID_MAGIC 'QILM' + struct map_fileheader { uint32 mapMagic; @@ -82,16 +93,20 @@ struct map_fileheader uint32 liquidMapOffset; uint32 liquidMapSize; }; + #define MAP_AREA_NO_AREA 0x0001 + struct map_areaHeader { uint32 fourcc; uint16 flags; uint16 gridArea; }; + #define MAP_HEIGHT_NO_HEIGHT 0x0001 #define MAP_HEIGHT_AS_INT16 0x0002 #define MAP_HEIGHT_AS_INT8 0x0004 + struct map_heightHeader { uint32 fourcc; @@ -99,8 +114,10 @@ struct map_heightHeader float gridHeight; float gridMaxHeight; }; + #define MAP_LIQUID_NO_TYPE 0x0001 #define MAP_LIQUID_NO_HEIGHT 0x0002 + struct map_liquidHeader { uint32 fourcc; @@ -112,6 +129,7 @@ struct map_liquidHeader uint8 height; float liquidLevel; }; + enum ZLiquidStatus { LIQUID_MAP_NO_WATER = 0x00000000, @@ -120,20 +138,25 @@ enum ZLiquidStatus LIQUID_MAP_IN_WATER = 0x00000004, LIQUID_MAP_UNDER_WATER = 0x00000008 }; + #define MAP_LIQUID_TYPE_NO_WATER 0x00 #define MAP_LIQUID_TYPE_WATER 0x01 #define MAP_LIQUID_TYPE_OCEAN 0x02 #define MAP_LIQUID_TYPE_MAGMA 0x04 #define MAP_LIQUID_TYPE_SLIME 0x08 + #define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME) + #define MAP_LIQUID_TYPE_DARK_WATER 0x10 #define MAP_LIQUID_TYPE_WMO_WATER 0x20 + struct LiquidData { uint32 type; float level; float depth_level; }; + class GridMap { uint32 m_flags; @@ -162,9 +185,11 @@ class GridMap float m_liquidLevel; uint8 *m_liquid_type; float *m_liquid_map; + bool loadAreaData(FILE *in, uint32 offset, uint32 size); bool loadHeihgtData(FILE *in, uint32 offset, uint32 size); bool loadLiquidData(FILE *in, uint32 offset, uint32 size); + // Get height functions and pointers typedef float (GridMap::*pGetHeightPtr) (float x, float y) const; pGetHeightPtr m_gridGetHeight; @@ -172,29 +197,35 @@ class GridMap float getHeightFromUint16(float x, float y) const; float getHeightFromUint8(float x, float y) const; float getHeightFromFlat(float x, float y) const; + public: GridMap(); ~GridMap(); bool loadData(char *filaname); void unloadData(); + uint16 getArea(float x, float y); inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);} float getLiquidLevel(float x, float y); uint8 getTerrainType(float x, float y); ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0); }; + struct CreatureMover { CreatureMover() : x(0), y(0), z(0), ang(0) {} CreatureMover(float _x, float _y, float _z, float _ang) : x(_x), y(_y), z(_z), ang(_ang) {} + float x, y, z, ang; }; + // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform #if defined( __GNUC__ ) #pragma pack(1) #else #pragma pack(push,1) #endif + struct InstanceTemplate { uint32 map; @@ -209,26 +240,33 @@ struct InstanceTemplate float startLocO; uint32 script_id; }; + enum LevelRequirementVsMode { LEVELREQUIREMENT_HEROIC = 70 }; + #if defined( __GNUC__ ) #pragma pack() #else #pragma pack(pop) #endif + typedef UNORDERED_MAP<Creature*, CreatureMover> CreatureMoveList; + #define MAX_HEIGHT 100000.0f // can be use for find ground height at surface #define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE #define MIN_UNLOAD_DELAY 1 // immediate unload + typedef std::map<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHolderType; + class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex> { friend class MapReference; public: Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL); virtual ~Map(); + // currently unused for normal maps bool CanUnload(uint32 diff) { @@ -237,80 +275,105 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj m_unloadTimer -= diff; return false; } + virtual bool Add(Player *); virtual void Remove(Player *, bool); template<class T> void Add(T *); template<class T> void Remove(T *, bool); + virtual void Update(const uint32&); + /* void MessageBroadcast(Player *, WorldPacket *, bool to_self); void MessageBroadcast(WorldObject *, WorldPacket *); void MessageDistBroadcast(Player *, WorldPacket *, float dist, bool to_self, bool own_team_only = false); void MessageDistBroadcast(WorldObject *, WorldPacket *, float dist); */ + float GetVisibilityDistance() const { return m_VisibleDistance; } //function for setting up visibility distance for maps on per-type/per-Id basis virtual void InitVisibilityDistance(); + void PlayerRelocation(Player *, float x, float y, float z, float angl); void CreatureRelocation(Creature *creature, float x, float y, float, float); + template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor); + bool IsRemovalGrid(float x, float y) const { GridPair p = Trinity::ComputeGridPair(x, y); return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL ); } + 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(); + void ResetGridExpiry(NGridType &grid, float factor = 1) const { grid.ResetTimeTracker((time_t)((float)i_gridExpiry*factor)); } + time_t GetGridExpiry(void) const { return i_gridExpiry; } uint32 GetId(void) const { return i_mapEntry->MapID; } + static bool ExistMap(uint32 mapid, int gx, int gy); static bool ExistVMap(uint32 mapid, int gx, int gy); + static void InitStateMachine(); static void DeleteStateMachine(); + Map const * GetParent() const { return m_parentMap; } + // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; float GetVmapHeight(float x, float y, float z, bool useMaps) const; bool IsInWater(float x, float y, float z, float min_depth = 2.0f) const; + ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0) const; + uint16 GetAreaFlag(float x, float y, float z) const; uint8 GetTerrainType(float x, float y ) const; float GetWaterLevel(float x, float y ) const; bool IsUnderWater(float x, float y, float z) const; + static uint32 GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id); static uint32 GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id); static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id); + uint32 GetAreaId(float x, float y, float z) const { return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); } + uint32 GetZoneId(float x, float y, float z) const { return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); } + void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const { GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),GetId()); } + void MoveAllCreaturesInMoveList(); void RemoveAllObjectsInRemoveList(); void RelocationNotify(); virtual void RemoveAllPlayers(); + bool CreatureRespawnRelocation(Creature *c); // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader + // assert print helper bool CheckGridIntegrity(Creature* c, bool moved) const; + uint32 GetInstanceId() const { return i_InstanceId; } uint8 GetSpawnMode() const { return (i_spawnMode); } virtual bool CanEnter(Player* /*player*/) { return true; } const char* GetMapName() const; + bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); } // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); } @@ -330,41 +393,57 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj y = i_mapEntry->entrance_y; return true; } + void AddObjectToRemoveList(WorldObject *obj); void AddObjectToSwitchList(WorldObject *obj, bool on); virtual void DelayedUpdate(const uint32 diff); + virtual bool RemoveBones(uint64 guid, float x, float y); + void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair); + void resetMarkedCells() { marked_cells.reset(); } bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } void markCell(uint32 pCellId) { marked_cells.set(pCellId); } + bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } uint32 GetPlayersCountExceptGMs() const; bool ActiveObjectsNearGrid(uint32 x, uint32 y) const; + void AddUnitToNotify(Unit* unit); void RemoveUnitFromNotify(Unit *unit); void AddWorldObject(WorldObject *obj) { i_worldObjects.insert(obj); } void RemoveWorldObject(WorldObject *obj) { i_worldObjects.erase(obj); } + void SendToPlayers(WorldPacket const* data) const; + typedef MapRefManager PlayerList; PlayerList const& GetPlayers() const { return m_mapRefManager; } + //per-map script storage void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target); void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); + // 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 ¬ifier); template<class NOTIFIER> void VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier); template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier); CreatureGroupHolderType CreatureGroupHolder; + void UpdateIteratorBack(Player *player); + #ifdef MAP_BASED_RAND_GEN MTRand mtRand; int32 irand(int32 min, int32 max) { return int32 (mtRand.randInt(max - min)) + min; } @@ -373,6 +452,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj double rand_norm() { return mtRand.randExc(); } double rand_chance() { return mtRand.randExc(100.0); } #endif + TempSummon *SummonCreature(uint32 entry, const Position &pos, SummonPropertiesEntry const *properties = NULL, uint32 duration = 0, Unit *summoner = NULL, uint32 vehId = 0); Creature* GetCreature(uint64 guid); GameObject* GetGameObject(uint64 guid); @@ -382,56 +462,78 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj void LoadVMap(int gx, int gy); void LoadMap(int gx,int gy, bool reload = false); GridMap *GetGrid(float x, float y); + void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } + void SendInitSelf( Player * player ); + void SendInitTransports( Player * player ); void SendRemoveTransports( Player * player ); + bool CreatureCellRelocation(Creature *creature, Cell new_cell); + void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang); CreatureMoveList i_creaturesToMove; + bool loaded(const GridPair &) const; void EnsureGridCreated(const GridPair &); bool EnsureGridLoaded(Cell const&); void EnsureGridLoadedAtEnter(Cell const&, Player* player = NULL); + void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } + template<class T> void AddType(T *obj); template<class T> void RemoveType(T *obj, bool); + NGridType* getNGrid(uint32 x, uint32 y) const { ASSERT(x < MAX_NUMBER_OF_GRIDS); ASSERT(y < MAX_NUMBER_OF_GRIDS); return i_grids[x][y]; } + bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); } void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); } + void setNGrid(NGridType* grid, uint32 x, uint32 y); void ScriptsProcess(); + 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 MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>::Lock Guard; + MapEntry const* i_mapEntry; uint8 i_spawnMode; uint32 i_InstanceId; uint32 m_unloadTimer; float m_VisibleDistance; + MapRefManager m_mapRefManager; MapRefManager::iterator m_mapRefIter; + typedef std::set<WorldObject*> ActiveNonPlayers; ActiveNonPlayers m_activeNonPlayers; ActiveNonPlayers::iterator m_activeNonPlayersIter; + private: time_t i_gridExpiry; + //used for fast base_map (e.g. MapInstanced class object) search for //InstanceMaps and BattleGroundMaps... Map* m_parentMap; + typedef GridReadGuard ReadGuard; typedef GridWriteGuard WriteGuard; + NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; GridMap *GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP*TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells; + IntervalTimer m_notifyTimer; + bool i_notifyLock, i_scriptLock; std::vector<Unit*> i_unitsToNotifyBacklog; std::vector<Unit*> i_unitsToNotify; @@ -439,20 +541,26 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj std::map<WorldObject*, bool> i_objectsToSwitch; std::set<WorldObject*> i_worldObjects; std::multimap<time_t, ScriptAction> m_scriptSchedule; + // Type specific code for add/remove to/from grid template<class T> void AddToGrid(T*, NGridType *, Cell const&); + template<class T> void AddNotifier(T*); + template<class T> void RemoveFromGrid(T*, NGridType *, Cell const&); + template<class T> void DeleteFromWorld(T*); + template<class T> void AddToActiveHelper(T* obj) { m_activeNonPlayers.insert(obj); } + template<class T> void RemoveFromActiveHelper(T* obj) { @@ -470,6 +578,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj m_activeNonPlayers.erase(obj); } }; + enum InstanceResetMethod { INSTANCE_RESET_ALL, @@ -479,6 +588,7 @@ enum InstanceResetMethod INSTANCE_RESET_GROUP_JOIN, INSTANCE_RESET_RESPAWN_DELAY }; + class TRINITY_DLL_SPEC InstanceMap : public Map { public: @@ -497,6 +607,7 @@ class TRINITY_DLL_SPEC InstanceMap : public Map void SendResetWarnings(uint32 timeLeft) const; void SetResetSchedule(bool on); uint32 GetMaxPlayers() const; + virtual void InitVisibilityDistance(); private: bool m_resetAfterUnload; @@ -504,19 +615,23 @@ class TRINITY_DLL_SPEC InstanceMap : public Map InstanceData* i_data; uint32 i_script_id; }; + class TRINITY_DLL_SPEC BattleGroundMap : public Map { public: BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent); ~BattleGroundMap(); + bool Add(Player *); void Remove(Player *, bool); bool CanEnter(Player* player); void SetUnload(); //void UnloadAll(bool pForce); void RemoveAllPlayers(); + virtual void InitVisibilityDistance(); }; + /*inline uint64 Map::CalculateGridMask(const uint32 &y) const @@ -526,6 +641,7 @@ Map::CalculateGridMask(const uint32 &y) const return mask; } */ + template<class LOCK_TYPE, class T, class CONTAINER> inline void Map::Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor) @@ -534,6 +650,7 @@ Map::Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> & const uint32 y = cell->GridY(); const uint32 cell_x = cell->CellX(); const uint32 cell_y = cell->CellY(); + if( !cell->NoCreate() || loaded(GridPair(x,y)) ) { EnsureGridLoaded(cell); @@ -541,6 +658,7 @@ Map::Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> & getNGrid(x, y)->Visit(cell_x, cell_y, visitor); } } + template<class NOTIFIER> inline void Map::VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier) @@ -551,11 +669,13 @@ Map::VisitAll(const float &x, const float &y, float radius, NOTIFIER ¬ifier) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); CellLock<GridReadGuard> cell_lock(cell, p); + TypeContainerVisitor<NOTIFIER, WorldTypeMapContainer> world_object_notifier(notifier); cell_lock->Visit(cell_lock, world_object_notifier, *this, radius, x_off, y_off); TypeContainerVisitor<NOTIFIER, GridTypeMapContainer > grid_object_notifier(notifier); cell_lock->Visit(cell_lock, grid_object_notifier, *this, radius, x_off, y_off); } + template<class NOTIFIER> inline void Map::VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier) @@ -566,9 +686,11 @@ Map::VisitWorld(const float &x, const float &y, float radius, NOTIFIER ¬ifier cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); CellLock<GridReadGuard> cell_lock(cell, p); + TypeContainerVisitor<NOTIFIER, WorldTypeMapContainer> world_object_notifier(notifier); cell_lock->Visit(cell_lock, world_object_notifier, *this, radius, x_off, y_off); } + template<class NOTIFIER> inline void Map::VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier) @@ -579,6 +701,7 @@ Map::VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); CellLock<GridReadGuard> cell_lock(cell, p); + TypeContainerVisitor<NOTIFIER, GridTypeMapContainer > grid_object_notifier(notifier); cell_lock->Visit(cell_lock, grid_object_notifier, *this, radius, x_off, y_off); } |