2 * Copyright (C) 2005-2013 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
23 #include "Platform/Define.h"
24 #include "Policies/ThreadingModel.h"
25 #include "ace/RW_Thread_Mutex.h"
26 #include "ace/Thread_Mutex.h"
28 #include "DBCStructure.h"
29 #include "GridDefines.h"
33 #include "SharedDefines.h"
35 #include "GameSystem/GridRefManager.h"
36 #include "MapRefManager.h"
37 #include "Utilities/TypeList.h"
38 #include "ScriptMgr.h"
39 #include "CreatureLinkingMgr.h"
50 class MapPersistentState
;
51 class WorldPersistentState
;
52 class DungeonPersistentState
;
53 class BattleGroundPersistentState
;
58 // 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
59 #if defined( __GNUC__ )
65 struct InstanceTemplate
67 uint32 map
; // instance map
68 uint32 parent
; // non-continent parent instance (for instance with entrance in another instances)
69 // or 0 (not related to continent 0 map id)
77 uint32 map
; // non-instance map
81 enum LevelRequirementVsMode
83 LEVELREQUIREMENT_HEROIC
= 70
86 #if defined( __GNUC__ )
92 #define MIN_UNLOAD_DELAY 1 // immediate unload
94 class MANGOS_DLL_SPEC Map
: public GridRefManager
<NGridType
>
96 friend class MapReference
;
97 friend class ObjectGridLoader
;
98 friend class ObjectWorldLoader
;
101 Map(uint32 id
, time_t, uint32 InstanceId
, uint8 SpawnMode
);
106 // currently unused for normal maps
107 bool CanUnload(uint32 diff
)
109 if (!m_unloadTimer
) return false;
110 if (m_unloadTimer
<= diff
) return true;
111 m_unloadTimer
-= diff
;
115 virtual bool Add(Player
*);
116 virtual void Remove(Player
*, bool);
117 template<class T
> void Add(T
*);
118 template<class T
> void Remove(T
*, bool);
120 static void DeleteFromWorld(Player
* player
); // player object will deleted at call
122 virtual void Update(const uint32
&);
124 void MessageBroadcast(Player
*, WorldPacket
*, bool to_self
);
125 void MessageBroadcast(WorldObject
*, WorldPacket
*);
126 void MessageDistBroadcast(Player
*, WorldPacket
*, float dist
, bool to_self
, bool own_team_only
= false);
127 void MessageDistBroadcast(WorldObject
*, WorldPacket
*, float dist
);
129 float GetVisibilityDistance() const { return m_VisibleDistance
; }
130 // function for setting up visibility distance for maps on per-type/per-Id basis
131 virtual void InitVisibilityDistance();
133 void PlayerRelocation(Player
*, float x
, float y
, float z
, float angl
);
134 void CreatureRelocation(Creature
* creature
, float x
, float y
, float z
, float orientation
);
136 template<class T
, class CONTAINER
> void Visit(const Cell
& cell
, TypeContainerVisitor
<T
, CONTAINER
>& visitor
);
138 bool IsRemovalGrid(float x
, float y
) const
140 GridPair p
= MaNGOS::ComputeGridPair(x
, y
);
141 return(!getNGrid(p
.x_coord
, p
.y_coord
) || getNGrid(p
.x_coord
, p
.y_coord
)->GetGridState() == GRID_STATE_REMOVAL
);
144 bool IsLoaded(float x
, float y
) const
146 GridPair p
= MaNGOS::ComputeGridPair(x
, y
);
150 bool GetUnloadLock(const GridPair
& p
) const { return getNGrid(p
.x_coord
, p
.y_coord
)->getUnloadLock(); }
151 void SetUnloadLock(const GridPair
& p
, bool on
) { getNGrid(p
.x_coord
, p
.y_coord
)->setUnloadExplicitLock(on
); }
152 void LoadGrid(const Cell
& cell
, bool no_unload
= false);
153 bool UnloadGrid(const uint32
& x
, const uint32
& y
, bool pForce
);
154 virtual void UnloadAll(bool pForce
);
156 void ResetGridExpiry(NGridType
& grid
, float factor
= 1) const
158 grid
.ResetTimeTracker((time_t)((float)i_gridExpiry
* factor
));
161 time_t GetGridExpiry(void) const { return i_gridExpiry
; }
162 uint32
GetId(void) const { return i_id
; }
164 // some calls like isInWater should not use vmaps due to processor power
165 // can return INVALID_HEIGHT if under z+2 z coord not found height
167 virtual void RemoveAllObjectsInRemoveList();
169 bool CreatureRespawnRelocation(Creature
* c
); // used only in CreatureRelocation and ObjectGridUnloader
171 bool CheckGridIntegrity(Creature
* c
, bool moved
) const;
173 uint32
GetInstanceId() const { return i_InstanceId
; }
174 virtual bool CanEnter(Player
* player
);
175 const char* GetMapName() const;
177 // have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap
178 // _currently_ spawnmode == difficulty, but this can be changes later, so use appropriate spawmmode/difficult functions
179 // for simplify later code support
180 // regular difficulty = continent/dungeon normal/first raid normal difficulty
181 uint8
GetSpawnMode() const { return (i_spawnMode
); }
182 Difficulty
GetDifficulty() const { return Difficulty(GetSpawnMode()); }
183 bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY
; }
184 uint32
GetMaxPlayers() const; // dependent from map difficulty
185 uint32
GetMaxResetDelay() const; // dependent from map difficulty
186 MapDifficultyEntry
const* GetMapDifficulty() const; // dependent from map difficulty
188 bool Instanceable() const { return i_mapEntry
&& i_mapEntry
->Instanceable(); }
189 // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
190 bool IsDungeon() const { return i_mapEntry
&& i_mapEntry
->IsDungeon(); }
191 bool IsRaid() const { return i_mapEntry
&& i_mapEntry
->IsRaid(); }
192 bool IsNonRaidDungeon() const { return i_mapEntry
&& i_mapEntry
->IsNonRaidDungeon(); }
193 bool IsRaidOrHeroicDungeon() const { return IsRaid() || GetDifficulty() > DUNGEON_DIFFICULTY_NORMAL
; }
194 bool IsBattleGround() const { return i_mapEntry
&& i_mapEntry
->IsBattleGround(); }
195 bool IsBattleArena() const { return i_mapEntry
&& i_mapEntry
->IsBattleArena(); }
196 bool IsBattleGroundOrArena() const { return i_mapEntry
&& i_mapEntry
->IsBattleGroundOrArena(); }
198 // can't be NULL for loaded map
199 MapPersistentState
* GetPersistentState() const { return m_persistentState
; }
201 void AddObjectToRemoveList(WorldObject
* obj
);
203 void UpdateObjectVisibility(WorldObject
* obj
, Cell cell
, CellPair cellpair
);
205 void resetMarkedCells() { marked_cells
.reset(); }
206 bool isCellMarked(uint32 pCellId
) { return marked_cells
.test(pCellId
); }
207 void markCell(uint32 pCellId
) { marked_cells
.set(pCellId
); }
209 bool HavePlayers() const { return !m_mapRefManager
.isEmpty(); }
210 uint32
GetPlayersCountExceptGMs() const;
211 bool ActiveObjectsNearGrid(uint32 x
, uint32 y
) const;
213 void SendToPlayers(WorldPacket
const* data
) const;
215 typedef MapRefManager PlayerList
;
216 PlayerList
const& GetPlayers() const { return m_mapRefManager
; }
218 // per-map script storage
219 bool ScriptsStart(ScriptMapMapName
const& scripts
, uint32 id
, Object
* source
, Object
* target
);
220 void ScriptCommandStart(ScriptInfo
const& script
, uint32 delay
, Object
* source
, Object
* target
);
222 // must called with AddToWorld
223 void AddToActive(WorldObject
* obj
);
224 // must called with RemoveFromWorld
225 void RemoveFromActive(WorldObject
* obj
);
227 Player
* GetPlayer(ObjectGuid guid
);
228 Creature
* GetCreature(ObjectGuid guid
);
229 Pet
* GetPet(ObjectGuid guid
);
230 Creature
* GetAnyTypeCreature(ObjectGuid guid
); // normal creature or pet or vehicle
231 GameObject
* GetGameObject(ObjectGuid guid
);
232 DynamicObject
* GetDynamicObject(ObjectGuid guid
);
233 Corpse
* GetCorpse(ObjectGuid guid
); // !!! find corpse can be not in world
234 Unit
* GetUnit(ObjectGuid guid
); // only use if sure that need objects at current map, specially for player case
235 WorldObject
* GetWorldObject(ObjectGuid guid
); // only use if sure that need objects at current map, specially for player case
237 typedef TypeUnorderedMapContainer
<AllMapStoredObjectTypes
, ObjectGuid
> MapStoredObjectTypesContainer
;
238 MapStoredObjectTypesContainer
& GetObjectsStore() { return m_objectsStore
; }
240 void AddUpdateObject(Object
* obj
)
242 i_objectsToClientUpdate
.insert(obj
);
245 void RemoveUpdateObject(Object
* obj
)
247 i_objectsToClientUpdate
.erase(obj
);
250 // DynObjects currently
251 uint32
GenerateLocalLowGuid(HighGuid guidhigh
);
253 // get corresponding TerrainData object for this particular map
254 const TerrainInfo
* GetTerrain() const { return m_TerrainData
; }
256 void CreateInstanceData(bool load
);
257 InstanceData
* GetInstanceData() { return i_data
; }
258 uint32
GetScriptId() const { return i_script_id
; }
260 void MonsterYellToMap(ObjectGuid guid
, int32 textId
, uint32 language
, Unit
* target
);
261 void MonsterYellToMap(CreatureInfo
const* cinfo
, int32 textId
, uint32 language
, Unit
* target
, uint32 senderLowGuid
= 0);
262 void PlayDirectSoundToMap(uint32 soundId
, uint32 zoneId
= 0);
265 bool IsInLineOfSight(float srcX
, float srcY
, float srcZ
, float destX
, float destY
, float destZ
);
266 bool GetObjectHitPos(float srcX
, float srcY
, float srcZ
, float destX
, float destY
, float destZ
, float& resX
, float& resY
, float& resZ
, float pModifyDist
);
268 // Get Holder for Creature Linking
269 CreatureLinkingHolder
* GetCreatureLinkingHolder() { return &m_creatureLinkingHolder
; }
272 void LoadMapAndVMap(int gx
, int gy
);
274 void SetTimer(uint32 t
) { i_gridExpiry
= t
< MIN_GRID_DELAY
? MIN_GRID_DELAY
: t
; }
276 void SendInitSelf(Player
* player
);
278 void SendInitTransports(Player
* player
);
279 void SendRemoveTransports(Player
* player
);
281 bool CreatureCellRelocation(Creature
* creature
, Cell new_cell
);
283 bool loaded(const GridPair
&) const;
284 void EnsureGridCreated(const GridPair
&);
285 bool EnsureGridLoaded(Cell
const&);
286 void EnsureGridLoadedAtEnter(Cell
const&, Player
* player
= NULL
);
288 void buildNGridLinkage(NGridType
* pNGridType
) { pNGridType
->link(this); }
290 template<class T
> void AddType(T
* obj
);
291 template<class T
> void RemoveType(T
* obj
, bool);
293 NGridType
* getNGrid(uint32 x
, uint32 y
) const
295 MANGOS_ASSERT(x
< MAX_NUMBER_OF_GRIDS
);
296 MANGOS_ASSERT(y
< MAX_NUMBER_OF_GRIDS
);
297 return i_grids
[x
][y
];
300 bool isGridObjectDataLoaded(uint32 x
, uint32 y
) const { return getNGrid(x
, y
)->isGridObjectDataLoaded(); }
301 void setGridObjectDataLoaded(bool pLoaded
, uint32 x
, uint32 y
) { getNGrid(x
, y
)->setGridObjectDataLoaded(pLoaded
); }
303 void setNGrid(NGridType
* grid
, uint32 x
, uint32 y
);
304 void ScriptsProcess();
306 void SendObjectUpdates();
307 std::set
<Object
*> i_objectsToClientUpdate
;
310 MapEntry
const* i_mapEntry
;
314 uint32 m_unloadTimer
;
315 float m_VisibleDistance
;
316 MapPersistentState
* m_persistentState
;
318 MapRefManager m_mapRefManager
;
319 MapRefManager::iterator m_mapRefIter
;
321 typedef std::set
<WorldObject
*> ActiveNonPlayers
;
322 ActiveNonPlayers m_activeNonPlayers
;
323 ActiveNonPlayers::iterator m_activeNonPlayersIter
;
324 MapStoredObjectTypesContainer m_objectsStore
;
329 NGridType
* i_grids
[MAX_NUMBER_OF_GRIDS
][MAX_NUMBER_OF_GRIDS
];
331 // Shared geodata object with map coord info...
332 TerrainInfo
* const m_TerrainData
;
333 bool m_bLoadedGrids
[MAX_NUMBER_OF_GRIDS
][MAX_NUMBER_OF_GRIDS
];
335 std::bitset
<TOTAL_NUMBER_OF_CELLS_PER_MAP
* TOTAL_NUMBER_OF_CELLS_PER_MAP
> marked_cells
;
337 std::set
<WorldObject
*> i_objectsToRemove
;
339 typedef std::multimap
<time_t, ScriptAction
> ScriptScheduleMap
;
340 ScriptScheduleMap m_scriptSchedule
;
342 InstanceData
* i_data
;
345 // Map local low guid counters
346 ObjectGuidGenerator
<HIGHGUID_UNIT
> m_CreatureGuids
;
347 ObjectGuidGenerator
<HIGHGUID_GAMEOBJECT
> m_GameObjectGuids
;
348 ObjectGuidGenerator
<HIGHGUID_DYNAMICOBJECT
> m_DynObjectGuids
;
349 ObjectGuidGenerator
<HIGHGUID_PET
> m_PetGuids
;
350 ObjectGuidGenerator
<HIGHGUID_VEHICLE
> m_VehicleGuids
;
352 // Type specific code for add/remove to/from grid
354 void AddToGrid(T
*, NGridType
*, Cell
const&);
357 void RemoveFromGrid(T
*, NGridType
*, Cell
const&);
359 // Holder for information about linked mobs
360 CreatureLinkingHolder m_creatureLinkingHolder
;
363 class MANGOS_DLL_SPEC WorldMap
: public Map
366 using Map::GetPersistentState
; // hide in subclass for overwrite
368 WorldMap(uint32 id
, time_t expiry
) : Map(id
, expiry
, 0, REGULAR_DIFFICULTY
) {}
371 // can't be NULL for loaded map
372 WorldPersistentState
* GetPersistanceState() const;
375 class MANGOS_DLL_SPEC DungeonMap
: public Map
378 using Map::GetPersistentState
; // hide in subclass for overwrite
380 DungeonMap(uint32 id
, time_t, uint32 InstanceId
, uint8 SpawnMode
);
382 bool Add(Player
*) override
;
383 void Remove(Player
*, bool) override
;
384 void Update(const uint32
&) override
;
385 bool Reset(InstanceResetMethod method
);
386 void PermBindAllPlayers(Player
* player
);
387 void UnloadAll(bool pForce
) override
;
388 void SendResetWarnings(uint32 timeLeft
) const;
389 void SetResetSchedule(bool on
);
391 // can't be NULL for loaded map
392 DungeonPersistentState
* GetPersistanceState() const;
394 virtual void InitVisibilityDistance() override
;
396 bool m_resetAfterUnload
;
397 bool m_unloadWhenEmpty
;
400 class MANGOS_DLL_SPEC BattleGroundMap
: public Map
403 using Map::GetPersistentState
; // hide in subclass for overwrite
405 BattleGroundMap(uint32 id
, time_t, uint32 InstanceId
, uint8 spawnMode
);
408 void Update(const uint32
&) override
;
409 bool Add(Player
*) override
;
410 void Remove(Player
*, bool) override
;
411 bool CanEnter(Player
* player
) override
;
413 void UnloadAll(bool pForce
) override
;
415 virtual void InitVisibilityDistance() override
;
416 BattleGround
* GetBG() { return m_bg
; }
417 void SetBG(BattleGround
* bg
) { m_bg
= bg
; }
419 // can't be NULL for loaded map
420 BattleGroundPersistentState
* GetPersistanceState() const;
426 template<class T
, class CONTAINER
>
428 Map::Visit(const Cell
& cell
, TypeContainerVisitor
<T
, CONTAINER
>& visitor
)
430 const uint32 x
= cell
.GridX();
431 const uint32 y
= cell
.GridY();
432 const uint32 cell_x
= cell
.CellX();
433 const uint32 cell_y
= cell
.CellY();
435 if (!cell
.NoCreate() || loaded(GridPair(x
, y
)))
437 EnsureGridLoaded(cell
);
438 getNGrid(x
, y
)->Visit(cell_x
, cell_y
, visitor
);