OregonCore  revision 71a6c59-git
Your Favourite TBC server
Map.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Map.h"
19 #include "MapManager.h"
20 #include "GridStates.h"
21 #include "ScriptMgr.h"
22 #include "VMapFactory.h"
23 #include "MapInstanced.h"
24 #include "CellImpl.h"
25 #include "GridNotifiers.h"
26 #include "GridNotifiersImpl.h"
27 #include "Transports.h"
28 #include "InstanceData.h"
29 #include "ObjectAccessor.h"
30 #include "ObjectMgr.h"
31 #include "DynamicTree.h"
32 #include "MoveMap.h"
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  UnloadAll();
43 
44  while (!i_worldObjects.empty())
45  {
46  WorldObject* obj = *i_worldObjects.begin();
47  ASSERT(obj->IsWorldObject());
48  //ASSERT(obj->GetTypeId() == TYPEID_CORPSE);
49  obj->RemoveFromWorld();
50  obj->ResetMap();
51  }
52 
53  if (!m_scriptSchedule.empty())
54  sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size());
55 }
56 
57 bool Map::ExistMap(uint32 mapid, int gx, int gy)
58 {
59  int len = sWorld.GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1;
60  char* tmp = new char[len];
61  snprintf(tmp, len, (char*)(sWorld.GetDataPath() + "maps/%03u%02u%02u.map").c_str(), mapid, gx, gy);
62 
63  bool ret = false;
64  FILE* pf = fopen(tmp, "rb");
65 
66  if (!pf)
67  sLog.outError("Map file '%s': does not exist!", tmp);
68  else
69  {
70  map_fileheader header;
71  if (fread(&header, sizeof(header), 1, pf) == 1)
72  {
73  if (header.mapMagic != uint32(MAP_MAGIC) || header.versionMagic != uint32(MAP_VERSION_MAGIC))
74  sLog.outError("Map file '%s' is from an incompatible clientversion. Please recreate using the mapextractor.", tmp);
75  else
76  ret = true;
77  }
78  fclose(pf);
79  }
80  delete [] tmp;
81  return ret;
82 }
83 
84 bool Map::ExistVMap(uint32 mapid, int gx, int gy)
85 {
87  {
88  if (vmgr->isMapLoadingEnabled())
89  {
90  bool exists = vmgr->existsMap((sWorld.GetDataPath() + "vmaps").c_str(), mapid, gx, gy);
91  if (!exists)
92  {
93  std::string name = vmgr->getDirFileName(mapid, gx, gy);
94  sLog.outError("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());
95  return false;
96  }
97  }
98  }
99 
100  return true;
101 }
102 
103 void Map::LoadMMap(int gx, int gy)
104 {
106  return;
107 
108  bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(GetId(), gx, gy);
109  if (mmapLoadResult)
110  sLog.outDetail("MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
111  else
112  sLog.outDetail("Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
113 }
114 
115 void Map::LoadVMap(int gx, int gy)
116 {
117  if (!VMAP::VMapFactory::createOrGetVMapManager()->isMapLoadingEnabled())
118  return;
119  // x and y are swapped !!
120  int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath() + "vmaps").c_str(), GetId(), gx, gy);
121  switch (vmapLoadResult)
122  {
124  sLog.outVMap("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
125  break;
127  sLog.outVMap("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
128  break;
130  DEBUG_LOG("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
131  break;
132  }
133 }
134 
135 void Map::LoadMap(int gx, int gy, bool reload)
136 {
137  if (i_InstanceId != 0)
138  {
139  if (GridMaps[gx][gy])
140  return;
141 
142  // load grid map for base map
143  if (!m_parentMap->GridMaps[gx][gy])
145 
146  ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridCoord(gx, gy));
147  GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy];
148  return;
149  }
150 
151  if (GridMaps[gx][gy] && !reload)
152  return;
153 
154  //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?)
155  if (GridMaps[gx][gy])
156  {
157  sLog.outDetail("Unloading previously loaded map %u before reloading.", GetId());
158  delete (GridMaps[gx][gy]);
159  GridMaps[gx][gy] = nullptr;
160  }
161 
162  // map file name
163  char* tmp = nullptr;
164  int len = sWorld.GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1;
165  tmp = new char[len];
166  snprintf(tmp, len, (char*)(sWorld.GetDataPath() + "maps/%03u%02u%02u.map").c_str(), GetId(), gx, gy);
167  sLog.outDetail("Loading map %s", tmp);
168  // loading data
169  GridMaps[gx][gy] = new GridMap();
170  if (!GridMaps[gx][gy]->loadData(tmp))
171  sLog.outError("Error loading map file: \n %s\n", tmp);
172  delete [] tmp;
173 }
174 
175 void Map::LoadMapAndVMap(int gx, int gy)
176 {
177  LoadMap(gx, gy);
178  // Only load the data for the base map
179  if (i_InstanceId == 0)
180  {
181  LoadVMap(gx, gy);
182  LoadMMap(gx, gy);
183  }
184 }
185 
187 {
188  si_GridStates[GRID_STATE_INVALID] = new InvalidState;
189  si_GridStates[GRID_STATE_ACTIVE] = new ActiveState;
190  si_GridStates[GRID_STATE_IDLE] = new IdleState;
191  si_GridStates[GRID_STATE_REMOVAL] = new RemovalState;
192 }
193 
195 {
196  delete si_GridStates[GRID_STATE_INVALID];
197  delete si_GridStates[GRID_STATE_ACTIVE];
198  delete si_GridStates[GRID_STATE_IDLE];
199  delete si_GridStates[GRID_STATE_REMOVAL];
200 }
201 
202 Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent):
203  i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
208 {
209  m_parentMap = (_parent ? _parent : this);
210 
211  for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
212  {
213  for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j)
214  {
215  //z code
216  GridMaps[idx][j] = NULL;
217  setNGrid(NULL, idx, j);
218  }
219  }
220 
221  //lets initialize visibility distance for map
223 }
224 
226 {
227  //init visibility for continents
228  m_VisibleDistance = sWorld.GetMaxVisibleDistanceOnContinents();
230 }
231 
232 // Template specialization of utility methods
233 template<class T>
234 void Map::AddToGrid(T* obj, Cell const& cell)
235 {
236  NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
237  if (obj->IsWorldObject())
238  grid->GetGridType(cell.CellX(), cell.CellY()).template AddWorldObject<T>(obj);
239  else
240  grid->GetGridType(cell.CellX(), cell.CellY()).template AddGridObject<T>(obj);
241 }
242 
243 template<>
244 void Map::AddToGrid(Creature* obj, Cell const& cell)
245 {
246  NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
247  if (obj->IsWorldObject())
248  grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj);
249  else
250  grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
251 
252  obj->SetCurrentCell(cell);
253 }
254 
255 template<>
256 void Map::AddToGrid(Corpse* obj, Cell const& cell)
257 {
258  NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
259  if (grid->isGridObjectDataLoaded())
260  {
261  if (obj->IsWorldObject())
262  grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj);
263  else
264  grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
265  }
266 }
267 
269 {
272  if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
273  {
274  sLog.outError("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);
275  return;
276  }
277 
278  Cell cell(p);
279  if (!IsGridLoaded(GridCoord(cell.data.Part.grid_x, cell.data.Part.grid_y)))
280  return;
281 
282  DEBUG_LOG("Switch object " UI64FMTD " from grid[%u,%u] %u", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
283  NGridType* ngrid = getNGrid(cell.GridX(), cell.GridY());
284  ASSERT(ngrid != NULL);
285 
286  GridType &grid = ngrid->GetGridType(cell.CellX(), cell.CellY());
287 
288  obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
289  if (on)
290  {
291  grid.AddWorldObject(obj);
292  AddWorldObject(obj);
293  }
294  else
295  {
296  grid.AddGridObject(obj);
297  RemoveWorldObject(obj);
298  }
299 
300  obj->m_isTempWorldObject = on;
301 }
302 
303 template<class T>
305 {
306  // Note: In case resurrectable corpse and pet its removed from global lists in own destructor
307  delete obj;
308 }
309 
310 template<>
312 {
314  delete pl;
315 }
316 
317 //Create NGrid so the object can be added to it
318 //But object data is not loaded here
320 {
321  if (!getNGrid(p.x_coord, p.y_coord))
322  {
323  Guard guard(*this);
324  if (!getNGrid(p.x_coord, p.y_coord))
325  {
326  sLog.outMap("Creating grid[%u,%u] for map %u instance %u", p.x_coord, p.y_coord, GetId(), i_InstanceId);
327 
329  p.x_coord, p.y_coord);
330 
331  // build a linkage between this map and NGridType
333 
335 
336  //z coord
337  int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
338  int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
339 
340  if (!GridMaps[gx][gy])
341  LoadMapAndVMap(gx, gy);
342  }
343  }
344 }
345 
346 //Load NGrid and make it active
348 {
349  EnsureGridLoaded(cell);
350  NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
351  ASSERT(grid != NULL);
352 
353  // refresh grid state & timer
354  if (grid->GetGridState() != GRID_STATE_ACTIVE)
355  {
356  sLog.outDebug("Active object " UI64FMTD " triggers loading of grid [%u, %u] on map %u", object->GetGUID(), cell.GridX(), cell.GridY(), GetId());
357  ResetGridExpiry(*grid, 0.1f);
359  }
360 }
361 
362 //Create NGrid and load the object data in it
363 bool Map::EnsureGridLoaded(const Cell& cell)
364 {
365  EnsureGridCreated(GridCoord(cell.GridX(), cell.GridY()));
366  NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
367 
368  ASSERT(grid != NULL);
369  if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY()))
370  {
371  sLog.outMap("Loading grid[%u,%u] for map %u instance %u", cell.GridX(), cell.GridY(), GetId(), i_InstanceId);
372 
373  setGridObjectDataLoaded(true, cell.GridX(), cell.GridY());
374 
375  ObjectGridLoader loader(*grid, this, cell);
376  loader.LoadN();
377 
378  // Add resurrectable corpses to world object list in grid
379  ObjectAccessor::Instance().AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this);
380 
381  Balance();
382  return true;
383  }
384 
385  return false;
386 }
387 
388 void Map::LoadGrid(float x, float y)
389 {
390  EnsureGridLoaded(Cell(x, y));
391 }
392 
394 {
395  // Check if we are adding to correct map
396  ASSERT (player->GetMap() == this);
397 
399  if (p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
400  {
401  sLog.outError("Map::AddToMap: Player (GUID: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), p.x_coord, p.y_coord);
402  return false;
403  }
404 
405  player->SetMap(this);
406 
407  Cell cell(p);
408  EnsureGridLoadedForActiveObject(cell, player);
409  AddToGrid(player, cell);
410 
411  player->SetMap(this);
412  player->AddToWorld();
413 
414  SendInitSelf(player);
415  SendInitTransports(player);
416 
417  player->m_clientGUIDs.clear();
418  player->UpdateObjectVisibility(false);
419 
420  return true;
421 }
422 
423 template<class T>
424 bool Map::AddToMap(T *obj)
425 {
426  if (obj->IsInWorld()) // need some clean up later
427  {
428  obj->UpdateObjectVisibility(true);
429  return true;
430  }
431 
432  CellCoord p = Oregon::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
434  {
435  sLog.outError("Map::AddToMap: 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);
436  return false;
437  }
438 
439  Cell cell(p);
440  if (obj->isActiveObject())
442  else
443  EnsureGridCreated(GridCoord(cell.GridX(), cell.GridY()));
444 
445  AddToGrid(obj, cell);
446  obj->AddToWorld();
447 
448  if (obj->isActiveObject())
449  AddToActive(obj);
450 
451  DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());
452 
453  //trigger needs to cast spell, if not update, cannot see visual
454  obj->UpdateObjectVisibility(true);
455 
456  return true;
457 }
458 
460 {
461  // Check for valid position
462  if (!obj->IsPositionValid())
463  return;
464 
465  // Update mobs/objects in ALL visible cells around object!
467 
468  for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
469  {
470  for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
471  {
472  // marked cells are those that have been visited
473  // don't visit the same cell twice
474  uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
475  if (isCellMarked(cell_id))
476  continue;
477 
478  markCell(cell_id);
479  CellCoord pair(x, y);
480  Cell cell(pair);
481  cell.SetNoCreate();
482  Visit(cell, gridVisitor);
483  Visit(cell, worldVisitor);
484  }
485  }
486 }
487 
488 bool Map::IsGridLoaded(const GridCoord &p) const
489 {
491 }
492 
493 void Map::Update(const uint32& t_diff)
494 {
495  m_dyn_tree.update(t_diff);
496 
497  // update active cells around players and active objects
499 
500  Oregon::ObjectUpdater updater(t_diff);
501  // for creature
503  // for pets
505 
506  // the player iterator is stored in the map object
507  // to make sure calls to Map::RemoveFromMap don't invalidate it
509  {
510  Player* player = m_mapRefIter->GetSource();
511 
512  if (!player || !player->IsInWorld())
513  continue;
514 
515  player->Update(t_diff);
516 
517  VisitNearbyCellsOf(player, grid_object_update, world_object_update);
518 
519  // If player is using far sight, visit that object too
520  if (WorldObject* viewPoint = player->GetViewpoint())
521  {
522  if (Creature* viewCreature = viewPoint->ToCreature())
523  VisitNearbyCellsOf(viewCreature, grid_object_update, world_object_update);
524  else if (DynamicObject* viewObject = viewPoint->ToDynObject())
525  VisitNearbyCellsOf(viewObject, grid_object_update, world_object_update);
526  }
527 
528  // Handle updates for creatures in combat with player and are more than 60 yards away
529  if (player->IsInCombat())
530  {
531  std::vector<Creature*> updateList;
533 
534  while (ref)
535  {
536  if (Unit* unit = ref->GetSource()->getOwner())
537  if (unit->ToCreature() && unit->GetMapId() == player->GetMapId() && !unit->IsWithinDistInMap(player, GetVisibilityRange(), false))
538  updateList.push_back(unit->ToCreature());
539 
540  ref = ref->next();
541  }
542 
543  // Process deferred update list for player
544  for (Creature* c : updateList)
545  VisitNearbyCellsOf(c, grid_object_update, world_object_update);
546  }
547  }
548 
549  // non-player active objects, increasing iterator in the loop in case of object removal
551  {
554 
555  if (!obj || !obj->IsInWorld())
556  continue;
557 
558  VisitNearbyCellsOf(obj, grid_object_update, world_object_update);
559  }
560 
561  // Process necessary scripts
562  if (!m_scriptSchedule.empty())
563  {
564  i_scriptLock = true;
565  ScriptsProcess();
566  i_scriptLock = false;
567  }
568 
570 
571  if (!m_mapRefManager.isEmpty() || !m_activeNonPlayers.empty())
573 }
574 
576 {
577  template<class T>inline void resetNotify(GridRefManager<T>& m)
578  {
579  for (typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
580  iter->GetSource()->ResetAllNotifies();
581  }
582  template<class T> void Visit(GridRefManager<T>&) {}
584  {
585  resetNotify<Creature>(m);
586  }
588  {
589  resetNotify<Player>(m);
590  }
591 };
592 
594 {
596  {
597  NGridType* grid = i->GetSource();
598 
599  if (grid->GetGridState() != GRID_STATE_ACTIVE)
600  continue;
601 
602  grid->getGridInfoRef()->getRelocationTimer().TUpdate(diff);
603  if (!grid->getGridInfoRef()->getRelocationTimer().TPassed())
604  continue;
605 
606  uint32 gx = grid->getX(), gy = grid->getY();
607  float monsterSightRadius = (float)sWorld.getConfig(CONFIG_SIGHT_MONSTER);
608 
609  CellCoord cell_min(gx * MAX_NUMBER_OF_CELLS, gy * MAX_NUMBER_OF_CELLS);
610  CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord + MAX_NUMBER_OF_CELLS);
611 
612  for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x)
613  {
614  for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y)
615  {
616  uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
617  if (!isCellMarked(cell_id))
618  continue;
619 
620  CellCoord pair(x, y);
621  Cell cell(pair);
622  cell.SetNoCreate();
623 
624  Oregon::DelayedUnitRelocation cell_relocationCreature(cell, pair, *this, monsterSightRadius);
625  Oregon::DelayedUnitRelocation cell_relocationPlayer(cell, pair, *this, MAX_VISIBILITY_DISTANCE);
626  TypeContainerVisitor<Oregon::DelayedUnitRelocation, GridTypeMapContainer > grid_object_relocation(cell_relocationCreature);
627  TypeContainerVisitor<Oregon::DelayedUnitRelocation, WorldTypeMapContainer > world_object_relocation(cell_relocationPlayer);
628  Visit(cell, grid_object_relocation);
629  Visit(cell, world_object_relocation);
630  }
631  }
632  }
633 
634  ResetNotifier reset;
638  {
639  NGridType* grid = i->GetSource();
640 
641  if (grid->GetGridState() != GRID_STATE_ACTIVE)
642  continue;
643 
644  if (!grid->getGridInfoRef()->getRelocationTimer().TPassed())
645  continue;
646 
648 
649  uint32 gx = grid->getX(), gy = grid->getY();
650 
651  CellCoord cell_min(gx * MAX_NUMBER_OF_CELLS, gy * MAX_NUMBER_OF_CELLS);
652  CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord + MAX_NUMBER_OF_CELLS);
653 
654  for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x)
655  {
656  for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y)
657  {
658  uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
659  if (!isCellMarked(cell_id))
660  continue;
661 
662  CellCoord pair(x, y);
663  Cell cell(pair);
664  cell.SetNoCreate();
665  Visit(cell, grid_notifier);
666  Visit(cell, world_notifier);
667  }
668  }
669  }
670 }
671 
672 void Map::RemovePlayerFromMap(Player* player, bool remove)
673 {
674  player->RemoveFromWorld();
675  SendRemoveTransports(player);
676 
677  player->UpdateObjectVisibility(true);
678  if (player->IsInGrid())
679  player->RemoveFromGrid();
680  else
681  ASSERT(remove); //maybe deleted in logoutplayer when player is not in a map
682 
683  if (remove)
684  DeleteFromWorld(player);
685 }
686 
687 template<class T>
688 void Map::RemoveFromMap(T *obj, bool remove)
689 {
690  obj->RemoveFromWorld();
691  if (obj->isActiveObject())
692  RemoveFromActive(obj);
693 
694  obj->UpdateObjectVisibility(true);
695  obj->RemoveFromGrid();
696 
697  obj->ResetMap();
698 
699  if (remove)
700  {
701  // if option set then object already saved at this moment
703  obj->SaveRespawnTime();
704  DeleteFromWorld(obj);
705  }
706 }
707 
708 void
709 Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
710 {
711  ASSERT(player);
712 
713  Cell old_cell(player->GetPositionX(), player->GetPositionY());
714  Cell new_cell(x, y);
715 
716  player->Relocate(x, y, z, orientation);
717 
718  if (old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell))
719  {
720  DEBUG_LOG("Player %s relocation grid[%u,%u]cell[%u,%u]->grid[%u,%u]cell[%u,%u]", player->GetName(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
721 
722  player->RemoveFromGrid();
723 
724  if (old_cell.DiffGrid(new_cell))
725  EnsureGridLoadedForActiveObject(new_cell, player);
726 
727  AddToGrid(player, new_cell);
728  }
729 
730  player->UpdateObjectVisibility(false);
731 }
732 
733 void
734 Map::CreatureRelocation(Creature* creature, float x, float y, float z, float ang, bool respawnRelocationOnFail)
735 {
736  ASSERT(CheckGridIntegrity(creature, false));
737 
738  Cell old_cell = creature->GetCurrentCell();
739  Cell new_cell(x, y);
740 
741  if (!respawnRelocationOnFail && !getNGrid(new_cell.GridX(), new_cell.GridY()))
742  return;
743 
744  // delay creature move for grid/cell to grid/cell moves
745  if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
746  {
747  #ifdef OREGON_DEBUG
748  sLog.outMap("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());
749  #endif
750  AddCreatureToMoveList(creature, x, y, z, ang);
751  // in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList
752  }
753  else
754  {
755  creature->Relocate(x, y, z, ang);
756  creature->UpdateObjectVisibility(false);
757  }
758 
759  ASSERT(CheckGridIntegrity(creature, true));
760 }
761 
762 void Map::AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang)
763 {
764  if (!c)
765  return;
766 
767  i_creaturesToMove[c] = CreatureMover(x, y, z, ang);
768 }
769 
771 {
772  while (!i_creaturesToMove.empty())
773  {
774  // get data and remove element;
775  CreatureMoveList::iterator iter = i_creaturesToMove.begin();
776  Creature* c = iter->first;
777  CreatureMover cm = iter->second;
778  i_creaturesToMove.erase(iter);
779 
780  // calculate cells
781  CellCoord new_val = Oregon::ComputeCellCoord(cm.x, cm.y);
782  Cell new_cell(new_val);
783 
784  // do move or do move to respawn or remove creature if previous all fail
785  if (CreatureCellRelocation(c, new_cell))
786  {
787  // update pos
788  c->Relocate(cm.x, cm.y, cm.z, cm.ang);
789  //CreatureRelocationNotify(c,new_cell,new_cell.cellPair());
790  c->UpdateObjectVisibility(false);
791  }
792  else
793  {
794  // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid
795  // creature coordinates will be updated and notifiers send
797  {
798  // ... or unload (if respawn grid also not loaded)
799  #ifdef OREGON_DEBUG
800  sLog.outMap("Creature (GUID: %u Entry: %u) cannot be move to unloaded respawn grid.", c->GetGUIDLow(), c->GetEntry());
801  #endif
802  // crash fix for pets moving to unloaded cells.
803  if (c->IsPet())
804  ((Pet*)c)->Remove(PET_SAVE_NOT_IN_SLOT, true);
805  else
807  }
808  }
809  }
810 }
811 
813 {
814  Cell const& old_cell = c->GetCurrentCell();
815  if (!old_cell.DiffGrid(new_cell)) // in same grid
816  {
817  // if in same cell then none do
818  if (old_cell.DiffCell(new_cell))
819  {
820  #ifdef OREGON_DEBUG
821  sLog.outMap("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());
822  #endif
823 
824  c->RemoveFromGrid();
825  AddToGrid(c, new_cell);
826  }
827  else
828  {
829  #ifdef OREGON_DEBUG
830  sLog.outMap("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());
831  #endif
832  }
833 
834  return true;
835  }
836 
837  // in diff. grids but active creature
838  if (c->isActiveObject())
839  {
840  EnsureGridLoadedForActiveObject(new_cell, c);
841 
842  #ifdef OREGON_DEBUG
843  sLog.outMap("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());
844  #endif
845 
846  c->RemoveFromGrid();
847  AddToGrid(c, new_cell);
848 
849  return true;
850  }
851 
852  // in diff. loaded grid normal creature
853  if (IsGridLoaded(GridCoord(new_cell.GridX(), new_cell.GridY())))
854  {
855  #ifdef OREGON_DEBUG
856  sLog.outMap("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());
857  #endif
858 
859  c->RemoveFromGrid();
860  EnsureGridCreated(GridCoord(new_cell.GridX(), new_cell.GridY()));
861  AddToGrid(c, new_cell);
862 
863  return true;
864  }
865 
866  // fail to move: normal creature attempt move to unloaded grid
867  #ifdef OREGON_DEBUG
868  sLog.outMap("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());
869  #endif
870  return false;
871 }
872 
874 {
875  float resp_x, resp_y, resp_z, resp_o;
876  c->GetRespawnPosition(resp_x, resp_y, resp_z, &resp_o);
877 
878  Cell resp_cell(resp_x, resp_y);
879 
880  c->CombatStop();
881  c->GetMotionMaster()->Clear();
882 
883  #ifdef OREGON_DEBUG
884  sLog.outMap("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());
885  #endif
886 
887  // teleport it to respawn point (like normal respawn if player see)
888  if (CreatureCellRelocation(c, resp_cell))
889  {
890  c->Relocate(resp_x, resp_y, resp_z, resp_o);
891  c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators
892  //CreatureRelocationNotify(c,resp_cell,resp_cell.cellPair());
893  c->UpdateObjectVisibility(false);
894  return true;
895  }
896  else
897  return false;
898 }
899 
900 bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll)
901 {
902  const uint32 x = ngrid.getX();
903  const uint32 y = ngrid.getY();
904 
905  {
906  if (!unloadAll)
907  {
908  //pets, possessed creatures (must be active), transport passengers
910  return false;
911 
912  if (ActiveObjectsNearGrid(ngrid))
913  return false;
914  }
915 
916  sLog.outMap("Unloading grid[%u,%u] for map %u", x, y, GetId());
917 
918  if (!unloadAll)
919  {
920  // Finish creature moves, remove and delete all creatures with delayed remove before moving to respawn grids
921  // Must know real mob position before move
923 
924  // move creatures to respawn grids if this is diff.grid or to remove list
925  ObjectGridEvacuator worker;
927  ngrid.VisitAllGrids(visitor);
928 
929  // Finish creature moves, remove and delete all creatures with delayed remove before unload
931  }
932 
933  {
934  ObjectGridCleaner worker;
936  ngrid.VisitAllGrids(visitor);
937  }
938 
940 
941  {
942  ObjectGridUnloader worker;
944  ngrid.VisitAllGrids(visitor);
945  }
946 
947  ASSERT(i_objectsToRemove.empty());
948 
949  delete &ngrid;
950  setNGrid(NULL, x, y);
951  }
952 
953  int gx = (MAX_NUMBER_OF_GRIDS - 1) - x;
954  int gy = (MAX_NUMBER_OF_GRIDS - 1) - y;
955 
956  // delete grid map, but don't delete if it is from parent map (and thus only reference)
957  //+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps
958  {
959  if (i_InstanceId == 0)
960  {
961  if (GridMaps[gx][gy])
962  {
963  GridMaps[gx][gy]->unloadData();
964  delete GridMaps[gx][gy];
965  }
968  }
969  else
970  ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy));
971 
972  GridMaps[gx][gy] = NULL;
973  }
974  DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x, y, GetId());
975  return true;
976 }
977 
979 {
980  if (HavePlayers())
981  {
982  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
983  {
984  Player* plr = itr->GetSource();
985  if (!plr->IsBeingTeleportedFar())
986  {
987  // this is happening for bg
988  sLog.outError("Map::UnloadAll: player %s is still in map %u during unload, this should not happen!", plr->GetName(), GetId());
989  plr->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation());
990  }
991  }
992  }
993 }
994 
996 {
997  // clear all delayed moves, useless anyway do this moves before map unload.
998  i_creaturesToMove.clear();
999 
1001  {
1002  NGridType& grid(*i->GetSource());
1003  ++i;
1004  UnloadGrid(grid, true); // deletes the grid and removes it from the GridRefManager
1005  }
1006 }
1007 
1008 //*****************************
1009 // Grid function
1010 //*****************************
1012 {
1013  m_flags = 0;
1014  // Area data
1015  m_gridArea = 0;
1016  m_area_map = NULL;
1017  // Height level data
1018  m_gridHeight = INVALID_HEIGHT;
1019  m_gridGetHeight = &GridMap::getHeightFromFlat;
1020  m_V9 = NULL;
1021  m_V8 = NULL;
1022  // Liquid data
1023  m_liquidType = 0;
1024  m_liquid_offX = 0;
1025  m_liquid_offY = 0;
1026  m_liquid_width = 0;
1027  m_liquid_height = 0;
1028  m_liquidLevel = INVALID_HEIGHT;
1029  _liquidEntry = NULL;
1030  _liquidFlags = NULL;
1031  _liquidMap = NULL;
1032 }
1033 
1035 {
1036  unloadData();
1037 }
1038 
1039 bool GridMap::loadData(const char* filename)
1040 {
1041  // Unload old data if exist
1042  unloadData();
1043 
1044  map_fileheader header;
1045  // Not return error if file not found
1046  FILE* in = fopen(filename, "rb");
1047  if (!in)
1048  return true;
1049 
1050  if (fread(&header, sizeof(header), 1, in) != 1)
1051  {
1052  fclose(in);
1053  return false;
1054  }
1055 
1056  if (header.mapMagic == uint32(MAP_MAGIC) && header.versionMagic == uint32(MAP_VERSION_MAGIC))
1057  {
1058  // loadup area data
1059  if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize))
1060  {
1061  sLog.outError("Error loading map area data\n");
1062  fclose(in);
1063  return false;
1064  }
1065  // loadup height data
1066  if (header.heightMapOffset && !loadHeightData(in, header.heightMapOffset, header.heightMapSize))
1067  {
1068  sLog.outError("Error loading map height data\n");
1069  fclose(in);
1070  return false;
1071  }
1072  // loadup liquid data
1073  if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize))
1074  {
1075  sLog.outError("Error loading map liquids data\n");
1076  fclose(in);
1077  return false;
1078  }
1079  fclose(in);
1080  return true;
1081  }
1082  sLog.outError("Map file '%s' is from an incompatible clientversion. Please recreate using the mapextractor.", filename);
1083  fclose(in);
1084  return false;
1085 }
1086 
1088 {
1089  delete[] m_area_map;
1090  delete[] m_V9;
1091  delete[] m_V8;
1092  delete[] _liquidEntry;
1093  delete[] _liquidFlags;
1094  delete[] _liquidMap;
1095  m_area_map = NULL;
1096  m_V9 = NULL;
1097  m_V8 = NULL;
1098  _liquidEntry = NULL;
1099  _liquidFlags = NULL;
1100  _liquidMap = NULL;
1101  m_gridGetHeight = &GridMap::getHeightFromFlat;
1102 }
1103 
1104 bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/)
1105 {
1106  map_areaHeader header;
1107  fseek(in, offset, SEEK_SET);
1108 
1109  if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != uint32(MAP_AREA_MAGIC))
1110  return false;
1111 
1112  m_gridArea = header.gridArea;
1113  if (!(header.flags & MAP_AREA_NO_AREA))
1114  {
1115  m_area_map = new uint16 [16 * 16];
1116  if (fread(m_area_map, sizeof(uint16), 16 * 16, in) != 16 * 16)
1117  return false;
1118  }
1119  return true;
1120 }
1121 
1122 bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/)
1123 {
1124  map_heightHeader header;
1125  fseek(in, offset, SEEK_SET);
1126 
1127  if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != uint32(MAP_HEIGHT_MAGIC))
1128  return false;
1129 
1130  m_gridHeight = header.gridHeight;
1131  if (!(header.flags & MAP_HEIGHT_NO_HEIGHT))
1132  {
1133  if ((header.flags & MAP_HEIGHT_AS_INT16))
1134  {
1135  m_uint16_V9 = new uint16 [129 * 129];
1136  m_uint16_V8 = new uint16 [128 * 128];
1137  if (fread(m_uint16_V9, sizeof(uint16), 129 * 129, in) != 129 * 129 ||
1138  fread(m_uint16_V8, sizeof(uint16), 128 * 128, in) != 128 * 128)
1139  return false;
1140  m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;
1141  m_gridGetHeight = &GridMap::getHeightFromUint16;
1142  }
1143  else if ((header.flags & MAP_HEIGHT_AS_INT8))
1144  {
1145  m_uint8_V9 = new uint8 [129 * 129];
1146  m_uint8_V8 = new uint8 [128 * 128];
1147  if (fread(m_uint8_V9, sizeof(uint8), 129 * 129, in) != 129 * 129 ||
1148  fread(m_uint8_V8, sizeof(uint8), 128 * 128, in) != 128 * 128)
1149  return false;
1150  m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255;
1151  m_gridGetHeight = &GridMap::getHeightFromUint8;
1152  }
1153  else
1154  {
1155  m_V9 = new float [129 * 129];
1156  m_V8 = new float [128 * 128];
1157  if (fread(m_V9, sizeof(float), 129 * 129, in) != 129 * 129 ||
1158  fread(m_V8, sizeof(float), 128 * 128, in) != 128 * 128)
1159  return false;
1160  m_gridGetHeight = &GridMap::getHeightFromFloat;
1161  }
1162  }
1163  else
1164  m_gridGetHeight = &GridMap::getHeightFromFlat;
1165  return true;
1166 }
1167 
1168 bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
1169 {
1170  map_liquidHeader header;
1171  fseek(in, offset, SEEK_SET);
1172 
1173  if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != uint32(MAP_LIQUID_MAGIC))
1174  return false;
1175 
1176  m_liquidType = header.liquidType;
1177  m_liquid_offX = header.offsetX;
1178  m_liquid_offY = header.offsetY;
1179  m_liquid_width = header.width;
1180  m_liquid_height = header.height;
1181  m_liquidLevel = header.liquidLevel;
1182 
1183  if (!(header.flags & MAP_LIQUID_NO_TYPE))
1184  {
1185  _liquidEntry = new uint16[16*16];
1186  if (fread(_liquidEntry, sizeof(uint16), 16*16, in) != 16*16)
1187  return false;
1188 
1189  _liquidFlags = new uint8[16*16];
1190  if (fread(_liquidFlags, sizeof(uint8), 16*16, in) != 16*16)
1191  return false;
1192  }
1193  if (!(header.flags & MAP_LIQUID_NO_HEIGHT))
1194  {
1195  _liquidMap = new float[m_liquid_width * m_liquid_height];
1196  if (fread(_liquidMap, sizeof(float), m_liquid_width * m_liquid_height, in) != m_liquid_width * m_liquid_height)
1197  return false;
1198  }
1199  return true;
1200 }
1201 
1202 uint16 GridMap::getArea(float x, float y)
1203 {
1204  if (!m_area_map)
1205  return m_gridArea;
1206 
1207  x = 16 * (CENTER_GRID_ID - x/SIZE_OF_GRIDS);
1208  y = 16 * (CENTER_GRID_ID - y/SIZE_OF_GRIDS);
1209  int lx = (int)x & 15;
1210  int ly = (int)y & 15;
1211  return m_area_map[lx * 16 + ly];
1212 }
1213 
1214 float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const
1215 {
1216  return m_gridHeight;
1217 }
1218 
1219 float GridMap::getHeightFromFloat(float x, float y) const
1220 {
1221  if (!m_V8 || !m_V9)
1222  return m_gridHeight;
1223 
1226 
1227  int x_int = (int)x;
1228  int y_int = (int)y;
1229  x -= x_int;
1230  y -= y_int;
1231  x_int &= (MAP_RESOLUTION - 1);
1232  y_int &= (MAP_RESOLUTION - 1);
1233 
1234  // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
1235  // +--------------> X
1236  // | h1-------h2 Coordinates is:
1237  // | | \ 1 / | h1 0,0
1238  // | | \ / | h2 0,1
1239  // | | 2 h5 3 | h3 1,0
1240  // | | / \ | h4 1,1
1241  // | | / 4 \ | h5 1/2,1/2
1242  // | h3-------h4
1243  // V Y
1244  // For find height need
1245  // 1 - detect triangle
1246  // 2 - solve linear equation from triangle points
1247  // Calculate coefficients for solve h = a*x + b*y + c
1248 
1249  float a, b, c;
1250  // Select triangle:
1251  if (x + y < 1)
1252  {
1253  if (x > y)
1254  {
1255  // 1 triangle (h1, h2, h5 points)
1256  float h1 = m_V9[(x_int) * 129 + y_int];
1257  float h2 = m_V9[(x_int + 1) * 129 + y_int];
1258  float h5 = 2 * m_V8[x_int * 128 + y_int];
1259  a = h2 - h1;
1260  b = h5 - h1 - h2;
1261  c = h1;
1262  }
1263  else
1264  {
1265  // 2 triangle (h1, h3, h5 points)
1266  float h1 = m_V9[x_int * 129 + y_int ];
1267  float h3 = m_V9[x_int * 129 + y_int + 1];
1268  float h5 = 2 * m_V8[x_int * 128 + y_int];
1269  a = h5 - h1 - h3;
1270  b = h3 - h1;
1271  c = h1;
1272  }
1273  }
1274  else
1275  {
1276  if (x > y)
1277  {
1278  // 3 triangle (h2, h4, h5 points)
1279  float h2 = m_V9[(x_int + 1) * 129 + y_int ];
1280  float h4 = m_V9[(x_int + 1) * 129 + y_int + 1];
1281  float h5 = 2 * m_V8[x_int * 128 + y_int];
1282  a = h2 + h4 - h5;
1283  b = h4 - h2;
1284  c = h5 - h4;
1285  }
1286  else
1287  {
1288  // 4 triangle (h3, h4, h5 points)
1289  float h3 = m_V9[(x_int) * 129 + y_int + 1];
1290  float h4 = m_V9[(x_int + 1) * 129 + y_int + 1];
1291  float h5 = 2 * m_V8[x_int * 128 + y_int];
1292  a = h4 - h3;
1293  b = h3 + h4 - h5;
1294  c = h5 - h4;
1295  }
1296  }
1297  // Calculate height
1298  return a * x + b * y + c;
1299 }
1300 
1301 float GridMap::getHeightFromUint8(float x, float y) const
1302 {
1303  if (!m_uint8_V8 || !m_uint8_V9)
1304  return m_gridHeight;
1305 
1308 
1309  int x_int = (int)x;
1310  int y_int = (int)y;
1311  x -= x_int;
1312  y -= y_int;
1313  x_int &= (MAP_RESOLUTION - 1);
1314  y_int &= (MAP_RESOLUTION - 1);
1315 
1316  int32 a, b, c;
1317  uint8* V9_h1_ptr = &m_uint8_V9[x_int * 128 + x_int + y_int];
1318  if (x + y < 1)
1319  {
1320  if (x > y)
1321  {
1322  // 1 triangle (h1, h2, h5 points)
1323  int32 h1 = V9_h1_ptr[ 0];
1324  int32 h2 = V9_h1_ptr[129];
1325  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1326  a = h2 - h1;
1327  b = h5 - h1 - h2;
1328  c = h1;
1329  }
1330  else
1331  {
1332  // 2 triangle (h1, h3, h5 points)
1333  int32 h1 = V9_h1_ptr[0];
1334  int32 h3 = V9_h1_ptr[1];
1335  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1336  a = h5 - h1 - h3;
1337  b = h3 - h1;
1338  c = h1;
1339  }
1340  }
1341  else
1342  {
1343  if (x > y)
1344  {
1345  // 3 triangle (h2, h4, h5 points)
1346  int32 h2 = V9_h1_ptr[129];
1347  int32 h4 = V9_h1_ptr[130];
1348  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1349  a = h2 + h4 - h5;
1350  b = h4 - h2;
1351  c = h5 - h4;
1352  }
1353  else
1354  {
1355  // 4 triangle (h3, h4, h5 points)
1356  int32 h3 = V9_h1_ptr[ 1];
1357  int32 h4 = V9_h1_ptr[130];
1358  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1359  a = h4 - h3;
1360  b = h3 + h4 - h5;
1361  c = h5 - h4;
1362  }
1363  }
1364  // Calculate height
1365  return (float)((a * x) + (b * y) + c) * m_gridIntHeightMultiplier + m_gridHeight;
1366 }
1367 
1368 float GridMap::getHeightFromUint16(float x, float y) const
1369 {
1370  if (!m_uint16_V8 || !m_uint16_V9)
1371  return m_gridHeight;
1372 
1375 
1376  int x_int = (int)x;
1377  int y_int = (int)y;
1378  x -= x_int;
1379  y -= y_int;
1380  x_int &= (MAP_RESOLUTION - 1);
1381  y_int &= (MAP_RESOLUTION - 1);
1382 
1383  int32 a, b, c;
1384  uint16* V9_h1_ptr = &m_uint16_V9[x_int * 128 + x_int + y_int];
1385  if (x + y < 1)
1386  {
1387  if (x > y)
1388  {
1389  // 1 triangle (h1, h2, h5 points)
1390  int32 h1 = V9_h1_ptr[ 0];
1391  int32 h2 = V9_h1_ptr[129];
1392  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1393  a = h2 - h1;
1394  b = h5 - h1 - h2;
1395  c = h1;
1396  }
1397  else
1398  {
1399  // 2 triangle (h1, h3, h5 points)
1400  int32 h1 = V9_h1_ptr[0];
1401  int32 h3 = V9_h1_ptr[1];
1402  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1403  a = h5 - h1 - h3;
1404  b = h3 - h1;
1405  c = h1;
1406  }
1407  }
1408  else
1409  {
1410  if (x > y)
1411  {
1412  // 3 triangle (h2, h4, h5 points)
1413  int32 h2 = V9_h1_ptr[129];
1414  int32 h4 = V9_h1_ptr[130];
1415  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1416  a = h2 + h4 - h5;
1417  b = h4 - h2;
1418  c = h5 - h4;
1419  }
1420  else
1421  {
1422  // 4 triangle (h3, h4, h5 points)
1423  int32 h3 = V9_h1_ptr[ 1];
1424  int32 h4 = V9_h1_ptr[130];
1425  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1426  a = h4 - h3;
1427  b = h3 + h4 - h5;
1428  c = h5 - h4;
1429  }
1430  }
1431  // Calculate height
1432  return (float)((a * x) + (b * y) + c) * m_gridIntHeightMultiplier + m_gridHeight;
1433 }
1434 
1435 float GridMap::getLiquidLevel(float x, float y)
1436 {
1437  if (!_liquidMap)
1438  return m_liquidLevel;
1439 
1442 
1443  int cx_int = ((int)x & (MAP_RESOLUTION - 1)) - m_liquid_offY;
1444  int cy_int = ((int)y & (MAP_RESOLUTION - 1)) - m_liquid_offX;
1445 
1446  if (cx_int < 0 || cx_int >= m_liquid_height)
1447  return INVALID_HEIGHT;
1448  if (cy_int < 0 || cy_int >= m_liquid_width)
1449  return INVALID_HEIGHT;
1450 
1451  return _liquidMap[cx_int * m_liquid_width + cy_int];
1452 }
1453 
1455 {
1456  if (!_liquidFlags)
1457  return 0;
1458 
1459  x = 16 * (CENTER_GRID_ID - x/SIZE_OF_GRIDS);
1460  y = 16 * (CENTER_GRID_ID - y/SIZE_OF_GRIDS);
1461  int lx = (int)x & 15;
1462  int ly = (int)y & 15;
1463  return _liquidFlags[lx * 16 + ly];
1464 }
1465 
1466 // Get water state on map
1467 inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
1468 {
1469  // Check water type (if no water return)
1470  if (!m_liquidType && !_liquidFlags)
1471  return LIQUID_MAP_NO_WATER;
1472 
1473  // Get cell
1474  float cx = MAP_RESOLUTION * (CENTER_GRID_ID - x/SIZE_OF_GRIDS);
1475  float cy = MAP_RESOLUTION * (CENTER_GRID_ID - y/SIZE_OF_GRIDS);
1476 
1477  int x_int = (int)cx & (MAP_RESOLUTION - 1);
1478  int y_int = (int)cy & (MAP_RESOLUTION - 1);
1479 
1480  // Check water type in cell
1481  int idx=(x_int>>3)*16 + (y_int>>3);
1482  uint8 type = _liquidFlags ? _liquidFlags[idx] : 1 << m_liquidType;
1483  uint32 entry = 0;
1484  if (_liquidEntry)
1485  {
1486  if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(_liquidEntry[idx]))
1487  {
1488  entry = liquidEntry->Id;
1489  uint32 liqTypeIdx = liquidEntry->Type;
1490  if ((entry < 21) && (type & MAP_LIQUID_TYPE_WATER))
1491  {
1492  // only basic liquid stored in maps actualy so in some case we need to override type depend on area
1493  // actualy only Hyjal Mount and Coilfang raid be overrided here
1494  if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(getArea(x, y), MAPID_INVALID))
1495  {
1496  uint32 overrideLiquid = area->LiquidTypeOverride;
1497  if (!overrideLiquid && area->zone)
1498  if (area = GetAreaEntryByAreaID(area->zone))
1499  overrideLiquid = area->LiquidTypeOverride;
1500 
1501  if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
1502  {
1503  entry = overrideLiquid;
1504  liqTypeIdx = liq->Type;
1505  }
1506  }
1507  }
1508 
1509  type |= (1 << liqTypeIdx) | (type & MAP_LIQUID_TYPE_DARK_WATER);
1510  }
1511  }
1512 
1513  if (type == 0)
1514  return LIQUID_MAP_NO_WATER;
1515 
1516  // Check req liquid type mask
1517  if (ReqLiquidType && !(ReqLiquidType & type))
1518  return LIQUID_MAP_NO_WATER;
1519 
1520  // Check water level:
1521  // Check water height map
1522  int lx_int = x_int - m_liquid_offY;
1523  int ly_int = y_int - m_liquid_offX;
1524  if (lx_int < 0 || lx_int >= m_liquid_height)
1525  return LIQUID_MAP_NO_WATER;
1526  if (ly_int < 0 || ly_int >= m_liquid_width)
1527  return LIQUID_MAP_NO_WATER;
1528 
1529  // Get water level
1530  float liquid_level = _liquidMap ? _liquidMap[lx_int * m_liquid_width + ly_int] : m_liquidLevel;
1531  // Get ground level (sub 0.2 for fix some errors)
1532  float ground_level = getHeight(x, y);
1533 
1534  // Check water level and ground level
1535  if (liquid_level < ground_level || z < ground_level - 2)
1536  return LIQUID_MAP_NO_WATER;
1537 
1538  // All ok in water -> store data
1539  if (data)
1540  {
1541  data->entry = entry;
1542  data->type_flags = type;
1543  data->level = liquid_level;
1544  data->depth_level = ground_level;
1545  }
1546 
1547  // For speed check as int values
1548  float delta = liquid_level - z;
1549 
1550  // Get position delta
1551  if (delta > 2.0f) // Under water
1552  return LIQUID_MAP_UNDER_WATER;
1553  if (delta > 0.0f) // In water
1554  return LIQUID_MAP_IN_WATER;
1555  if (delta > -0.1f) // Walk on water
1556  return LIQUID_MAP_WATER_WALK;
1557  // Above water
1558  return LIQUID_MAP_ABOVE_WATER;
1559 }
1560 
1561 inline GridMap* Map::GetGrid(float x, float y)
1562 {
1563  // half opt method
1564  int gx = (int)(CENTER_GRID_ID - x / SIZE_OF_GRIDS); //grid x
1565  int gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); //grid y
1566 
1567  // ensure GridMap is loaded
1569 
1570  return GridMaps[gx][gy];
1571 }
1572 
1573 float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool /*swim = false*/) const
1574 {
1575  if (const_cast<Map*>(this)->GetGrid(x, y))
1576  {
1577  // we need ground level (including grid height version) for proper return water level in point
1578  float ground_z = GetHeight(x, y, z, true, 50.0f);
1579  if (ground)
1580  *ground = ground_z;
1581 
1582  LiquidData liquid_status;
1583 
1584  ZLiquidStatus res = getLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status);
1585  return res ? liquid_status.level : ground_z;
1586  }
1587 
1589 }
1590 
1591 float Map::GetHeight(float x, float y, float z, bool checkVMap, float maxSearchDist) const
1592 {
1593  // find raw .map surface under Z coordinates
1594  float mapHeight = VMAP_INVALID_HEIGHT_VALUE;
1595  float realHeight = VMAP_INVALID_HEIGHT_VALUE;
1596  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1597  {
1598  float gridHeight = gmap->getHeight(x, y);
1599  // look from a bit higher pos to find the floor, ignore under surface case
1600  if (z + 2.0f > gridHeight)
1601  mapHeight = gridHeight;
1602  }
1603 
1604  float vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
1605  if (checkVMap)
1606  {
1608  if (vmgr->isHeightCalcEnabled())
1609  vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor
1610  }
1611 
1612  // Explicitly set map data, and use it if no change.
1613  realHeight = mapHeight;
1614 
1615  // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
1616  // vmapheight set for any under Z value or <= INVALID_HEIGHT
1617  if (vmapHeight > INVALID_HEIGHT)
1618  {
1619  if (mapHeight > INVALID_HEIGHT)
1620  {
1621  // we have mapheight and vmapheight and must select more appropriate
1622 
1623  // we are already under the surface or vmap height above map heigt
1624  // or if the distance of the vmap height is less the land height distance
1625  if (vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z))
1626  realHeight = vmapHeight;
1627  else
1628  realHeight = mapHeight; // better use .map surface height
1629  }
1630  else
1631  realHeight = vmapHeight; // we have only vmapHeight (if have)
1632  }
1633 
1634  return std::max<float>(realHeight, m_dyn_tree.getHeight(x, y, z, maxSearchDist));
1635 }
1636 
1637 inline bool IsOutdoorWMO(uint32 mogpFlags, uint32 mapId)
1638 {
1639  // if this flag is set we are outdoors and can mount up
1640  if (mogpFlags & 0x8000)
1641  return true;
1642 
1643  // if flag 0x800 is set and we are in non-flyable areas we cannot mount up even if we are physically outdoors
1644  if (mapId != 530 && mogpFlags & 0x800)
1645  return false;
1646 
1647  // if this flag is set we are physically outdoors, mounting up is allowed if previous check failed
1648  return mogpFlags & 0x8;
1649 }
1650 
1651 bool Map::IsOutdoors(float x, float y, float z) const
1652 {
1653  uint32 mogpFlags;
1654  int32 adtId, rootId, groupId;
1655 
1656  // no wmo found? -> outside by default
1657  if (!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
1658  return true;
1659 
1660  return IsOutdoorWMO(mogpFlags, i_mapEntry->MapID);
1661 }
1662 
1663 bool Map::GetAreaInfo(float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
1664 {
1665  float vmap_z = z;
1667  if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId))
1668  {
1669  // check if there's terrain between player height and object height
1670  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1671  {
1672  float _mapheight = gmap->getHeight(x, y);
1673  // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
1674  if (z + 2.0f > _mapheight && _mapheight > vmap_z)
1675  return false;
1676  }
1677  return true;
1678  }
1679  return false;
1680 }
1681 
1682 uint16 Map::GetAreaFlag(float x, float y, float z, bool* isOutdoors) const
1683 {
1684  uint32 mogpFlags;
1685  int32 adtId, rootId, groupId;
1686  WMOAreaTableEntry const* wmoEntry = 0;
1687  AreaTableEntry const* atEntry = 0;
1688  bool haveAreaInfo = false;
1689 
1690  if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
1691  {
1692  haveAreaInfo = true;
1693  if ((wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId)))
1694  atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
1695  }
1696 
1697  uint16 areaflag;
1698 
1699  if (atEntry)
1700  areaflag = atEntry->exploreFlag;
1701  else
1702  {
1703  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1704  areaflag = gmap->getArea(x, y);
1705  // this used while not all *.map files generated (instances)
1706  else
1707  areaflag = GetAreaFlagByMapId(i_mapEntry->MapID);
1708  }
1709 
1710  if (isOutdoors)
1711  {
1712  if (haveAreaInfo)
1713  *isOutdoors = IsOutdoorWMO(mogpFlags, i_mapEntry->MapID);
1714  else
1715  *isOutdoors = true;
1716  }
1717  return areaflag;
1718 }
1719 
1720 uint8 Map::GetTerrainType(float x, float y) const
1721 {
1722  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1723  return gmap->getTerrainType(x, y);
1724  else
1725  return 0;
1726 }
1727 
1728 ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const
1729 {
1732  float liquid_level = INVALID_HEIGHT;
1733  float ground_level = INVALID_HEIGHT;
1734  uint32 liquid_type = 0;
1735  if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type))
1736  {
1737  sLog.outVMap("getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type);
1738  // Check water level and ground level
1739  if (liquid_level > ground_level && z > ground_level - 2)
1740  {
1741  // All ok in water -> store data
1742  if (data)
1743  {
1744  // hardcoded in client like this convert ocean to lava
1745  if (GetId() == 530 && liquid_type == 2)
1746  liquid_type = 3;
1747 
1748  uint32 liquidFlagType = 0;
1749  if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquid_type))
1750  liquidFlagType = 1 << liq->Type;
1751 
1752  data->level = liquid_level;
1753  data->depth_level = ground_level;
1754 
1755  data->entry = liquid_type;
1756  data->type_flags = liquidFlagType;
1757  }
1758 
1759  // For speed check as int values
1760  float delta = liquid_level - z;
1761 
1762  // Get position delta
1763  if (delta > 2.0f) // Under water
1764  return LIQUID_MAP_UNDER_WATER;
1765  if (delta > 0.0f) // In water
1766  return LIQUID_MAP_IN_WATER;
1767  if (delta > -0.1f) // Walk on water
1768  return LIQUID_MAP_WATER_WALK;
1769  result = LIQUID_MAP_ABOVE_WATER;
1770  }
1771  }
1772 
1773  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1774  {
1775  LiquidData map_data;
1776  ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data);
1777  // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
1778  if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
1779  {
1780  if (data)
1781  {
1782  // hardcoded in client like this
1783  if (GetId() == 530 && map_data.entry == 2)
1784  map_data.entry = 15;
1785 
1786  *data = map_data;
1787  }
1788  return map_result;
1789  }
1790  }
1791  return result;
1792 }
1793 
1794 float Map::GetWaterLevel(float x, float y) const
1795 {
1796  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1797  return gmap->getLiquidLevel(x, y);
1798  else
1799  return 0;
1800 }
1801 
1802 bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2) const
1803 {
1804  return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
1805  && m_dyn_tree.isInLineOfSight(x1, y1, z1, x2, y2, z2);
1806 }
1807 
1808 bool Map::getObjectHitPos(float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
1809 {
1810  G3D::Vector3 startPos = G3D::Vector3(x1, y1, z1);
1811  G3D::Vector3 dstPos = G3D::Vector3(x2, y2, z2);
1812 
1813  G3D::Vector3 resultPos;
1814  bool result = m_dyn_tree.getObjectHitPos(startPos, dstPos, resultPos, modifyDist);
1815 
1816  rx = resultPos.x;
1817  ry = resultPos.y;
1818  rz = resultPos.z;
1819  return result;
1820 }
1821 
1823 {
1824  AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
1825 
1826  if (entry)
1827  return entry->ID;
1828  else
1829  return 0;
1830 }
1831 
1833 {
1834  AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
1835 
1836  if (entry)
1837  return (entry->zone != 0) ? entry->zone : entry->ID;
1838  else
1839  return 0;
1840 }
1841 
1842 bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const
1843 {
1844  LiquidData liquid_status;
1845  LiquidData* liquid_ptr = data ? data : &liquid_status;
1846  return (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0;
1847 }
1848 
1849 bool Map::IsUnderWater(float x, float y, float z) const
1850 {
1851  if (const_cast<Map*>(this)->GetGrid(x, y))
1852  {
1854  return true;
1855  }
1856  return false;
1857 }
1858 
1859 bool Map::IsSwimmable(float x, float y, float z, LiquidData* data) const
1860 {
1861  LiquidData liquid_status;
1862  LiquidData* liquid_ptr = data ? data : &liquid_status;
1864  {
1865  if (liquid_ptr->level - liquid_ptr->depth_level > 1.5f)
1866  return true;
1867  }
1868 
1869  return false;
1870 }
1871 
1872 bool Map::CheckGridIntegrity(Creature* c, bool moved) const
1873 {
1874  Cell const& cur_cell = c->GetCurrentCell();
1875 
1876  Cell xy_cell(c->GetPositionX(), c->GetPositionY());
1877  if (xy_cell != cur_cell)
1878  {
1879  sLog.outMap("Creature (GUID: %u) X: %f Y: %f (%s) is in grid[%u,%u]cell[%u,%u] instead of grid[%u,%u]cell[%u,%u]",
1880  c->GetGUIDLow(),
1881  c->GetPositionX(), c->GetPositionY(), (moved ? "final" : "original"),
1882  cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(),
1883  xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY());
1884  return true; // not crash at error, just output error in debug mode
1885  }
1886 
1887  return true;
1888 }
1889 
1890 const char* Map::GetMapName() const
1891 {
1892  return i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0";
1893 }
1894 
1896 {
1897  cell.SetNoCreate();
1898  Oregon::VisibleChangesNotifier notifier(*obj);
1900  cell.Visit(cellpair, player_notifier, *this, *obj, obj->GetVisibilityRange());
1901 }
1902 
1904 {
1905  Oregon::VisibleNotifier notifier(*player);
1906 
1907  cell.SetNoCreate();
1910  cell.Visit(cellpair, world_notifier, *this, *player->m_seer, player->GetVisibilityRange());
1911  cell.Visit(cellpair, grid_notifier, *this, *player->m_seer, player->GetVisibilityRange());
1912 
1913  // send data
1914  notifier.SendToSelf();
1915 }
1916 
1918 {
1919  sLog.outDetail("Creating player data for himself %u", player->GetGUIDLow());
1920 
1921  UpdateData data;
1922 
1923  bool hasTransport = false;
1924 
1925  // attach to player data current transport data
1926  if (Transport* transport = player->GetTransport())
1927  {
1928  hasTransport = true;
1929  transport->BuildCreateUpdateBlockForPlayer(&data, player);
1930  }
1931 
1932  // build data for self presence in world at own client (one time for map)
1933  player->BuildCreateUpdateBlockForPlayer(&data, player);
1934 
1935  // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
1936  if (Transport* transport = player->GetTransport())
1937  {
1938  for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
1939  {
1940  if (player != (*itr) && player->HaveAtClient(*itr))
1941  {
1942  hasTransport = true;
1943  (*itr)->BuildCreateUpdateBlockForPlayer(&data, player);
1944  }
1945  }
1946  }
1947 
1948  WorldPacket packet;
1949  data.BuildPacket(&packet, hasTransport);
1950  player->GetSession()->SendPacket(&packet);
1951 }
1952 
1954 {
1955  // Hack to send out transports
1957 
1958  // no transports at map
1959  if (tmap.find(player->GetMapId()) == tmap.end())
1960  return;
1961 
1962  UpdateData transData;
1963 
1964  MapManager::TransportSet& tset = tmap[player->GetMapId()];
1965 
1966  bool hasTransport = false;
1967 
1968  for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
1969  {
1970  // send data for current transport in other place
1971  if ((*i) != player->GetTransport() && (*i)->GetMapId() == GetId())
1972  {
1973  hasTransport = true;
1974  (*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
1975  }
1976  }
1977 
1978  WorldPacket packet;
1979  transData.BuildPacket(&packet, hasTransport);
1980  player->GetSession()->SendPacket(&packet);
1981 }
1982 
1984 {
1985  // Hack to send out transports
1987 
1988  // no transports at map
1989  if (tmap.find(player->GetMapId()) == tmap.end())
1990  return;
1991 
1992  UpdateData transData;
1993 
1994  MapManager::TransportSet& tset = tmap[player->GetMapId()];
1995 
1996  // except used transport
1997  for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
1998  if ((*i) != player->GetTransport() && (*i)->GetMapId() != GetId())
1999  (*i)->BuildOutOfRangeUpdateBlock(&transData);
2000 
2001  WorldPacket packet;
2002  transData.BuildPacket(&packet);
2003  player->GetSession()->SendPacket(&packet);
2004 }
2005 
2006 inline void Map::setNGrid(NGridType* grid, uint32 x, uint32 y)
2007 {
2008  if (x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS)
2009  {
2010  sLog.outError("map::setNGrid() Invalid grid coordinates found: %d, %d!", x, y);
2011  ASSERT(false);
2012  }
2013  i_grids[x][y] = grid;
2014 }
2015 
2016 void Map::DelayedUpdate(const uint32 t_diff)
2017 {
2019 
2020  // 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 !
2021  // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
2022  if (!IsBattlegroundOrArena())
2023  {
2025  {
2026  NGridType* grid = i->GetSource();
2027  GridInfo* info = i->GetSource()->getGridInfoRef();
2028  ++i; // The update might delete the map and we need the next map before the iterator gets invalid
2029  ASSERT(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
2030  si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, t_diff);
2031  }
2032  }
2033 }
2034 
2036 {
2037  ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2038 
2039  obj->CleanupsBeforeDelete(); // remove or simplify at least cross referenced links
2040 
2041  i_objectsToRemove.insert(obj);
2042  //sLog.outMap("Object (GUID: %u TypeId: %u) added to removing list.",obj->GetGUIDLow(),obj->GetTypeId());
2043 }
2044 
2046 {
2047  ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2048  // i_objectsToSwitch is iterated only in Map::RemoveAllObjectsInRemoveList() and it uses
2049  // the contained objects only if GetTypeId() == TYPEID_UNIT , so we can return in all other cases
2050  if (obj->GetTypeId() != TYPEID_UNIT)
2051  return;
2052 
2053  std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.find(obj);
2054  if (itr == i_objectsToSwitch.end())
2055  i_objectsToSwitch.insert(itr, std::make_pair(obj, on));
2056  else if (itr->second != on)
2057  i_objectsToSwitch.erase(itr);
2058  else
2059  ASSERT(false);
2060 }
2061 
2063 {
2064  while (!i_objectsToSwitch.empty())
2065  {
2066  std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.begin();
2067  WorldObject* obj = itr->first;
2068  bool on = itr->second;
2069  i_objectsToSwitch.erase(itr);
2070 
2071  if (obj->GetTypeId() == TYPEID_UNIT && !obj->IsPermanentWorldObject())
2072  SwitchGridContainers(obj->ToCreature(), on);
2073  }
2074 
2075  //sLog.outMap("Object remover 1 check.");
2076  while (!i_objectsToRemove.empty())
2077  {
2078  std::set<WorldObject*>::iterator itr = i_objectsToRemove.begin();
2079  WorldObject* obj = *itr;
2080 
2081  switch (obj->GetTypeId())
2082  {
2083  case TYPEID_CORPSE:
2084  {
2085  Corpse* corpse = ObjectAccessor::Instance().GetCorpse(*obj, obj->GetGUID());
2086  if (!corpse)
2087  sLog.outError("Tried to delete corpse/bones %u that is not in map.", obj->GetGUIDLow());
2088  else
2089  RemoveFromMap(corpse, true);
2090  break;
2091  }
2092  case TYPEID_DYNAMICOBJECT:
2093  RemoveFromMap((DynamicObject*)obj, true);
2094  break;
2095  case TYPEID_GAMEOBJECT:
2096  RemoveFromMap((GameObject*)obj, true);
2097  break;
2098  case TYPEID_UNIT:
2099  // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call
2100  // make sure that like sources auras/etc removed before destructor start
2101  obj->ToCreature()->CleanupsBeforeDelete();
2102  RemoveFromMap(obj->ToCreature(), true);
2103  break;
2104  default:
2105  sLog.outError("Non-grid object (TypeId: %u) is in grid object remove list, ignored.", obj->GetTypeId());
2106  break;
2107  }
2108 
2109  i_objectsToRemove.erase(itr);
2110  }
2111 
2112  //sLog.outMap("Object remover 2 check.");
2113 }
2114 
2116 {
2117  uint32 count = 0;
2119  if (!itr->GetSource()->IsGameMaster())
2120  ++count;
2121  return count;
2122 }
2123 
2124 void Map::SendToPlayers(WorldPacket const* data) const
2125 {
2127  itr->GetSource()->GetSession()->SendPacket(data);
2128 }
2129 
2130 bool Map::ActiveObjectsNearGrid(NGridType const& ngrid) const
2131 {
2132  CellCoord cell_min(ngrid.getX() * MAX_NUMBER_OF_CELLS, ngrid.getY() * MAX_NUMBER_OF_CELLS);
2133  CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord + MAX_NUMBER_OF_CELLS);
2134 
2135  //we must find visible range in cells so we unload only non-visible cells...
2136  float viewDist = GetVisibilityRange();
2137  int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1;
2138 
2139  cell_min << cell_range;
2140  cell_min -= cell_range;
2141  cell_max >> cell_range;
2142  cell_max += cell_range;
2143 
2144  for (MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
2145  {
2146  Player* plr = iter->GetSource();
2147 
2149  if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2150  (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2151  return true;
2152  }
2153 
2154  for (ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter)
2155  {
2156  WorldObject* obj = *iter;
2157 
2159  if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2160  (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2161  return true;
2162  }
2163 
2164  return false;
2165 }
2166 
2168 {
2169  AddToActiveHelper(c);
2170 
2171  // also not allow unloading spawn grid to prevent creating creature clone at load
2172  if (!c->IsPet() && c->GetDBTableGUIDLow())
2173  {
2174  float x, y, z;
2175  c->GetRespawnPosition(x, y, z);
2177  if (getNGrid(p.x_coord, p.y_coord))
2179  else
2180  {
2182  sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] not loaded.",
2183  c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2184  }
2185  }
2186 }
2187 
2189 {
2191 
2192  // also allow unloading spawn grid
2193  if (!c->IsPet() && c->GetDBTableGUIDLow())
2194  {
2195  float x, y, z;
2196  c->GetRespawnPosition(x, y, z);
2198  if (getNGrid(p.x_coord, p.y_coord))
2200  else
2201  {
2203  sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] not loaded.",
2204  c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2205  }
2206  }
2207 }
2208 
2209 template bool Map::AddToMap(Corpse*);
2210 template bool Map::AddToMap(Creature*);
2211 template bool Map::AddToMap(GameObject*);
2212 template bool Map::AddToMap(DynamicObject*);
2213 
2214 template void Map::RemoveFromMap(Corpse*, bool);
2215 template void Map::RemoveFromMap(Creature*, bool);
2216 template void Map::RemoveFromMap(GameObject*, bool);
2217 template void Map::RemoveFromMap(DynamicObject*, bool);
2218 
2219 /* ******* Dungeon Instance Maps ******* */
2220 
2221 InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
2222  : Map(id, expiry, InstanceId, SpawnMode, _parent),
2223  m_resetAfterUnload(false), m_unloadWhenEmpty(false),
2224  i_data(NULL)
2225 {
2226  //lets initialize visibility distance for dungeons
2228 
2229  // the timer is started by default, and stopped when the first player joins
2230  // this make sure it gets unloaded if for some reason no player joins
2232 }
2233 
2235 {
2236  delete i_data;
2237  i_data = NULL;
2238 }
2239 
2241 {
2242  //init visibility distance for instances
2243  m_VisibleDistance = sWorld.GetMaxVisibleDistanceInInstances();
2245 }
2246 
2247 /*
2248  Do map specific checks to see if the player can enter
2249 */
2251 {
2252  if (player->GetMapRef().getTarget() == this)
2253  {
2254  sLog.outError("InstanceMap::CannotEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
2255  ASSERT(false);
2257  }
2258 
2259  // allow GM's to enter
2260  if (player->IsGameMaster())
2261  return Map::CannotEnter(player);
2262 
2263  // cannot enter if the instance is full (player cap), GMs don't count
2264  InstanceTemplate const* iTemplate = sObjectMgr.GetInstanceTemplate(GetId());
2265  if (GetPlayersCountExceptGMs() >= iTemplate->maxPlayers)
2266  {
2267  sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName());
2268  return CANNOT_ENTER_MAX_PLAYERS;
2269  }
2270 
2271  // cannot enter while an encounter is in progress (unless this is a relog, in which case it is permitted)
2272  if (!player->IsLoading() && IsRaid() && GetInstanceData() && GetInstanceData()->IsEncounterInProgress())
2274 
2275  // cannot enter if player is permanent saved to a different instance id
2276  if (InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetDifficulty()))
2277  if (playerBind->perm && playerBind->save)
2278  if (playerBind->save->GetInstanceId() != GetInstanceId())
2280 
2281  return Map::CannotEnter(player);
2282 }
2283 
2284 /*
2285  Do map specific checks and add the player to the map if successful.
2286 */
2288 {
2289  // @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode
2290  // GMs still can teleport player in instance.
2291  // Is it needed?
2292 
2293  {
2294  Guard guard(*this);
2295  //if (!CanEnter(player))
2296  //return false;
2297 
2298  // Dungeon only code
2299  if (IsDungeon())
2300  {
2301  // get or create an instance save for the map
2302  InstanceSave* mapSave = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2303  if (!mapSave)
2304  {
2305  sLog.outDetail("InstanceMap::AddToMap: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
2306  mapSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), DungeonDifficulty(GetSpawnMode()), 0, true);
2307  }
2308 
2309  // check for existing instance binds
2310  InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetSpawnMode());
2311  if (playerBind && playerBind->perm)
2312  {
2313  // cannot enter other instances if bound permanently
2314  if (playerBind->save != mapSave)
2315  {
2316  sLog.outError("InstanceMap::AddToMap: player %s(%d) is permanently bound to instance %d,%d,%d,%d,%d,%d but he is being put into instance %d,%d,%d,%d,%d,%d", player->GetName(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset());
2317  return false;
2318  }
2319  }
2320  else
2321  {
2322  Group* pGroup = player->GetGroup();
2323  if (pGroup)
2324  {
2325  // solo saves should be reset when entering a group
2326  InstanceGroupBind* groupBind = pGroup->GetBoundInstance(this);
2327  if (playerBind)
2328  {
2329  sLog.outError("InstanceMap::AddToMap: player %s(%d) is being put into instance %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(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), GUID_LOPART(pGroup->GetLeaderGUID()), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset());
2330  if (groupBind) sLog.outError("InstanceMap::AddToMap: the group is bound to the instance %d,%d,%d,%d,%d,%d", groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset());
2331  //ASSERT(false);
2332  return false;
2333  }
2334  // bind to the group or keep using the group save
2335  if (!groupBind)
2336  pGroup->BindToInstance(mapSave, false);
2337  else
2338  {
2339  // cannot jump to a different instance without resetting it
2340  if (groupBind->save != mapSave)
2341  {
2342  sLog.outError("InstanceMap::AddToMap: 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(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(pGroup->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty());
2343  if (mapSave)
2344  sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount());
2345  else
2346  sLog.outError("MapSave NULL");
2347 
2348  if (groupBind->save)
2349  sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
2350  else
2351  sLog.outError("GroupBind save NULL");
2352  return false;
2353  }
2354  // if the group/leader is permanently bound to the instance
2355  // players also become permanently bound when they enter
2356  if (groupBind->perm)
2357  {
2359  data << uint32(0);
2360  player->GetSession()->SendPacket(&data);
2361  player->BindToInstance(mapSave, true);
2362  }
2363  }
2364  }
2365  else
2366  {
2367  // set up a solo bind or continue using it
2368  if (!playerBind)
2369  player->BindToInstance(mapSave, false);
2370  else
2371  // cannot jump to a different instance without resetting it
2372  ASSERT(playerBind->save == mapSave);
2373  }
2374  }
2375  }
2376 
2377  // for normal instances cancel the reset schedule when the
2378  // first player enters (no players yet)
2379  SetResetSchedule(false);
2380 
2381  player->SendInitWorldStates();
2382  sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName());
2383  // initialize unload state
2384  m_unloadTimer = 0;
2385  m_resetAfterUnload = false;
2386  m_unloadWhenEmpty = false;
2387  }
2388 
2389  // this will acquire the same mutex so it cannot be in the previous block
2390  Map::AddPlayerToMap(player);
2391 
2392  if (i_data)
2393  i_data->OnPlayerEnter(player);
2394 
2395  return true;
2396 }
2397 
2398 void InstanceMap::Update(const uint32& t_diff)
2399 {
2400  Map::Update(t_diff);
2401 
2402  if (i_data)
2403  i_data->Update(t_diff);
2404 }
2405 
2406 void InstanceMap::RemovePlayerFromMap(Player* player, bool remove)
2407 {
2408  sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName());
2409  //if last player set unload timer
2410  if (!m_unloadTimer && m_mapRefManager.getSize() == 1)
2412  Map::RemovePlayerFromMap(player, remove);
2413  // for normal instances schedule the reset after all players have left
2414  SetResetSchedule(true);
2415 }
2416 
2418 {
2419  if (i_data != NULL)
2420  return;
2421 
2422  InstanceTemplate const* mInstance = sObjectMgr.GetInstanceTemplate(GetId());
2423  if (mInstance)
2424  {
2425  i_script_id = mInstance->script_id;
2426  i_data = sScriptMgr.CreateInstanceData(this);
2427  }
2428 
2429  if (!i_data)
2430  return;
2431 
2432  i_data->Initialize();
2433 
2434  if (load)
2435  {
2436  // @todo make a global storage for this
2437  QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT data FROM instance WHERE map = '%u' AND id = '%u'", GetId(), i_InstanceId);
2438  if (result)
2439  {
2440  Field* fields = result->Fetch();
2441  const char* data = fields[0].GetString();
2442  if (data && *data)
2443  {
2444  sLog.outMap("Loading instance data for %s with id %u", sObjectMgr.GetScriptName(i_script_id), i_InstanceId);
2445  i_data->Load(data);
2446  }
2447  }
2448  }
2449 }
2450 
2451 /*
2452  Returns true if there are no players in the instance
2453 */
2455 {
2456  // note: since the map may not be loaded when the instance needs to be reset
2457  // the instance must be deleted from the DB by InstanceSaveManager
2458 
2459  if (HavePlayers())
2460  {
2461  if (method == INSTANCE_RESET_ALL)
2462  {
2463  // notify the players to leave the instance so it can be reset
2464  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2465  itr->GetSource()->SendResetFailedNotify(GetId());
2466  }
2467  else
2468  {
2469  if (method == INSTANCE_RESET_GLOBAL)
2470  // set the homebind timer for players inside (1 minute)
2471  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2472  itr->GetSource()->m_InstanceValid = false;
2473 
2474  // the unload timer is not started
2475  // instead the map will unload immediately after the players have left
2476  m_unloadWhenEmpty = true;
2477  m_resetAfterUnload = true;
2478  }
2479  }
2480  else
2481  {
2482  // unloaded at next update
2484  m_resetAfterUnload = true;
2485  }
2486 
2487  return m_mapRefManager.isEmpty();
2488 }
2489 
2491 {
2492  if (!IsDungeon())
2493  return;
2494 
2495  InstanceSave* save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2496  if (!save)
2497  {
2498  sLog.outError("Cannot bind players, no instance save available for map!");
2499  return;
2500  }
2501 
2502  Group* group = player->GetGroup();
2503  // group members outside the instance group don't get bound
2504  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2505  {
2506  Player* plr = itr->GetSource();
2507  // players inside an instance cannot be bound to other instances
2508  // some players may already be permanently bound, in this case nothing happens
2509  InstancePlayerBind* bind = plr->GetBoundInstance(save->GetMapId(), save->GetDifficulty());
2510  if (!bind || !bind->perm)
2511  {
2512  plr->BindToInstance(save, true);
2514  data << uint32(0);
2515  plr->GetSession()->SendPacket(&data);
2516  }
2517 
2518  // if the leader is not in the instance the group will not get a perm bind
2519  if (group && group->GetLeaderGUID() == plr->GetGUID())
2520  group->BindToInstance(save, true);
2521  }
2522 }
2523 
2525 {
2526  InstanceSave* save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2527  return time_t(save ? save->GetDifficulty() : DIFFICULTY_NORMAL);
2528 }
2529 
2531 {
2532  ASSERT(!HavePlayers());
2533 
2534  if (m_resetAfterUnload == true)
2535  sObjectMgr.DeleteRespawnTimeForInstance(GetInstanceId());
2536 
2537  Map::UnloadAll();
2538 }
2539 
2541 {
2543  itr->GetSource()->SendInstanceResetWarning(GetId(), timeLeft);
2544 }
2545 
2547 {
2548  // only for normal instances
2549  // the reset time is only scheduled when there are no payers inside
2550  // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
2551  if (IsDungeon() && !HavePlayers() && !IsRaid() && !IsHeroic())
2552  {
2553  InstanceSave* save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2554  if (!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId());
2555  else sInstanceSaveMgr.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), GetInstanceId()));
2556  }
2557 }
2558 
2559 /* ******* Battleground Instance Maps ******* */
2560 
2561 BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent)
2562  : Map(id, expiry, InstanceId, DIFFICULTY_NORMAL, _parent)
2563 {
2564  //lets initialize visibility distance for BG/Arenas
2566 }
2567 
2569 {
2570 }
2571 
2573 {
2574  //init visibility distance for BG/Arenas
2575  m_VisibleDistance = sWorld.GetMaxVisibleDistanceInBGArenas();
2577 }
2578 
2580 {
2581  if (player->GetMapRef().getTarget() == this)
2582  {
2583  sLog.outError("BGMap::CannotEnter - player %u is already in map!", player->GetGUIDLow());
2584  ASSERT(false);
2586  }
2587 
2588  if (player->GetBattlegroundId() != GetInstanceId())
2590 
2591  // player number limit is checked in bgmgr, no need to do it here
2592 
2593  return Map::CannotEnter(player);
2594 }
2595 
2597 {
2598  {
2599  Guard guard(*this);
2600  //if (!CanEnter(player))
2601  //return false;
2602  // reset instance validity, battleground maps do not homebind
2603  player->m_InstanceValid = true;
2604  }
2605  return Map::AddPlayerToMap(player);
2606 }
2607 
2609 {
2610  sLog.outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName());
2611  Map::RemovePlayerFromMap(player, remove);
2612 }
2613 
2615 {
2617 }
2618 
2620 {
2621  if (HavePlayers())
2622  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2623  if (Player* plr = itr->GetSource())
2624  if (!plr->IsBeingTeleportedFar())
2625  plr->TeleportTo(plr->GetBattlegroundEntryPoint());
2626 
2627 }
2628 
2629 Creature*
2631 {
2632  return ObjectAccessor::GetObjectInMap(guid, this, (Creature*)NULL);
2633 }
2634 
2635 GameObject*
2637 {
2638  return ObjectAccessor::GetObjectInMap(guid, this, (GameObject*)NULL);
2639 }
2640 
2643 {
2644  return ObjectAccessor::GetObjectInMap(guid, this, (DynamicObject*)NULL);
2645 }
2646 
2648 {
2649  if (m_mapRefIter == player->GetMapRef())
2651 }
2652 
std::multimap< time_t, ScriptAction > m_scriptSchedule
Definition: Map.h:643
float GetGridActivationRange() const
Definition: Object.cpp:1531
bool BuildPacket(WorldPacket *packet, bool hasTransport=false)
Definition: UpdateData.cpp:103
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map *_parent)
Definition: Map.cpp:2221
InstanceSave * save
Definition: Group.h:145
EnterState CannotEnter(Player *player) override
Definition: Map.cpp:2250
Definition: NGrid.h:75
bool GetAreaInfo(float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId) const
Definition: Map.cpp:1663
virtual void ResetMap()
Definition: Object.cpp:1972
AreaTableEntry const * GetAreaEntryByAreaID(uint32 area_id)
Definition: DBCStores.cpp:623
bool IsInWater(float x, float y, float z, LiquidData *data=nullptr) const
Definition: Map.cpp:1842
#define MAP_LIQUID_NO_TYPE
Definition: Map.h:111
void AddCorpsesToGrid(GridCoord const &gridpair, GridType &grid, Map *map)
DBCStorage< LiquidTypeEntry > sLiquidTypeStore(LiquidTypefmt)
bool IsBattlegroundOrArena() const
Definition: Map.h:447
bool AddToMap(T *)
Definition: Map.cpp:424
void CreatureRelocation(Creature *creature, float x, float y, float z, float ang, bool respawnRelocationOnFail=true)
Definition: Map.cpp:734
virtual void unloadMap(unsigned int pMapId, int x, int y)=0
void SendRemoveTransports(Player *player)
Definition: Map.cpp:1983
ClientGUIDs m_clientGUIDs
Definition: Player.h:2459
Group * GetGroup()
Definition: Player.h:2577
#define SIZE_OF_GRID_CELL
Definition: GridDefines.h:44
DungeonDifficulty GetDifficulty() const
Definition: Map.h:419
uint8 offsetY
Definition: Map.h:120
Definition: Corpse.h:48
#define snprintf
Definition: Common.h:129
bool Reset(uint8 method)
Definition: Map.cpp:2454
uint8 GetSpawnMode() const
Definition: Map.h:394
float getHeightFromUint8(float x, float y) const
Definition: Map.cpp:1301
void InitVisibilityDistance() override
Definition: Map.cpp:2240
void RemoveFromGrid()
Definition: Object.h:605
uint8 height
Definition: Map.h:122
bool EnsureGridLoaded(Cell const &)
Definition: Map.cpp:363
std::set< WorldObject * > i_objectsToRemove
Definition: Map.h:640
virtual void Update(uint32)
Definition: InstanceData.h:114
uint32 fourcc
Definition: Map.h:105
float depth_level
Definition: Map.h:152
float getLiquidLevel(float x, float y)
Definition: Map.cpp:1435
virtual void InitVisibilityDistance()
Definition: Map.cpp:225
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
#define SIZE_OF_GRIDS
Definition: GridDefines.h:35
void AddToGrid(T *object, Cell const &cell)
Definition: Map.cpp:234
bool IsBeingTeleportedFar() const
Definition: Player.h:2046
virtual void RemovePlayerFromMap(Player *, bool)
Definition: Map.cpp:672
MapEntry const * i_mapEntry
Definition: Map.h:599
static bool ExistVMap(uint32 mapid, int gx, int gy)
Definition: Map.cpp:84
bool isCellMarked(uint32 pCellId)
Definition: Map.h:463
uint16 flags
Definition: Map.h:117
uint32 areaMapSize
Definition: Map.h:81
float m_VisibleDistance
Definition: Map.h:603
#define MAPID_INVALID
Definition: Object.h:571
void Visit(PlayerMapType &m)
Definition: Map.cpp:587
Definition: NGrid.h:30
void LoadGrid(float x, float y)
Definition: Map.cpp:388
uint8 GetPlayerCount()
uint32 MapID
Definition: DBCStructure.h:514
time_t i_gridExpiry
Definition: Map.h:625
Map * GetMap() const
Definition: Object.h:841
virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const =0
bool m_isTempWorldObject
Definition: Creature.h:803
void SwitchGridContainers(Creature *creature, bool toWorldContainer)
Definition: Map.cpp:268
void decUnloadActiveLock()
Definition: NGrid.h:117
void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang)
Definition: Map.cpp:762
uint32 GetDBTableGUIDLow() const
Definition: Creature.h:476
InstanceGroupBind * BindToInstance(InstanceSave *save, bool permanent, bool load=false)
Definition: Group.cpp:1628
void Clear(bool reset=true)
Definition: MotionMaster.h:145
~BattlegroundMap() override
Definition: Map.cpp:2568
grid_state_t GetGridState(void) const
Definition: NGrid.h:99
void RemoveAllPlayers() override
Definition: Map.cpp:2619
void VisitNearbyCellsOf(WorldObject *obj, TypeContainerVisitor< Oregon::ObjectUpdater, GridTypeMapContainer > &gridVisitor, TypeContainerVisitor< Oregon::ObjectUpdater, WorldTypeMapContainer > &worldVisitor)
Definition: Map.cpp:459
DungeonDifficulty GetDifficulty()
void TUpdate(int32 diff)
Definition: Timer.h:210
uint32 CellY() const
Definition: Cell.h:72
bool IsLoading() const
Definition: Player.cpp:20710
GridMap * GetGrid(float x, float y)
Definition: Map.cpp:1561
void AddToWorld() override
Definition: Player.cpp:1838
bool IsRaid() const
Definition: Map.h:431
void RemoveFromActiveHelper(T *obj)
Definition: Map.h:659
void SendInitWorldStates(bool force=false, uint32 forceZoneId=0)
Definition: Player.cpp:7665
Map * m_parentMap
Definition: Map.h:629
void SetResetSchedule(bool on)
Definition: Map.cpp:2546
void SendInitTransports(Player *player)
Definition: Map.cpp:1953
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:400
static void DeleteStateMachine()
Definition: Map.cpp:194
union Cell::@1 data
float m_homebindY
Definition: Player.h:2442
EnterState CannotEnter(Player *player) override
Definition: Map.cpp:2579
#define CENTER_GRID_ID
Definition: GridDefines.h:36
Definition: Map.h:155
#define MAP_HEIGHT_NO_HEIGHT
Definition: Map.h:99
Definition: Field.h:24
void UpdateIteratorBack(Player *player)
Definition: Map.cpp:2647
#define MAX_NUMBER_OF_CELLS
Definition: GridDefines.h:43
void RemovePlayerFromMap(Player *, bool) override
Definition: Map.cpp:2406
virtual void Update(Map &, NGridType &, GridInfo &, const uint32 t_diff) const =0
float gridMaxHeight
Definition: Map.h:108
bool DiffCell(const Cell &cell) const
Definition: Cell.h:59
void Visit(CreatureMapType &m)
Definition: Map.cpp:583
AreaTableEntry const * GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_id)
Definition: DBCStores.cpp:632
uint8 offsetX
Definition: Map.h:119
void RemoveFromMap(T *, bool)
Definition: Map.cpp:688
NGridType * getNGrid(uint32 x, uint32 y) const
Definition: Map.h:572
#define MAP_LIQUID_NO_HEIGHT
Definition: Map.h:112
MotionMaster * GetMotionMaster()
Definition: Unit.h:1890
bool IsInCombat() const
Definition: Unit.h:1243
bool DiffGrid(const Cell &cell) const
Definition: Cell.h:65
float ang
Definition: Map.h:220
std::map< WorldObject *, bool > i_objectsToSwitch
Definition: Map.h:641
void Update(const uint32 &) override
Definition: Map.cpp:2398
#define DEFAULT_VISIBILITY_NOTIFY_PERIOD
Definition: NGrid.h:28
void unloadData()
Definition: Map.cpp:1087
float GetHeight(float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const
Definition: Map.cpp:1591
uint32 m_homebindMapId
Definition: Player.h:2439
void SetCurrentCell(Cell const &cell)
Definition: Creature.h:642
#define sLog
Log class singleton.
Definition: Log.h:187
uint32 flags
Definition: Map.h:106
WMOAreaTableEntry const * GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid)
Definition: DBCStores.cpp:615
struct Cell::@1::@2 Part
void Remove(const GameObjectModel &mdl)
Definition: Map.h:533
uint32 getSize() const
Definition: LinkedList.h:115
float GetVisibilityRange() const
Definition: Object.cpp:1552
uint32 fourcc
Definition: Map.h:116
~InstanceMap() override
Definition: Map.cpp:2234
void UnloadAll() override
Definition: Map.cpp:2530
#define MAX_NUMBER_OF_GRIDS
Definition: GridDefines.h:33
uint32 GetMapId()
virtual void CleanupsBeforeDelete()
Definition: Object.cpp:1156
Transport * GetTransport() const
Definition: Player.h:2391
ZLiquidStatus
Definition: Map.h:126
ACE_INT32 int32
Definition: Define.h:67
uint8 GetGroupCount()
void UpdateObjectVisibility(bool forced=true) override
Definition: Unit.cpp:13525
void Update(uint32 time) override
Definition: Player.cpp:1042
NULL Dbg ErrDB Arena Chat Char Map MMap false
Definition: Log.cpp:556
bool IsDungeon() const
Definition: Map.h:427
void LoadVMap(int gx, int gy)
Definition: Map.cpp:115
uint32 areaMapOffset
Definition: Map.h:80
void resetNotify(GridRefManager< T > &m)
Definition: Map.cpp:577
void AddToActiveHelper(T *obj)
Definition: Map.h:653
Definition: Grid.h:45
void AddObjectToRemoveList(WorldObject *obj)
Definition: Map.cpp:2035
bool IsWorldObject() const
Definition: Object.cpp:1112
void SetNoCreate()
Definition: Cell.h:76
void RemoveWorldObject(WorldObject *obj)
Definition: Map.h:483
uint32 y_coord
Definition: GridDefines.h:142
bool IsGameMaster() const
Definition: Player.h:1009
void RemovePlayerFromMap(Player *, bool) override
Definition: Map.cpp:2608
uint32 GetGUIDLow() const
Definition: Object.h:166
bool IsGridLoaded(float x, float y) const
Definition: Map.h:307
float GetWaterOrGroundLevel(float x, float y, float z, float *ground=NULL, bool swim=false) const
Definition: Map.cpp:1573
void RemoveFromActive(T *obj)
Definition: Map.h:511
DynamicObject * ToDynObject()
Definition: Object.h:407
GridMap()
Definition: Map.cpp:1011
static CellArea CalculateCellArea(float x, float y, float radius)
Definition: CellImpl.h:48
uint32 x_coord
Definition: GridDefines.h:141
void update(uint32 diff)
static uint32 GetAreaId(uint16 areaflag, uint32 map_id)
Definition: Map.cpp:1822
bool ActiveObjectsNearGrid(NGridType const &ngrid) const
Definition: Map.cpp:2130
void RemoveAllObjectsInRemoveList()
Definition: Map.cpp:2062
uint16 gridArea
Definition: Map.h:96
DungeonDifficulty
iterator begin()
Definition: MapRefManager.h:48
uint8 i_spawnMode
Definition: Map.h:600
#define sObjectMgr
Definition: ObjectMgr.h:1285
uint32 i_script_id
Definition: Map.h:716
void SendPacket(WorldPacket const *packet)
bool IsInGrid() const
Definition: Object.h:603
ActiveNonPlayers m_activeNonPlayers
Definition: Map.h:611
bool i_scriptLock
Definition: Map.h:639
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
bool unloadMap(uint32 mapId, int32 x, int32 y)
Definition: MoveMap.cpp:255
uint16 liquidType
Definition: Map.h:118
#define TOTAL_NUMBER_OF_CELLS_PER_MAP
Definition: GridDefines.h:49
GridType & GetGridType(const uint32 x, const uint32 y)
Definition: NGrid.h:85
virtual void Load(const char *data)
Definition: InstanceData.h:101
void RemoveFromWorld() override
Definition: Player.cpp:1850
const char * GetString() const
Definition: Field.h:41
CreatureMoveList i_creaturesToMove
Definition: Map.h:557
#define MAP_LIQUID_TYPE_DARK_WATER
Definition: Map.h:144
#define MIN_UNLOAD_DELAY
Definition: Map.h:262
uint8 width
Definition: Map.h:121
virtual void OnPlayerEnter(Player *)
Definition: InstanceData.h:121
DynamicMapTree m_dyn_tree
Definition: Map.h:624
GridMap * GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition: Map.h:632
void UpdateObjectVisibility(WorldObject *obj, Cell cell, CellCoord cellpair)
Definition: Map.cpp:1895
float liquidLevel
Definition: Map.h:123
uint32 GetWorldObjectCountInNGrid() const
Definition: NGrid.h:138
float z
Definition: Map.h:220
InstanceSave * save
Definition: Player.h:746
uint32 GetId(void) const
Definition: Map.h:333
BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map *_parent)
Definition: Map.cpp:2561
void setNGrid(NGridType *grid, uint32 x, uint32 y)
Definition: Map.cpp:2006
time_t GetResetTime()
Definition: Map.cpp:2524
void CreateInstanceData(bool load)
Definition: Map.cpp:2417
uint8 GetTypeId() const
Definition: Object.h:210
bool isGridObjectDataLoaded(uint32 x, uint32 y) const
Definition: Map.h:579
float getHeightFromUint16(float x, float y) const
Definition: Map.cpp:1368
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition: Player.cpp:1488
bool loadMap(uint32 mapId, int32 x, int32 y)
Definition: MoveMap.cpp:172
float x
Definition: Map.h:220
Creature * GetCreature(uint64 guid)
Definition: Map.cpp:2630
void PermBindAllPlayers(Player *player)
Definition: Map.cpp:2490
ACE_UINT8 uint8
Definition: Define.h:73
uint32 GetInstanceId()
float GetOrientation() const
Definition: Position.h:100
std::set< Transport * > TransportSet
Definition: MapManager.h:126
uint32 heightMapOffset
Definition: Map.h:82
#define UI64FMTD
Definition: Common.h:149
void AddObjectToSwitchList(WorldObject *obj, bool on)
Definition: Map.cpp:2045
void Relocate(float x, float y)
Definition: Position.h:65
void markCell(uint32 pCellId)
Definition: Map.h:467
bool m_resetAfterUnload
Definition: Map.h:713
Definition: Cell.h:29
void EnsureGridCreated(const GridCoord &)
Definition: Map.cpp:319
const bool & IsInWorld() const
Definition: Object.h:135
void resetMarkedCells()
Definition: Map.h:459
uint32 m_unloadTimer
Definition: Map.h:602
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2)=0
virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const =0
InstanceData * GetInstanceData()
Definition: Map.h:700
DynamicObject * GetDynamicObject(uint64 guid)
Definition: Map.cpp:2642
static int32 GetVisibilityNotifyPeriodInInstances()
Definition: World.h:724
HostileRefManager & getHostileRefManager()
Definition: Unit.h:1733
float GetWaterLevel(float x, float y) const
Definition: Map.cpp:1794
bool loadData(const char *filename)
Definition: Map.cpp:1039
void AddGridObject(SPECIFIC_OBJECT *obj)
Definition: Grid.h:111
bool IsHeroic() const
Definition: Map.h:435
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data=0) const
Definition: Map.cpp:1728
void DeleteFromWorld(T *)
Definition: Map.cpp:304
#define MAP_RESOLUTION
Definition: GridDefines.h:51
virtual void Update(const uint32 &)
Definition: Map.cpp:493
float getHeightFromFlat(float x, float y) const
Definition: Map.cpp:1214
float GetPositionY() const
Definition: Position.h:98
void VisitAllGrids(TypeContainerVisitor< T, TypeMapContainer< TT > > &visitor)
Definition: NGrid.h:123
uint32 CellX() const
Definition: Cell.h:71
bool loadLiquidData(FILE *in, uint32 offset, uint32 size)
Definition: Map.cpp:1168
void UpdateObjectsVisibilityFor(Player *player, Cell cell, CellCoord cellpair)
Definition: Map.cpp:1903
const char * GetMapName() const
Definition: Map.cpp:1890
float getHeightFromFloat(float x, float y) const
Definition: Map.cpp:1219
HostileReference * next()
float level
Definition: Map.h:151
CellCoord low_bound
Definition: Cell.h:42
virtual void RemoveFromWorld() override
Definition: Object.cpp:1169
static int32 GetVisibilityNotifyPeriodOnContinents()
Definition: World.h:720
#define VMAP_INVALID_HEIGHT_VALUE
Definition: IVMapManager.h:41
uint32 GetInstanceId() const
Definition: Object.h:688
bool isActiveObject() const
Definition: Object.h:911
virtual void Initialize()
Definition: InstanceData.h:98
void SendToPlayers(WorldPacket const *data) const
Definition: Map.cpp:2124
void LoadMapAndVMap(int gx, int gy)
Definition: Map.cpp:175
void CombatStop(bool cast=false)
Definition: Unit.cpp:7518
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map *_parent=NULL)
Definition: Map.cpp:202
static uint32 GetZoneId(uint16 areaflag, uint32 map_id)
Definition: Map.cpp:1832
#define DEBUG_LOG(...)
Definition: Log.h:194
void PlayerRelocation(Player *, float x, float y, float z, float orientation)
Definition: Map.cpp:709
~Map() override
Definition: Map.cpp:40
bool m_InstanceValid
Definition: Player.h:2543
void SetGridState(grid_state_t s)
Definition: NGrid.h:100
std::map< uint32, TransportSet > TransportMap
Definition: MapManager.h:129
void UpdateObjectVisibility(bool forced=true) override
Definition: Player.cpp:18890
GridInfo * getGridInfoRef()
Definition: NGrid.h:111
TransportMap m_TransportsByMap
Definition: MapManager.h:130
uint32 GridY() const
Definition: Cell.h:74
InstancePlayerBind * GetBoundInstance(uint32 mapid, uint8 difficulty)
Definition: Player.cpp:15855
uint32 GetMapId() const
Definition: Object.h:591
uint32 type_flags
Definition: Map.h:149
virtual VMAPLoadResult loadMap(const char *pBasePath, unsigned int pMapId, int x, int y)=0
bool IsUnderWater(float x, float y, float z) const
Definition: Map.cpp:1849
bool HavePlayers() const
Definition: Map.h:472
bool isEmpty() const
Definition: LinkedList.h:97
uint32 liquidMapOffset
Definition: Map.h:84
void InitVisibilityDistance() override
Definition: Map.cpp:2572
virtual bool AddPlayerToMap(Player *)
Definition: Map.cpp:393
#define MAP_LIQUID_TYPE_WATER
Definition: Map.h:140
time_t GetResetTime()
Definition: Map.h:266
std::set< WorldObject * > i_worldObjects
Definition: Map.h:642
uint32 entry
Definition: Map.h:150
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2) const
Definition: Map.cpp:1802
uint32 liquidMapSize
Definition: Map.h:85
uint16 flags
Definition: Map.h:95
float GetVisibilityRange() const
Definition: Map.h:291
void Balance()
Definition: Map.h:532
void TReset(int32 diff, int32 period)
Definition: Timer.h:218
bool isHeightCalcEnabled() const
Definition: IVMapManager.h:86
InstancePlayerBind * BindToInstance(InstanceSave *save, bool permanent, bool load=false)
Definition: Player.cpp:15896
#define sInstanceSaveMgr
void incUnloadActiveLock()
Definition: NGrid.h:116
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:167
uint16 getArea(float x, float y)
Definition: Map.cpp:1202
virtual void RemoveAllPlayers()
Definition: Map.cpp:978
InstanceData * i_data
Definition: Map.h:715
void EnsureGridLoadedForActiveObject(Cell const &, WorldObject *object)
Definition: Map.cpp:347
bool IsPet() const
Definition: Unit.h:1048
bool UnloadGrid(NGridType &ngrid, bool pForce)
Definition: Map.cpp:900
#define MAX_VISIBILITY_DISTANCE
Definition: Object.h:38
const char * GetName() const
Definition: Object.h:704
float gridHeight
Definition: Map.h:107
void buildNGridLinkage(NGridType *pNGridType)
Definition: Map.h:564
void RemoveObject(T *object)
uint32 heightMapSize
Definition: Map.h:83
bool CheckGridIntegrity(Creature *c, bool moved) const
Definition: Map.cpp:1872
uint8 GetTerrainType(float x, float y) const
Definition: Map.cpp:1720
ACE_UINT64 uint64
Definition: Define.h:70
int32 getY() const
Definition: NGrid.h:102
Definition: Cell.h:46
Cell const & GetCurrentCell() const
Definition: Creature.h:638
virtual void UnloadAll()
Definition: Map.cpp:995
uint32 GetBattlegroundId() const
Definition: Player.h:2200
void LoadMap(int gx, int gy, bool reload=false)
Definition: Map.cpp:135
~GridMap()
Definition: Map.cpp:1034
void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const override
Definition: Player.cpp:3693
const uint64 & GetLeaderGUID() const
Definition: Group.h:222
bool HaveAtClient(WorldObject const *u) const
Definition: Player.cpp:18687
void LoadMMap(int gx, int gy)
Definition: Map.cpp:103
HostileReference * getFirst()
static int32 GetVisibilityNotifyPeriodInBGArenas()
Definition: World.h:728
bool CreatureCellRelocation(Creature *creature, Cell new_cell)
Definition: Map.cpp:812
virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist)=0
ActiveNonPlayers::iterator m_activeNonPlayersIter
Definition: Map.h:612
Unit * getOwner() const
#define MAP_ALL_LIQUIDS
Definition: Map.h:142
void Visit(const Cell &cell, TypeContainerVisitor< T, CONTAINER > &visitor)
int32 m_VisibilityNotifyPeriod
Definition: Map.h:608
int32 getX() const
Definition: NGrid.h:101
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
uint32 exploreFlag
Definition: DBCStructure.h:44
FROM * GetSource() const
Definition: Reference.h:92
MapReference & GetMapRef()
Definition: Player.h:2637
bool CreatureRespawnRelocation(Creature *c)
Definition: Map.cpp:873
bool AddPlayerToMap(Player *) override
Definition: Map.cpp:2287
uint32 fourcc
Definition: Map.h:94
Creature * ToCreature()
Definition: Object.h:395
PeriodicTimer & getRelocationTimer()
Definition: NGrid.h:49
uint8 getTerrainType(float x, float y)
Definition: Map.cpp:1454
void AddToActive(T *obj)
Definition: Map.h:502
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data=0)
Definition: Map.cpp:1467
void MoveAllCreaturesInMoveList()
Definition: Map.cpp:770
void CleanupsBeforeDelete() override
Definition: Unit.cpp:11165
NGridType * i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition: Map.h:631
uint32 maxPlayers
Definition: Map.h:234
void SetUnload()
Definition: Map.cpp:2614
uint32 i_InstanceId
Definition: Map.h:601
virtual void DelayedUpdate(const uint32 diff)
Definition: Map.cpp:2016
iterator begin()
void Visit(GridRefManager< T > &)
Definition: Map.cpp:582
static IVMapManager * createOrGetVMapManager()
void SetMap(Map *map) override
Definition: Player.cpp:20704
bool loadAreaData(FILE *in, uint32 offset, uint32 size)
Definition: Map.cpp:1104
#define ASSERT
Definition: Errors.h:29
bool getObjectHitPos(const G3D::Vector3 &pPos1, const G3D::Vector3 &pPos2, G3D::Vector3 &pResultHitPos, float pModifyDist) const
GridState * si_GridStates[MAX_GRID_STATE]
Definition: Map.cpp:38
bool IsOutdoorWMO(uint32 mogpFlags, uint32 mapId)
Definition: Map.cpp:1637
uint32 mapMagic
Definition: Map.h:77
static bool ExistMap(uint32 mapid, int gx, int gy)
Definition: Map.cpp:57
CellCoord high_bound
Definition: Cell.h:43
static MMapManager * createOrGetMMapManager()
Definition: MoveMap.cpp:34
#define sScriptMgr
Definition: Group.h:526
#define INVALID_HEIGHT
Definition: Map.h:259
EnterState
Definition: Map.h:399
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2) const
uint32 GetEntry() const
Definition: Object.h:192
bool IsOutdoors(float x, float y, float z) const
Definition: Map.cpp:1651
bool IsPositionValid() const
Definition: Position.cpp:40
WorldSession * GetSession() const
Definition: Player.h:1944
#define sWorld
Definition: World.h:860
void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y)
Definition: Map.h:583
static bool IsPathfindingEnabled(uint32 mapId)
Definition: MoveMap.cpp:61
InstanceGroupBind * GetBoundInstance(Player *player)
Definition: Group.cpp:1591
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
void AddWorldObject(WorldObject *obj)
Definition: Map.h:479
ACE_UINT16 uint16
Definition: Define.h:72
#define MAP_AREA_NO_AREA
Definition: Map.h:90
#define MAP_HEIGHT_AS_INT8
Definition: Map.h:101
MapRefManager::iterator m_mapRefIter
Definition: Map.h:606
float getHeight(float x, float y, float z, float maxSearchDist) const
WorldObject * m_seer
Definition: Player.h:2351
static T * GetObjectInMap(uint64 guid, Map *map, T *)
virtual EnterState CannotEnter(Player *)
Definition: Map.h:414
ACE_UINT32 uint32
Definition: Define.h:71
void GetRespawnPosition(float &x, float &y, float &z, float *ori=NULL, float *dist=NULL) const
Definition: Creature.cpp:2321
void Initialize()
float GetPositionX() const
Definition: Position.h:97
void SendResetWarnings(uint32 timeLeft) const
Definition: Map.cpp:2540
static void InitStateMachine()
Definition: Map.cpp:186
GameObject * GetGameObject(uint64 guid)
Definition: Map.cpp:2636
static Corpse * GetCorpse(WorldObject const &u, uint64 guid)
bool getObjectHitPos(float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist)
Definition: Map.cpp:1808
Definition: Unit.h:908
void ResetGridExpiry(NGridType &grid, float factor=1) const
Definition: Map.h:324
bool m_unloadWhenEmpty
Definition: Map.h:714
bool isGridObjectDataLoaded() const
Definition: NGrid.h:108
float y
Definition: Map.h:220
MapRefManager m_mapRefManager
Definition: Map.h:605
void ScriptsProcess()
Definition: MapScripts.cpp:288
MapReference const * nocheck_prev() const
Definition: MapReference.h:61
void SendInitSelf(Player *player)
Definition: Map.cpp:1917
Definition: Player.h:922
NGrid< MAX_NUMBER_OF_CELLS, Player, AllWorldObjectTypes, AllGridObjectTypes > NGridType
Definition: GridDefines.h:67
uint32 GetInstanceId() const
Definition: Map.h:390
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition: CellImpl.h:121
char * name[16]
Definition: DBCStructure.h:518
TO * getTarget() const
Definition: Reference.h:90
float m_homebindX
Definition: Player.h:2441
bool AddPlayerToMap(Player *) override
Definition: Map.cpp:2596
CoordPair< MAX_NUMBER_OF_GRIDS > GridCoord
Definition: GridDefines.h:145
#define MAP_HEIGHT_AS_INT16
Definition: Map.h:100
bool TPassed() const
Definition: Timer.h:214
uint32 GetPlayersCountExceptGMs() const
Definition: Map.cpp:2115
#define MAP_LIQUID_TYPE_OCEAN
Definition: Map.h:138
uint32 script_id
Definition: Map.h:241
bool IsSwimmable(float x, float y, float z, LiquidData *data=nullptr) const
Definition: Map.cpp:1859
virtual bool IsEncounterInProgress() const
iterator end()
Definition: MapRefManager.h:52
bool IsPermanentWorldObject() const
Definition: Object.h:917
Definition: Pet.h:146
WorldObject * GetViewpoint() const
Definition: Player.cpp:20480
uint32 GetAreaFlagByMapId(uint32 mapid)
Definition: DBCStores.cpp:643
uint32 GridX() const
Definition: Cell.h:73
Definition: Group.h:154
uint32 versionMagic
Definition: Map.h:78
bool loadHeightData(FILE *in, uint32 offset, uint32 size)
Definition: Map.cpp:1122
float m_homebindZ
Definition: Player.h:2443
void AddWorldObject(SPECIFIC_OBJECT *obj)
Definition: Grid.h:58
uint16 GetAreaFlag(float x, float y, float z, bool *isOutdoors=0) const
Definition: Map.cpp:1682
const uint64 & GetGUID() const
Definition: Object.h:162
#define DEFAULT_VISIBILITY_DISTANCE
Definition: Object.h:40
GridCoord ComputeGridCoord(float x, float y)
Definition: GridDefines.h:162
void ProcessRelocationNotifies(const uint32 &diff)
Definition: Map.cpp:593