2 * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
3 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "GridDefines.h"
27 #include "SharedDefines.h"
28 #include "GridRefManager.h"
29 #include "MapRefManager.h"
30 #include "DynamicTree.h"
31 #include "ObjectGuid.h"
38 #include <unordered_set>
41 class BattlegroundMap
;
43 class GameObjectModel
;
48 class InstanceScenario
;
58 struct MapDifficultyEntry
;
63 struct SummonPropertiesEntry
;
65 enum Difficulty
: uint8
;
66 enum WeatherState
: uint32
;
68 namespace Trinity
{ struct ObjectUpdater
; }
69 namespace G3D
{ class Plane
; }
73 ObjectGuid sourceGUID
;
74 ObjectGuid targetGUID
;
75 ObjectGuid ownerGUID
; ///> owner of source if source is item
76 ScriptInfo
const* script
; ///> pointer to static script data
79 /// Represents a map magic value of 4 bytes (used in versions)
82 char asChar
[4]; ///> Non-null terminated string
83 uint32 asUInt
; ///> uint32 representation
86 // ******************************************
87 // Map file format defines
88 // ******************************************
92 u_map_magic versionMagic
;
93 u_map_magic buildMagic
;
96 uint32 heightMapOffset
;
98 uint32 liquidMapOffset
;
104 #define MAP_AREA_NO_AREA 0x0001
106 struct map_areaHeader
113 #define MAP_HEIGHT_NO_HEIGHT 0x0001
114 #define MAP_HEIGHT_AS_INT16 0x0002
115 #define MAP_HEIGHT_AS_INT8 0x0004
116 #define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008
118 struct map_heightHeader
126 #define MAP_LIQUID_NO_TYPE 0x0001
127 #define MAP_LIQUID_NO_HEIGHT 0x0002
129 struct map_liquidHeader
144 LIQUID_MAP_NO_WATER
= 0x00000000,
145 LIQUID_MAP_ABOVE_WATER
= 0x00000001,
146 LIQUID_MAP_WATER_WALK
= 0x00000002,
147 LIQUID_MAP_IN_WATER
= 0x00000004,
148 LIQUID_MAP_UNDER_WATER
= 0x00000008
151 #define MAP_LIQUID_TYPE_NO_WATER 0x00
152 #define MAP_LIQUID_TYPE_WATER 0x01
153 #define MAP_LIQUID_TYPE_OCEAN 0x02
154 #define MAP_LIQUID_TYPE_MAGMA 0x04
155 #define MAP_LIQUID_TYPE_SLIME 0x08
157 #define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)
159 #define MAP_LIQUID_TYPE_DARK_WATER 0x10
169 class TC_GAME_API GridMap
182 G3D::Plane
* _minHeightPlanes
;
185 float _gridIntHeightMultiplier
;
192 uint16
* _liquidEntry
;
196 uint16 _liquidGlobalEntry
;
197 uint8 _liquidGlobalFlags
;
204 bool loadAreaData(FILE* in
, uint32 offset
, uint32 size
);
205 bool loadHeightData(FILE* in
, uint32 offset
, uint32 size
);
206 bool loadLiquidData(FILE* in
, uint32 offset
, uint32 size
);
208 // Get height functions and pointers
209 typedef float (GridMap::*GetHeightPtr
) (float x
, float y
) const;
210 GetHeightPtr _gridGetHeight
;
211 float getHeightFromFloat(float x
, float y
) const;
212 float getHeightFromUint16(float x
, float y
) const;
213 float getHeightFromUint8(float x
, float y
) const;
214 float getHeightFromFlat(float x
, float y
) const;
219 bool loadData(const char* filename
);
222 uint16
getArea(float x
, float y
) const;
223 inline float getHeight(float x
, float y
) const {return (this->*_gridGetHeight
)(x
, y
);}
224 float getMinHeight(float x
, float y
) const;
225 float getLiquidLevel(float x
, float y
) const;
226 uint8
getTerrainType(float x
, float y
) const;
227 ZLiquidStatus
getLiquidStatus(float x
, float y
, float z
, uint8 ReqLiquidType
, LiquidData
* data
= 0);
228 bool fileExists() const { return _fileExists
; }
231 #pragma pack(push, 1)
233 struct ZoneDynamicInfo
238 std::unique_ptr
<Weather
> DefaultWeather
;
239 WeatherState WeatherId
;
241 uint32 OverrideLightId
;
242 uint32 LightFadeInTime
;
247 #define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
248 #define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
249 #define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT
250 #define DEFAULT_HEIGHT_SEARCH 50.0f // default search distance to find height at nearby locations
251 #define MIN_UNLOAD_DELAY 1 // immediate unload
253 typedef std::map
<ObjectGuid::LowType
/*leaderDBGUID*/, CreatureGroup
*> CreatureGroupHolderType
;
255 typedef std::unordered_map
<uint32
/*zoneId*/, ZoneDynamicInfo
> ZoneDynamicInfoMap
;
257 typedef TypeUnorderedMapContainer
<AllMapStoredObjectTypes
, ObjectGuid
> MapStoredObjectTypesContainer
;
259 class TC_GAME_API Map
: public GridRefManager
<NGridType
>
261 friend class MapReference
;
263 Map(uint32 id
, time_t, uint32 InstanceId
, uint8 SpawnMode
, Map
* _parent
= NULL
);
266 MapEntry
const* GetEntry() const { return i_mapEntry
; }
268 // currently unused for normal maps
269 bool CanUnload(uint32 diff
)
274 if (m_unloadTimer
<= diff
)
277 m_unloadTimer
-= diff
;
281 virtual bool AddPlayerToMap(Player
* player
, bool initPlayer
= true);
282 virtual void RemovePlayerFromMap(Player
*, bool);
284 template<class T
> bool AddToMap(T
*);
285 template<class T
> void RemoveFromMap(T
*, bool);
287 void VisitNearbyCellsOf(WorldObject
* obj
, TypeContainerVisitor
<Trinity::ObjectUpdater
, GridTypeMapContainer
> &gridVisitor
, TypeContainerVisitor
<Trinity::ObjectUpdater
, WorldTypeMapContainer
> &worldVisitor
);
288 virtual void Update(const uint32
);
290 float GetVisibilityRange() const { return m_VisibleDistance
; }
291 //function for setting up visibility distance for maps on per-type/per-Id basis
292 virtual void InitVisibilityDistance();
294 void PlayerRelocation(Player
*, float x
, float y
, float z
, float orientation
);
295 void CreatureRelocation(Creature
* creature
, float x
, float y
, float z
, float ang
, bool respawnRelocationOnFail
= true);
296 void GameObjectRelocation(GameObject
* go
, float x
, float y
, float z
, float orientation
, bool respawnRelocationOnFail
= true);
297 void DynamicObjectRelocation(DynamicObject
* go
, float x
, float y
, float z
, float orientation
);
298 void AreaTriggerRelocation(AreaTrigger
* at
, float x
, float y
, float z
, float orientation
);
300 template<class T
, class CONTAINER
>
301 void Visit(const Cell
& cell
, TypeContainerVisitor
<T
, CONTAINER
> &visitor
);
303 bool IsRemovalGrid(float x
, float y
) const
305 GridCoord p
= Trinity::ComputeGridCoord(x
, y
);
306 return !getNGrid(p
.x_coord
, p
.y_coord
) || getNGrid(p
.x_coord
, p
.y_coord
)->GetGridState() == GRID_STATE_REMOVAL
;
309 bool IsGridLoaded(float x
, float y
) const
311 return IsGridLoaded(Trinity::ComputeGridCoord(x
, y
));
314 bool GetUnloadLock(const GridCoord
&p
) const { return getNGrid(p
.x_coord
, p
.y_coord
)->getUnloadLock(); }
315 void SetUnloadLock(const GridCoord
&p
, bool on
) { getNGrid(p
.x_coord
, p
.y_coord
)->setUnloadExplicitLock(on
); }
316 void LoadGrid(float x
, float y
);
318 bool UnloadGrid(NGridType
& ngrid
, bool pForce
);
319 virtual void UnloadAll();
321 void ResetGridExpiry(NGridType
&grid
, float factor
= 1) const
323 grid
.ResetTimeTracker(time_t(float(i_gridExpiry
)*factor
));
326 time_t GetGridExpiry() const { return i_gridExpiry
; }
328 bool HasGrid(uint32 mapId
, int32 gx
, int32 gy
) const;
329 static bool ExistMap(uint32 mapid
, int gx
, int gy
);
330 static bool ExistVMap(uint32 mapid
, int gx
, int gy
);
332 static void InitStateMachine();
333 static void DeleteStateMachine();
335 Map
const* GetParent() const { return m_parentMap
; }
336 void AddChildTerrainMap(Map
* map
) { m_childTerrainMaps
->push_back(map
); map
->m_parentTerrainMap
= this; }
337 void UnlinkAllChildTerrainMaps() { m_childTerrainMaps
->clear(); }
339 // some calls like isInWater should not use vmaps due to processor power
340 // can return INVALID_HEIGHT if under z+2 z coord not found height
341 float GetStaticHeight(PhaseShift
const& phaseShift
, float x
, float y
, float z
, bool checkVMap
= true, float maxSearchDist
= DEFAULT_HEIGHT_SEARCH
) const;
342 float GetMinHeight(float x
, float y
) const;
344 ZLiquidStatus
getLiquidStatus(PhaseShift
const& phaseShift
, float x
, float y
, float z
, uint8 ReqLiquidType
, LiquidData
* data
= nullptr) const;
346 uint32
GetAreaId(PhaseShift
const& phaseShift
, float x
, float y
, float z
, bool *isOutdoors
) const;
347 bool GetAreaInfo(PhaseShift
const& phaseShift
, float x
, float y
, float z
, uint32
& mogpflags
, int32
& adtId
, int32
& rootId
, int32
& groupId
) const;
348 uint32
GetAreaId(PhaseShift
const& phaseShift
, float x
, float y
, float z
) const;
349 uint32
GetZoneId(PhaseShift
const& phaseShift
, float x
, float y
, float z
) const;
350 void GetZoneAndAreaId(PhaseShift
const& phaseShift
, uint32
& zoneid
, uint32
& areaid
, float x
, float y
, float z
) const;
352 bool IsOutdoors(PhaseShift
const& phaseShift
, float x
, float y
, float z
) const;
354 uint8
GetTerrainType(PhaseShift
const& phaseShift
, float x
, float y
) const;
355 float GetWaterLevel(PhaseShift
const& phaseShift
, float x
, float y
) const;
356 bool IsInWater(PhaseShift
const& phaseShift
, float x
, float y
, float z
, LiquidData
* data
= nullptr) const;
357 bool IsUnderWater(PhaseShift
const& phaseShift
, float x
, float y
, float z
) const;
359 void MoveAllCreaturesInMoveList();
360 void MoveAllGameObjectsInMoveList();
361 void MoveAllDynamicObjectsInMoveList();
362 void MoveAllAreaTriggersInMoveList();
363 void RemoveAllObjectsInRemoveList();
364 virtual void RemoveAllPlayers();
366 // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader
367 bool CreatureRespawnRelocation(Creature
* c
, bool diffGridOnly
);
368 bool GameObjectRespawnRelocation(GameObject
* go
, bool diffGridOnly
);
370 // assert print helper
371 bool CheckGridIntegrity(Creature
* c
, bool moved
) const;
373 uint32
GetInstanceId() const { return i_InstanceId
; }
374 uint8
GetSpawnMode() const { return (i_spawnMode
); }
379 CANNOT_ENTER_ALREADY_IN_MAP
= 1, // Player is already in the map
380 CANNOT_ENTER_NO_ENTRY
, // No map entry was found for the target map ID
381 CANNOT_ENTER_UNINSTANCED_DUNGEON
, // No instance template was found for dungeon map
382 CANNOT_ENTER_DIFFICULTY_UNAVAILABLE
, // Requested instance difficulty is not available for target map
383 CANNOT_ENTER_NOT_IN_RAID
, // Target instance is a raid instance and the player is not in a raid group
384 CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE
, // Player is dead and their corpse is not in target instance
385 CANNOT_ENTER_INSTANCE_BIND_MISMATCH
, // Player's permanent instance save is not compatible with their group's current instance bind
386 CANNOT_ENTER_TOO_MANY_INSTANCES
, // Player has entered too many instances recently
387 CANNOT_ENTER_MAX_PLAYERS
, // Target map already has the maximum number of players allowed
388 CANNOT_ENTER_ZONE_IN_COMBAT
, // A boss encounter is currently in progress on the target map
389 CANNOT_ENTER_UNSPECIFIED_REASON
391 virtual EnterState
CannotEnter(Player
* /*player*/) { return CAN_ENTER
; }
392 const char* GetMapName() const;
394 // have meaning only for instanced map (that have set real difficulty)
395 Difficulty
GetDifficultyID() const { return Difficulty(GetSpawnMode()); }
396 MapDifficultyEntry
const* GetMapDifficulty() const;
397 uint8
GetDifficultyLootItemContext() const;
399 uint32
GetId() const;
400 bool Instanceable() const;
401 bool IsDungeon() const;
402 bool IsNonRaidDungeon() const;
404 bool IsRaidOrHeroicDungeon() const;
405 bool IsHeroic() const;
406 bool Is25ManRaid() const; // since 25man difficulties are 1 and 3, we can check them like that
407 bool IsBattleground() const;
408 bool IsBattleArena() const;
409 bool IsBattlegroundOrArena() const;
410 bool IsGarrison() const;
411 bool GetEntrancePos(int32
&mapid
, float &x
, float &y
);
413 void AddObjectToRemoveList(WorldObject
* obj
);
414 void AddObjectToSwitchList(WorldObject
* obj
, bool on
);
415 virtual void DelayedUpdate(const uint32 diff
);
417 void resetMarkedCells() { marked_cells
.reset(); }
418 bool isCellMarked(uint32 pCellId
) { return marked_cells
.test(pCellId
); }
419 void markCell(uint32 pCellId
) { marked_cells
.set(pCellId
); }
421 bool HavePlayers() const { return !m_mapRefManager
.isEmpty(); }
422 uint32
GetPlayersCountExceptGMs() const;
423 bool ActiveObjectsNearGrid(NGridType
const& ngrid
) const;
425 void AddWorldObject(WorldObject
* obj
) { i_worldObjects
.insert(obj
); }
426 void RemoveWorldObject(WorldObject
* obj
) { i_worldObjects
.erase(obj
); }
428 void SendToPlayers(WorldPacket
const* data
) const;
430 typedef MapRefManager PlayerList
;
431 PlayerList
const& GetPlayers() const { return m_mapRefManager
; }
433 //per-map script storage
434 void ScriptsStart(std::map
<uint32
, std::multimap
<uint32
, ScriptInfo
> > const& scripts
, uint32 id
, Object
* source
, Object
* target
);
435 void ScriptCommandStart(ScriptInfo
const& script
, uint32 delay
, Object
* source
, Object
* target
);
437 // must called with AddToWorld
439 void AddToActive(T
* obj
);
441 // must called with RemoveFromWorld
443 void RemoveFromActive(T
* obj
);
445 template<class T
> void SwitchGridContainers(T
* obj
, bool on
);
446 CreatureGroupHolderType CreatureGroupHolder
;
448 void UpdateIteratorBack(Player
* player
);
450 TempSummon
* SummonCreature(uint32 entry
, Position
const& pos
, SummonPropertiesEntry
const* properties
= NULL
, uint32 duration
= 0, Unit
* summoner
= NULL
, uint32 spellId
= 0, uint32 vehId
= 0);
451 void SummonCreatureGroup(uint8 group
, std::list
<TempSummon
*>* list
= NULL
);
452 AreaTrigger
* GetAreaTrigger(ObjectGuid
const& guid
);
453 Conversation
* GetConversation(ObjectGuid
const& guid
);
454 Corpse
* GetCorpse(ObjectGuid
const& guid
);
455 Creature
* GetCreature(ObjectGuid
const& guid
);
456 DynamicObject
* GetDynamicObject(ObjectGuid
const& guid
);
457 GameObject
* GetGameObject(ObjectGuid
const& guid
);
458 Pet
* GetPet(ObjectGuid
const& guid
);
459 Transport
* GetTransport(ObjectGuid
const& guid
);
461 MapStoredObjectTypesContainer
& GetObjectsStore() { return _objectsStore
; }
463 typedef std::unordered_multimap
<ObjectGuid::LowType
, Creature
*> CreatureBySpawnIdContainer
;
464 CreatureBySpawnIdContainer
& GetCreatureBySpawnIdStore() { return _creatureBySpawnIdStore
; }
466 typedef std::unordered_multimap
<ObjectGuid::LowType
, GameObject
*> GameObjectBySpawnIdContainer
;
467 GameObjectBySpawnIdContainer
& GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore
; }
469 std::unordered_set
<Corpse
*> const* GetCorpsesInCell(uint32 cellId
) const
471 auto itr
= _corpsesByCell
.find(cellId
);
472 if (itr
!= _corpsesByCell
.end())
478 Corpse
* GetCorpseByPlayer(ObjectGuid
const& ownerGuid
) const
480 auto itr
= _corpsesByPlayer
.find(ownerGuid
);
481 if (itr
!= _corpsesByPlayer
.end())
487 MapInstanced
* ToMapInstanced() { if (Instanceable()) return reinterpret_cast<MapInstanced
*>(this); return NULL
; }
488 MapInstanced
const* ToMapInstanced() const { if (Instanceable()) return reinterpret_cast<MapInstanced
const*>(this); return NULL
; }
490 InstanceMap
* ToInstanceMap() { if (IsDungeon()) return reinterpret_cast<InstanceMap
*>(this); else return NULL
; }
491 InstanceMap
const* ToInstanceMap() const { if (IsDungeon()) return reinterpret_cast<InstanceMap
const*>(this); return NULL
; }
493 BattlegroundMap
* ToBattlegroundMap() { if (IsBattlegroundOrArena()) return reinterpret_cast<BattlegroundMap
*>(this); else return NULL
; }
494 BattlegroundMap
const* ToBattlegroundMap() const { if (IsBattlegroundOrArena()) return reinterpret_cast<BattlegroundMap
const*>(this); return NULL
; }
496 float GetWaterOrGroundLevel(PhaseShift
const& phaseShift
, float x
, float y
, float z
, float* ground
= nullptr, bool swim
= false) const;
497 float GetHeight(PhaseShift
const& phaseShift
, float x
, float y
, float z
, bool vmap
= true, float maxSearchDist
= DEFAULT_HEIGHT_SEARCH
) const;
498 bool isInLineOfSight(PhaseShift
const& phaseShift
, float x1
, float y1
, float z1
, float x2
, float y2
, float z2
) const;
499 void Balance() { _dynamicTree
.balance(); }
500 void RemoveGameObjectModel(const GameObjectModel
& model
) { _dynamicTree
.remove(model
); }
501 void InsertGameObjectModel(const GameObjectModel
& model
) { _dynamicTree
.insert(model
); }
502 bool ContainsGameObjectModel(const GameObjectModel
& model
) const { return _dynamicTree
.contains(model
);}
503 bool getObjectHitPos(PhaseShift
const& phaseShift
, float x1
, float y1
, float z1
, float x2
, float y2
, float z2
, float& rx
, float &ry
, float& rz
, float modifyDist
);
505 virtual ObjectGuid::LowType
GetOwnerGuildId(uint32
/*team*/ = TEAM_OTHER
) const { return UI64LIT(0); }
509 time_t GetLinkedRespawnTime(ObjectGuid guid
) const;
510 time_t GetCreatureRespawnTime(ObjectGuid::LowType dbGuid
) const
512 std::unordered_map
<ObjectGuid::LowType
/*dbGUID*/, time_t>::const_iterator itr
= _creatureRespawnTimes
.find(dbGuid
);
513 if (itr
!= _creatureRespawnTimes
.end())
519 time_t GetGORespawnTime(ObjectGuid::LowType dbGuid
) const
521 std::unordered_map
<ObjectGuid::LowType
/*dbGUID*/, time_t>::const_iterator itr
= _goRespawnTimes
.find(dbGuid
);
522 if (itr
!= _goRespawnTimes
.end())
528 void SaveCreatureRespawnTime(ObjectGuid::LowType dbGuid
, time_t respawnTime
);
529 void RemoveCreatureRespawnTime(ObjectGuid::LowType dbGuid
);
530 void SaveGORespawnTime(ObjectGuid::LowType dbGuid
, time_t respawnTime
);
531 void RemoveGORespawnTime(ObjectGuid::LowType dbGuid
);
532 void LoadRespawnTimes();
533 void DeleteRespawnTimes();
535 void LoadCorpseData();
536 void DeleteCorpseData();
537 void AddCorpse(Corpse
* corpse
);
538 void RemoveCorpse(Corpse
* corpse
);
539 Corpse
* ConvertCorpseToBones(ObjectGuid
const& ownerGuid
, bool insignia
= false);
540 void RemoveOldCorpses();
542 static void DeleteRespawnTimesInDB(uint16 mapId
, uint32 instanceId
);
544 void SendInitTransports(Player
* player
);
545 void SendRemoveTransports(Player
* player
);
546 void SendUpdateTransportVisibility(Player
* player
);
547 void SendZoneDynamicInfo(uint32 zoneId
, Player
* player
) const;
548 void SendZoneWeather(uint32 zoneId
, Player
* player
) const;
549 void SendZoneWeather(ZoneDynamicInfo
const& zoneDynamicInfo
, Player
* player
) const;
551 void SetZoneMusic(uint32 zoneId
, uint32 musicId
);
552 Weather
* GetOrGenerateZoneDefaultWeather(uint32 zoneId
);
553 void SetZoneWeather(uint32 zoneId
, WeatherState weatherId
, float weatherGrade
);
554 void SetZoneOverrideLight(uint32 zoneId
, uint32 lightId
, uint32 fadeInTime
);
556 void UpdateAreaDependentAuras();
558 template<HighGuid high
>
559 inline ObjectGuid::LowType
GenerateLowGuid()
561 static_assert(ObjectGuidTraits
<high
>::MapSpecific
, "Only map specific guid can be generated in Map context");
562 return GetGuidSequenceGenerator
<high
>().Generate();
565 void AddUpdateObject(Object
* obj
)
567 _updateObjects
.insert(obj
);
570 void RemoveUpdateObject(Object
* obj
)
572 _updateObjects
.erase(obj
);
576 void LoadMapAndVMap(int gx
, int gy
);
577 void LoadVMap(int gx
, int gy
);
578 void LoadMap(int gx
, int gy
, bool reload
= false);
579 static void LoadMapImpl(Map
* map
, int gx
, int gy
, bool reload
);
580 void UnloadMap(int gx
, int gy
);
581 static void UnloadMapImpl(Map
* map
, int gx
, int gy
);
582 void LoadMMap(int gx
, int gy
);
583 GridMap
* GetGrid(float x
, float y
);
584 GridMap
* GetGrid(uint32 mapId
, float x
, float y
);
586 void SetTimer(uint32 t
) { i_gridExpiry
= t
< MIN_GRID_DELAY
? MIN_GRID_DELAY
: t
; }
588 void SendInitSelf(Player
* player
);
590 bool CreatureCellRelocation(Creature
* creature
, Cell new_cell
);
591 bool GameObjectCellRelocation(GameObject
* go
, Cell new_cell
);
592 bool DynamicObjectCellRelocation(DynamicObject
* go
, Cell new_cell
);
593 bool AreaTriggerCellRelocation(AreaTrigger
* at
, Cell new_cell
);
595 template<class T
> void InitializeObject(T
* obj
);
596 void AddCreatureToMoveList(Creature
* c
, float x
, float y
, float z
, float ang
);
597 void RemoveCreatureFromMoveList(Creature
* c
);
598 void AddGameObjectToMoveList(GameObject
* go
, float x
, float y
, float z
, float ang
);
599 void RemoveGameObjectFromMoveList(GameObject
* go
);
600 void AddDynamicObjectToMoveList(DynamicObject
* go
, float x
, float y
, float z
, float ang
);
601 void RemoveDynamicObjectFromMoveList(DynamicObject
* go
);
602 void AddAreaTriggerToMoveList(AreaTrigger
* at
, float x
, float y
, float z
, float ang
);
603 void RemoveAreaTriggerFromMoveList(AreaTrigger
* at
);
605 bool _creatureToMoveLock
;
606 std::vector
<Creature
*> _creaturesToMove
;
608 bool _gameObjectsToMoveLock
;
609 std::vector
<GameObject
*> _gameObjectsToMove
;
611 bool _dynamicObjectsToMoveLock
;
612 std::vector
<DynamicObject
*> _dynamicObjectsToMove
;
614 bool _areaTriggersToMoveLock
;
615 std::vector
<AreaTrigger
*> _areaTriggersToMove
;
617 bool IsGridLoaded(const GridCoord
&) const;
618 void EnsureGridCreated(const GridCoord
&);
619 void EnsureGridCreated_i(const GridCoord
&);
620 bool EnsureGridLoaded(Cell
const&);
621 void EnsureGridLoadedForActiveObject(Cell
const&, WorldObject
* object
);
623 void buildNGridLinkage(NGridType
* pNGridType
) { pNGridType
->link(this); }
625 NGridType
* getNGrid(uint32 x
, uint32 y
) const
627 ASSERT(x
< MAX_NUMBER_OF_GRIDS
&& y
< MAX_NUMBER_OF_GRIDS
);
628 return i_grids
[x
][y
];
631 bool isGridObjectDataLoaded(uint32 x
, uint32 y
) const { return getNGrid(x
, y
)->isGridObjectDataLoaded(); }
632 void setGridObjectDataLoaded(bool pLoaded
, uint32 x
, uint32 y
) { getNGrid(x
, y
)->setGridObjectDataLoaded(pLoaded
); }
634 void setNGrid(NGridType
* grid
, uint32 x
, uint32 y
);
635 void ScriptsProcess();
637 void SendObjectUpdates();
640 void SetUnloadReferenceLock(const GridCoord
&p
, bool on
) { getNGrid(p
.x_coord
, p
.y_coord
)->setUnloadReferenceLock(on
); }
641 virtual void LoadGridObjects(NGridType
* grid
, Cell
const& cell
);
644 std::mutex _gridLock
;
646 MapEntry
const* i_mapEntry
;
649 uint32 m_unloadTimer
;
650 float m_VisibleDistance
;
651 DynamicMapTree _dynamicTree
;
653 MapRefManager m_mapRefManager
;
654 MapRefManager::iterator m_mapRefIter
;
656 int32 m_VisibilityNotifyPeriod
;
658 typedef std::set
<WorldObject
*> ActiveNonPlayers
;
659 ActiveNonPlayers m_activeNonPlayers
;
660 ActiveNonPlayers::iterator m_activeNonPlayersIter
;
662 // Objects that must update even in inactive grids without activating them
663 typedef std::set
<Transport
*> TransportsContainer
;
664 TransportsContainer _transports
;
665 TransportsContainer::iterator _transportsUpdateIter
;
668 Player
* _GetScriptPlayerSourceOrTarget(Object
* source
, Object
* target
, const ScriptInfo
* scriptInfo
) const;
669 Creature
* _GetScriptCreatureSourceOrTarget(Object
* source
, Object
* target
, const ScriptInfo
* scriptInfo
, bool bReverse
= false) const;
670 Unit
* _GetScriptUnit(Object
* obj
, bool isSource
, const ScriptInfo
* scriptInfo
) const;
671 Player
* _GetScriptPlayer(Object
* obj
, bool isSource
, const ScriptInfo
* scriptInfo
) const;
672 Creature
* _GetScriptCreature(Object
* obj
, bool isSource
, const ScriptInfo
* scriptInfo
) const;
673 WorldObject
* _GetScriptWorldObject(Object
* obj
, bool isSource
, const ScriptInfo
* scriptInfo
) const;
674 void _ScriptProcessDoor(Object
* source
, Object
* target
, const ScriptInfo
* scriptInfo
) const;
675 GameObject
* _FindGameObject(WorldObject
* pWorldObject
, ObjectGuid::LowType guid
) const;
679 //used for fast base_map (e.g. MapInstanced class object) search for
680 //InstanceMaps and BattlegroundMaps...
681 Map
* m_parentMap
; // points to MapInstanced* or self (always same map id)
682 Map
* m_parentTerrainMap
; // points to m_parentMap of MapEntry::ParentMapID
683 std::vector
<Map
*>* m_childTerrainMaps
; // contains m_parentMap of maps that have MapEntry::ParentMapID == GetId()
685 NGridType
* i_grids
[MAX_NUMBER_OF_GRIDS
][MAX_NUMBER_OF_GRIDS
];
686 GridMap
* GridMaps
[MAX_NUMBER_OF_GRIDS
][MAX_NUMBER_OF_GRIDS
];
687 std::bitset
<TOTAL_NUMBER_OF_CELLS_PER_MAP
*TOTAL_NUMBER_OF_CELLS_PER_MAP
> marked_cells
;
689 //these functions used to process player/mob aggro reactions and
690 //visibility calculations. Highly optimized for massive calculations
691 void ProcessRelocationNotifies(const uint32 diff
);
694 std::set
<WorldObject
*> i_objectsToRemove
;
695 std::map
<WorldObject
*, bool> i_objectsToSwitch
;
696 std::set
<WorldObject
*> i_worldObjects
;
698 typedef std::multimap
<time_t, ScriptAction
> ScriptScheduleMap
;
699 ScriptScheduleMap m_scriptSchedule
;
701 // Type specific code for add/remove to/from grid
703 void AddToGrid(T
* object
, Cell
const& cell
);
706 void DeleteFromWorld(T
*);
708 void AddToActiveHelper(WorldObject
* obj
)
710 m_activeNonPlayers
.insert(obj
);
713 void RemoveFromActiveHelper(WorldObject
* obj
)
715 // Map::Update for active object in proccess
716 if (m_activeNonPlayersIter
!= m_activeNonPlayers
.end())
718 ActiveNonPlayers::iterator itr
= m_activeNonPlayers
.find(obj
);
719 if (itr
== m_activeNonPlayers
.end())
721 if (itr
== m_activeNonPlayersIter
)
722 ++m_activeNonPlayersIter
;
723 m_activeNonPlayers
.erase(itr
);
726 m_activeNonPlayers
.erase(obj
);
729 std::unordered_map
<ObjectGuid::LowType
/*dbGUID*/, time_t> _creatureRespawnTimes
;
730 std::unordered_map
<ObjectGuid::LowType
/*dbGUID*/, time_t> _goRespawnTimes
;
732 ZoneDynamicInfoMap _zoneDynamicInfo
;
733 IntervalTimer _weatherUpdateTimer
;
734 uint32 _defaultLight
;
736 template<HighGuid high
>
737 inline ObjectGuidGeneratorBase
& GetGuidSequenceGenerator()
739 auto itr
= _guidGenerators
.find(high
);
740 if (itr
== _guidGenerators
.end())
741 itr
= _guidGenerators
.insert(std::make_pair(high
, Trinity::make_unique
<ObjectGuidGenerator
<high
>>())).first
;
746 std::map
<HighGuid
, std::unique_ptr
<ObjectGuidGeneratorBase
>> _guidGenerators
;
747 MapStoredObjectTypesContainer _objectsStore
;
748 CreatureBySpawnIdContainer _creatureBySpawnIdStore
;
749 GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore
;
750 std::unordered_map
<uint32
/*cellId*/, std::unordered_set
<Corpse
*>> _corpsesByCell
;
751 std::unordered_map
<ObjectGuid
, Corpse
*> _corpsesByPlayer
;
752 std::unordered_set
<Corpse
*> _corpseBones
;
754 std::unordered_set
<Object
*> _updateObjects
;
757 enum InstanceResetMethod
760 INSTANCE_RESET_CHANGE_DIFFICULTY
,
761 INSTANCE_RESET_GLOBAL
,
762 INSTANCE_RESET_GROUP_DISBAND
,
763 INSTANCE_RESET_GROUP_JOIN
,
764 INSTANCE_RESET_RESPAWN_DELAY
767 class TC_GAME_API InstanceMap
: public Map
770 InstanceMap(uint32 id
, time_t, uint32 InstanceId
, uint8 SpawnMode
, Map
* _parent
);
772 bool AddPlayerToMap(Player
* player
, bool initPlayer
= true) override
;
773 void RemovePlayerFromMap(Player
*, bool) override
;
774 void Update(const uint32
) override
;
775 void CreateInstanceData(bool load
);
776 bool Reset(uint8 method
);
777 uint32
GetScriptId() const { return i_script_id
; }
778 std::string
const& GetScriptName() const;
779 InstanceScript
* GetInstanceScript() { return i_data
; }
780 InstanceScript
const* GetInstanceScript() const { return i_data
; }
781 InstanceScenario
* GetInstanceScenario() { return i_scenario
; }
782 InstanceScenario
const* GetInstanceScenario() const { return i_scenario
; }
783 void SetInstanceScenario(InstanceScenario
* scenario
) { i_scenario
= scenario
; }
784 void PermBindAllPlayers();
785 void UnloadAll() override
;
786 EnterState
CannotEnter(Player
* player
) override
;
787 void SendResetWarnings(uint32 timeLeft
) const;
788 void SetResetSchedule(bool on
);
790 /* this checks if any players have a permanent bind (included reactivatable expired binds) to the instance ID
791 it needs a DB query, so use sparingly */
792 bool HasPermBoundPlayers() const;
793 uint32
GetMaxPlayers() const;
794 uint32
GetMaxResetDelay() const;
796 virtual void InitVisibilityDistance() override
;
798 bool m_resetAfterUnload
;
799 bool m_unloadWhenEmpty
;
800 InstanceScript
* i_data
;
802 InstanceScenario
* i_scenario
;
805 class TC_GAME_API BattlegroundMap
: public Map
808 BattlegroundMap(uint32 id
, time_t, uint32 InstanceId
, Map
* _parent
, uint8 spawnMode
);
811 bool AddPlayerToMap(Player
* player
, bool initPlayer
= true) override
;
812 void RemovePlayerFromMap(Player
*, bool) override
;
813 EnterState
CannotEnter(Player
* player
) override
;
815 //void UnloadAll(bool pForce);
816 void RemoveAllPlayers() override
;
818 virtual void InitVisibilityDistance() override
;
819 Battleground
* GetBG() { return m_bg
; }
820 void SetBG(Battleground
* bg
) { m_bg
= bg
; }
825 template<class T
, class CONTAINER
>
826 inline void Map::Visit(Cell
const& cell
, TypeContainerVisitor
<T
, CONTAINER
>& visitor
)
828 const uint32 x
= cell
.GridX();
829 const uint32 y
= cell
.GridY();
830 const uint32 cell_x
= cell
.CellX();
831 const uint32 cell_y
= cell
.CellY();
833 if (!cell
.NoCreate() || IsGridLoaded(GridCoord(x
, y
)))
835 EnsureGridLoaded(cell
);
836 getNGrid(x
, y
)->VisitGrid(cell_x
, cell_y
, visitor
);