Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Map.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battleground.h"
7#include "BattlePetSpawnMgr.h"
8#include "CellImpl.h"
9#include "DynamicTree.h"
10#include "GridNotifiers.h"
11#include "GridNotifiersImpl.h"
12#include "GridStates.h"
13#include "Group.h"
14#include "InstanceScript.h"
15#include "Map.h"
16#include "MapInstanced.h"
17#include "MapLifecycle.h"
18#include "MapManager.h"
19#include "MMapFactory.h"
20#include "ObjectAccessor.h"
21#include "ObjectMgr.h"
22#include "Pet.h"
23#include "ScriptMgr.h"
24#include "Transport.h"
25#include "Vehicle.h"
26#include "VMapFactory.h"
27
28u_map_magic MapMagic = { {'M', 'A', 'P', 'S'} };
29u_map_magic MapVersionMagic = { {'v', '1', '.', '4'} };
30u_map_magic MapAreaMagic = { {'A', 'R', 'E', 'A'} };
31u_map_magic MapHeightMagic = { {'M', 'H', 'G', 'T'} };
32u_map_magic MapLiquidMagic = { {'M', 'L', 'I', 'Q'} };
33
34#define DEFAULT_GRID_EXPIRY 300
35#define MAX_GRID_LOAD_TIME 50
36#define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld->getRate(RATE_CREATURE_AGGRO))
37
39
41{
42 sScriptMgr->OnDestroyMap(this);
43
44 UnloadAll();
45
46 while (!i_worldObjects.empty())
47 {
48 WorldObject* obj = *i_worldObjects.begin();
49 ASSERT(obj->IsWorldObject());
50 //ASSERT(obj->GetTypeId() == TYPEID_CORPSE);
51 obj->RemoveFromWorld();
52 obj->ResetMap();
53 }
54
55 for (TransportsContainer::iterator itr = _transports.begin(); itr != _transports.end();)
56 {
57 Transport* transport = *itr;
58 ++itr;
59
60 // Destroy local transports
61 TransportTemplate const* transportTemplate = transport->GetTransportTemplate();
62 if (!transportTemplate || transportTemplate->inInstance)
63 {
64 transport->RemoveFromWorld();
65 delete transport;
66 }
67 }
68
69 if (!m_scriptSchedule.empty())
70 sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size());
71
73}
74
75bool Map::ExistMap(uint32 mapid, int gx, int gy)
76{
77 int len = sWorld->GetDataPath().length() + strlen("maps/%04u_%02u_%02u.map") + 1;
78 char* fileName = new char[len];
79 snprintf(fileName, len, (char*)(sWorld->GetDataPath() + "maps/%04u_%02u_%02u.map").c_str(), mapid, gx, gy);
80
81 bool ret = false;
82 FILE* pf = fopen(fileName, "rb");
83
84 if (!pf)
85 SF_LOG_ERROR("maps", "Map file '%s': does not exist!", fileName);
86 else
87 {
88 map_fileheader header;
89 if (fread(&header, sizeof(header), 1, pf) == 1)
90 {
91 /*if (header.mapMagic.asUInt != MapMagic.asUInt || header.versionMagic.asUInt != MapVersionMagic.asUInt)
92 SF_LOG_ERROR("maps", "Map file '%s' is from an incompatible map version (%.*s %.*s), %.*s %.*s is expected. Please recreate using the mapextractor.",
93 fileName, 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar);
94 else*/
95 ret = true;
96 }
97 fclose(pf);
98 }
99
100 delete[] fileName;
101 return ret;
102}
103
104bool Map::ExistVMap(uint32 mapid, int gx, int gy)
105{
107 {
108 if (vmgr->isMapLoadingEnabled())
109 {
110 bool exists = vmgr->existsMap((sWorld->GetDataPath() + "vmaps").c_str(), mapid, gx, gy);
111 if (!exists)
112 {
113 std::string name = vmgr->getDirFileName(mapid, gx, gy);
114 SF_LOG_ERROR("maps", "VMap file '%s' is missing or points to wrong version of vmap file. Redo vmaps with latest version of vmap_assembler.exe.", (sWorld->GetDataPath() + "vmaps/" + name).c_str());
115 return false;
116 }
117 }
118 }
119
120 return true;
121}
122
123void Map::LoadMMap(int gx, int gy)
124{
125 bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy);
126
127 if (mmapLoadResult)
128 SF_LOG_INFO("maps", "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
129 else
130 SF_LOG_INFO("maps", "Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
131}
132
133void Map::LoadVMap(int gx, int gy)
134{
135 // x and y are swapped !!
136 int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld->GetDataPath() + "vmaps").c_str(), GetId(), gx, gy);
137 switch (vmapLoadResult)
138 {
140 SF_LOG_INFO("maps", "VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
141 break;
143 SF_LOG_INFO("maps", "Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
144 break;
146 SF_LOG_DEBUG("maps", "Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
147 break;
148 }
149}
150
151void Map::LoadMap(int gx, int gy, bool reload)
152{
153 if (i_InstanceId != 0)
154 {
155 if (GridMaps[gx][gy])
156 return;
157
158 // load grid map for base map
159 if (!m_parentMap->GridMaps[gx][gy])
160 m_parentMap->EnsureGridCreated_i(GridCoord(63 - gx, 63 - gy));
161
162 ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridCoord(gx, gy));
163 GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy];
164 return;
165 }
166
167 if (GridMaps[gx][gy] && !reload)
168 return;
169
170 //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?)
171 if (GridMaps[gx][gy])
172 {
173 SF_LOG_INFO("maps", "Unloading previously loaded map %u before reloading.", GetId());
174 sScriptMgr->OnUnloadGridMap(this, GridMaps[gx][gy], gx, gy);
175
176 delete (GridMaps[gx][gy]);
177 GridMaps[gx][gy] = NULL;
178 }
179
180 // map file name
181 char* tmp = NULL;
182 int len = sWorld->GetDataPath().length() + strlen("maps/%04u_%02u_%02u.map") + 1;
183 tmp = new char[len];
184 snprintf(tmp, len, (char*)(sWorld->GetDataPath() + "maps/%04u_%02u_%02u.map").c_str(), GetId(), gx, gy);
185 SF_LOG_INFO("maps", "Loading map %s", tmp);
186 // loading data
187 GridMaps[gx][gy] = new GridMap();
188 if (!GridMaps[gx][gy]->loadData(tmp))
189 SF_LOG_ERROR("maps", "Error loading map file: \n %s\n", tmp);
190 delete[] tmp;
191
192 sScriptMgr->OnLoadGridMap(this, GridMaps[gx][gy], gx, gy);
193}
194
195void Map::LoadMapAndVMap(int gx, int gy)
196{
197 LoadMap(gx, gy);
198 // Only load the data for the base map
199 if (i_InstanceId == 0)
200 {
201 LoadVMap(gx, gy);
202 LoadMMap(gx, gy);
203 }
204}
205
213
221
222Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) :
224 i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
228 i_gridExpiry(expiry),
229 i_scriptLock(false)
230{
231 m_parentMap = (_parent ? _parent : this);
232 for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
233 {
234 for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j)
235 {
236 //z code
237 GridMaps[idx][j] = NULL;
238 setNGrid(NULL, idx, j);
239 }
240 }
241
242 //lets initialize visibility distance for map
244
245 sScriptMgr->OnCreateMap(this);
246}
247
254
255// Template specialization of utility methods
256template<class T>
257void Map::AddToGrid(T* obj, Cell const& cell)
258{
259 NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
260 if (obj->IsWorldObject())
261 grid->GetGridType(cell.CellX(), cell.CellY()).template AddWorldObject<T>(obj);
262 else
263 grid->GetGridType(cell.CellX(), cell.CellY()).template AddGridObject<T>(obj);
264}
265
266template<>
267void Map::AddToGrid(Creature* obj, Cell const& cell)
268{
269 NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
270 if (obj->IsWorldObject())
271 grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj);
272 else
273 grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
274
275 obj->SetCurrentCell(cell);
276}
277
278template<>
279void Map::AddToGrid(GameObject* obj, Cell const& cell)
280{
281 NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
282 grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
283
284 obj->SetCurrentCell(cell);
285}
286
287template<class T>
288void Map::SwitchGridContainers(T* /*obj*/, bool /*on*/) { }
289
290template<>
292{
295 if (!p.IsCoordValid())
296 {
297 SF_LOG_ERROR("maps", "Map::SwitchGridContainers: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
298 return;
299 }
300
301 Cell cell(p);
303 return;
304
305 SF_LOG_DEBUG("maps", "Switch object " UI64FMTD " from grid[%u, %u] %u", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
306 NGridType* ngrid = getNGrid(cell.GridX(), cell.GridY());
307 ASSERT(ngrid != NULL);
308
309 GridType& grid = ngrid->GetGridType(cell.CellX(), cell.CellY());
310
311 obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
312
313 if (on)
314 {
315 grid.AddWorldObject(obj);
316 AddWorldObject(obj);
317 }
318 else
319 {
320 grid.AddGridObject(obj);
322 }
323
324 obj->m_isTempWorldObject = on;
325}
326
327template<>
329{
332 if (!p.IsCoordValid())
333 {
334 SF_LOG_ERROR("maps", "Map::SwitchGridContainers: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
335 return;
336 }
337
338 Cell cell(p);
340 return;
341
342 SF_LOG_DEBUG("maps", "Switch object " UI64FMTD " from grid[%u, %u] %u", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
343 NGridType* ngrid = getNGrid(cell.GridX(), cell.GridY());
344 ASSERT(ngrid != NULL);
345
346 GridType& grid = ngrid->GetGridType(cell.CellX(), cell.CellY());
347
348 obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
349
350 if (on)
351 {
352 grid.AddWorldObject(obj);
353 AddWorldObject(obj);
354 }
355 else
356 {
357 grid.AddGridObject(obj);
359 }
360}
361
362template<class T>
364{
365 // Note: In case resurrectable corpse and pet its removed from global lists in own destructor
366 delete obj;
367}
368
369template<>
371{
372 sObjectAccessor->RemoveObject(player);
373 sObjectAccessor->RemoveUpdateObject(player);
374 delete player;
375}
376
378{
379 std::lock_guard<std::mutex> guard(GridLock);
381}
382
383//Create NGrid so the object can be added to it
384//But object data is not loaded here
386{
387 if (!p.IsCoordValid())
388 {
389 SF_LOG_ERROR("maps", "EnsureGridCreated_i: invalid grid [%u, %u] for map %u instance %u", p.x_coord, p.y_coord, GetId(), i_InstanceId);
390 return;
391 }
392
393 if (!getNGrid(p.x_coord, p.y_coord))
394 {
395 SF_LOG_DEBUG("maps", "Creating grid[%u, %u] for map %u instance %u", p.x_coord, p.y_coord, GetId(), i_InstanceId);
396
398 p.x_coord, p.y_coord);
399
400 // build a linkage between this map and NGridType
402
404
405 //z coord
406 int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
407 int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
408
409 if (!GridMaps[gx][gy])
410 LoadMapAndVMap(gx, gy);
411 }
412}
413
414//Load NGrid and make it active
416{
417 EnsureGridLoaded(cell);
418 NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
419 ASSERT(grid != NULL);
420
421 // refresh grid state & timer
422 if (grid->GetGridState() != GRID_STATE_ACTIVE)
423 {
424 SF_LOG_DEBUG("maps", "Active object " UI64FMTD " triggers loading of grid [%u, %u] on map %u", object->GetGUID(), cell.GridX(), cell.GridY(), GetId());
425 ResetGridExpiry(*grid, 0.1f);
427 }
428}
429
430//Create NGrid and load the object data in it
432{
433 EnsureGridCreated(GridCoord(cell.GridX(), cell.GridY()));
434 NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
435
436 ASSERT(grid != NULL);
437 if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY()))
438 {
439 SF_LOG_DEBUG("maps", "Loading grid[%u, %u] for map %u instance %u", cell.GridX(), cell.GridY(), GetId(), i_InstanceId);
440
441 setGridObjectDataLoaded(true, cell.GridX(), cell.GridY());
442
443 ObjectGridLoader loader(*grid, this, cell);
444 loader.LoadN();
445
446 // Add resurrectable corpses to world object list in grid
447 sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this);
448 Balance();
449 return true;
450 }
451
452 return false;
453}
454
455void Map::LoadGrid(float x, float y)
456{
457 EnsureGridLoaded(Cell(x, y));
458}
459
461{
462 CellCoord cellCoord = Skyfire::ComputeCellCoord(player->GetPositionX(), player->GetPositionY());
463 if (!cellCoord.IsCoordValid())
464 {
465 SF_LOG_ERROR("maps", "Map::Add: Player (GUID: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
466 return false;
467 }
468
469 Cell cell(cellCoord);
471 AddToGrid(player, cell);
472
473 // Check if we are adding to correct map
474 ASSERT(player->GetMap() == this);
475 player->SetMap(this);
476 player->AddToWorld();
477
478 player->m_clientGUIDs.clear();
479 SendInitSelf(player);
480 SendInitTransports(player);
481
482 player->UpdateObjectVisibility(false);
483 player->UpdatePhasing();
484 sScriptMgr->OnPlayerEnterMap(this, player);
485 return true;
486}
487
488template<class T>
489void Map::InitializeObject(T* /*obj*/) { }
490
491template<>
496
497template<>
502
503template<class T>
504bool Map::AddToMap(T* obj)
505{
507 Skyfire::Maps::GetAddObjectAction(obj->IsInWorld(), true);
509 {
510 ASSERT(obj->IsInGrid());
511 obj->UpdateObjectVisibility(true);
512 return true;
513 }
514
515 CellCoord cellCoord = Skyfire::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
516 //It will create many problems (including crashes) if an object is not added to grid after creation
517 //The correct way to fix it is to make AddToMap return false and delete the object if it is not added to grid
518 //But now AddToMap is used in too many places, I will just see how many ASSERT failures it will cause
519 ASSERT(cellCoord.IsCoordValid());
520 action = Skyfire::Maps::GetAddObjectAction(false, cellCoord.IsCoordValid());
522 {
523 SF_LOG_ERROR("maps", "Map::Add: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
524 return false; //Should delete object
525 }
526
527 Cell cell(cellCoord);
528 if (obj->isActiveObject())
530 else
531 EnsureGridCreated(GridCoord(cell.GridX(), cell.GridY()));
532 AddToGrid(obj, cell);
533 SF_LOG_DEBUG("maps", "Object %u enters grid[%u, %u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());
534
535 //Must already be set before AddToMap. Usually during obj->Create.
536 //obj->SetMap(this);
537 obj->AddToWorld();
538
539 InitializeObject(obj);
540
541 if (Creature* creature = obj->ToCreature())
542 sBattlePetSpawnMgr->OnCreatureAdded(creature);
543
544 if (obj->isActiveObject())
545 AddToActive(obj);
546
547 obj->RebuildTerrainSwaps();
548
549 //something, such as vehicle, needs to be update immediately
550 //also, trigger needs to cast spell, if not update, cannot see visual
551 obj->UpdateObjectVisibility(true);
552 return true;
553}
554
555template<>
557{
561 return true;
562
564 action = Skyfire::Maps::GetAddObjectAction(false, cellCoord.IsCoordValid());
566 {
567 SF_LOG_ERROR("maps", "Map::Add: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
568 return false; //Should delete object
569 }
570
571 obj->AddToWorld();
572 _transports.insert(obj);
573
574 if (!GetPlayers().isEmpty())
575 {
576 for (Map::PlayerList::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
577 {
578 Player* player = itr->GetSource();
579 if (player->GetTransport() == obj || !player->IsInWorld())
580 continue;
581
582 UpdateData data(GetId());
583 obj->BuildCreateUpdateBlockForPlayer(&data, player);
584 WorldPacket packet;
585 data.BuildPacket(&packet);
586 player->SendDirectMessage(&packet);
587 player->m_clientGUIDs.insert(obj->GetGUID());
588 }
589 }
590
591 return true;
592}
593
594bool Map::IsGridLoaded(const GridCoord& p) const
595{
596 if (!p.IsCoordValid())
597 return false;
598
600}
601
603{
604 // Check for valid position
605 if (!obj->IsPositionValid())
606 return;
607
608 // Update mobs/objects in ALL visible cells around object!
610
611 for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
612 {
613 for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
614 {
615 // marked cells are those that have been visited
616 // don't visit the same cell twice
617 uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
618 if (isCellMarked(cell_id))
619 continue;
620
621 markCell(cell_id);
622 CellCoord pair(x, y);
623 Cell cell(pair);
624 cell.SetNoCreate();
625 Visit(cell, gridVisitor);
626 Visit(cell, worldVisitor);
627 }
628 }
629}
630
631void Map::Update(const uint32 t_diff)
632{
633 _dynamicTree.update(t_diff);
636 {
637 Player* player = m_mapRefIter->GetSource();
638 if (player && player->IsInWorld())
639 {
640 //player->Update(t_diff);
641 WorldSession* session = player->GetSession();
642 MapSessionFilter updater(session);
643 session->Update(t_diff, updater);
644 }
645 }
648
649 Skyfire::ObjectUpdater updater(t_diff);
650 // for creature
652 // for pets
654
655 // the player iterator is stored in the map object
656 // to make sure calls to Map::Remove don't invalidate it
658 {
659 Player* player = m_mapRefIter->GetSource();
660
661 if (!player || !player->IsInWorld())
662 continue;
663
664 // update players at tick
665 player->Update(t_diff);
666
667 VisitNearbyCellsOf(player, grid_object_update, world_object_update);
668
669 // If player is using far sight, visit that object too
670 if (WorldObject* viewPoint = player->GetViewpoint())
671 {
672 if (Creature* viewCreature = viewPoint->ToCreature())
673 VisitNearbyCellsOf(viewCreature, grid_object_update, world_object_update);
674 else if (DynamicObject* viewObject = viewPoint->ToDynObject())
675 VisitNearbyCellsOf(viewObject, grid_object_update, world_object_update);
676 }
677 }
678
679 // non-player active objects, increasing iterator in the loop in case of object removal
681 {
684
685 if (!obj || !obj->IsInWorld())
686 continue;
687
688 VisitNearbyCellsOf(obj, grid_object_update, world_object_update);
689 }
690
692 {
695
696 if (!obj->IsInWorld())
697 continue;
698
699 obj->Update(t_diff);
700 }
701
703 if (!m_scriptSchedule.empty())
704 {
705 i_scriptLock = true;
707 i_scriptLock = false;
708 }
709
712
713 if (!m_mapRefManager.isEmpty() || !m_activeNonPlayers.empty())
715
716 sScriptMgr->OnMapUpdate(this, t_diff);
717}
718
720{
721 template<class T>inline void resetNotify(GridRefManager<T>& m)
722 {
723 for (typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
724 iter->GetSource()->ResetAllNotifies();
725 }
726 template<class T> void Visit(GridRefManager<T>&) { }
729};
730
732{
734 {
735 NGridType* grid = i->GetSource();
736
737 if (grid->GetGridState() != GRID_STATE_ACTIVE)
738 continue;
739
741 if (!grid->getGridInfoRef()->getRelocationTimer().TPassed())
742 continue;
743
744 uint32 gx = grid->getX(), gy = grid->getY();
745
747 CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord + MAX_NUMBER_OF_CELLS);
748
749 for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x)
750 {
751 for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y)
752 {
753 uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
754 if (!isCellMarked(cell_id))
755 continue;
756
757 CellCoord pair(x, y);
758 Cell cell(pair);
759 cell.SetNoCreate();
760
761 Skyfire::DelayedUnitRelocation cell_relocation(cell, pair, *this, MAX_VISIBILITY_DISTANCE);
764 Visit(cell, grid_object_relocation);
765 Visit(cell, world_object_relocation);
766 }
767 }
768 }
769
770 ResetNotifier reset;
774 {
775 NGridType* grid = i->GetSource();
776
777 if (grid->GetGridState() != GRID_STATE_ACTIVE)
778 continue;
779
780 if (!grid->getGridInfoRef()->getRelocationTimer().TPassed())
781 continue;
782
784
785 uint32 gx = grid->getX(), gy = grid->getY();
786
788 CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord + MAX_NUMBER_OF_CELLS);
789
790 for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x)
791 {
792 for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y)
793 {
794 uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
795 if (!isCellMarked(cell_id))
796 continue;
797
798 CellCoord pair(x, y);
799 Cell cell(pair);
800 cell.SetNoCreate();
801 Visit(cell, grid_notifier);
802 Visit(cell, world_notifier);
803 }
804 }
805 }
806}
807
808void Map::RemovePlayerFromMap(Player* player, bool remove)
809{
810 sScriptMgr->OnPlayerLeaveMap(this, player);
811
812 player->RemoveFromWorld();
813 SendRemoveTransports(player);
814
815 player->UpdateObjectVisibility(true);
816 if (player->IsInGrid())
817 player->RemoveFromGrid();
818 else
819 ASSERT(remove); //maybe deleted in logoutplayer when player is not in a map
820
821 if (remove)
822 DeleteFromWorld(player);
823}
824
825template<class T>
826void Map::RemoveFromMap(T* obj, bool remove)
827{
828 if (Creature* creature = obj->ToCreature())
829 sBattlePetSpawnMgr->OnCreatureRemoved(creature);
830
831 obj->RemoveFromWorld();
832 if (obj->isActiveObject())
833 RemoveFromActive(obj);
834
835 obj->UpdateObjectVisibility(true);
836 obj->RemoveFromGrid();
837
838 obj->ResetMap();
839
840 if (remove)
841 {
842 // if option set then object already saved at this moment
844 obj->SaveRespawnTime();
845 DeleteFromWorld(obj);
846 }
847}
848
849template<>
850void Map::RemoveFromMap(Transport* obj, bool remove)
851{
852 obj->RemoveFromWorld();
853
855 {
856 TransportsContainer::iterator itr = _transports.find(obj);
857 if (itr == _transports.end())
858 return;
859 if (itr == _transportsUpdateIter)
861 _transports.erase(itr);
862 }
863 else
864 _transports.erase(obj);
865
866 obj->ResetMap();
867
868 if (remove)
869 {
870 // if option set then object already saved at this moment
872 obj->SaveRespawnTime();
873 DeleteFromWorld(obj);
874 }
875}
876
877void Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
878{
879 ASSERT(player);
880
881 Cell old_cell(player->GetPositionX(), player->GetPositionY());
882 Cell new_cell(x, y);
883
889
890 player->Relocate(x, y, z, orientation);
891 if (player->IsVehicle())
893
894 if (old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell))
895 {
896 SF_LOG_DEBUG("maps", "Player %s relocation grid[%u, %u]cell[%u, %u]->grid[%u, %u]cell[%u, %u]", player->GetName().c_str(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
897
898 player->RemoveFromGrid();
899
900 if (old_cell.DiffGrid(new_cell))
901 EnsureGridLoadedForActiveObject(new_cell, player);
902
903 AddToGrid(player, new_cell);
904 }
905
906 player->UpdateObjectVisibility(false);
907}
908
909void Map::CreatureRelocation(Creature* creature, float x, float y, float z, float ang, bool respawnRelocationOnFail)
910{
911 ASSERT(CheckGridIntegrity(creature, false));
912
913 Cell old_cell = creature->GetCurrentCell();
914 Cell new_cell(x, y);
915
916 if (!respawnRelocationOnFail && !getNGrid(new_cell.GridX(), new_cell.GridY()))
917 return;
918
924
925 // delay creature move for grid/cell to grid/cell moves
926 if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
927 {
928#ifdef SKYFIRE_DEBUG
929 SF_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", creature->GetGUIDLow(), creature->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());
930#endif
931 AddCreatureToMoveList(creature, x, y, z, ang);
932 // in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList
933 }
934 else
935 {
936 creature->Relocate(x, y, z, ang);
937 if (creature->IsVehicle())
938 creature->GetVehicleKit()->RelocatePassengers();
939 creature->UpdateObjectVisibility(false);
941 }
942
943 ASSERT(CheckGridIntegrity(creature, true));
944}
945
946void Map::GameObjectRelocation(GameObject* go, float x, float y, float z, float orientation, bool respawnRelocationOnFail)
947{
948 Cell integrity_check(go->GetPositionX(), go->GetPositionY());
949 Cell old_cell = go->GetCurrentCell();
950
951 ASSERT(integrity_check == old_cell);
952 Cell new_cell(x, y);
953
954 if (!respawnRelocationOnFail && !getNGrid(new_cell.GridX(), new_cell.GridY()))
955 return;
956
957 // delay creature move for grid/cell to grid/cell moves
958 if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
959 {
960#ifdef SKYFIRE_DEBUG
961 SF_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) added to moving list from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
962#endif
963 AddGameObjectToMoveList(go, x, y, z, orientation);
964 // in diffcell/diffgrid case notifiers called at finishing move go in Map::MoveAllGameObjectsInMoveList
965 }
966 else
967 {
968 go->Relocate(x, y, z, orientation);
970 go->UpdateObjectVisibility(false);
972 }
973
974 old_cell = go->GetCurrentCell();
975 integrity_check = Cell(go->GetPositionX(), go->GetPositionY());
976 ASSERT(integrity_check == old_cell);
977}
978
979void Map::AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang)
980{
984 return;
985
987 _creaturesToMove.push_back(c);
988
989 c->SetNewCellPosition(x, y, z, ang);
990}
991
996
997void Map::AddGameObjectToMoveList(GameObject* go, float x, float y, float z, float ang)
998{
1002 return;
1003
1005 _gameObjectsToMove.push_back(go);
1006
1007 go->SetNewCellPosition(x, y, z, ang);
1008}
1009
1014
1016{
1017 _creatureToMoveLock = true;
1018 for (std::vector<Creature*>::iterator itr = _creaturesToMove.begin(); itr != _creaturesToMove.end(); ++itr)
1019 {
1020 Creature* c = *itr;
1021 if (c->FindMap() != this) //pet is teleported to another map
1022 continue;
1023
1025 continue;
1026
1027 if (!c->IsInWorld())
1028 continue;
1029
1030 // do move or do move to respawn or remove creature if previous all fail
1032 {
1033 // update pos
1034 c->Relocate(c->_newPosition);
1035 if (c->IsVehicle())
1037 //CreatureRelocationNotify(c, new_cell, new_cell.cellCoord());
1038 c->UpdateObjectVisibility(false);
1039 }
1040 else
1041 {
1042 // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid
1043 // creature coordinates will be updated and notifiers send
1044 if (!CreatureRespawnRelocation(c, false))
1045 {
1046 // ... or unload (if respawn grid also not loaded)
1047#ifdef SKYFIRE_DEBUG
1048 SF_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.", c->GetGUIDLow(), c->GetEntry());
1049#endif
1050 //AddObjectToRemoveList(Pet*) should only be called in Pet::Remove
1051 //This may happen when a player just logs in and a pet moves to a nearby unloaded cell
1052 //To avoid this, we can load nearby cells when player log in
1053 //But this check is always needed to ensure safety
1055 //need to check why pet is frequently relocated to an unloaded cell
1056 if (c->IsPet())
1057 ((Pet*)c)->Remove(PET_SAVE_NOT_IN_SLOT, true);
1058 else
1060 }
1061 }
1062 }
1063 _creaturesToMove.clear();
1064 _creatureToMoveLock = false;
1065}
1066
1068{
1070 for (std::vector<GameObject*>::iterator itr = _gameObjectsToMove.begin(); itr != _gameObjectsToMove.end(); ++itr)
1071 {
1072 GameObject* go = *itr;
1073 if (go->FindMap() != this) //transport is teleported to another map
1074 continue;
1075
1077 continue;
1078
1079 if (!go->IsInWorld())
1080 continue;
1081
1082 // do move or do move to respawn or remove creature if previous all fail
1084 {
1085 // update pos
1086 go->Relocate(go->_newPosition);
1087 go->UpdateModelPosition();
1088 go->UpdateObjectVisibility(false);
1089 }
1090 else
1091 {
1092 // if GameObject can't be move in new cell/grid (not loaded) move it to repawn cell/grid
1093 // GameObject coordinates will be updated and notifiers send
1094 if (!GameObjectRespawnRelocation(go, false))
1095 {
1096 // ... or unload (if respawn grid also not loaded)
1097#ifdef SKYFIRE_DEBUG
1098 SF_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.", go->GetGUIDLow(), go->GetEntry());
1099#endif
1101 }
1102 }
1103 }
1104 _gameObjectsToMove.clear();
1105 _gameObjectsToMoveLock = false;
1106}
1107
1109{
1110 Cell const& old_cell = c->GetCurrentCell();
1111 if (!old_cell.DiffGrid(new_cell)) // in same grid
1112 {
1113 // if in same cell then none do
1114 if (old_cell.DiffCell(new_cell))
1115 {
1116#ifdef SKYFIRE_DEBUG
1117 SF_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
1118#endif
1119
1120 c->RemoveFromGrid();
1121 AddToGrid(c, new_cell);
1122 }
1123 else
1124 {
1125#ifdef SKYFIRE_DEBUG
1126 SF_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved in same grid[%u, %u]cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
1127#endif
1128 }
1129
1130 return true;
1131 }
1132
1133 // in diff. grids but active creature
1134 if (c->isActiveObject())
1135 {
1137
1138#ifdef SKYFIRE_DEBUG
1139 SF_LOG_DEBUG("maps", "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());
1140#endif
1141
1142 c->RemoveFromGrid();
1143 AddToGrid(c, new_cell);
1144
1145 return true;
1146 }
1147
1148 // in diff. loaded grid normal creature
1149 if (IsGridLoaded(GridCoord(new_cell.GridX(), new_cell.GridY())))
1150 {
1151#ifdef SKYFIRE_DEBUG
1152 SF_LOG_DEBUG("maps", "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());
1153#endif
1154
1155 c->RemoveFromGrid();
1156 EnsureGridCreated(GridCoord(new_cell.GridX(), new_cell.GridY()));
1157 AddToGrid(c, new_cell);
1158
1159 return true;
1160 }
1161
1162 // fail to move: normal creature attempt move to unloaded grid
1163#ifdef SKYFIRE_DEBUG
1164 SF_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) attempted to 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());
1165#endif
1166 return false;
1167}
1168
1170{
1171 Cell const& old_cell = go->GetCurrentCell();
1172 if (!old_cell.DiffGrid(new_cell)) // in same grid
1173 {
1174 // if in same cell then none do
1175 if (old_cell.DiffCell(new_cell))
1176 {
1177#ifdef SKYFIRE_DEBUG
1178 SF_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved in grid[%u, %u] from cell[%u, %u] to cell[%u, %u].", go->GetGUIDLow(), go->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
1179#endif
1180
1181 go->RemoveFromGrid();
1182 AddToGrid(go, new_cell);
1183 }
1184 else
1185 {
1186#ifdef SKYFIRE_DEBUG
1187 SF_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved in same grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
1188#endif
1189 }
1190
1191 return true;
1192 }
1193
1194 // in diff. grids but active GameObject
1195 if (go->isActiveObject())
1196 {
1197 EnsureGridLoadedForActiveObject(new_cell, go);
1198
1199#ifdef SKYFIRE_DEBUG
1200 SF_LOG_DEBUG("maps", "Active GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
1201#endif
1202
1203 go->RemoveFromGrid();
1204 AddToGrid(go, new_cell);
1205
1206 return true;
1207 }
1208
1209 // in diff. loaded grid normal GameObject
1210 if (IsGridLoaded(GridCoord(new_cell.GridX(), new_cell.GridY())))
1211 {
1212#ifdef SKYFIRE_DEBUG
1213 SF_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
1214#endif
1215
1216 go->RemoveFromGrid();
1217 EnsureGridCreated(GridCoord(new_cell.GridX(), new_cell.GridY()));
1218 AddToGrid(go, new_cell);
1219
1220 return true;
1221 }
1222
1223 // fail to move: normal GameObject attempt move to unloaded grid
1224#ifdef SKYFIRE_DEBUG
1225 SF_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) attempted to move from grid[%u, %u]cell[%u, %u] to unloaded grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->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());
1226#endif
1227 return false;
1228}
1229
1230bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly)
1231{
1232 float resp_x, resp_y, resp_z, resp_o;
1233 c->GetRespawnPosition(resp_x, resp_y, resp_z, &resp_o);
1234 Cell resp_cell(resp_x, resp_y);
1235
1236 //creature will be unloaded with grid
1237 if (diffGridOnly && !c->GetCurrentCell().DiffGrid(resp_cell))
1238 return true;
1239
1240 c->CombatStop();
1241 c->GetMotionMaster()->Clear();
1242
1243#ifdef SKYFIRE_DEBUG
1244 SF_LOG_DEBUG("maps", "Creature (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to respawn grid[%u, %u]cell[%u, %u].", c->GetGUIDLow(), c->GetEntry(), c->GetCurrentCell().GridX(), c->GetCurrentCell().GridY(), c->GetCurrentCell().CellX(), c->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
1245#endif
1246
1247 // teleport it to respawn point (like normal respawn if player see)
1248 if (CreatureCellRelocation(c, resp_cell))
1249 {
1250 c->Relocate(resp_x, resp_y, resp_z, resp_o);
1251 c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators
1252 //CreatureRelocationNotify(c, resp_cell, resp_cell.GetCellCoord());
1253 c->UpdateObjectVisibility(false);
1254 return true;
1255 }
1256
1257 return false;
1258}
1259
1261{
1262 float resp_x, resp_y, resp_z, resp_o;
1263 go->GetRespawnPosition(resp_x, resp_y, resp_z, &resp_o);
1264 Cell resp_cell(resp_x, resp_y);
1265
1266 //GameObject will be unloaded with grid
1267 if (diffGridOnly && !go->GetCurrentCell().DiffGrid(resp_cell))
1268 return true;
1269
1270#ifdef SKYFIRE_DEBUG
1271 SF_LOG_DEBUG("maps", "GameObject (GUID: %u Entry: %u) moved from grid[%u, %u]cell[%u, %u] to respawn grid[%u, %u]cell[%u, %u].", go->GetGUIDLow(), go->GetEntry(), go->GetCurrentCell().GridX(), go->GetCurrentCell().GridY(), go->GetCurrentCell().CellX(), go->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
1272#endif
1273
1274 // teleport it to respawn point (like normal respawn if player see)
1275 if (GameObjectCellRelocation(go, resp_cell))
1276 {
1277 go->Relocate(resp_x, resp_y, resp_z, resp_o);
1278 go->UpdateObjectVisibility(false);
1279 return true;
1280 }
1281
1282 return false;
1283}
1284
1285bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll)
1286{
1287 const uint32 x = ngrid.getX();
1288 const uint32 y = ngrid.getY();
1289
1290 {
1291 if (!unloadAll)
1292 {
1293 //pets, possessed creatures (must be active), transport passengers
1295 return false;
1296
1297 if (ActiveObjectsNearGrid(ngrid))
1298 return false;
1299 }
1300
1301 SF_LOG_DEBUG("maps", "Unloading grid[%u, %u] for map %u", x, y, GetId());
1302
1303 if (!unloadAll)
1304 {
1305 // Finish creature moves, remove and delete all creatures with delayed remove before moving to respawn grids
1306 // Must know real mob position before move
1309
1310 // move creatures to respawn grids if this is diff.grid or to remove list
1311 ObjectGridEvacuator worker;
1313 ngrid.VisitAllGrids(visitor);
1314
1315 // Finish creature moves, remove and delete all creatures with delayed remove before unload
1318 }
1319
1320 {
1321 ObjectGridCleaner worker;
1323 ngrid.VisitAllGrids(visitor);
1324 }
1325
1327
1328 {
1329 ObjectGridUnloader worker;
1331 ngrid.VisitAllGrids(visitor);
1332 }
1333
1334 ASSERT(i_objectsToRemove.empty());
1335
1336 delete& ngrid;
1337 setNGrid(NULL, x, y);
1338 }
1339 int gx = (MAX_NUMBER_OF_GRIDS - 1) - x;
1340 int gy = (MAX_NUMBER_OF_GRIDS - 1) - y;
1341
1342 // delete grid map, but don't delete if it is from parent map (and thus only reference)
1343 //+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps
1344 {
1345 if (i_InstanceId == 0)
1346 {
1347 if (GridMaps[gx][gy])
1348 {
1349 GridMaps[gx][gy]->unloadData();
1350 delete GridMaps[gx][gy];
1351 }
1354 }
1355 else
1356 ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy));
1357
1358 GridMaps[gx][gy] = NULL;
1359 }
1360 SF_LOG_DEBUG("maps", "Unloading grid[%u, %u] for map %u finished", x, y, GetId());
1361 return true;
1362}
1363
1365{
1366 if (HavePlayers())
1367 {
1368 for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
1369 {
1370 Player* player = itr->GetSource();
1371 if (!player->IsBeingTeleportedFar())
1372 {
1373 // this is happening for bg
1374 SF_LOG_ERROR("maps", "Map::UnloadAll: player %s is still in map %u during unload, this should not happen!", player->GetName().c_str(), GetId());
1375 player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->GetOrientation());
1376 }
1377 }
1378 }
1379}
1380
1382{
1383 // clear all delayed moves, useless anyway do this moves before map unload.
1384 _creaturesToMove.clear();
1385 _gameObjectsToMove.clear();
1386
1388 {
1389 NGridType& grid(*i->GetSource());
1390 ++i;
1391 UnloadGrid(grid, true); // deletes the grid and removes it from the GridRefManager
1392 }
1393}
1394
1395// *****************************
1396// Grid function
1397// *****************************
1398bool GridMap::loadData(char* filename)
1399{
1400 // Unload old data if exist
1401 unloadData();
1402
1403 map_fileheader header;
1404 // Not return error if file not found
1405 FILE* in = fopen(filename, "rb");
1406 if (!in)
1407 return true;
1408
1409 if (fread(&header, sizeof(header), 1, in) != 1)
1410 {
1411 fclose(in);
1412 return false;
1413 }
1414
1415 if (header.mapMagic.asUInt == MapMagic.asUInt && header.versionMagic.asUInt == MapVersionMagic.asUInt)
1416 {
1417 // load up area data
1418 if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize))
1419 {
1420 SF_LOG_ERROR("maps", "Error loading map area data\n");
1421 fclose(in);
1422 return false;
1423 }
1424 // load up height data
1425 if (header.heightMapOffset && !loadHeightData(in, header.heightMapOffset, header.heightMapSize))
1426 {
1427 SF_LOG_ERROR("maps", "Error loading map height data\n");
1428 fclose(in);
1429 return false;
1430 }
1431 // load up liquid data
1432 if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize))
1433 {
1434 SF_LOG_ERROR("maps", "Error loading map liquids data\n");
1435 fclose(in);
1436 return false;
1437 }
1438 fclose(in);
1439 return true;
1440 }
1441
1442 SF_LOG_ERROR("maps", "Map file '%s' is from an incompatible map version (%.*s %.*s), %.*s %.*s is expected. Please recreate using the mapextractor.",
1443 filename, 4, header.mapMagic.asChar, 4, header.versionMagic.asChar, 4, MapMagic.asChar, 4, MapVersionMagic.asChar);
1444 fclose(in);
1445 return false;
1446}
1447
1449{
1450 delete[] m_V9;
1451 delete[] m_V8;
1452 delete[] m_areaMap;
1453 delete[] m_liquidEntry;
1454 delete[] m_liquidFlags;
1455 delete[] m_liquidMap;
1456 m_V9 = NULL;
1457 m_V8 = NULL;
1458 m_areaMap = NULL;
1459 m_liquidEntry = NULL;
1460 m_liquidFlags = NULL;
1461 m_liquidMap = NULL;
1463}
1464
1465bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/)
1466{
1467 map_areaHeader header;
1468 fseek(in, offset, SEEK_SET);
1469
1470 if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapAreaMagic.asUInt)
1471 return false;
1472
1473 m_gridArea = header.gridArea;
1474 if (!(header.flags & MAP_AREA_NO_AREA))
1475 {
1476 m_areaMap = new uint16[16 * 16];
1477 if (fread(m_areaMap, sizeof(uint16), 16 * 16, in) != 16 * 16)
1478 return false;
1479 }
1480 return true;
1481}
1482
1483bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/)
1484{
1485 map_heightHeader header;
1486 fseek(in, offset, SEEK_SET);
1487
1488 if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapHeightMagic.asUInt)
1489 return false;
1490
1491 m_gridHeight = header.gridHeight;
1492 if (!(header.flags & MAP_HEIGHT_NO_HEIGHT))
1493 {
1494 if ((header.flags & MAP_HEIGHT_AS_INT16))
1495 {
1496 m_uint16_V9 = new uint16[129 * 129];
1497 m_uint16_V8 = new uint16[128 * 128];
1498 if (fread(m_uint16_V9, sizeof(uint16), 129 * 129, in) != 129 * 129 ||
1499 fread(m_uint16_V8, sizeof(uint16), 128 * 128, in) != 128 * 128)
1500 return false;
1501 m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;
1503 }
1504 else if ((header.flags & MAP_HEIGHT_AS_INT8))
1505 {
1506 m_uint8_V9 = new uint8[129 * 129];
1507 m_uint8_V8 = new uint8[128 * 128];
1508 if (fread(m_uint8_V9, sizeof(uint8), 129 * 129, in) != 129 * 129 ||
1509 fread(m_uint8_V8, sizeof(uint8), 128 * 128, in) != 128 * 128)
1510 return false;
1511 m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255;
1513 }
1514 else
1515 {
1516 m_V9 = new float[129 * 129];
1517 m_V8 = new float[128 * 128];
1518 if (fread(m_V9, sizeof(float), 129 * 129, in) != 129 * 129 ||
1519 fread(m_V8, sizeof(float), 128 * 128, in) != 128 * 128)
1520 return false;
1522 }
1523 }
1524 else
1526 return true;
1527}
1528
1529bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
1530{
1531 map_liquidHeader header;
1532 fseek(in, offset, SEEK_SET);
1533
1534 if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != MapLiquidMagic.asUInt)
1535 return false;
1536
1537 m_liquidType = header.liquidType;
1538 m_liquidOffX = header.offsetX;
1539 m_liquidOffY = header.offsetY;
1540 m_liquidWidth = header.width;
1541 m_liquidHeight = header.height;
1542 m_liquidLevel = header.liquidLevel;
1543
1544 if (!(header.flags & MAP_LIQUID_NO_TYPE))
1545 {
1546 m_liquidEntry = new uint16[16 * 16];
1547 if (fread(m_liquidEntry, sizeof(uint16), 16 * 16, in) != 16 * 16)
1548 return false;
1549
1550 m_liquidFlags = new uint8[16 * 16];
1551 if (fread(m_liquidFlags, sizeof(uint8), 16 * 16, in) != 16 * 16)
1552 return false;
1553 }
1554 if (!(header.flags & MAP_LIQUID_NO_HEIGHT))
1555 {
1557 if (fread(m_liquidMap, sizeof(float), m_liquidWidth * m_liquidHeight, in) != (uint32(m_liquidWidth) * uint32(m_liquidHeight)))
1558 return false;
1559 }
1560 return true;
1561}
1562
1563uint16 GridMap::getArea(float x, float y) const
1564{
1565 if (!m_areaMap)
1566 return m_gridArea;
1567
1568 x = 16 * (32 - x / SIZE_OF_GRIDS);
1569 y = 16 * (32 - y / SIZE_OF_GRIDS);
1570 int lx = (int)x & 15;
1571 int ly = (int)y & 15;
1572 return m_areaMap[lx * 16 + ly];
1573}
1574
1575float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const
1576{
1577 return m_gridHeight;
1578}
1579
1580float GridMap::getHeightFromFloat(float x, float y) const
1581{
1582 if (!m_V8 || !m_V9)
1583 return m_gridHeight;
1584
1585 x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
1586 y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
1587
1588 int x_int = (int)x;
1589 int y_int = (int)y;
1590 x -= x_int;
1591 y -= y_int;
1592 x_int &= (MAP_RESOLUTION - 1);
1593 y_int &= (MAP_RESOLUTION - 1);
1594
1595 // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
1596 // +--------------> X
1597 // | h1-------h2 Coordinates is:
1598 // | | \ 1 / | h1 0, 0
1599 // | | \ / | h2 0, 1
1600 // | | 2 h5 3 | h3 1, 0
1601 // | | / \ | h4 1, 1
1602 // | | / 4 \ | h5 1/2, 1/2
1603 // | h3-------h4
1604 // V Y
1605 // For find height need
1606 // 1 - detect triangle
1607 // 2 - solve linear equation from triangle points
1608 // Calculate coefficients for solve h = a*x + b*y + c
1609
1610 float a, b, c;
1611 // Select triangle:
1612 if (x + y < 1)
1613 {
1614 if (x > y)
1615 {
1616 // 1 triangle (h1, h2, h5 points)
1617 float h1 = m_V9[(x_int) * 129 + y_int];
1618 float h2 = m_V9[(x_int + 1) * 129 + y_int];
1619 float h5 = 2 * m_V8[x_int * 128 + y_int];
1620 a = h2 - h1;
1621 b = h5 - h1 - h2;
1622 c = h1;
1623 }
1624 else
1625 {
1626 // 2 triangle (h1, h3, h5 points)
1627 float h1 = m_V9[x_int * 129 + y_int];
1628 float h3 = m_V9[x_int * 129 + y_int + 1];
1629 float h5 = 2 * m_V8[x_int * 128 + y_int];
1630 a = h5 - h1 - h3;
1631 b = h3 - h1;
1632 c = h1;
1633 }
1634 }
1635 else
1636 {
1637 if (x > y)
1638 {
1639 // 3 triangle (h2, h4, h5 points)
1640 float h2 = m_V9[(x_int + 1) * 129 + y_int];
1641 float h4 = m_V9[(x_int + 1) * 129 + y_int + 1];
1642 float h5 = 2 * m_V8[x_int * 128 + y_int];
1643 a = h2 + h4 - h5;
1644 b = h4 - h2;
1645 c = h5 - h4;
1646 }
1647 else
1648 {
1649 // 4 triangle (h3, h4, h5 points)
1650 float h3 = m_V9[(x_int) * 129 + y_int + 1];
1651 float h4 = m_V9[(x_int + 1) * 129 + y_int + 1];
1652 float h5 = 2 * m_V8[x_int * 128 + y_int];
1653 a = h4 - h3;
1654 b = h3 + h4 - h5;
1655 c = h5 - h4;
1656 }
1657 }
1658 // Calculate height
1659 return a * x + b * y + c;
1660}
1661
1662float GridMap::getHeightFromUint8(float x, float y) const
1663{
1664 if (!m_uint8_V8 || !m_uint8_V9)
1665 return m_gridHeight;
1666
1667 x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
1668 y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
1669
1670 int x_int = (int)x;
1671 int y_int = (int)y;
1672 x -= x_int;
1673 y -= y_int;
1674 x_int &= (MAP_RESOLUTION - 1);
1675 y_int &= (MAP_RESOLUTION - 1);
1676
1677 int32 a, b, c;
1678 uint8* V9_h1_ptr = &m_uint8_V9[x_int * 128 + x_int + y_int];
1679 if (x + y < 1)
1680 {
1681 if (x > y)
1682 {
1683 // 1 triangle (h1, h2, h5 points)
1684 int32 h1 = V9_h1_ptr[0];
1685 int32 h2 = V9_h1_ptr[129];
1686 int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1687 a = h2 - h1;
1688 b = h5 - h1 - h2;
1689 c = h1;
1690 }
1691 else
1692 {
1693 // 2 triangle (h1, h3, h5 points)
1694 int32 h1 = V9_h1_ptr[0];
1695 int32 h3 = V9_h1_ptr[1];
1696 int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1697 a = h5 - h1 - h3;
1698 b = h3 - h1;
1699 c = h1;
1700 }
1701 }
1702 else
1703 {
1704 if (x > y)
1705 {
1706 // 3 triangle (h2, h4, h5 points)
1707 int32 h2 = V9_h1_ptr[129];
1708 int32 h4 = V9_h1_ptr[130];
1709 int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1710 a = h2 + h4 - h5;
1711 b = h4 - h2;
1712 c = h5 - h4;
1713 }
1714 else
1715 {
1716 // 4 triangle (h3, h4, h5 points)
1717 int32 h3 = V9_h1_ptr[1];
1718 int32 h4 = V9_h1_ptr[130];
1719 int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1720 a = h4 - h3;
1721 b = h3 + h4 - h5;
1722 c = h5 - h4;
1723 }
1724 }
1725 // Calculate height
1726 return (float)((a * x) + (b * y) + c) * m_gridIntHeightMultiplier + m_gridHeight;
1727}
1728
1729float GridMap::getHeightFromUint16(float x, float y) const
1730{
1731 if (!m_uint16_V8 || !m_uint16_V9)
1732 return m_gridHeight;
1733
1734 x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
1735 y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
1736
1737 int x_int = (int)x;
1738 int y_int = (int)y;
1739 x -= x_int;
1740 y -= y_int;
1741 x_int &= (MAP_RESOLUTION - 1);
1742 y_int &= (MAP_RESOLUTION - 1);
1743
1744 int32 a, b, c;
1745 uint16* V9_h1_ptr = &m_uint16_V9[x_int * 128 + x_int + y_int];
1746 if (x + y < 1)
1747 {
1748 if (x > y)
1749 {
1750 // 1 triangle (h1, h2, h5 points)
1751 int32 h1 = V9_h1_ptr[0];
1752 int32 h2 = V9_h1_ptr[129];
1753 int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1754 a = h2 - h1;
1755 b = h5 - h1 - h2;
1756 c = h1;
1757 }
1758 else
1759 {
1760 // 2 triangle (h1, h3, h5 points)
1761 int32 h1 = V9_h1_ptr[0];
1762 int32 h3 = V9_h1_ptr[1];
1763 int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1764 a = h5 - h1 - h3;
1765 b = h3 - h1;
1766 c = h1;
1767 }
1768 }
1769 else
1770 {
1771 if (x > y)
1772 {
1773 // 3 triangle (h2, h4, h5 points)
1774 int32 h2 = V9_h1_ptr[129];
1775 int32 h4 = V9_h1_ptr[130];
1776 int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1777 a = h2 + h4 - h5;
1778 b = h4 - h2;
1779 c = h5 - h4;
1780 }
1781 else
1782 {
1783 // 4 triangle (h3, h4, h5 points)
1784 int32 h3 = V9_h1_ptr[1];
1785 int32 h4 = V9_h1_ptr[130];
1786 int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1787 a = h4 - h3;
1788 b = h3 + h4 - h5;
1789 c = h5 - h4;
1790 }
1791 }
1792 // Calculate height
1793 return (float)((a * x) + (b * y) + c) * m_gridIntHeightMultiplier + m_gridHeight;
1794}
1795
1796float GridMap::getLiquidLevel(float x, float y) const
1797{
1798 if (!m_liquidMap)
1799 return m_liquidLevel;
1800
1801 x = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
1802 y = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
1803
1804 int cx_int = ((int)x & (MAP_RESOLUTION - 1)) - m_liquidOffY;
1805 int cy_int = ((int)y & (MAP_RESOLUTION - 1)) - m_liquidOffX;
1806
1807 if (cx_int < 0 || cx_int >= m_liquidHeight)
1808 return INVALID_HEIGHT;
1809 if (cy_int < 0 || cy_int >= m_liquidWidth)
1810 return INVALID_HEIGHT;
1811
1812 return m_liquidMap[cx_int * m_liquidWidth + cy_int];
1813}
1814
1815// Why does this return LIQUID data?
1816uint8 GridMap::getTerrainType(float x, float y) const
1817{
1818 if (!m_liquidFlags)
1819 return 0;
1820
1821 x = 16 * (32 - x / SIZE_OF_GRIDS);
1822 y = 16 * (32 - y / SIZE_OF_GRIDS);
1823 int lx = (int)x & 15;
1824 int ly = (int)y & 15;
1825 return m_liquidFlags[lx * 16 + ly];
1826}
1827
1828// Get water state on map
1829inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
1830{
1831 // Check water type (if no water return)
1832 if (!m_liquidType && !m_liquidFlags)
1833 return LIQUID_MAP_NO_WATER;
1834
1835 // Get cell
1836 float cx = MAP_RESOLUTION * (32 - x / SIZE_OF_GRIDS);
1837 float cy = MAP_RESOLUTION * (32 - y / SIZE_OF_GRIDS);
1838
1839 int x_int = (int)cx & (MAP_RESOLUTION - 1);
1840 int y_int = (int)cy & (MAP_RESOLUTION - 1);
1841
1842 // Check water type in cell
1843 int idx = (x_int >> 3) * 16 + (y_int >> 3);
1845 uint32 entry = 0;
1846 if (m_liquidEntry)
1847 {
1848 if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(m_liquidEntry[idx]))
1849 {
1850 entry = liquidEntry->Id;
1852 uint32 liqTypeIdx = liquidEntry->Type;
1853 if (entry < 21)
1854 {
1856 {
1857 uint32 overrideLiquid = area->m_LiquidType[liquidEntry->Type];
1858 if (!overrideLiquid && area->m_ParentAreaID)
1859 {
1860 area = GetAreaEntryByAreaID(area->m_ParentAreaID);
1861 if (area)
1862 overrideLiquid = area->m_LiquidType[liquidEntry->Type];
1863 }
1864
1865 if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
1866 {
1867 entry = overrideLiquid;
1868 liqTypeIdx = liq->Type;
1869 }
1870 }
1871 }
1872
1873 type |= 1 << liqTypeIdx;
1874 }
1875 }
1876
1877 if (type == 0)
1878 return LIQUID_MAP_NO_WATER;
1879
1880 // Check req liquid type mask
1881 if (ReqLiquidType && !(ReqLiquidType & type))
1882 return LIQUID_MAP_NO_WATER;
1883
1884 // Check water level:
1885 // Check water height map
1886 int lx_int = x_int - m_liquidOffY;
1887 int ly_int = y_int - m_liquidOffX;
1888 if (lx_int < 0 || lx_int >= m_liquidHeight)
1889 return LIQUID_MAP_NO_WATER;
1890 if (ly_int < 0 || ly_int >= m_liquidWidth)
1891 return LIQUID_MAP_NO_WATER;
1892
1893 // Get water level
1894 float liquid_level = m_liquidMap ? m_liquidMap[lx_int * m_liquidWidth + ly_int] : m_liquidLevel;
1895 // Get ground level (sub 0.2 for fix some errors)
1896 float ground_level = getHeight(x, y);
1897
1898 // Check water level and ground level
1899 if (liquid_level < ground_level || z < ground_level - 2)
1900 return LIQUID_MAP_NO_WATER;
1901
1902 // All ok in water -> store data
1903 if (data)
1904 {
1905 data->entry = entry;
1906 data->type_flags = type;
1907 data->level = liquid_level;
1908 data->depth_level = ground_level;
1909 }
1910
1911 // For speed check as int values
1912 float delta = liquid_level - z;
1913
1914 if (delta > 2.0f) // Under water
1916 if (delta > 0.0f) // In water
1917 return LIQUID_MAP_IN_WATER;
1918 if (delta > -0.1f) // Walk on water
1919 return LIQUID_MAP_WATER_WALK;
1920 // Above water
1922}
1923
1924inline GridMap* Map::GetGrid(float x, float y)
1925{
1926 if (!Skyfire::IsValidMapCoord(x, y))
1927 return NULL;
1928
1929 GridCoord const gridCoord = Skyfire::ComputeGridCoord(x, y);
1930 if (!gridCoord.IsCoordValid())
1931 return NULL;
1932
1933 int const gx = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.x_coord;
1934 int const gy = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.y_coord;
1935
1936 EnsureGridCreated(gridCoord);
1937
1938 return GridMaps[gx][gy];
1939}
1940
1941float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool /*swim = false*/) const
1942{
1943 if (const_cast<Map*>(this)->GetGrid(x, y))
1944 {
1945 // we need ground level (including grid height version) for proper return water level in point
1946 float ground_z = GetHeight(PHASEMASK_NORMAL, x, y, z, true, 50.0f);
1947 if (ground)
1948 *ground = ground_z;
1949
1950 LiquidData liquid_status;
1951
1952 ZLiquidStatus res = getLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status);
1953 return res ? liquid_status.level : ground_z;
1954 }
1955
1957}
1958
1959float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const
1960{
1961 // find raw .map surface under Z coordinates
1962 float mapHeight = VMAP_INVALID_HEIGHT_VALUE;
1963 if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1964 {
1965 float gridHeight = gmap->getHeight(x, y);
1966 // look from a bit higher pos to find the floor, ignore under surface case
1967 if (z + 2.0f > gridHeight)
1968 mapHeight = gridHeight;
1969 }
1970
1971 float vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
1972 if (checkVMap)
1973 {
1975 if (vmgr->isHeightCalcEnabled())
1976 vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor
1977 }
1978
1979 // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
1980 // vmapheight set for any under Z value or <= INVALID_HEIGHT
1981 if (vmapHeight > INVALID_HEIGHT)
1982 {
1983 if (mapHeight > INVALID_HEIGHT)
1984 {
1985 // we have mapheight and vmapheight and must select more appropriate
1986
1987 // we are already under the surface or vmap height above map heigt
1988 // or if the distance of the vmap height is less the land height distance
1989 if (z < mapHeight || vmapHeight > mapHeight || fabs(mapHeight - z) > fabs(vmapHeight - z))
1990 return vmapHeight;
1991 else
1992 return mapHeight; // better use .map surface height
1993 }
1994 else
1995 return vmapHeight; // we have only vmapHeight (if have)
1996 }
1997
1998 return mapHeight; // explicitly use map data
1999}
2000
2001inline bool IsOutdoorWMO(uint32 mogpFlags, int32 /*adtId*/, int32 /*rootId*/, int32 /*groupId*/, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry)
2002{
2003 bool outdoor = true;
2004
2005 if (wmoEntry && atEntry)
2006 {
2007 if (atEntry->m_flags & AREA_FLAG_OUTSIDE)
2008 return true;
2009 if (atEntry->m_flags & AREA_FLAG_INSIDE)
2010 return false;
2011 }
2012
2013 outdoor = mogpFlags & 0x8;
2014
2015 if (wmoEntry)
2016 {
2017 if (wmoEntry->Flags & 4)
2018 return true;
2019 if ((wmoEntry->Flags & 2) != 0)
2020 outdoor = false;
2021 }
2022 return outdoor;
2023}
2024
2025bool Map::IsOutdoors(float x, float y, float z) const
2026{
2027 uint32 mogpFlags;
2028 int32 adtId, rootId, groupId;
2029
2030 // no wmo found? -> outside by default
2031 if (!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
2032 return true;
2033
2034 AreaTableEntry const* atEntry = 0;
2035 WMOAreaTableEntry const* wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId);
2036 if (wmoEntry)
2037 {
2038 SF_LOG_DEBUG("maps", "Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId);
2039 atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
2040 }
2041 return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
2042}
2043
2044bool Map::GetAreaInfo(float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
2045{
2046 float vmap_z = z;
2048 if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId))
2049 {
2050 // check if there's terrain between player height and object height
2051 if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
2052 {
2053 float _mapheight = gmap->getHeight(x, y);
2054 // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
2055 if (z + 2.0f > _mapheight && _mapheight > vmap_z)
2056 return false;
2057 }
2058 return true;
2059 }
2060 return false;
2061}
2062
2063uint16 Map::GetAreaFlag(float x, float y, float z, bool* isOutdoors) const
2064{
2065 uint32 mogpFlags;
2066 int32 adtId, rootId, groupId;
2067 WMOAreaTableEntry const* wmoEntry = 0;
2068 AreaTableEntry const* atEntry = 0;
2069 bool haveAreaInfo = false;
2070
2071 if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
2072 {
2073 haveAreaInfo = true;
2074 wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId);
2075 if (wmoEntry)
2076 atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
2077 }
2078
2079 uint16 areaflag;
2080
2081 if (atEntry)
2082 areaflag = atEntry->m_AreaBit;
2083 else
2084 {
2085 if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
2086 areaflag = gmap->getArea(x, y);
2087 // this used while not all *.map files generated (instances)
2088 else
2089 areaflag = GetAreaFlagByMapId(i_mapEntry->MapID);
2090 }
2091
2092 if (isOutdoors)
2093 {
2094 if (haveAreaInfo)
2095 *isOutdoors = IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry);
2096 else
2097 *isOutdoors = true;
2098 }
2099 return areaflag;
2100}
2101
2102uint8 Map::GetTerrainType(float x, float y) const
2103{
2104 if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
2105 return gmap->getTerrainType(x, y);
2106 else
2107 return 0;
2108}
2109
2110ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const
2111{
2114 float liquid_level = INVALID_HEIGHT;
2115 float ground_level = INVALID_HEIGHT;
2116 uint32 liquid_type = 0;
2117 if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type))
2118 {
2119 SF_LOG_DEBUG("maps", "getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type);
2120 // Check water level and ground level
2121 if (liquid_level > ground_level && z > ground_level - 2)
2122 {
2123 // All ok in water -> store data
2124 if (data)
2125 {
2126 // hardcoded in client like this
2127 if (GetId() == 530 && liquid_type == 2)
2128 liquid_type = 15;
2129
2130 uint32 liquidFlagType = 0;
2131 if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquid_type))
2132 liquidFlagType = liq->Type;
2133
2134 if (liquid_type && liquid_type < 21)
2135 {
2136 if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(GetAreaFlag(x, y, z), GetId()))
2137 {
2138 uint32 overrideLiquid = area->m_LiquidType[liquidFlagType];
2139 if (!overrideLiquid && area->m_ParentAreaID)
2140 {
2141 area = GetAreaEntryByAreaID(area->m_ParentAreaID);
2142 if (area)
2143 overrideLiquid = area->m_LiquidType[liquidFlagType];
2144 }
2145
2146 if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
2147 {
2148 liquid_type = overrideLiquid;
2149 liquidFlagType = liq->Type;
2150 }
2151 }
2152 }
2153
2154 data->level = liquid_level;
2155 data->depth_level = ground_level;
2156
2157 data->entry = liquid_type;
2158 data->type_flags = 1 << liquidFlagType;
2159 }
2160
2161 float delta = liquid_level - z;
2162
2163 // Get position delta
2164 if (delta > 2.0f) // Under water
2166 if (delta > 0.0f) // In water
2167 return LIQUID_MAP_IN_WATER;
2168 if (delta > -0.1f) // Walk on water
2169 return LIQUID_MAP_WATER_WALK;
2170 result = LIQUID_MAP_ABOVE_WATER;
2171 }
2172 }
2173
2174 if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
2175 {
2176 LiquidData map_data;
2177 ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data);
2178 // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
2179 if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
2180 {
2181 if (data)
2182 {
2183 // hardcoded in client like this
2184 if (GetId() == 530 && map_data.entry == 2)
2185 map_data.entry = 15;
2186
2187 *data = map_data;
2188 }
2189 return map_result;
2190 }
2191 }
2192 return result;
2193}
2194
2195float Map::GetWaterLevel(float x, float y) const
2196{
2197 if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
2198 return gmap->getLiquidLevel(x, y);
2199 else
2200 return 0;
2201}
2202
2204{
2205 AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
2206
2207 if (entry)
2208 return entry->m_ID;
2209 else
2210 return 0;
2211}
2212
2214{
2215 AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
2216
2217 if (entry)
2218 return (entry->m_ParentAreaID != 0) ? entry->m_ParentAreaID : entry->m_ID;
2219 else
2220 return 0;
2221}
2222
2224{
2225 AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
2226
2227 areaid = entry ? entry->m_ID : 0;
2228 zoneid = entry ? ((entry->m_ParentAreaID != 0) ? entry->m_ParentAreaID : entry->m_ID) : 0;
2229}
2230
2231bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
2232{
2233 return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
2234 && _dynamicTree.isInLineOfSight(x1, y1, z1, x2, y2, z2, phasemask);
2235}
2236
2237bool Map::getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
2238{
2239 G3D::Vector3 startPos(x1, y1, z1);
2240 G3D::Vector3 dstPos(x2, y2, z2);
2241
2242 G3D::Vector3 resultPos;
2243 bool result = _dynamicTree.getObjectHitPos(phasemask, startPos, dstPos, resultPos, modifyDist);
2244
2245 rx = resultPos.x;
2246 ry = resultPos.y;
2247 rz = resultPos.z;
2248 return result;
2249}
2250
2251float Map::GetHeight(uint32 phasemask, float x, float y, float z, bool vmap/*=true*/, float maxSearchDist/*=DEFAULT_HEIGHT_SEARCH*/) const
2252{
2253 return std::max<float>(GetHeight(x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phasemask));
2254}
2255
2256bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const
2257{
2258 LiquidData liquid_status;
2259 LiquidData* liquid_ptr = data ? data : &liquid_status;
2261}
2262
2263bool Map::IsUnderWater(float x, float y, float z) const
2264{
2266}
2267
2268bool Map::CheckGridIntegrity(Creature* c, bool moved) const
2269{
2270 Cell const& cur_cell = c->GetCurrentCell();
2271 Cell xy_cell(c->GetPositionX(), c->GetPositionY());
2272 if (xy_cell != cur_cell)
2273 {
2274 SF_LOG_DEBUG("maps", "Creature (GUID: %u) X: %f Y: %f (%s) is in grid[%u, %u]cell[%u, %u] instead of grid[%u, %u]cell[%u, %u]",
2275 c->GetGUIDLow(),
2276 c->GetPositionX(), c->GetPositionY(), (moved ? "final" : "original"),
2277 cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(),
2278 xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY());
2279 return true; // not crash at error, just output error in debug mode
2280 }
2281
2282 return true;
2283}
2284
2285char const* Map::GetMapName() const
2286{
2287 return i_mapEntry ? i_mapEntry->name : "UNNAMEDMAP\x0";
2288}
2289
2291{
2292 cell.SetNoCreate();
2293 Skyfire::VisibleChangesNotifier notifier(*obj);
2295 cell.Visit(cellpair, player_notifier, *this, *obj, obj->GetVisibilityRange());
2296}
2297
2299{
2300 Skyfire::VisibleNotifier notifier(*player);
2301
2302 cell.SetNoCreate();
2305 cell.Visit(cellpair, world_notifier, *this, *player, player->GetSightRange());
2306 cell.Visit(cellpair, grid_notifier, *this, *player, player->GetSightRange());
2307
2308 // send data
2309 notifier.SendToSelf();
2310}
2311
2313{
2314 SF_LOG_INFO("maps", "Creating player data for himself %u", player->GetGUIDLow());
2315
2316 UpdateData data(player->GetMapId());
2317
2318 // attach to player data current transport data
2319 if (Transport* transport = player->GetTransport())
2320 {
2321 transport->BuildCreateUpdateBlockForPlayer(&data, player);
2322 }
2323
2324 // build data for self presence in world at own client (one time for map)
2325 player->BuildCreateUpdateBlockForPlayer(&data, player);
2326
2327 // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
2328 if (Transport* transport = player->GetTransport())
2329 {
2330 for (std::set<WorldObject*>::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
2331 {
2332 if (player != (*itr) && player->HaveAtClient(*itr))
2333 {
2334 (*itr)->BuildCreateUpdateBlockForPlayer(&data, player);
2335 }
2336 }
2337 }
2338
2339 WorldPacket packet;
2340 data.BuildPacket(&packet);
2341 player->GetSession()->SendPacket(&packet);
2342}
2343
2345{
2346 // Hack to send out transports
2347 UpdateData transData(player->GetMapId());
2348 for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i)
2349 {
2350 if (*i != player->GetTransport())
2351 {
2352 (*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
2353 player->m_clientGUIDs.insert((*i)->GetGUID());
2354 }
2355 }
2356
2357 WorldPacket packet;
2358 transData.BuildPacket(&packet);
2359 player->GetSession()->SendPacket(&packet);
2360}
2361
2363{
2364 // Hack to send out transports
2365 UpdateData transData(player->GetMapId());
2366 for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i)
2367 if (*i != player->GetTransport())
2368 (*i)->BuildOutOfRangeUpdateBlock(&transData);
2369
2370 WorldPacket packet;
2371 transData.BuildPacket(&packet);
2372 player->GetSession()->SendPacket(&packet);
2373}
2374
2375void Map::PreserveTransportVisibility(std::set<uint64>& guids) const
2376{
2377 for (TransportsContainer::const_iterator itr = _transports.begin(); itr != _transports.end(); ++itr)
2378 guids.erase((*itr)->GetGUID());
2379}
2380
2381inline void Map::setNGrid(NGridType* grid, uint32 x, uint32 y)
2382{
2384 {
2385 SF_LOG_ERROR("maps", "map::setNGrid() Invalid grid coordinates found: %d, %d!", x, y);
2386 ASSERT(false);
2387 }
2388 i_grids[x][y] = grid;
2389}
2390
2391void Map::DelayedUpdate(const uint32 t_diff)
2392{
2394
2395 // 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 !
2396 // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
2397 if (!IsBattlegroundOrArena())
2398 {
2400 {
2401 NGridType* grid = i->GetSource();
2402 GridInfo* info = i->GetSource()->getGridInfoRef();
2403 ++i; // The update might delete the map and we need the next map before the iterator gets invalid
2404 ASSERT(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
2405 si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, t_diff);
2406 }
2407 }
2408}
2409
2411{
2412 ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2413
2414 obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links
2415
2419 i_objectsToRemove.insert(obj);
2420
2421 //SF_LOG_DEBUG("maps", "Object (GUID: %u TypeId: %u) added to removing list.", obj->GetGUIDLow(), obj->GetTypeId());
2422}
2423
2425{
2426 ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2427
2428 bool const supportedObjectType = obj->GetTypeId() == TypeID::TYPEID_UNIT ||
2430 std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.find(obj);
2432 supportedObjectType,
2433 itr != i_objectsToSwitch.end(),
2434 itr != i_objectsToSwitch.end() && itr->second,
2435 on);
2436
2438 return;
2439
2441 i_objectsToSwitch.insert(itr, std::make_pair(obj, on));
2443 i_objectsToSwitch.erase(itr);
2444 else
2445 ASSERT(false);
2446}
2447
2449{
2450 while (!i_objectsToSwitch.empty())
2451 {
2452 std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.begin();
2453 WorldObject* obj = itr->first;
2454 bool on = itr->second;
2455 i_objectsToSwitch.erase(itr);
2456
2457 if (!obj->IsPermanentWorldObject())
2458 {
2459 switch (obj->GetTypeId())
2460 {
2463 break;
2466 break;
2467 default:
2468 break;
2469 }
2470 }
2471 }
2472
2473 //SF_LOG_DEBUG("maps", "Object remover 1 check.");
2474 while (!i_objectsToRemove.empty())
2475 {
2476 std::set<WorldObject*>::iterator itr = i_objectsToRemove.begin();
2477 WorldObject* obj = *itr;
2478
2479 switch (obj->GetTypeId())
2480 {
2482 {
2483 Corpse* corpse = ObjectAccessor::GetCorpse(*obj, obj->GetGUID());
2484 if (!corpse)
2485 SF_LOG_ERROR("maps", "Tried to delete corpse/bones %u that is not in map.", obj->GetGUIDLow());
2486 else
2487 RemoveFromMap(corpse, true);
2488 break;
2489 }
2491 RemoveFromMap((DynamicObject*)obj, true);
2492 break;
2494 RemoveFromMap((AreaTrigger*)obj, true);
2495 break;
2497 RemoveFromMap((GameObject*)obj, true);
2498 break;
2500 // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call
2501 // make sure that like sources auras/etc removed before destructor start
2503 RemoveFromMap(obj->ToCreature(), true);
2504 break;
2505 default:
2506 SF_LOG_ERROR("maps", "Non-grid object (TypeId: %u) is in grid object remove list, ignored.", uint8(obj->GetTypeId()));
2507 break;
2508 }
2509
2510 i_objectsToRemove.erase(itr);
2511 }
2512
2513 //SF_LOG_DEBUG("maps", "Object remover 2 check.");
2514}
2515
2517{
2518 uint32 count = 0;
2519 for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2520 if (!itr->GetSource()->IsGameMaster())
2521 ++count;
2522 return count;
2523}
2524
2525void Map::SendToPlayers(WorldPacket const* data) const
2526{
2527 for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2528 itr->GetSource()->GetSession()->SendPacket(data);
2529}
2530
2532{
2533 CellCoord cell_min(ngrid.getX() * MAX_NUMBER_OF_CELLS, ngrid.getY() * MAX_NUMBER_OF_CELLS);
2534 CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord + MAX_NUMBER_OF_CELLS);
2535
2536 //we must find visible range in cells so we unload only non-visible cells...
2537 float viewDist = GetVisibilityRange();
2538 int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1;
2539
2540 cell_min.dec_x(cell_range);
2541 cell_min.dec_y(cell_range);
2542 cell_max.inc_x(cell_range);
2543 cell_max.inc_y(cell_range);
2544
2545 for (MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
2546 {
2547 Player* player = iter->GetSource();
2548
2550 if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2551 (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2552 return true;
2553 }
2554
2555 for (ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter)
2556 {
2557 WorldObject* obj = *iter;
2558
2560 if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2561 (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2562 return true;
2563 }
2564
2565 return false;
2566}
2567
2568template<class T>
2570{
2571 AddToActiveHelper(obj);
2572}
2573
2574template <>
2576{
2578
2579 // also not allow unloading spawn grid to prevent creating creature clone at load
2580 if (!c->IsPet() && c->GetDBTableGUIDLow())
2581 {
2582 float x, y, z;
2583 c->GetRespawnPosition(x, y, z);
2585 if (!p.IsCoordValid())
2586 {
2587 SF_LOG_ERROR("maps", "Active creature (GUID: %u Entry: %u) has invalid respawn coordinates X:%f Y:%f Z:%f",
2588 c->GetGUIDLow(), c->GetEntry(), x, y, z);
2589 return;
2590 }
2591
2592 if (getNGrid(p.x_coord, p.y_coord))
2594 else
2595 {
2597 SF_LOG_ERROR("maps", "Active creature (GUID: %u Entry: %u) added to grid[%u, %u] but spawn grid[%u, %u] was not loaded.",
2598 c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2599 }
2600 }
2601}
2602
2603template<>
2608
2609template<class T>
2610void Map::RemoveFromActive(T* /*obj*/) { }
2611
2612template <>
2614{
2616
2617 // also allow unloading spawn grid
2618 if (!c->IsPet() && c->GetDBTableGUIDLow())
2619 {
2620 float x, y, z;
2621 c->GetRespawnPosition(x, y, z);
2623 if (!p.IsCoordValid())
2624 {
2625 SF_LOG_ERROR("maps", "Active creature (GUID: %u Entry: %u) has invalid respawn coordinates X:%f Y:%f Z:%f",
2626 c->GetGUIDLow(), c->GetEntry(), x, y, z);
2627 return;
2628 }
2629
2630 if (getNGrid(p.x_coord, p.y_coord))
2632 else
2633 {
2635 SF_LOG_ERROR("maps", "Active creature (GUID: %u Entry: %u) removed from grid[%u, %u] but spawn grid[%u, %u] was not loaded.",
2636 c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2637 }
2638 }
2639}
2640
2641template<>
2646
2647template bool Map::AddToMap(Corpse*);
2648template bool Map::AddToMap(Creature*);
2649template bool Map::AddToMap(GameObject*);
2650template bool Map::AddToMap(DynamicObject*);
2651template bool Map::AddToMap(AreaTrigger*);
2652
2653template void Map::RemoveFromMap(Corpse*, bool);
2654template void Map::RemoveFromMap(Creature*, bool);
2655template void Map::RemoveFromMap(GameObject*, bool);
2656template void Map::RemoveFromMap(DynamicObject*, bool);
2657template void Map::RemoveFromMap(AreaTrigger*, bool);
2658
2659/* ******* Dungeon Instance Maps ******* */
2660
2661InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
2662 : Map(id, expiry, InstanceId, SpawnMode, _parent),
2664 i_data(NULL), i_script_id(0)
2665{
2666 //lets initialize visibility distance for dungeons
2668
2669 // the timer is started by default, and stopped when the first player joins
2670 // this make sure it gets unloaded if for some reason no player joins
2672}
2673
2675{
2676 delete i_data;
2677 i_data = NULL;
2678}
2679
2686
2687/*
2688 Do map specific checks to see if the player can enter
2689*/
2691{
2692 if (player->GetMapRef().getTarget() == this)
2693 {
2694 if (player->IsBeingForcedTeleportFar())
2695 return Map::CanEnter(player);
2696
2697 SF_LOG_ERROR("maps", "InstanceMap::CanEnter - player %s(%u) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
2698 ASSERT(false);
2699 return false;
2700 }
2701
2702 // allow GM's to enter
2703 if (player->IsGameMaster())
2704 return Map::CanEnter(player);
2705
2706 // cannot enter if the instance is full (player cap), GMs don't count
2707 uint32 maxPlayers = GetMaxPlayers();
2708 if (GetPlayersCountExceptGMs() >= maxPlayers)
2709 {
2710 SF_LOG_INFO("maps", "MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName().c_str());
2712 return false;
2713 }
2714
2715 // cannot enter while an encounter is in progress on raids
2716 /*Group* group = player->GetGroup();
2717 if (!player->IsGameMaster() && group && group->InCombatToInstance(GetInstanceId()) && player->GetMapId() != GetId())*/
2718 if (IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress())
2719 {
2721 return false;
2722 }
2723
2724 // cannot enter if instance is in use by another party/soloer that have a
2725 // permanent save in the same instance id
2726
2727 PlayerList const& playerList = GetPlayers();
2728
2729 if (!playerList.isEmpty())
2730 for (PlayerList::const_iterator i = playerList.begin(); i != playerList.end(); ++i)
2731 if (Player* iPlayer = i->GetSource())
2732 {
2733 if (iPlayer->IsGameMaster()) // bypass GMs
2734 continue;
2735 if (!player->GetGroup()) // player has not group and there is someone inside, deny entry
2736 {
2738 return false;
2739 }
2740 // player inside instance has no group or his groups is different to entering player's one, deny entry
2741 if (!iPlayer->GetGroup() || iPlayer->GetGroup() != player->GetGroup())
2742 {
2744 return false;
2745 }
2746 break;
2747 }
2748
2749 return Map::CanEnter(player);
2750}
2751
2752/*
2753 Do map specific checks and add the player to the map if successful.
2754*/
2756{
2758 // GMs still can teleport player in instance.
2759 // Is it needed?
2760
2761 {
2762 std::lock_guard<std::mutex> guard(Lock);
2763 // Check moved to void WorldSession::HandleMoveWorldportAckOpcode()
2764 //if (!CanEnter(player))
2765 //return false;
2766
2767 // Dungeon only code
2768 if (IsInstance())
2769 {
2770 Group* group = player->GetGroup();
2771
2772 // increase current instances (hourly limit)
2773 if (!group || !group->isLFGGroup())
2774 player->AddInstanceEnterTime(GetInstanceId(), time(NULL));
2775
2776 // get or create an instance save for the map
2777 InstanceSave* mapSave = sInstanceSaveMgr->GetInstanceSave(GetInstanceId());
2778 if (!mapSave)
2779 {
2780 SF_LOG_INFO("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
2781 mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), DifficultyID(GetSpawnMode()), 0, true);
2782 }
2783
2784 ASSERT(mapSave);
2785
2786 // check for existing instance binds
2788 if (playerBind && playerBind->perm)
2789 {
2790 // cannot enter other instances if bound permanently
2791 if (playerBind->save != mapSave)
2792 {
2793 SF_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset());
2794 return false;
2795 }
2796 }
2797 else
2798 {
2799 if (group)
2800 {
2801 // solo saves should be reset when entering a group
2802 InstanceGroupBind* groupBind = group->GetBoundInstance(this);
2803 if (playerBind && playerBind->save != mapSave)
2804 {
2805 SF_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %d and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(group->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
2806 if (groupBind)
2807 SF_LOG_ERROR("maps", "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
2808 //ASSERT(false);
2809 return false;
2810 }
2811 // bind to the group or keep using the group save
2812 if (!groupBind)
2813 group->BindToInstance(mapSave, false);
2814 else
2815 {
2816 // cannot jump to a different instance without resetting it
2817 if (groupBind->save != mapSave)
2818 {
2819 SF_LOG_ERROR("maps", "InstanceMap::Add: player %s(%d) is being put into instance %d, %d, %d but he is in group %d which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(group->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty());
2820 SF_LOG_ERROR("maps", "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount());
2821 if (groupBind->save)
2822 SF_LOG_ERROR("maps", "GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
2823 else
2824 SF_LOG_ERROR("maps", "GroupBind save NULL");
2825 return false;
2826 }
2827 // if the group/leader is permanently bound to the instance
2828 // players also become permanently bound when they enter
2829 if (groupBind->perm)
2830 {
2832 data << uint32(60000);
2833 data << uint32(i_data ? i_data->GetCompletedEncounterMask() : 0);
2834 data.WriteBit(0); // events it throws: 1 : INSTANCE_LOCK_WARNING 0 : INSTANCE_LOCK_STOP / INSTANCE_LOCK_START
2835 data.WriteBit(0);
2836 data.FlushBits();
2837 player->GetSession()->SendPacket(&data);
2838 player->SetPendingBind(mapSave->GetInstanceId(), 60000);
2839 }
2840 }
2841 }
2842 else
2843 {
2844 // set up a solo bind or continue using it
2845 if (!playerBind)
2846 player->BindToInstance(mapSave, false);
2847 else
2848 // cannot jump to a different instance without resetting it
2849 ASSERT(playerBind->save == mapSave);
2850 }
2851 }
2852 }
2853
2854 // for normal instances cancel the reset schedule when the
2855 // first player enters (no players yet)
2856 SetResetSchedule(false);
2857
2858 SF_LOG_INFO("maps", "MAP: Player '%s' entered instance '%u' of map '%s'", player->GetName().c_str(), GetInstanceId(), GetMapName());
2859 // initialize unload state
2860 m_unloadTimer = 0;
2861 m_resetAfterUnload = false;
2862 m_unloadWhenEmpty = false;
2863 }
2864
2865 // this will acquire the same mutex so it cannot be in the previous block
2866 Map::AddPlayerToMap(player);
2867
2868 if (i_data)
2869 i_data->OnPlayerEnter(player);
2870
2871 return true;
2872}
2873
2874void InstanceMap::Update(const uint32 t_diff)
2875{
2876 Map::Update(t_diff);
2877
2878 if (i_data)
2879 i_data->Update(t_diff);
2880}
2881
2883{
2884 SF_LOG_INFO("maps", "MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to another map", player->GetName().c_str(), GetInstanceId(), GetMapName());
2885 //if last player set unload timer
2886 if (!m_unloadTimer && m_mapRefManager.getSize() == 1)
2888 Map::RemovePlayerFromMap(player, remove);
2889 // for normal instances schedule the reset after all players have left
2890 SetResetSchedule(true);
2891}
2892
2894{
2895 if (i_data != NULL)
2896 return;
2897
2898 InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(GetId());
2899 if (mInstance)
2900 {
2901 i_script_id = mInstance->ScriptId;
2902 i_data = sScriptMgr->CreateInstanceData(this);
2903 }
2904
2905 if (!i_data)
2906 return;
2907
2908 i_data->Initialize();
2909
2910 if (load)
2911 {
2913 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_INSTANCE);
2914 stmt->setUInt16(0, uint16(GetId()));
2915 stmt->setUInt32(1, i_InstanceId);
2916 PreparedQueryResult result = CharacterDatabase.Query(stmt);
2917
2918 if (result)
2919 {
2920 Field* fields = result->Fetch();
2921 std::string data = fields[0].GetString();
2922 i_data->SetCompletedEncountersMask(fields[1].GetUInt32());
2923 if (data != "")
2924 {
2925 SF_LOG_DEBUG("maps", "Loading instance data for `%s` with id %u", sObjectMgr->GetScriptName(i_script_id), i_InstanceId);
2926 i_data->Load(data.c_str());
2927 }
2928 }
2929 }
2930}
2931
2932/*
2933 Returns true if there are no players in the instance
2934*/
2936{
2937 // note: since the map may not be loaded when the instance needs to be reset
2938 // the instance must be deleted from the DB by InstanceSaveManager
2939
2940 if (HavePlayers())
2941 {
2943 {
2944 // notify the players to leave the instance so it can be reset
2945 for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2946 itr->GetSource()->SendResetFailedNotify(GetId());
2947 }
2948 else
2949 {
2951 // set the homebind timer for players inside (1 minute)
2952 for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2953 itr->GetSource()->m_InstanceValid = false;
2954
2955 // the unload timer is not started
2956 // instead the map will unload immediately after the players have left
2957 m_unloadWhenEmpty = true;
2958 m_resetAfterUnload = true;
2959 }
2960 }
2961 else
2962 {
2963 // unloaded at next update
2965 m_resetAfterUnload = true;
2966 }
2967
2968 return m_mapRefManager.isEmpty();
2969}
2970
2972{
2973 if (!IsInstance())
2974 return;
2975
2976 InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(GetInstanceId());
2977 if (!save)
2978 {
2979 SF_LOG_ERROR("maps", "Cannot bind player (GUID: %u, Name: %s), because no instance save is available for instance map (Name: %s, Entry: %u, InstanceId: %u)!", source->GetGUIDLow(), source->GetName().c_str(), source->GetMap()->GetMapName(), source->GetMapId(), GetInstanceId());
2980 return;
2981 }
2982
2983 Group* group = source->GetGroup();
2984 // group members outside the instance group don't get bound
2985 for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2986 {
2987 Player* player = itr->GetSource();
2988 // players inside an instance cannot be bound to other instances
2989 // some players may already be permanently bound, in this case nothing happens
2990 InstancePlayerBind* bind = player->GetBoundInstance(save->GetMapId(), save->GetDifficulty());
2991 if (!bind || !bind->perm)
2992 {
2993 player->BindToInstance(save, true);
2995 data.WriteBit(player->IsGameMaster()); // isGM?
2996 data.FlushBits();
2997 player->GetSession()->SendPacket(&data);
2998
2999 player->GetSession()->SendCalendarRaidLockout(save, true);
3000 }
3001
3002 // if the leader is not in the instance the group will not get a perm bind
3003 if (group && group->GetLeaderGUID() == player->GetGUID())
3004 group->BindToInstance(save, true);
3005 }
3006}
3007
3009{
3010 ASSERT(!HavePlayers());
3011
3012 if (m_resetAfterUnload == true)
3014
3016}
3017
3019{
3020 for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
3021 itr->GetSource()->SendInstanceResetWarning(GetId(), itr->GetSource()->GetDifficulty(GetEntry()), timeLeft);
3022}
3023
3025{
3026 // only for normal instances
3027 // the reset time is only scheduled when there are no payers inside
3028 // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
3030 {
3031 if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(GetInstanceId()))
3032 sInstanceSaveMgr->ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), DifficultyID(GetSpawnMode()), GetInstanceId()));
3033 else
3034 SF_LOG_ERROR("maps", "InstanceMap::SetResetSchedule: cannot turn schedule %s, there is no save information for instance (map [id: %u, name: %s], instance id: %u, difficulty: %u)",
3035 on ? "on" : "off", GetId(), GetMapName(), GetInstanceId(), DifficultyID(GetSpawnMode()));
3036 }
3037}
3038
3043
3044bool Map::IsHeroic() const
3045{
3046 if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(i_spawnMode))
3047 {
3048 switch (i_spawnMode)
3049 {
3052 case DIFFICULTY_HEROIC:
3054 return true;
3055 default:
3056 return false;
3057 break;
3058 }
3059 }
3060 return false;
3061}
3062
3064{
3065 if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(i_spawnMode))
3066 {
3067 switch (i_spawnMode)
3068 {
3072 return true;
3073 default:
3074 return false;
3075 break;
3076 }
3077 }
3078 return false;
3079}
3080
3082{
3083 if (MapDifficulty const* mapDiff = GetMapDifficulty())
3084 {
3085 if (mapDiff->maxPlayers || IsRegularDifficulty()) // Normal case (expect that regular difficulty always have correct maxplayers)
3086 return mapDiff->maxPlayers;
3087 else // DBC have 0 maxplayers for heroic instances with expansion < 2
3088 { // The heroic entry exists, so we don't have to check anything, simply return normal max players
3090 return normalDiff ? normalDiff->maxPlayers : 0;
3091 }
3092 }
3093 else // I'd rather ASSERT(false);
3094 return 0;
3095}
3096
3098{
3099 MapDifficulty const* mapDiff = GetMapDifficulty();
3100 return mapDiff ? mapDiff->resetTime : 0;
3101}
3102
3103/* ******* Battleground Instance Maps ******* */
3104
3105BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent, uint8 spawnMode)
3106 : Map(id, expiry, InstanceId, spawnMode, _parent), m_bg(NULL)
3107{
3108 //lets initialize visibility distance for BG/Arenas
3110}
3111
3113{
3114 if (m_bg)
3115 {
3116 //unlink to prevent crash, always unlink all pointer reference before destruction
3117 m_bg->SetBgMap(NULL);
3118 m_bg = NULL;
3119 }
3120}
3121
3128
3130{
3131 if (player->GetMapRef().getTarget() == this)
3132 {
3133 SF_LOG_ERROR("maps", "BGMap::CanEnter - player %u is already in map!", player->GetGUIDLow());
3134 ASSERT(false);
3135 return false;
3136 }
3137
3138 if (player->GetBattlegroundId() != GetInstanceId())
3139 return false;
3140
3141 // player number limit is checked in bgmgr, no need to do it here
3142
3143 return Map::CanEnter(player);
3144}
3145
3147{
3148 {
3149 std::lock_guard<std::mutex> guard(Lock);
3150 //Check moved to void WorldSession::HandleMoveWorldportAckOpcode()
3151 //if (!CanEnter(player))
3152 //return false;
3153 // reset instance validity, battleground maps do not homebind
3154 player->m_InstanceValid = true;
3155 }
3156 return Map::AddPlayerToMap(player);
3157}
3158
3160{
3161 SF_LOG_INFO("maps", "MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to another map", player->GetName().c_str(), GetInstanceId(), GetMapName());
3162 Map::RemovePlayerFromMap(player, remove);
3163}
3164
3169
3171{
3172 if (HavePlayers())
3173 for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
3174 if (Player* player = itr->GetSource())
3175 if (!player->IsBeingTeleportedFar())
3176 player->TeleportTo(player->GetBattlegroundEntryPoint());
3177}
3178
3180{
3181 return ObjectAccessor::GetObjectInMap(guid, this, (Creature*)NULL);
3182}
3183
3185{
3186 return ObjectAccessor::GetObjectInMap(guid, this, (GameObject*)NULL);
3187}
3188
3190{
3192 return NULL;
3193
3194 for (TransportsContainer::const_iterator itr = _transports.begin(); itr != _transports.end(); ++itr)
3195 if ((*itr)->GetGUID() == guid)
3196 return *itr;
3197
3198 return NULL;
3199}
3200
3205
3207{
3208 if (m_mapRefIter == player->GetMapRef())
3209 m_mapRefIter = m_mapRefIter->nocheck_prev();
3210}
3211
3212void Map::SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime)
3213{
3214 if (!respawnTime)
3215 {
3216 // Delete only
3218 return;
3219 }
3220
3221 _creatureRespawnTimes[dbGuid] = respawnTime;
3222
3224 stmt->setUInt32(0, dbGuid);
3225 stmt->setUInt32(1, uint32(respawnTime));
3226 stmt->setUInt16(2, GetId());
3227 stmt->setUInt32(3, GetInstanceId());
3228 CharacterDatabase.Execute(stmt);
3229}
3230
3232{
3233 _creatureRespawnTimes.erase(dbGuid);
3234
3236 stmt->setUInt32(0, dbGuid);
3237 stmt->setUInt16(1, GetId());
3238 stmt->setUInt32(2, GetInstanceId());
3239 CharacterDatabase.Execute(stmt);
3240}
3241
3242void Map::SaveGORespawnTime(uint32 dbGuid, time_t respawnTime)
3243{
3244 if (!respawnTime)
3245 {
3246 // Delete only
3247 RemoveGORespawnTime(dbGuid);
3248 return;
3249 }
3250
3251 _goRespawnTimes[dbGuid] = respawnTime;
3252
3253 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN);
3254 stmt->setUInt32(0, dbGuid);
3255 stmt->setUInt32(1, uint32(respawnTime));
3256 stmt->setUInt16(2, GetId());
3257 stmt->setUInt32(3, GetInstanceId());
3258 CharacterDatabase.Execute(stmt);
3259}
3260
3262{
3263 _goRespawnTimes.erase(dbGuid);
3264
3265 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN);
3266 stmt->setUInt32(0, dbGuid);
3267 stmt->setUInt16(1, GetId());
3268 stmt->setUInt32(2, GetInstanceId());
3269 CharacterDatabase.Execute(stmt);
3270}
3271
3273{
3275 stmt->setUInt16(0, GetId());
3276 stmt->setUInt32(1, GetInstanceId());
3277 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
3278 {
3279 do
3280 {
3281 Field* fields = result->Fetch();
3282 uint32 loguid = fields[0].GetUInt32();
3283 uint32 respawnTime = fields[1].GetUInt32();
3284
3285 _creatureRespawnTimes[loguid] = time_t(respawnTime);
3286 } while (result->NextRow());
3287 }
3288
3289 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GO_RESPAWNS);
3290 stmt->setUInt16(0, GetId());
3291 stmt->setUInt32(1, GetInstanceId());
3292 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
3293 {
3294 do
3295 {
3296 Field* fields = result->Fetch();
3297 uint32 loguid = fields[0].GetUInt32();
3298 uint32 respawnTime = fields[1].GetUInt32();
3299
3300 _goRespawnTimes[loguid] = time_t(respawnTime);
3301 } while (result->NextRow());
3302 }
3303}
3304
3306{
3307 _creatureRespawnTimes.clear();
3308 _goRespawnTimes.clear();
3309
3311}
3312
3314{
3316 stmt->setUInt16(0, mapId);
3317 stmt->setUInt32(1, instanceId);
3318 CharacterDatabase.Execute(stmt);
3319
3320 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE);
3321 stmt->setUInt16(0, mapId);
3322 stmt->setUInt32(1, instanceId);
3323 CharacterDatabase.Execute(stmt);
3324}
3325
3327{
3328 uint64 linkedGuid = sObjectMgr->GetLinkedRespawnGuid(guid);
3329 switch (GUID_HIPART(linkedGuid))
3330 {
3331 case HIGHGUID_UNIT:
3332 return GetCreatureRespawnTime(GUID_LOPART(linkedGuid));
3334 return GetGORespawnTime(GUID_LOPART(linkedGuid));
3335 default:
3336 break;
3337 }
3338
3339 return time_t(0);
3340}
#define sBattlePetSpawnMgr
@ CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE
@ CHAR_DEL_GO_RESPAWN
@ CHAR_SEL_INSTANCE
@ CHAR_REP_CREATURE_RESPAWN
@ CHAR_DEL_CREATURE_RESPAWN
@ CHAR_DEL_GO_RESPAWN_BY_INSTANCE
@ CHAR_REP_GO_RESPAWN
@ CHAR_SEL_CREATURE_RESPAWNS
@ CHAR_SEL_GO_RESPAWNS
DifficultyID
Definition DBCEnums.h:330
@ DIFFICULTY_NONE
Definition DBCEnums.h:331
@ DIFFICULTY_10MAN_HEROIC
Definition DBCEnums.h:336
@ DIFFICULTY_25MAN_NORMAL
Definition DBCEnums.h:335
@ DIFFICULTY_SCE_HEROIC
Definition DBCEnums.h:341
@ DIFFICULTY_HEROIC
Definition DBCEnums.h:333
@ DIFFICULTY_25MAN_LFR
Definition DBCEnums.h:338
@ DIFFICULTY_25MAN_HEROIC
Definition DBCEnums.h:337
@ AREA_FLAG_OUTSIDE
Definition DBCEnums.h:323
@ AREA_FLAG_INSIDE
Definition DBCEnums.h:322
uint32 GetAreaFlagByMapId(uint32 mapid)
MapDifficulty const * GetMapDifficultyData(uint32 mapId, DifficultyID difficulty)
AreaTableEntry const * GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_id)
DBCStorage< DifficultyEntry > sDifficultyStore(Difficultyfmt)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
AreaTableEntry const * GetAreaEntryByAreaID(uint32 area_id)
DBCStorage< LiquidTypeEntry > sLiquidTypeStore(LiquidTypefmt)
WMOAreaTableEntry const * GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid)
std::int32_t int32
Definition Define.h:73
#define UI64FMTD
Definition Define.h:64
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::uint16_t uint16
Definition Define.h:78
#define ASSERT
Definition Errors.h:29
#define MAX_NUMBER_OF_CELLS
Definition GridDefines.h:22
#define MAP_RESOLUTION
Definition GridDefines.h:41
#define TOTAL_NUMBER_OF_CELLS_PER_MAP
Definition GridDefines.h:39
GridRefManager< Creature > CreatureMapType
Definition GridDefines.h:51
GridRefManager< Player > PlayerMapType
Definition GridDefines.h:54
#define SIZE_OF_GRIDS
Definition GridDefines.h:26
CoordPair< MAX_NUMBER_OF_GRIDS > GridCoord
#define MAX_NUMBER_OF_GRIDS
Definition GridDefines.h:24
#define SIZE_OF_GRID_CELL
Definition GridDefines.h:34
CoordPair< TOTAL_NUMBER_OF_CELLS_PER_MAP > CellCoord
NGrid< MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes > NGridType
Definition GridDefines.h:69
Grid< Player, AllWorldObjectTypes, AllGridObjectTypes > GridType
Definition GridDefines.h:68
#define VMAP_INVALID_HEIGHT_VALUE
#define sInstanceSaveMgr
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
u_map_magic MapVersionMagic
Definition Map.cpp:29
u_map_magic MapMagic
Definition Map.cpp:28
u_map_magic MapLiquidMagic
Definition Map.cpp:32
GridState * si_GridStates[MAX_GRID_STATE]
Definition Map.cpp:38
u_map_magic MapHeightMagic
Definition Map.cpp:31
u_map_magic MapAreaMagic
Definition Map.cpp:30
bool IsOutdoorWMO(uint32 mogpFlags, int32, int32, int32, WMOAreaTableEntry const *wmoEntry, AreaTableEntry const *atEntry)
Definition Map.cpp:2001
ZLiquidStatus
Definition Map.h:114
@ LIQUID_MAP_UNDER_WATER
Definition Map.h:119
@ LIQUID_MAP_NO_WATER
Definition Map.h:115
@ LIQUID_MAP_IN_WATER
Definition Map.h:118
@ LIQUID_MAP_ABOVE_WATER
Definition Map.h:116
@ LIQUID_MAP_WATER_WALK
Definition Map.h:117
#define MIN_UNLOAD_DELAY
Definition Map.h:145
#define MAP_HEIGHT_AS_INT8
Definition Map.h:88
#define MAP_AREA_NO_AREA
Definition Map.h:77
#define MAP_LIQUID_NO_TYPE
Definition Map.h:98
#define MAP_LIQUID_NO_HEIGHT
Definition Map.h:99
#define MAP_LIQUID_TYPE_WATER
Definition Map.h:123
#define MAP_LIQUID_TYPE_DARK_WATER
Definition Map.h:130
#define MAP_LIQUID_TYPE_OCEAN
Definition Map.h:124
InstanceResetMethod
Definition Map.h:627
@ INSTANCE_RESET_GLOBAL
Definition Map.h:630
@ INSTANCE_RESET_CHANGE_DIFFICULTY
Definition Map.h:629
#define MAP_HEIGHT_NO_HEIGHT
Definition Map.h:86
#define MAP_ALL_LIQUIDS
Definition Map.h:128
#define INVALID_HEIGHT
Definition Map.h:142
#define MAP_HEIGHT_AS_INT16
Definition Map.h:87
@ GRID_STATE_REMOVAL
Definition NGrid.h:53
@ GRID_STATE_INVALID
Definition NGrid.h:50
@ GRID_STATE_IDLE
Definition NGrid.h:52
@ GRID_STATE_ACTIVE
Definition NGrid.h:51
@ MAX_GRID_STATE
Definition NGrid.h:54
#define DEFAULT_VISIBILITY_NOTIFY_PERIOD
Definition NGrid.h:17
@ PHASEMASK_NORMAL
Definition Object.h:80
@ TYPEID_GAMEOBJECT
Definition Object.h:56
@ TYPEID_DYNAMICOBJECT
Definition Object.h:57
@ TYPEID_UNIT
Definition Object.h:54
@ TYPEID_CORPSE
Definition Object.h:58
@ TYPEID_AREATRIGGER
Definition Object.h:59
#define MAX_VISIBILITY_DISTANCE
Definition Object.h:23
#define DEFAULT_VISIBILITY_DISTANCE
Definition Object.h:25
#define MAPID_INVALID
Definition Object.h:531
#define sObjectAccessor
uint32 GUID_LOPART(uint64 x)
@ HIGHGUID_GAMEOBJECT
@ HIGHGUID_MO_TRANSPORT
@ HIGHGUID_UNIT
uint32 GUID_HIPART(uint64 guid)
#define sObjectMgr
Definition ObjectMgr.h:1617
@ PET_SAVE_NOT_IN_SLOT
Definition PetDefines.h:25
@ TRANSFER_ABORT_ZONE_IN_COMBAT
Definition Player.h:794
Skyfire::AutoPtr< PreparedResultSet, Skyfire::Mutex > PreparedQueryResult
Definition QueryResult.h:94
#define sScriptMgr
Definition ScriptMgr.h:764
@ MOVEMENTFLAG_HOVER
Definition Unit.h:751
@ UNIT_FIELD_HOVER_HEIGHT
virtual void InitVisibilityDistance() OVERRIDE
Definition Map.cpp:3122
BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map *_parent, uint8 spawnMode)
Definition Map.cpp:3105
bool CanEnter(Player *player) OVERRIDE
Definition Map.cpp:3129
void SetUnload()
Definition Map.cpp:3165
void RemovePlayerFromMap(Player *, bool) OVERRIDE
Definition Map.cpp:3159
Battleground * m_bg
Definition Map.h:682
void RemoveAllPlayers() OVERRIDE
Definition Map.cpp:3170
bool AddPlayerToMap(Player *) OVERRIDE
Definition Map.cpp:3146
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void FlushBits()
Definition ByteBuffer.h:154
uint32 GetDBTableGUIDLow() const
Definition Creature.h:445
void GetRespawnPosition(float &x, float &y, float &z, float *ori=NULL, float *dist=NULL) const
bool m_isTempWorldObject
Definition Creature.h:664
Definition Field.h:16
std::string GetString() const
Definition Field.h:228
uint32 GetUInt32() const
Definition Field.h:105
void RemoveFromWorld() OVERRIDE
void AddToWorld() OVERRIDE
void SaveRespawnTime() OVERRIDE
void UpdateModelPosition()
void GetRespawnPosition(float &x, float &y, float &z, float *ori=NULL) const
void AddWorldObject(SPECIFIC_OBJECT *obj)
Definition Grid.h:45
void AddGridObject(SPECIFIC_OBJECT *obj)
Definition Grid.h:98
PeriodicTimer & getRelocationTimer()
Definition NGrid.h:38
Definition Map.h:148
uint8 m_liquidOffY
Definition Map.h:175
uint8 m_liquidHeight
Definition Map.h:177
bool loadAreaData(FILE *in, uint32 offset, uint32 size)
Definition Map.cpp:1465
GetHeightPtr m_gridGetHeight
Definition Map.h:186
float getHeightFromFlat(float x, float y) const
Definition Map.cpp:1575
void unloadData()
Definition Map.cpp:1448
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data=0)
Definition Map.cpp:1829
uint8 * m_uint8_V8
Definition Map.h:158
uint16 m_liquidType
Definition Map.h:173
uint16 * m_uint16_V8
Definition Map.h:157
uint16 getArea(float x, float y) const
Definition Map.cpp:1563
float m_gridHeight
Definition Map.h:161
uint8 getTerrainType(float x, float y) const
Definition Map.cpp:1816
float getHeightFromFloat(float x, float y) const
Definition Map.cpp:1580
float getHeightFromUint16(float x, float y) const
Definition Map.cpp:1729
uint16 m_gridArea
Definition Map.h:172
uint8 * m_uint8_V9
Definition Map.h:153
uint16 * m_areaMap
Definition Map.h:165
bool loadData(char *filaname)
Definition Map.cpp:1398
float getLiquidLevel(float x, float y) const
Definition Map.cpp:1796
float * m_V9
Definition Map.h:151
uint8 * m_liquidFlags
Definition Map.h:170
uint16 * m_uint16_V9
Definition Map.h:152
uint8 m_liquidWidth
Definition Map.h:176
float m_liquidLevel
Definition Map.h:168
float getHeightFromUint8(float x, float y) const
Definition Map.cpp:1662
float getHeight(float x, float y) const
Definition Map.h:204
float * m_liquidMap
Definition Map.h:171
bool loadHeightData(FILE *in, uint32 offset, uint32 size)
Definition Map.cpp:1483
uint16 * m_liquidEntry
Definition Map.h:169
uint8 m_liquidOffX
Definition Map.h:174
bool loadLiquidData(FILE *in, uint32 offset, uint32 size)
Definition Map.cpp:1529
float m_gridIntHeightMultiplier
Definition Map.h:162
float * m_V8
Definition Map.h:156
void RemoveFromGrid()
Definition Object.h:558
bool IsInGrid() const
Definition Object.h:556
LinkedListHead::Iterator< GridReference< OBJECT > > iterator
Definition Group.h:147
bool isLFGGroup() const
Definition Group.cpp:2543
InstanceGroupBind * BindToInstance(InstanceSave *save, bool permanent, bool load=false)
Definition Group.cpp:2426
InstanceGroupBind * GetBoundInstance(Player *player)
Definition Group.cpp:2393
uint64 GetLeaderGUID() const
Definition Group.cpp:2568
bool m_resetAfterUnload
Definition Map.h:659
void CreateInstanceData(bool load)
Definition Map.cpp:2893
bool m_unloadWhenEmpty
Definition Map.h:660
void PermBindAllPlayers(Player *source)
Definition Map.cpp:2971
void SendResetWarnings(uint32 timeLeft) const
Definition Map.cpp:3018
uint32 GetMaxPlayers() const
Definition Map.cpp:3081
uint32 GetMaxResetDelay() const
Definition Map.cpp:3097
bool CanEnter(Player *player) OVERRIDE
Definition Map.cpp:2690
bool Reset(InstanceResetMethod method)
Definition Map.cpp:2935
InstanceScript * i_data
Definition Map.h:661
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map *_parent)
Definition Map.cpp:2661
bool AddPlayerToMap(Player *) OVERRIDE
Definition Map.cpp:2755
void SetResetSchedule(bool on)
Definition Map.cpp:3024
void Update(const uint32) OVERRIDE
Definition Map.cpp:2874
uint32 i_script_id
Definition Map.h:662
InstanceScript * GetInstanceScript()
Definition Map.h:647
void RemovePlayerFromMap(Player *, bool) OVERRIDE
Definition Map.cpp:2882
virtual void InitVisibilityDistance() OVERRIDE
Definition Map.cpp:2680
void UnloadAll() OVERRIDE
Definition Map.cpp:3008
~InstanceMap()
Definition Map.cpp:2674
DifficultyID GetDifficulty() const
uint8 GetPlayerCount() const
uint8 GetGroupCount() const
uint32 GetInstanceId() const
uint32 GetMapId() const
bool CanReset() const
bool isEmpty() const
Definition LinkedList.h:86
static MMapManager * createOrGetMMapManager()
bool unloadMap(uint32 mapId, int32 x, int32 y)
bool loadMap(const std::string &basePath, uint32 mapId, int32 x, int32 y)
bool unloadMapInstance(uint32 mapId, uint32 instanceId)
MapEntry const * i_mapEntry
Definition Map.h:541
uint8 i_spawnMode
Definition Map.h:542
bool _creatureToMoveLock
Definition Map.h:507
std::map< WorldObject *, bool > i_objectsToSwitch
Definition Map.h:588
void UpdateObjectVisibility(WorldObject *obj, Cell cell, CellCoord cellpair)
Definition Map.cpp:2290
float GetWaterLevel(float x, float y) const
Definition Map.cpp:2195
std::vector< Creature * > _creaturesToMove
Definition Map.h:508
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const
Definition Map.cpp:2231
void GameObjectRelocation(GameObject *go, float x, float y, float z, float orientation, bool respawnRelocationOnFail=true)
Definition Map.cpp:946
void AddGameObjectToMoveList(GameObject *go, float x, float y, float z, float ang)
Definition Map.cpp:997
void CreatureRelocation(Creature *creature, float x, float y, float z, float ang, bool respawnRelocationOnFail=true)
Definition Map.cpp:909
bool IsBattlegroundOrArena() const
Definition Map.h:378
void RemoveFromActive(T *obj)
Definition Map.cpp:2610
bool UnloadGrid(NGridType &ngrid, bool pForce)
Definition Map.cpp:1285
DifficultyID GetDifficulty() const
Definition Map.h:363
static void GetZoneAndAreaIdByAreaFlag(uint32 &zoneid, uint32 &areaid, uint16 areaflag, uint32 map_id)
Definition Map.cpp:2223
TransportsContainer::iterator _transportsUpdateIter
Definition Map.h:560
void InitializeObject(T *obj)
Definition Map.cpp:489
static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId)
Definition Map.cpp:3313
void SwitchGridContainers(T *obj, bool on)
Definition Map.cpp:288
void AddObjectToRemoveList(WorldObject *obj)
Definition Map.cpp:2410
virtual void RemovePlayerFromMap(Player *, bool)
Definition Map.cpp:808
time_t GetGORespawnTime(uint32 dbGuid) const
Definition Map.h:465
void MoveAllGameObjectsInMoveList()
Definition Map.cpp:1067
void RemoveFromActiveHelper(WorldObject *obj)
Definition Map.h:606
void LoadGrid(float x, float y)
Definition Map.cpp:455
void PreserveTransportVisibility(std::set< uint64 > &guids) const
Definition Map.cpp:2375
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map *_parent=NULL)
Definition Map.cpp:222
Transport * GetTransport(uint64 guid)
Definition Map.cpp:3189
bool AddToMap(T *)
Definition Map.cpp:504
float GetHeight(float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const
Definition Map.cpp:1959
bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist)
Definition Map.cpp:2237
uint8 GetTerrainType(float x, float y) const
Definition Map.cpp:2102
void DeleteRespawnTimes()
Definition Map.cpp:3305
NGridType * i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition Map.h:578
uint32 m_unloadTimer
Definition Map.h:544
MapRefManager PlayerList
Definition Map.h:406
uint8 GetSpawnMode() const
Definition Map.h:358
MapDifficulty const * GetMapDifficulty() const
Definition Map.cpp:3039
std::mutex Lock
Definition Map.h:538
void SaveGORespawnTime(uint32 dbGuid, time_t respawnTime)
Definition Map.cpp:3242
void LoadMMap(int gx, int gy)
Definition Map.cpp:123
virtual void Update(const uint32)
Definition Map.cpp:631
Map * m_parentMap
Definition Map.h:576
void EnsureGridCreated(const GridCoord &)
Definition Map.cpp:377
bool IsRaid() const
Definition Map.h:372
void ProcessRelocationNotifies(const uint32 diff)
Definition Map.cpp:731
virtual void UnloadAll()
Definition Map.cpp:1381
NGridType * getNGrid(uint32 x, uint32 y) const
Definition Map.h:521
bool Is25ManRaid() const
Definition Map.cpp:3063
void AddToActiveHelper(WorldObject *obj)
Definition Map.h:601
bool _gameObjectsToMoveLock
Definition Map.h:510
static uint32 GetAreaIdByAreaFlag(uint16 areaflag, uint32 map_id)
Definition Map.cpp:2203
bool HavePlayers() const
Definition Map.h:397
MapRefManager m_mapRefManager
Definition Map.h:548
void resetMarkedCells()
Definition Map.h:393
bool ActiveObjectsNearGrid(NGridType const &ngrid) const
Definition Map.cpp:2531
virtual void DelayedUpdate(const uint32 diff)
Definition Map.cpp:2391
void RemoveCreatureFromMoveList(Creature *c)
Definition Map.cpp:992
void RemoveGORespawnTime(uint32 dbGuid)
Definition Map.cpp:3261
void ScriptsProcess()
Process queued scripts.
ScriptScheduleMap m_scriptSchedule
Definition Map.h:592
void AddWorldObject(WorldObject *obj)
Definition Map.h:401
void ResetGridExpiry(NGridType &grid, float factor=1) const
Definition Map.h:294
DynamicMapTree _dynamicTree
Definition Map.h:546
std::vector< GameObject * > _gameObjectsToMove
Definition Map.h:511
void LoadRespawnTimes()
Definition Map.cpp:3272
bool GameObjectRespawnRelocation(GameObject *go, bool diffGridOnly)
Definition Map.cpp:1260
time_t i_gridExpiry
Definition Map.h:572
int32 m_VisibilityNotifyPeriod
Definition Map.h:551
time_t GetCreatureRespawnTime(uint32 dbGuid) const
Definition Map.h:456
void EnsureGridLoadedForActiveObject(Cell const &, WorldObject *object)
Definition Map.cpp:415
GameObject * GetGameObject(uint64 guid)
Definition Map.cpp:3184
void LoadMap(int gx, int gy, bool reload=false)
Definition Map.cpp:151
void LoadVMap(int gx, int gy)
Definition Map.cpp:133
bool i_scriptLock
Definition Map.h:586
void SendInitSelf(Player *player)
Definition Map.cpp:2312
virtual void RemoveAllPlayers()
Definition Map.cpp:1364
bool isCellMarked(uint32 pCellId)
Definition Map.h:394
bool GameObjectCellRelocation(GameObject *go, Cell new_cell)
Definition Map.cpp:1169
void SendToPlayers(WorldPacket const *data) const
Definition Map.cpp:2525
std::mutex GridLock
Definition Map.h:539
void SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime)
Definition Map.cpp:3212
bool IsUnderWater(float x, float y, float z) const
Definition Map.cpp:2263
GridMap * GetGrid(float x, float y)
Definition Map.cpp:1924
static void DeleteStateMachine()
Definition Map.cpp:214
MapRefManager::iterator m_mapRefIter
Definition Map.h:549
bool CreatureCellRelocation(Creature *creature, Cell new_cell)
Definition Map.cpp:1108
bool IsInWater(float x, float y, float z, LiquidData *data=0) const
Definition Map.cpp:2256
uint16 GetAreaFlag(float x, float y, float z, bool *isOutdoors=0) const
Definition Map.cpp:2063
void Balance()
Definition Map.h:445
virtual ~Map()
Definition Map.cpp:40
virtual bool CanEnter(Player *)
Definition Map.h:359
void RemoveGameObjectFromMoveList(GameObject *go)
Definition Map.cpp:1010
void EnsureGridCreated_i(const GridCoord &)
Definition Map.cpp:385
Creature * GetCreature(uint64 guid)
Definition Map.cpp:3179
void RemoveWorldObject(WorldObject *obj)
Definition Map.h:402
std::set< WorldObject * > i_worldObjects
Definition Map.h:589
ActiveNonPlayers m_activeNonPlayers
Definition Map.h:554
void UpdateIteratorBack(Player *player)
Definition Map.cpp:3206
float GetWaterOrGroundLevel(float x, float y, float z, float *ground=NULL, bool swim=false) const
Definition Map.cpp:1941
void LoadMapAndVMap(int gx, int gy)
Definition Map.cpp:195
UNORDERED_MAP< uint32, time_t > _goRespawnTimes
Definition Map.h:623
void buildNGridLinkage(NGridType *pNGridType)
Definition Map.h:519
void Visit(const Cell &cell, TypeContainerVisitor< T, CONTAINER > &visitor)
Definition Map.h:686
MapEntry const * GetEntry() const
Definition Map.h:244
bool IsRegularDifficulty() const
Definition Map.h:364
std::set< WorldObject * > i_objectsToRemove
Definition Map.h:587
void AddToGrid(T *object, Cell const &cell)
Definition Map.cpp:257
uint32 GetPlayersCountExceptGMs() const
Definition Map.cpp:2516
bool IsGridLoaded(float x, float y) const
Definition Map.h:283
void DeleteFromWorld(T *)
Definition Map.cpp:363
void AddToActive(T *obj)
Definition Map.cpp:2569
void SendInitTransports(Player *player)
Definition Map.cpp:2344
float m_VisibleDistance
Definition Map.h:545
bool IsOutdoors(float x, float y, float z) const
Definition Map.cpp:2025
float GetVisibilityRange() const
Definition Map.h:267
bool IsRaidOrHeroicDungeon() const
Definition Map.h:373
void UpdateObjectsVisibilityFor(Player *player, Cell cell, CellCoord cellpair)
Definition Map.cpp:2298
bool CheckGridIntegrity(Creature *c, bool moved) const
Definition Map.cpp:2268
const char * GetMapName() const
Definition Map.cpp:2285
void RemoveAllObjectsInRemoveList()
Definition Map.cpp:2448
void MoveAllCreaturesInMoveList()
Definition Map.cpp:1015
DynamicObject * GetDynamicObject(uint64 guid)
Definition Map.cpp:3201
void markCell(uint32 pCellId)
Definition Map.h:395
void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang)
Definition Map.cpp:979
virtual void InitVisibilityDistance()
Definition Map.cpp:248
bool IsHeroic() const
Definition Map.cpp:3044
void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y)
Definition Map.h:528
void VisitNearbyCellsOf(WorldObject *obj, TypeContainerVisitor< Skyfire::ObjectUpdater, GridTypeMapContainer > &gridVisitor, TypeContainerVisitor< Skyfire::ObjectUpdater, WorldTypeMapContainer > &worldVisitor)
Definition Map.cpp:602
bool EnsureGridLoaded(Cell const &)
Definition Map.cpp:431
void RemoveFromMap(T *, bool)
Definition Map.cpp:826
virtual bool AddPlayerToMap(Player *)
Definition Map.cpp:460
bool GetAreaInfo(float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId) const
Definition Map.cpp:2044
uint32 GetInstanceId() const
Definition Map.h:357
TransportsContainer _transports
Definition Map.h:559
void SendRemoveTransports(Player *player)
Definition Map.cpp:2362
uint32 GetId(void) const
Definition Map.h:300
PlayerList const & GetPlayers() const
Definition Map.h:407
UNORDERED_MAP< uint32, time_t > _creatureRespawnTimes
Definition Map.h:622
static void InitStateMachine()
Definition Map.cpp:206
time_t GetLinkedRespawnTime(uint64 guid) const
Definition Map.cpp:3326
void PlayerRelocation(Player *, float x, float y, float z, float orientation)
Definition Map.cpp:877
bool CreatureRespawnRelocation(Creature *c, bool diffGridOnly)
Definition Map.cpp:1230
static bool ExistVMap(uint32 mapid, int gx, int gy)
Definition Map.cpp:104
void AddObjectToSwitchList(WorldObject *obj, bool on)
Definition Map.cpp:2424
uint32 i_InstanceId
Definition Map.h:543
ActiveNonPlayers::iterator m_activeNonPlayersIter
Definition Map.h:555
void RemoveCreatureRespawnTime(uint32 dbGuid)
Definition Map.cpp:3231
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data=0) const
Definition Map.cpp:2110
static uint32 GetZoneIdByAreaFlag(uint16 areaflag, uint32 map_id)
Definition Map.cpp:2213
bool isGridObjectDataLoaded(uint32 x, uint32 y) const
Definition Map.h:527
static bool ExistMap(uint32 mapid, int gx, int gy)
Definition Map.cpp:75
GridMap * GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition Map.h:579
bool IsInstance() const
Definition Map.h:368
void setNGrid(NGridType *grid, uint32 x, uint32 y)
Definition Map.cpp:2381
void SetCurrentCell(Cell const &cell)
Definition Object.h:598
MapObjectCellMoveState _moveState
Definition Object.h:600
Position _newPosition
Definition Object.h:601
void SetNewCellPosition(float x, float y, float z, float o)
Definition Object.h:602
Cell const & GetCurrentCell() const
Definition Object.h:597
iterator end()
LinkedListHead::Iterator< MapReference > iterator
iterator begin()
LinkedListHead::Iterator< MapReference const > const_iterator
void Clear(bool reset=true)
int32 getX() const
Definition NGrid.h:89
grid_state_t GetGridState(void) const
Definition NGrid.h:87
void decUnloadActiveLock()
Definition NGrid.h:105
uint32 GetWorldObjectCountInNGrid() const
Definition NGrid.h:161
void SetGridState(grid_state_t s)
Definition NGrid.h:88
GridType & GetGridType(const uint32 x, const uint32 y)
Definition NGrid.h:73
void incUnloadActiveLock()
Definition NGrid.h:104
GridInfo * getGridInfoRef()
Definition NGrid.h:99
int32 getY() const
Definition NGrid.h:90
void VisitAllGrids(TypeContainerVisitor< T, TypeMapContainer< TT > > &visitor)
Definition NGrid.h:133
static T * GetObjectInMap(uint64 guid, Map *map, T *)
static Corpse * GetCorpse(WorldObject const &u, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
DynamicObject * ToDynObject()
Definition Object.h:219
bool IsInWorld() const
Definition Object.h:114
uint32 GetGUIDLow() const
Definition Object.h:120
TypeID GetTypeId() const
Definition Object.h:131
virtual void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
Definition Object.cpp:172
float GetFloatValue(uint16 index) const
Definition Object.cpp:337
GameObject * ToGameObject()
Definition Object.h:213
uint32 GetEntry() const
Definition Object.h:125
Creature * ToCreature()
Definition Object.h:207
Definition Pet.h:28
bool m_InstanceValid
Definition Player.h:2922
InstancePlayerBind * GetBoundInstance(uint32 mapid, DifficultyID difficulty)
Definition Player.cpp:13877
ClientGUIDs m_clientGUIDs
Definition Player.h:2857
float m_homebindZ
Definition Player.h:2851
bool IsBeingTeleportedFar() const
Definition Player.h:2501
uint32 m_homebindMapId
Definition Player.h:2847
void SendDirectMessage(WorldPacket *data)
Definition Player.cpp:6904
void Update(uint32 time) override
Definition Player.cpp:1387
bool HaveAtClient(WorldObject const *u) const
Definition Player.cpp:18066
void AddInstanceEnterTime(uint32 instanceId, time_t enterTime)
Definition Player.cpp:14230
void UpdatePhasing()
Definition Player.cpp:23894
WorldSession * GetSession() const
Definition Player.h:2417
void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const override
Definition Player.cpp:4626
WorldObject * GetViewpoint() const
Definition Player.cpp:20314
float m_homebindY
Definition Player.h:2850
Group * GetGroup()
Definition Player.h:2972
bool IsGameMaster() const
Definition Player.h:1369
void SetPendingBind(uint32 instanceId, uint32 bindTimer)
Definition Player.cpp:14002
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:2090
MapReference & GetMapRef()
Definition Player.h:3038
uint32 GetBattlegroundId() const
Definition Player.h:2697
void AddToWorld() override
Definition Player.cpp:2418
void UpdateObjectVisibility(bool forced=true) override
Definition Player.cpp:18318
void SetMap(Map *map) override
Definition Player.cpp:21655
void SendTransferAborted(uint32 mapid, TransferAbortReason reason, uint8 arg=0)
Definition Player.cpp:18715
bool IsBeingForcedTeleportFar() const
Definition Player.h:2520
void RemoveFromWorld() override
Definition Player.cpp:2430
float m_homebindX
Definition Player.h:2849
InstancePlayerBind * BindToInstance(InstanceSave *save, bool permanent, bool load=false)
Definition Player.cpp:13932
void setUInt16(const uint8 index, const uint16 value)
void setUInt32(const uint8 index, const uint32 value)
TO * getTarget() const
Definition Reference.h:81
TransportTemplate const * GetTransportTemplate() const
Definition Transport.h:66
bool IsVehicle() const
Definition Unit.h:1523
void CombatStop(bool includingCast=false)
void UpdateObjectVisibility(bool forced=true) override
Definition Unit.cpp:7567
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
bool IsPet() const
Definition Unit.h:1511
void CleanupsBeforeDelete(bool finalCleanup=true) override
Definition Unit.cpp:5479
bool HasUnitMovementFlag(uint32 f) const
Definition Unit.h:2628
Vehicle * GetVehicleKit() const
Definition Unit.h:2739
bool BuildPacket(WorldPacket *packet)
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist)=0
virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const =0
bool isHeightCalcEnabled() const
virtual int loadMap(const char *pBasePath, unsigned int pMapId, int x, int y)=0
virtual void unloadMap(unsigned int pMapId, int x, int y)=0
virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const =0
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2)=0
static IVMapManager * createOrGetVMapManager()
void RelocatePassengers()
Relocate passengers. Must be called after m_base::Relocate.
Definition Vehicle.cpp:536
static float GetMaxVisibleDistanceInBGArenas()
Definition World.h:758
static float GetMaxVisibleDistanceInInstances()
Definition World.h:757
static int32 GetVisibilityNotifyPeriodOnContinents()
Definition World.h:760
static int32 GetVisibilityNotifyPeriodInBGArenas()
Definition World.h:762
static int32 GetVisibilityNotifyPeriodInInstances()
Definition World.h:761
static float GetMaxVisibleDistanceOnContinents()
Definition World.h:756
uint32 GetMapId() const
Definition Object.h:546
Map * GetMap() const
Definition Object.h:740
virtual void ResetMap()
Definition Object.cpp:2532
virtual void RemoveFromWorld()
Definition Object.cpp:1587
Map * FindMap() const
Definition Object.h:741
bool IsWorldObject() const
Definition Object.cpp:1531
float GetGridActivationRange() const
Definition Object.cpp:2054
bool IsPermanentWorldObject() const
Definition Object.h:779
bool isActiveObject() const
Definition Object.h:776
uint32 GetInstanceId() const
Definition Object.h:638
std::string const & GetName() const
Definition Object.h:664
float GetSightRange(WorldObject const *target=NULL) const
Definition Object.cpp:2078
Transport * GetTransport() const
Definition Object.h:797
float GetVisibilityRange() const
Definition Object.cpp:2070
virtual void Update(uint32)
Definition Object.h:616
virtual void UpdateObjectVisibility(bool forced=true)
Definition Object.cpp:3480
virtual void CleanupsBeforeDelete(bool finalCleanup=true)
Definition Object.cpp:1575
Player session in the World.
bool Update(uint32 diff, PacketFilter &updater)
Update the WorldSession (triggered by World update).
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void SendCalendarRaidLockout(InstanceSave const *save, bool add)
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
@ SMSG_INSTANCE_LOCK_WARNING_QUERY
Definition Opcodes.h:723
@ SMSG_INSTANCE_SAVE_CREATED
Definition Opcodes.h:726
#define sWorld
Definition World.h:910
@ CONFIG_INSTANCE_UNLOAD_DELAY
Definition World.h:243
@ CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY
Definition World.h:111
@ CONFIG_GRID_UNLOAD
Definition World.h:94
MapMoveQueueAddAction GetMoveQueueAddAction(MapObjectCellMoveState state, bool queueLocked)
@ MAP_REMOVE_LIST_ADD_INSERT
MapSwitchListAction GetSwitchListAction(bool supportedObjectType, bool alreadyQueued, bool queuedOn, bool requestedOn)
MapRemoveListAddAction GetRemoveListAddAction(bool alreadyQueued)
MapMoveQueueRemoveAction MarkMoveQueueEntryInactive(MapObjectCellMoveState &state, bool queueLocked)
MapAddObjectAction GetAddObjectAction(bool alreadyInWorld, bool validCoordinates)
@ MAP_SWITCH_LIST_ERASE_OPPOSITE
@ MAP_SWITCH_LIST_IGNORE_UNSUPPORTED_TYPE
@ MAP_ADD_OBJECT_REJECT_INVALID_COORDS
@ MAP_ADD_OBJECT_REFRESH_EXISTING
bool ConsumeMoveQueueEntry(MapObjectCellMoveState &state)
@ MAP_MOVE_QUEUE_ADD_SKIPPED_LOCKED
@ MAP_MOVE_QUEUE_ADD_APPEND
bool IsValidMapCoord(float c)
CellCoord ComputeCellCoord(float x, float y)
GridCoord ComputeGridCoord(float x, float y)
@ VMAP_LOAD_RESULT_ERROR
@ VMAP_LOAD_RESULT_OK
@ VMAP_LOAD_RESULT_IGNORED
uint32 m_AreaBit
uint32 m_ID
uint32 m_flags
uint32 m_ParentAreaID
CellCoord high_bound
Definition Cell.h:33
CellCoord low_bound
Definition Cell.h:32
Definition Cell.h:37
uint32 GridX() const
Definition Cell.h:63
void SetNoCreate()
Definition Cell.h:66
unsigned grid_y
Definition Cell.h:88
struct Cell::@253100141177133252213152253303204033205331220256::@054333305236276154171230343071320200077322155341 Part
uint32 GridY() const
Definition Cell.h:64
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition CellImpl.h:109
bool DiffGrid(const Cell &cell) const
Definition Cell.h:55
unsigned grid_x
Definition Cell.h:87
uint32 CellX() const
Definition Cell.h:61
uint32 CellY() const
Definition Cell.h:62
bool DiffCell(const Cell &cell) const
Definition Cell.h:49
union Cell::@253100141177133252213152253303204033205331220256 data
static CellArea CalculateCellArea(float x, float y, float radius)
Definition CellImpl.h:36
bool IsCoordValid() const
uint32 x_coord
void inc_y(uint32 val)
void dec_x(uint32 val)
Definition GridDefines.h:92
void inc_x(uint32 val)
uint32 y_coord
void dec_y(uint32 val)
InstanceSave * save
Definition Group.h:137
InstanceSave * save
Definition Player.h:931
uint32 ScriptId
Definition Map.h:220
uint32 entry
Definition Map.h:136
float depth_level
Definition Map.h:138
uint32 type_flags
Definition Map.h:135
float level
Definition Map.h:137
void TUpdate(int32 diff)
Definition Timer.h:154
bool TPassed() const
Definition Timer.h:155
void TReset(int32 diff, int32 period)
Definition Timer.h:156
float m_positionX
Definition Object.h:287
float m_positionY
Definition Object.h:288
float GetOrientation() const
Definition Object.h:331
bool IsPositionValid() const
Definition Object.cpp:2049
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
void Relocate(float x, float y)
Definition Object.h:302
void resetNotify(GridRefManager< T > &m)
Definition Map.cpp:721
void Visit(PlayerMapType &m)
Definition Map.cpp:728
void Visit(GridRefManager< T > &)
Definition Map.cpp:726
void Visit(CreatureMapType &m)
Definition Map.cpp:727
uint32 Flags
uint32 areaId
uint32 fourcc
Definition Map.h:81
uint16 gridArea
Definition Map.h:83
uint16 flags
Definition Map.h:82
u_map_magic mapMagic
Definition Map.h:64
uint32 liquidMapSize
Definition Map.h:72
uint32 areaMapOffset
Definition Map.h:67
uint32 heightMapSize
Definition Map.h:70
uint32 heightMapOffset
Definition Map.h:69
u_map_magic versionMagic
Definition Map.h:65
uint32 liquidMapOffset
Definition Map.h:71
uint32 areaMapSize
Definition Map.h:68
float gridMaxHeight
Definition Map.h:95
uint32 flags
Definition Map.h:93
float gridHeight
Definition Map.h:94
uint32 fourcc
Definition Map.h:92
uint8 offsetX
Definition Map.h:106
uint32 fourcc
Definition Map.h:103
uint8 width
Definition Map.h:108
uint8 height
Definition Map.h:109
uint16 liquidType
Definition Map.h:105
uint8 offsetY
Definition Map.h:107
float liquidLevel
Definition Map.h:110
uint16 flags
Definition Map.h:104
Represents a map magic value of 4 bytes (used in versions).
Definition Map.h:54
char asChar[4]
Definition Map.h:55
uint32 asUInt
Definition Map.h:56