Use reset time for normal/heroic from new DBC. Improve basic support for raid diffica...
[getmangos.git] / src / game / Map.h
blob6fe6fdf3b56921609ef6383cd40647a336900172
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #ifndef MANGOS_MAP_H
20 #define MANGOS_MAP_H
22 #include "Platform/Define.h"
23 #include "Policies/ThreadingModel.h"
24 #include "ace/RW_Thread_Mutex.h"
25 #include "ace/Thread_Mutex.h"
27 #include "DBCStructure.h"
28 #include "GridDefines.h"
29 #include "Cell.h"
30 #include "Object.h"
31 #include "Timer.h"
32 #include "SharedDefines.h"
33 #include "GameSystem/GridRefManager.h"
34 #include "MapRefManager.h"
36 #include <bitset>
37 #include <list>
39 class Unit;
40 class WorldPacket;
41 class InstanceData;
42 class Group;
43 class InstanceSave;
44 struct ScriptInfo;
45 struct ScriptAction;
46 class BattleGround;
49 typedef ACE_RW_Thread_Mutex GridRWLock;
51 template<class MUTEX, class LOCK_TYPE>
52 struct RGuard
54 RGuard(MUTEX &l) : i_lock(l.getReadLock()) {}
55 MaNGOS::GeneralLock<LOCK_TYPE> i_lock;
58 template<class MUTEX, class LOCK_TYPE>
59 struct WGuard
61 WGuard(MUTEX &l) : i_lock(l.getWriteLock()) {}
62 MaNGOS::GeneralLock<LOCK_TYPE> i_lock;
65 typedef RGuard<GridRWLock, ACE_Thread_Mutex> GridReadGuard;
66 typedef WGuard<GridRWLock, ACE_Thread_Mutex> GridWriteGuard;
67 typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard;
69 //******************************************
70 // Map file format defines
71 //******************************************
72 #define MAP_MAGIC 'SPAM'
73 #define MAP_VERSION_MAGIC '0.1w'
74 #define MAP_AREA_MAGIC 'AERA'
75 #define MAP_HEIGHT_MAGIC 'TGHM'
76 #define MAP_LIQUID_MAGIC 'QILM'
78 struct map_fileheader
80 uint32 mapMagic;
81 uint32 versionMagic;
82 uint32 areaMapOffset;
83 uint32 areaMapSize;
84 uint32 heightMapOffset;
85 uint32 heightMapSize;
86 uint32 liquidMapOffset;
87 uint32 liquidMapSize;
90 #define MAP_AREA_NO_AREA 0x0001
92 struct map_areaHeader
94 uint32 fourcc;
95 uint16 flags;
96 uint16 gridArea;
99 #define MAP_HEIGHT_NO_HEIGHT 0x0001
100 #define MAP_HEIGHT_AS_INT16 0x0002
101 #define MAP_HEIGHT_AS_INT8 0x0004
103 struct map_heightHeader
105 uint32 fourcc;
106 uint32 flags;
107 float gridHeight;
108 float gridMaxHeight;
111 #define MAP_LIQUID_NO_TYPE 0x0001
112 #define MAP_LIQUID_NO_HEIGHT 0x0002
114 struct map_liquidHeader
116 uint32 fourcc;
117 uint16 flags;
118 uint16 liquidType;
119 uint8 offsetX;
120 uint8 offsetY;
121 uint8 width;
122 uint8 height;
123 float liquidLevel;
126 enum ZLiquidStatus
128 LIQUID_MAP_NO_WATER = 0x00000000,
129 LIQUID_MAP_ABOVE_WATER = 0x00000001,
130 LIQUID_MAP_WATER_WALK = 0x00000002,
131 LIQUID_MAP_IN_WATER = 0x00000004,
132 LIQUID_MAP_UNDER_WATER = 0x00000008
135 #define MAP_LIQUID_TYPE_NO_WATER 0x00
136 #define MAP_LIQUID_TYPE_WATER 0x01
137 #define MAP_LIQUID_TYPE_OCEAN 0x02
138 #define MAP_LIQUID_TYPE_MAGMA 0x04
139 #define MAP_LIQUID_TYPE_SLIME 0x08
141 #define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
143 #define MAP_LIQUID_TYPE_DARK_WATER 0x10
144 #define MAP_LIQUID_TYPE_WMO_WATER 0x20
146 struct LiquidData
148 uint32 type;
149 float level;
150 float depth_level;
153 class GridMap
155 uint32 m_flags;
156 // Area data
157 uint16 m_gridArea;
158 uint16 *m_area_map;
159 // Height level data
160 float m_gridHeight;
161 float m_gridIntHeightMultiplier;
162 union{
163 float *m_V9;
164 uint16 *m_uint16_V9;
165 uint8 *m_uint8_V9;
167 union{
168 float *m_V8;
169 uint16 *m_uint16_V8;
170 uint8 *m_uint8_V8;
172 // Liquid data
173 uint16 m_liquidType;
174 uint8 m_liquid_offX;
175 uint8 m_liquid_offY;
176 uint8 m_liquid_width;
177 uint8 m_liquid_height;
178 float m_liquidLevel;
179 uint8 *m_liquid_type;
180 float *m_liquid_map;
182 bool loadAreaData(FILE *in, uint32 offset, uint32 size);
183 bool loadHeihgtData(FILE *in, uint32 offset, uint32 size);
184 bool loadLiquidData(FILE *in, uint32 offset, uint32 size);
186 // Get height functions and pointers
187 typedef float (GridMap::*pGetHeightPtr) (float x, float y) const;
188 pGetHeightPtr m_gridGetHeight;
189 float getHeightFromFloat(float x, float y) const;
190 float getHeightFromUint16(float x, float y) const;
191 float getHeightFromUint8(float x, float y) const;
192 float getHeightFromFlat(float x, float y) const;
194 public:
195 GridMap();
196 ~GridMap();
197 bool loadData(char *filaname);
198 void unloadData();
200 uint16 getArea(float x, float y);
201 inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);}
202 float getLiquidLevel(float x, float y);
203 uint8 getTerrainType(float x, float y);
204 ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0);
207 struct CreatureMover
209 CreatureMover() : x(0), y(0), z(0), ang(0) {}
210 CreatureMover(float _x, float _y, float _z, float _ang) : x(_x), y(_y), z(_z), ang(_ang) {}
212 float x, y, z, ang;
215 // 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
216 #if defined( __GNUC__ )
217 #pragma pack(1)
218 #else
219 #pragma pack(push,1)
220 #endif
222 struct InstanceTemplate
224 uint32 map;
225 uint32 parent;
226 uint32 levelMin;
227 uint32 levelMax;
228 uint32 maxPlayers;
229 uint32 maxPlayersHeroic;
230 uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset.
231 float startLocX;
232 float startLocY;
233 float startLocZ;
234 float startLocO;
235 uint32 script_id;
238 enum LevelRequirementVsMode
240 LEVELREQUIREMENT_HEROIC = 70
243 #if defined( __GNUC__ )
244 #pragma pack()
245 #else
246 #pragma pack(pop)
247 #endif
249 typedef UNORDERED_MAP<Creature*, CreatureMover> CreatureMoveList;
251 #define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
252 #define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
253 #define MIN_UNLOAD_DELAY 1 // immediate unload
255 class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>
257 friend class MapReference;
258 public:
259 Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL);
260 virtual ~Map();
262 // currently unused for normal maps
263 bool CanUnload(uint32 diff)
265 if(!m_unloadTimer) return false;
266 if(m_unloadTimer <= diff) return true;
267 m_unloadTimer -= diff;
268 return false;
271 virtual bool Add(Player *);
272 virtual void Remove(Player *, bool);
273 template<class T> void Add(T *);
274 template<class T> void Remove(T *, bool);
276 virtual void Update(const uint32&);
278 void MessageBroadcast(Player *, WorldPacket *, bool to_self);
279 void MessageBroadcast(WorldObject *, WorldPacket *);
280 void MessageDistBroadcast(Player *, WorldPacket *, float dist, bool to_self, bool own_team_only = false);
281 void MessageDistBroadcast(WorldObject *, WorldPacket *, float dist);
283 float GetVisibilityDistance() const { return m_VisibleDistance; }
284 //function for setting up visibility distance for maps on per-type/per-Id basis
285 virtual void InitVisibilityDistance();
287 void PlayerRelocation(Player *, float x, float y, float z, float angl);
288 void CreatureRelocation(Creature *creature, float x, float y, float, float);
290 template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor);
292 bool IsRemovalGrid(float x, float y) const
294 GridPair p = MaNGOS::ComputeGridPair(x, y);
295 return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL );
298 bool GetUnloadLock(const GridPair &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
299 void SetUnloadLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
300 void LoadGrid(const Cell& cell, bool no_unload = false);
301 bool UnloadGrid(const uint32 &x, const uint32 &y, bool pForce);
302 virtual void UnloadAll(bool pForce);
304 void ResetGridExpiry(NGridType &grid, float factor = 1) const
306 grid.ResetTimeTracker((time_t)((float)i_gridExpiry*factor));
309 time_t GetGridExpiry(void) const { return i_gridExpiry; }
310 uint32 GetId(void) const { return i_id; }
312 static bool ExistMap(uint32 mapid, int gx, int gy);
313 static bool ExistVMap(uint32 mapid, int gx, int gy);
315 static void InitStateMachine();
316 static void DeleteStateMachine();
318 Map const * GetParent() const { return m_parentMap; }
320 // some calls like isInWater should not use vmaps due to processor power
321 // can return INVALID_HEIGHT if under z+2 z coord not found height
322 float GetHeight(float x, float y, float z, bool pCheckVMap=true) const;
323 bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use
325 ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0) const;
327 uint16 GetAreaFlag(float x, float y, float z) const;
328 uint8 GetTerrainType(float x, float y ) const;
329 float GetWaterLevel(float x, float y ) const;
330 bool IsUnderWater(float x, float y, float z) const;
332 static uint32 GetAreaIdByAreaFlag(uint16 areaflag,uint32 map_id);
333 static uint32 GetZoneIdByAreaFlag(uint16 areaflag,uint32 map_id);
334 static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag,uint32 map_id);
336 uint32 GetAreaId(float x, float y, float z) const
338 return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),i_id);
341 uint32 GetZoneId(float x, float y, float z) const
343 return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),i_id);
346 void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const
348 GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),i_id);
351 virtual void MoveAllCreaturesInMoveList();
352 virtual void RemoveAllObjectsInRemoveList();
354 bool CreatureRespawnRelocation(Creature *c); // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader
356 // assert print helper
357 bool CheckGridIntegrity(Creature* c, bool moved) const;
359 uint32 GetInstanceId() const { return i_InstanceId; }
360 uint8 GetSpawnMode() const { return (i_spawnMode); }
361 virtual bool CanEnter(Player* /*player*/) { return true; }
362 const char* GetMapName() const;
364 bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); }
365 // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
366 bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
367 bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
368 bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
369 bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
370 bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
371 bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
372 bool GetEntrancePos(int32 &mapid, float &x, float &y)
374 if(!i_mapEntry)
375 return false;
376 if(i_mapEntry->entrance_map < 0)
377 return false;
378 mapid = i_mapEntry->entrance_map;
379 x = i_mapEntry->entrance_x;
380 y = i_mapEntry->entrance_y;
381 return true;
384 void AddObjectToRemoveList(WorldObject *obj);
385 void DoDelayedMovesAndRemoves();
387 virtual bool RemoveBones(uint64 guid, float x, float y);
389 void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
390 void UpdatePlayerVisibility(Player* player, Cell cell, CellPair cellpair);
391 void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair);
393 void resetMarkedCells() { marked_cells.reset(); }
394 bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
395 void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
397 bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
398 uint32 GetPlayersCountExceptGMs() const;
399 bool ActiveObjectsNearGrid(uint32 x,uint32 y) const;
401 void SendToPlayers(WorldPacket const* data) const;
403 typedef MapRefManager PlayerList;
404 PlayerList const& GetPlayers() const { return m_mapRefManager; }
406 //per-map script storage
407 void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target);
408 void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
410 // must called with AddToWorld
411 template<class T>
412 void AddToActive(T* obj) { AddToActiveHelper(obj); }
414 void AddToActive(Creature* obj);
416 // must called with RemoveFromWorld
417 template<class T>
418 void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); }
420 void RemoveFromActive(Creature* obj);
422 Creature* GetCreature(uint64 guid);
423 GameObject* GetGameObject(uint64 guid);
424 DynamicObject* GetDynamicObject(uint64 guid);
425 private:
426 void LoadMapAndVMap(int gx, int gy);
427 void LoadVMap(int gx, int gy);
428 void LoadMap(int gx,int gy, bool reload = false);
429 GridMap *GetGrid(float x, float y);
431 void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; }
433 void SendInitSelf( Player * player );
435 void SendInitTransports( Player * player );
436 void SendRemoveTransports( Player * player );
438 void PlayerRelocationNotify(Player* player, Cell cell, CellPair cellpair);
439 void CreatureRelocationNotify(Creature *creature, Cell newcell, CellPair newval);
441 bool CreatureCellRelocation(Creature *creature, Cell new_cell);
443 void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang);
444 CreatureMoveList i_creaturesToMove;
446 bool loaded(const GridPair &) const;
447 void EnsureGridCreated(const GridPair &);
448 bool EnsureGridLoaded(Cell const&);
449 void EnsureGridLoadedAtEnter(Cell const&, Player* player = NULL);
451 void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); }
453 template<class T> void AddType(T *obj);
454 template<class T> void RemoveType(T *obj, bool);
456 NGridType* getNGrid(uint32 x, uint32 y) const
458 ASSERT(x < MAX_NUMBER_OF_GRIDS);
459 ASSERT(y < MAX_NUMBER_OF_GRIDS);
460 return i_grids[x][y];
463 bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); }
464 void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); }
466 void setNGrid(NGridType* grid, uint32 x, uint32 y);
467 void ScriptsProcess();
469 protected:
470 void SetUnloadReferenceLock(const GridPair &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
472 typedef MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>::Lock Guard;
474 MapEntry const* i_mapEntry;
475 uint8 i_spawnMode;
476 uint32 i_id;
477 uint32 i_InstanceId;
478 uint32 m_unloadTimer;
479 float m_VisibleDistance;
481 MapRefManager m_mapRefManager;
482 MapRefManager::iterator m_mapRefIter;
484 typedef std::set<WorldObject*> ActiveNonPlayers;
485 ActiveNonPlayers m_activeNonPlayers;
486 ActiveNonPlayers::iterator m_activeNonPlayersIter;
487 private:
488 time_t i_gridExpiry;
490 //used for fast base_map (e.g. MapInstanced class object) search for
491 //InstanceMaps and BattleGroundMaps...
492 Map* m_parentMap;
494 typedef GridReadGuard ReadGuard;
495 typedef GridWriteGuard WriteGuard;
497 NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
498 GridMap *GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
499 std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP*TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells;
501 std::set<WorldObject *> i_objectsToRemove;
502 std::multimap<time_t, ScriptAction> m_scriptSchedule;
504 // Type specific code for add/remove to/from grid
505 template<class T>
506 void AddToGrid(T*, NGridType *, Cell const&);
508 template<class T>
509 void AddNotifier(T*, Cell const&, CellPair const&);
511 template<class T>
512 void RemoveFromGrid(T*, NGridType *, Cell const&);
514 template<class T>
515 void DeleteFromWorld(T*);
517 template<class T>
518 void AddToActiveHelper(T* obj)
520 m_activeNonPlayers.insert(obj);
523 template<class T>
524 void RemoveFromActiveHelper(T* obj)
526 // Map::Update for active object in proccess
527 if(m_activeNonPlayersIter != m_activeNonPlayers.end())
529 ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj);
530 if(itr==m_activeNonPlayersIter)
531 ++m_activeNonPlayersIter;
532 m_activeNonPlayers.erase(itr);
534 else
535 m_activeNonPlayers.erase(obj);
539 enum InstanceResetMethod
541 INSTANCE_RESET_ALL,
542 INSTANCE_RESET_CHANGE_DIFFICULTY,
543 INSTANCE_RESET_GLOBAL,
544 INSTANCE_RESET_GROUP_DISBAND,
545 INSTANCE_RESET_GROUP_JOIN,
546 INSTANCE_RESET_RESPAWN_DELAY
549 class MANGOS_DLL_SPEC InstanceMap : public Map
551 public:
552 InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent);
553 ~InstanceMap();
554 bool Add(Player *);
555 void Remove(Player *, bool);
556 void Update(const uint32&);
557 void CreateInstanceData(bool load);
558 bool Reset(uint8 method);
559 uint32 GetScriptId() { return i_script_id; }
560 InstanceData* GetInstanceData() { return i_data; }
561 void PermBindAllPlayers(Player *player);
562 void UnloadAll(bool pForce);
563 bool CanEnter(Player* player);
564 void SendResetWarnings(uint32 timeLeft) const;
565 void SetResetSchedule(bool on);
566 uint32 GetMaxPlayers() const;
568 virtual void InitVisibilityDistance();
569 private:
570 bool m_resetAfterUnload;
571 bool m_unloadWhenEmpty;
572 InstanceData* i_data;
573 uint32 i_script_id;
576 class MANGOS_DLL_SPEC BattleGroundMap : public Map
578 public:
579 BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent);
580 ~BattleGroundMap();
582 bool Add(Player *);
583 void Remove(Player *, bool);
584 bool CanEnter(Player* player);
585 void SetUnload();
586 void UnloadAll(bool pForce);
588 virtual void InitVisibilityDistance();
589 BattleGround* GetBG() { return m_bg; }
590 void SetBG(BattleGround* bg) { m_bg = bg; }
591 private:
592 BattleGround* m_bg;
595 /*inline
596 uint64
597 Map::CalculateGridMask(const uint32 &y) const
599 uint64 mask = 1;
600 mask <<= y;
601 return mask;
605 template<class LOCK_TYPE, class T, class CONTAINER>
606 inline void
607 Map::Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor)
609 const uint32 x = cell->GridX();
610 const uint32 y = cell->GridY();
611 const uint32 cell_x = cell->CellX();
612 const uint32 cell_y = cell->CellY();
614 if( !cell->NoCreate() || loaded(GridPair(x,y)) )
616 EnsureGridLoaded(cell);
617 //LOCK_TYPE guard(i_info[x][y]->i_lock);
618 getNGrid(x, y)->Visit(cell_x, cell_y, visitor);
621 #endif