OregonCore  revision 3611e8a-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] = NULL;
160  }
161 
162  // map file name
163  char* tmp = NULL;
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  FILE* in = fopen(filename, "rb");
1046  if (!in)
1047  return false;
1048 
1049  if (fread(&header, sizeof(header), 1, in) != 1)
1050  {
1051  fclose(in);
1052  return false;
1053  }
1054 
1055  if (header.mapMagic == uint32(MAP_MAGIC) && header.versionMagic == uint32(MAP_VERSION_MAGIC))
1056  {
1057  // loadup area data
1058  if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize))
1059  {
1060  sLog.outError("Error loading map area data\n");
1061  fclose(in);
1062  return false;
1063  }
1064  // loadup height data
1065  if (header.heightMapOffset && !loadHeightData(in, header.heightMapOffset, header.heightMapSize))
1066  {
1067  sLog.outError("Error loading map height data\n");
1068  fclose(in);
1069  return false;
1070  }
1071  // loadup liquid data
1072  if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize))
1073  {
1074  sLog.outError("Error loading map liquids data\n");
1075  fclose(in);
1076  return false;
1077  }
1078  fclose(in);
1079  return true;
1080  }
1081  sLog.outError("Map file '%s' is from an incompatible clientversion. Please recreate using the mapextractor.", filename);
1082  fclose(in);
1083  return false;
1084 }
1085 
1087 {
1088  delete[] m_area_map;
1089  delete[] m_V9;
1090  delete[] m_V8;
1091  delete[] _liquidEntry;
1092  delete[] _liquidFlags;
1093  delete[] _liquidMap;
1094  m_area_map = NULL;
1095  m_V9 = NULL;
1096  m_V8 = NULL;
1097  _liquidEntry = NULL;
1098  _liquidFlags = NULL;
1099  _liquidMap = NULL;
1100  m_gridGetHeight = &GridMap::getHeightFromFlat;
1101 }
1102 
1103 bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/)
1104 {
1105  map_areaHeader header;
1106  fseek(in, offset, SEEK_SET);
1107 
1108  if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != uint32(MAP_AREA_MAGIC))
1109  return false;
1110 
1111  m_gridArea = header.gridArea;
1112  if (!(header.flags & MAP_AREA_NO_AREA))
1113  {
1114  m_area_map = new uint16 [16 * 16];
1115  if (fread(m_area_map, sizeof(uint16), 16 * 16, in) != 16 * 16)
1116  return false;
1117  }
1118  return true;
1119 }
1120 
1121 bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/)
1122 {
1123  map_heightHeader header;
1124  fseek(in, offset, SEEK_SET);
1125 
1126  if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != uint32(MAP_HEIGHT_MAGIC))
1127  return false;
1128 
1129  m_gridHeight = header.gridHeight;
1130  if (!(header.flags & MAP_HEIGHT_NO_HEIGHT))
1131  {
1132  if ((header.flags & MAP_HEIGHT_AS_INT16))
1133  {
1134  m_uint16_V9 = new uint16 [129 * 129];
1135  m_uint16_V8 = new uint16 [128 * 128];
1136  if (fread(m_uint16_V9, sizeof(uint16), 129 * 129, in) != 129 * 129 ||
1137  fread(m_uint16_V8, sizeof(uint16), 128 * 128, in) != 128 * 128)
1138  return false;
1139  m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;
1140  m_gridGetHeight = &GridMap::getHeightFromUint16;
1141  }
1142  else if ((header.flags & MAP_HEIGHT_AS_INT8))
1143  {
1144  m_uint8_V9 = new uint8 [129 * 129];
1145  m_uint8_V8 = new uint8 [128 * 128];
1146  if (fread(m_uint8_V9, sizeof(uint8), 129 * 129, in) != 129 * 129 ||
1147  fread(m_uint8_V8, sizeof(uint8), 128 * 128, in) != 128 * 128)
1148  return false;
1149  m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255;
1150  m_gridGetHeight = &GridMap::getHeightFromUint8;
1151  }
1152  else
1153  {
1154  m_V9 = new float [129 * 129];
1155  m_V8 = new float [128 * 128];
1156  if (fread(m_V9, sizeof(float), 129 * 129, in) != 129 * 129 ||
1157  fread(m_V8, sizeof(float), 128 * 128, in) != 128 * 128)
1158  return false;
1159  m_gridGetHeight = &GridMap::getHeightFromFloat;
1160  }
1161  }
1162  else
1163  m_gridGetHeight = &GridMap::getHeightFromFlat;
1164  return true;
1165 }
1166 
1167 bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/)
1168 {
1169  map_liquidHeader header;
1170  fseek(in, offset, SEEK_SET);
1171 
1172  if (fread(&header, sizeof(header), 1, in) != 1 || header.fourcc != uint32(MAP_LIQUID_MAGIC))
1173  return false;
1174 
1175  m_liquidType = header.liquidType;
1176  m_liquid_offX = header.offsetX;
1177  m_liquid_offY = header.offsetY;
1178  m_liquid_width = header.width;
1179  m_liquid_height = header.height;
1180  m_liquidLevel = header.liquidLevel;
1181 
1182  if (!(header.flags & MAP_LIQUID_NO_TYPE))
1183  {
1184  _liquidEntry = new uint16[16*16];
1185  if (fread(_liquidEntry, sizeof(uint16), 16*16, in) != 16*16)
1186  return false;
1187 
1188  _liquidFlags = new uint8[16*16];
1189  if (fread(_liquidFlags, sizeof(uint8), 16*16, in) != 16*16)
1190  return false;
1191  }
1192  if (!(header.flags & MAP_LIQUID_NO_HEIGHT))
1193  {
1194  _liquidMap = new float[m_liquid_width * m_liquid_height];
1195  if (fread(_liquidMap, sizeof(float), m_liquid_width * m_liquid_height, in) != m_liquid_width * m_liquid_height)
1196  return false;
1197  }
1198  return true;
1199 }
1200 
1201 uint16 GridMap::getArea(float x, float y)
1202 {
1203  if (!m_area_map)
1204  return m_gridArea;
1205 
1206  x = 16 * (CENTER_GRID_ID - x/SIZE_OF_GRIDS);
1207  y = 16 * (CENTER_GRID_ID - y/SIZE_OF_GRIDS);
1208  int lx = (int)x & 15;
1209  int ly = (int)y & 15;
1210  return m_area_map[lx * 16 + ly];
1211 }
1212 
1213 float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const
1214 {
1215  return m_gridHeight;
1216 }
1217 
1218 float GridMap::getHeightFromFloat(float x, float y) const
1219 {
1220  if (!m_V8 || !m_V9)
1221  return m_gridHeight;
1222 
1225 
1226  int x_int = (int)x;
1227  int y_int = (int)y;
1228  x -= x_int;
1229  y -= y_int;
1230  x_int &= (MAP_RESOLUTION - 1);
1231  y_int &= (MAP_RESOLUTION - 1);
1232 
1233  // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
1234  // +--------------> X
1235  // | h1-------h2 Coordinates is:
1236  // | | \ 1 / | h1 0,0
1237  // | | \ / | h2 0,1
1238  // | | 2 h5 3 | h3 1,0
1239  // | | / \ | h4 1,1
1240  // | | / 4 \ | h5 1/2,1/2
1241  // | h3-------h4
1242  // V Y
1243  // For find height need
1244  // 1 - detect triangle
1245  // 2 - solve linear equation from triangle points
1246  // Calculate coefficients for solve h = a*x + b*y + c
1247 
1248  float a, b, c;
1249  // Select triangle:
1250  if (x + y < 1)
1251  {
1252  if (x > y)
1253  {
1254  // 1 triangle (h1, h2, h5 points)
1255  float h1 = m_V9[(x_int) * 129 + y_int];
1256  float h2 = m_V9[(x_int + 1) * 129 + y_int];
1257  float h5 = 2 * m_V8[x_int * 128 + y_int];
1258  a = h2 - h1;
1259  b = h5 - h1 - h2;
1260  c = h1;
1261  }
1262  else
1263  {
1264  // 2 triangle (h1, h3, h5 points)
1265  float h1 = m_V9[x_int * 129 + y_int ];
1266  float h3 = m_V9[x_int * 129 + y_int + 1];
1267  float h5 = 2 * m_V8[x_int * 128 + y_int];
1268  a = h5 - h1 - h3;
1269  b = h3 - h1;
1270  c = h1;
1271  }
1272  }
1273  else
1274  {
1275  if (x > y)
1276  {
1277  // 3 triangle (h2, h4, h5 points)
1278  float h2 = m_V9[(x_int + 1) * 129 + y_int ];
1279  float h4 = m_V9[(x_int + 1) * 129 + y_int + 1];
1280  float h5 = 2 * m_V8[x_int * 128 + y_int];
1281  a = h2 + h4 - h5;
1282  b = h4 - h2;
1283  c = h5 - h4;
1284  }
1285  else
1286  {
1287  // 4 triangle (h3, h4, h5 points)
1288  float h3 = m_V9[(x_int) * 129 + y_int + 1];
1289  float h4 = m_V9[(x_int + 1) * 129 + y_int + 1];
1290  float h5 = 2 * m_V8[x_int * 128 + y_int];
1291  a = h4 - h3;
1292  b = h3 + h4 - h5;
1293  c = h5 - h4;
1294  }
1295  }
1296  // Calculate height
1297  return a * x + b * y + c;
1298 }
1299 
1300 float GridMap::getHeightFromUint8(float x, float y) const
1301 {
1302  if (!m_uint8_V8 || !m_uint8_V9)
1303  return m_gridHeight;
1304 
1307 
1308  int x_int = (int)x;
1309  int y_int = (int)y;
1310  x -= x_int;
1311  y -= y_int;
1312  x_int &= (MAP_RESOLUTION - 1);
1313  y_int &= (MAP_RESOLUTION - 1);
1314 
1315  int32 a, b, c;
1316  uint8* V9_h1_ptr = &m_uint8_V9[x_int * 128 + x_int + y_int];
1317  if (x + y < 1)
1318  {
1319  if (x > y)
1320  {
1321  // 1 triangle (h1, h2, h5 points)
1322  int32 h1 = V9_h1_ptr[ 0];
1323  int32 h2 = V9_h1_ptr[129];
1324  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1325  a = h2 - h1;
1326  b = h5 - h1 - h2;
1327  c = h1;
1328  }
1329  else
1330  {
1331  // 2 triangle (h1, h3, h5 points)
1332  int32 h1 = V9_h1_ptr[0];
1333  int32 h3 = V9_h1_ptr[1];
1334  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1335  a = h5 - h1 - h3;
1336  b = h3 - h1;
1337  c = h1;
1338  }
1339  }
1340  else
1341  {
1342  if (x > y)
1343  {
1344  // 3 triangle (h2, h4, h5 points)
1345  int32 h2 = V9_h1_ptr[129];
1346  int32 h4 = V9_h1_ptr[130];
1347  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1348  a = h2 + h4 - h5;
1349  b = h4 - h2;
1350  c = h5 - h4;
1351  }
1352  else
1353  {
1354  // 4 triangle (h3, h4, h5 points)
1355  int32 h3 = V9_h1_ptr[ 1];
1356  int32 h4 = V9_h1_ptr[130];
1357  int32 h5 = 2 * m_uint8_V8[x_int * 128 + y_int];
1358  a = h4 - h3;
1359  b = h3 + h4 - h5;
1360  c = h5 - h4;
1361  }
1362  }
1363  // Calculate height
1364  return (float)((a * x) + (b * y) + c) * m_gridIntHeightMultiplier + m_gridHeight;
1365 }
1366 
1367 float GridMap::getHeightFromUint16(float x, float y) const
1368 {
1369  if (!m_uint16_V8 || !m_uint16_V9)
1370  return m_gridHeight;
1371 
1374 
1375  int x_int = (int)x;
1376  int y_int = (int)y;
1377  x -= x_int;
1378  y -= y_int;
1379  x_int &= (MAP_RESOLUTION - 1);
1380  y_int &= (MAP_RESOLUTION - 1);
1381 
1382  int32 a, b, c;
1383  uint16* V9_h1_ptr = &m_uint16_V9[x_int * 128 + x_int + y_int];
1384  if (x + y < 1)
1385  {
1386  if (x > y)
1387  {
1388  // 1 triangle (h1, h2, h5 points)
1389  int32 h1 = V9_h1_ptr[ 0];
1390  int32 h2 = V9_h1_ptr[129];
1391  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1392  a = h2 - h1;
1393  b = h5 - h1 - h2;
1394  c = h1;
1395  }
1396  else
1397  {
1398  // 2 triangle (h1, h3, h5 points)
1399  int32 h1 = V9_h1_ptr[0];
1400  int32 h3 = V9_h1_ptr[1];
1401  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1402  a = h5 - h1 - h3;
1403  b = h3 - h1;
1404  c = h1;
1405  }
1406  }
1407  else
1408  {
1409  if (x > y)
1410  {
1411  // 3 triangle (h2, h4, h5 points)
1412  int32 h2 = V9_h1_ptr[129];
1413  int32 h4 = V9_h1_ptr[130];
1414  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1415  a = h2 + h4 - h5;
1416  b = h4 - h2;
1417  c = h5 - h4;
1418  }
1419  else
1420  {
1421  // 4 triangle (h3, h4, h5 points)
1422  int32 h3 = V9_h1_ptr[ 1];
1423  int32 h4 = V9_h1_ptr[130];
1424  int32 h5 = 2 * m_uint16_V8[x_int * 128 + y_int];
1425  a = h4 - h3;
1426  b = h3 + h4 - h5;
1427  c = h5 - h4;
1428  }
1429  }
1430  // Calculate height
1431  return (float)((a * x) + (b * y) + c) * m_gridIntHeightMultiplier + m_gridHeight;
1432 }
1433 
1434 float GridMap::getLiquidLevel(float x, float y)
1435 {
1436  if (!_liquidMap)
1437  return m_liquidLevel;
1438 
1441 
1442  int cx_int = ((int)x & (MAP_RESOLUTION - 1)) - m_liquid_offY;
1443  int cy_int = ((int)y & (MAP_RESOLUTION - 1)) - m_liquid_offX;
1444 
1445  if (cx_int < 0 || cx_int >= m_liquid_height)
1446  return INVALID_HEIGHT;
1447  if (cy_int < 0 || cy_int >= m_liquid_width)
1448  return INVALID_HEIGHT;
1449 
1450  return _liquidMap[cx_int * m_liquid_width + cy_int];
1451 }
1452 
1454 {
1455  if (!_liquidFlags)
1456  return 0;
1457 
1458  x = 16 * (CENTER_GRID_ID - x/SIZE_OF_GRIDS);
1459  y = 16 * (CENTER_GRID_ID - y/SIZE_OF_GRIDS);
1460  int lx = (int)x & 15;
1461  int ly = (int)y & 15;
1462  return _liquidFlags[lx * 16 + ly];
1463 }
1464 
1465 // Get water state on map
1466 inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data)
1467 {
1468  // Check water type (if no water return)
1469  if (!m_liquidType && !_liquidFlags)
1470  return LIQUID_MAP_NO_WATER;
1471 
1472  // Get cell
1473  float cx = MAP_RESOLUTION * (CENTER_GRID_ID - x/SIZE_OF_GRIDS);
1474  float cy = MAP_RESOLUTION * (CENTER_GRID_ID - y/SIZE_OF_GRIDS);
1475 
1476  int x_int = (int)cx & (MAP_RESOLUTION - 1);
1477  int y_int = (int)cy & (MAP_RESOLUTION - 1);
1478 
1479  // Check water type in cell
1480  int idx=(x_int>>3)*16 + (y_int>>3);
1481  uint8 type = _liquidFlags ? _liquidFlags[idx] : 1 << m_liquidType;
1482  uint32 entry = 0;
1483  if (_liquidEntry)
1484  {
1485  if (LiquidTypeEntry const* liquidEntry = sLiquidTypeStore.LookupEntry(_liquidEntry[idx]))
1486  {
1487  entry = liquidEntry->Id;
1488  uint32 liqTypeIdx = liquidEntry->Type;
1489  if ((entry < 21) && (type & MAP_LIQUID_TYPE_WATER))
1490  {
1491  // only basic liquid stored in maps actualy so in some case we need to override type depend on area
1492  // actualy only Hyjal Mount and Coilfang raid be overrided here
1493  if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(getArea(x, y), MAPID_INVALID))
1494  {
1495  uint32 overrideLiquid = area->LiquidTypeOverride;
1496  if (!overrideLiquid && area->zone)
1497  if (area = GetAreaEntryByAreaID(area->zone))
1498  overrideLiquid = area->LiquidTypeOverride;
1499 
1500  if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(overrideLiquid))
1501  {
1502  entry = overrideLiquid;
1503  liqTypeIdx = liq->Type;
1504  }
1505  }
1506  }
1507 
1508  type |= (1 << liqTypeIdx) | (type & MAP_LIQUID_TYPE_DARK_WATER);
1509  }
1510  }
1511 
1512  if (type == 0)
1513  return LIQUID_MAP_NO_WATER;
1514 
1515  // Check req liquid type mask
1516  if (ReqLiquidType && !(ReqLiquidType & type))
1517  return LIQUID_MAP_NO_WATER;
1518 
1519  // Check water level:
1520  // Check water height map
1521  int lx_int = x_int - m_liquid_offY;
1522  int ly_int = y_int - m_liquid_offX;
1523  if (lx_int < 0 || lx_int >= m_liquid_height)
1524  return LIQUID_MAP_NO_WATER;
1525  if (ly_int < 0 || ly_int >= m_liquid_width)
1526  return LIQUID_MAP_NO_WATER;
1527 
1528  // Get water level
1529  float liquid_level = _liquidMap ? _liquidMap[lx_int * m_liquid_width + ly_int] : m_liquidLevel;
1530  // Get ground level (sub 0.2 for fix some errors)
1531  float ground_level = getHeight(x, y);
1532 
1533  // Check water level and ground level
1534  if (liquid_level < ground_level || z < ground_level - 2)
1535  return LIQUID_MAP_NO_WATER;
1536 
1537  // All ok in water -> store data
1538  if (data)
1539  {
1540  data->entry = entry;
1541  data->type_flags = type;
1542  data->level = liquid_level;
1543  data->depth_level = ground_level;
1544  }
1545 
1546  // For speed check as int values
1547  float delta = liquid_level - z;
1548 
1549  // Get position delta
1550  if (delta > 2.0f) // Under water
1551  return LIQUID_MAP_UNDER_WATER;
1552  if (delta > 0.0f) // In water
1553  return LIQUID_MAP_IN_WATER;
1554  if (delta > -0.1f) // Walk on water
1555  return LIQUID_MAP_WATER_WALK;
1556  // Above water
1557  return LIQUID_MAP_ABOVE_WATER;
1558 }
1559 
1560 inline GridMap* Map::GetGrid(float x, float y)
1561 {
1562  // half opt method
1563  int gx = (int)(CENTER_GRID_ID - x / SIZE_OF_GRIDS); //grid x
1564  int gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); //grid y
1565 
1566  // ensure GridMap is loaded
1568 
1569  return GridMaps[gx][gy];
1570 }
1571 
1572 float Map::GetWaterOrGroundLevel(float x, float y, float z, float* ground /*= NULL*/, bool /*swim = false*/) const
1573 {
1574  if (const_cast<Map*>(this)->GetGrid(x, y))
1575  {
1576  // we need ground level (including grid height version) for proper return water level in point
1577  float ground_z = GetHeight(x, y, z, true, 50.0f);
1578  if (ground)
1579  *ground = ground_z;
1580 
1581  LiquidData liquid_status;
1582 
1583  ZLiquidStatus res = getLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status);
1584  return res ? liquid_status.level : ground_z;
1585  }
1586 
1588 }
1589 
1590 float Map::GetHeight(float x, float y, float z, bool checkVMap, float maxSearchDist) const
1591 {
1592  // find raw .map surface under Z coordinates
1593  float mapHeight = VMAP_INVALID_HEIGHT_VALUE;
1594  float realHeight = VMAP_INVALID_HEIGHT_VALUE;
1595  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1596  {
1597  float gridHeight = gmap->getHeight(x, y);
1598  // look from a bit higher pos to find the floor, ignore under surface case
1599  if (z + 2.0f > gridHeight)
1600  mapHeight = gridHeight;
1601  }
1602 
1603  float vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
1604  if (checkVMap)
1605  {
1607  if (vmgr->isHeightCalcEnabled())
1608  vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor
1609  }
1610 
1611  // Explicitly set map data, and use it if no change.
1612  realHeight = mapHeight;
1613 
1614  // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT
1615  // vmapheight set for any under Z value or <= INVALID_HEIGHT
1616  if (vmapHeight > INVALID_HEIGHT)
1617  {
1618  if (mapHeight > INVALID_HEIGHT)
1619  {
1620  // we have mapheight and vmapheight and must select more appropriate
1621 
1622  // we are already under the surface or vmap height above map heigt
1623  // or if the distance of the vmap height is less the land height distance
1624  if (vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z))
1625  realHeight = vmapHeight;
1626  else
1627  realHeight = mapHeight; // better use .map surface height
1628  }
1629  else
1630  realHeight = vmapHeight; // we have only vmapHeight (if have)
1631  }
1632 
1633  return std::max<float>(realHeight, m_dyn_tree.getHeight(x, y, z, maxSearchDist));
1634 }
1635 
1636 inline bool IsOutdoorWMO(uint32 mogpFlags, uint32 mapId)
1637 {
1638  // if this flag is set we are outdoors and can mount up
1639  if (mogpFlags & 0x8000)
1640  return true;
1641 
1642  // if flag 0x800 is set and we are in non-flyable areas we cannot mount up even if we are physically outdoors
1643  if (mapId != 530 && mogpFlags & 0x800)
1644  return false;
1645 
1646  // if this flag is set we are physically outdoors, mounting up is allowed if previous check failed
1647  return mogpFlags & 0x8;
1648 }
1649 
1650 bool Map::IsOutdoors(float x, float y, float z) const
1651 {
1652  uint32 mogpFlags;
1653  int32 adtId, rootId, groupId;
1654 
1655  // no wmo found? -> outside by default
1656  if (!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
1657  return true;
1658 
1659  return IsOutdoorWMO(mogpFlags, i_mapEntry->MapID);
1660 }
1661 
1662 bool Map::GetAreaInfo(float x, float y, float z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
1663 {
1664  float vmap_z = z;
1666  if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId))
1667  {
1668  // check if there's terrain between player height and object height
1669  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1670  {
1671  float _mapheight = gmap->getHeight(x, y);
1672  // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice...
1673  if (z + 2.0f > _mapheight && _mapheight > vmap_z)
1674  return false;
1675  }
1676  return true;
1677  }
1678  return false;
1679 }
1680 
1681 uint16 Map::GetAreaFlag(float x, float y, float z, bool* isOutdoors) const
1682 {
1683  uint32 mogpFlags;
1684  int32 adtId, rootId, groupId;
1685  WMOAreaTableEntry const* wmoEntry = 0;
1686  AreaTableEntry const* atEntry = 0;
1687  bool haveAreaInfo = false;
1688 
1689  if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId))
1690  {
1691  haveAreaInfo = true;
1692  if ((wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId)))
1693  atEntry = GetAreaEntryByAreaID(wmoEntry->areaId);
1694  }
1695 
1696  uint16 areaflag;
1697 
1698  if (atEntry)
1699  areaflag = atEntry->exploreFlag;
1700  else
1701  {
1702  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1703  areaflag = gmap->getArea(x, y);
1704  // this used while not all *.map files generated (instances)
1705  else
1706  areaflag = GetAreaFlagByMapId(i_mapEntry->MapID);
1707  }
1708 
1709  if (isOutdoors)
1710  {
1711  if (haveAreaInfo)
1712  *isOutdoors = IsOutdoorWMO(mogpFlags, i_mapEntry->MapID);
1713  else
1714  *isOutdoors = true;
1715  }
1716  return areaflag;
1717 }
1718 
1719 uint8 Map::GetTerrainType(float x, float y) const
1720 {
1721  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1722  return gmap->getTerrainType(x, y);
1723  else
1724  return 0;
1725 }
1726 
1727 ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const
1728 {
1731  float liquid_level = INVALID_HEIGHT;
1732  float ground_level = INVALID_HEIGHT;
1733  uint32 liquid_type = 0;
1734  if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type))
1735  {
1736  sLog.outVMap("getLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type);
1737  // Check water level and ground level
1738  if (liquid_level > ground_level && z > ground_level - 2)
1739  {
1740  // All ok in water -> store data
1741  if (data)
1742  {
1743  // hardcoded in client like this convert ocean to lava
1744  if (GetId() == 530 && liquid_type == 2)
1745  liquid_type = 3;
1746 
1747  uint32 liquidFlagType = 0;
1748  if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquid_type))
1749  liquidFlagType = 1 << liq->Type;
1750 
1751  data->level = liquid_level;
1752  data->depth_level = ground_level;
1753 
1754  data->entry = liquid_type;
1755  data->type_flags = liquidFlagType;
1756  }
1757 
1758  // For speed check as int values
1759  float delta = liquid_level - z;
1760 
1761  // Get position delta
1762  if (delta > 2.0f) // Under water
1763  return LIQUID_MAP_UNDER_WATER;
1764  if (delta > 0.0f) // In water
1765  return LIQUID_MAP_IN_WATER;
1766  if (delta > -0.1f) // Walk on water
1767  return LIQUID_MAP_WATER_WALK;
1768  result = LIQUID_MAP_ABOVE_WATER;
1769  }
1770  }
1771 
1772  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1773  {
1774  LiquidData map_data;
1775  ZLiquidStatus map_result = gmap->getLiquidStatus(x, y, z, ReqLiquidType, &map_data);
1776  // Not override LIQUID_MAP_ABOVE_WATER with LIQUID_MAP_NO_WATER:
1777  if (map_result != LIQUID_MAP_NO_WATER && (map_data.level > ground_level))
1778  {
1779  if (data)
1780  {
1781  // hardcoded in client like this
1782  if (GetId() == 530 && map_data.entry == 2)
1783  {
1784  map_data.entry = 3;
1785  map_data.type_flags = MAP_LIQUID_TYPE_MAGMA;
1786  }
1787 
1788  *data = map_data;
1789  }
1790  return map_result;
1791  }
1792  }
1793  return result;
1794 }
1795 
1796 float Map::GetWaterLevel(float x, float y) const
1797 {
1798  if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
1799  return gmap->getLiquidLevel(x, y);
1800  else
1801  return 0;
1802 }
1803 
1804 bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2) const
1805 {
1806  return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2)
1807  && m_dyn_tree.isInLineOfSight(x1, y1, z1, x2, y2, z2);
1808 }
1809 
1810 bool Map::getObjectHitPos(float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
1811 {
1812  G3D::Vector3 startPos = G3D::Vector3(x1, y1, z1);
1813  G3D::Vector3 dstPos = G3D::Vector3(x2, y2, z2);
1814 
1815  G3D::Vector3 resultPos;
1816  bool result = m_dyn_tree.getObjectHitPos(startPos, dstPos, resultPos, modifyDist);
1817 
1818  rx = resultPos.x;
1819  ry = resultPos.y;
1820  rz = resultPos.z;
1821  return result;
1822 }
1823 
1825 {
1826  AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
1827 
1828  if (entry)
1829  return entry->ID;
1830  else
1831  return 0;
1832 }
1833 
1835 {
1836  AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id);
1837 
1838  if (entry)
1839  return (entry->zone != 0) ? entry->zone : entry->ID;
1840  else
1841  return 0;
1842 }
1843 
1844 bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const
1845 {
1846  LiquidData liquid_status;
1847  LiquidData* liquid_ptr = data ? data : &liquid_status;
1848  return (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0;
1849 }
1850 
1851 bool Map::IsUnderWater(float x, float y, float z) const
1852 {
1853  if (const_cast<Map*>(this)->GetGrid(x, y))
1854  {
1856  return true;
1857  }
1858  return false;
1859 }
1860 
1861 bool Map::IsSwimmable(float x, float y, float z, LiquidData* data) const
1862 {
1863  LiquidData liquid_status;
1864  LiquidData* liquid_ptr = data ? data : &liquid_status;
1866  {
1867  if (liquid_ptr->level - liquid_ptr->depth_level > 1.5f)
1868  return true;
1869  }
1870 
1871  return false;
1872 }
1873 
1874 bool Map::CheckGridIntegrity(Creature* c, bool moved) const
1875 {
1876  Cell const& cur_cell = c->GetCurrentCell();
1877 
1878  Cell xy_cell(c->GetPositionX(), c->GetPositionY());
1879  if (xy_cell != cur_cell)
1880  {
1881  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]",
1882  c->GetGUIDLow(),
1883  c->GetPositionX(), c->GetPositionY(), (moved ? "final" : "original"),
1884  cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(),
1885  xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY());
1886  return true; // not crash at error, just output error in debug mode
1887  }
1888 
1889  return true;
1890 }
1891 
1892 const char* Map::GetMapName() const
1893 {
1894  return i_mapEntry ? i_mapEntry->name[sWorld.GetDefaultDbcLocale()] : "UNNAMEDMAP\x0";
1895 }
1896 
1898 {
1899  cell.SetNoCreate();
1900  Oregon::VisibleChangesNotifier notifier(*obj);
1902  cell.Visit(cellpair, player_notifier, *this, *obj, obj->GetVisibilityRange());
1903 }
1904 
1906 {
1907  Oregon::VisibleNotifier notifier(*player);
1908 
1909  cell.SetNoCreate();
1912  cell.Visit(cellpair, world_notifier, *this, *player->m_seer, player->GetVisibilityRange());
1913  cell.Visit(cellpair, grid_notifier, *this, *player->m_seer, player->GetVisibilityRange());
1914 
1915  // send data
1916  notifier.SendToSelf();
1917 }
1918 
1920 {
1921  sLog.outDetail("Creating player data for himself %u", player->GetGUIDLow());
1922 
1923  UpdateData data;
1924 
1925  bool hasTransport = false;
1926 
1927  // attach to player data current transport data
1928  if (Transport* transport = player->GetTransport())
1929  {
1930  hasTransport = true;
1931  transport->BuildCreateUpdateBlockForPlayer(&data, player);
1932  }
1933 
1934  // build data for self presence in world at own client (one time for map)
1935  player->BuildCreateUpdateBlockForPlayer(&data, player);
1936 
1937  // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
1938  if (Transport* transport = player->GetTransport())
1939  {
1940  for (Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
1941  {
1942  if (player != (*itr) && player->HaveAtClient(*itr))
1943  {
1944  hasTransport = true;
1945  (*itr)->BuildCreateUpdateBlockForPlayer(&data, player);
1946  }
1947  }
1948  }
1949 
1950  WorldPacket packet;
1951  data.BuildPacket(&packet, hasTransport);
1952  player->GetSession()->SendPacket(&packet);
1953 }
1954 
1956 {
1957  // Hack to send out transports
1959 
1960  // no transports at map
1961  if (tmap.find(player->GetMapId()) == tmap.end())
1962  return;
1963 
1964  UpdateData transData;
1965 
1966  MapManager::TransportSet& tset = tmap[player->GetMapId()];
1967 
1968  bool hasTransport = false;
1969 
1970  for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
1971  {
1972  // send data for current transport in other place
1973  if ((*i) != player->GetTransport() && (*i)->GetMapId() == GetId())
1974  {
1975  hasTransport = true;
1976  (*i)->BuildCreateUpdateBlockForPlayer(&transData, player);
1977  }
1978  }
1979 
1980  WorldPacket packet;
1981  transData.BuildPacket(&packet, hasTransport);
1982  player->GetSession()->SendPacket(&packet);
1983 }
1984 
1986 {
1987  // Hack to send out transports
1989 
1990  // no transports at map
1991  if (tmap.find(player->GetMapId()) == tmap.end())
1992  return;
1993 
1994  UpdateData transData;
1995 
1996  MapManager::TransportSet& tset = tmap[player->GetMapId()];
1997 
1998  // except used transport
1999  for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i)
2000  if ((*i) != player->GetTransport() && (*i)->GetMapId() != GetId())
2001  (*i)->BuildOutOfRangeUpdateBlock(&transData);
2002 
2003  WorldPacket packet;
2004  transData.BuildPacket(&packet);
2005  player->GetSession()->SendPacket(&packet);
2006 }
2007 
2008 inline void Map::setNGrid(NGridType* grid, uint32 x, uint32 y)
2009 {
2010  if (x >= MAX_NUMBER_OF_GRIDS || y >= MAX_NUMBER_OF_GRIDS)
2011  {
2012  sLog.outError("map::setNGrid() Invalid grid coordinates found: %d, %d!", x, y);
2013  ASSERT(false);
2014  }
2015  i_grids[x][y] = grid;
2016 }
2017 
2018 void Map::DelayedUpdate(const uint32 t_diff)
2019 {
2021 
2022  // 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 !
2023  // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
2024  if (!IsBattlegroundOrArena())
2025  {
2027  {
2028  NGridType* grid = i->GetSource();
2029  GridInfo* info = i->GetSource()->getGridInfoRef();
2030  ++i; // The update might delete the map and we need the next map before the iterator gets invalid
2031  ASSERT(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
2032  si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, t_diff);
2033  }
2034  }
2035 }
2036 
2038 {
2039  ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2040 
2041  obj->CleanupsBeforeDelete(); // remove or simplify at least cross referenced links
2042 
2043  i_objectsToRemove.insert(obj);
2044  //sLog.outMap("Object (GUID: %u TypeId: %u) added to removing list.",obj->GetGUIDLow(),obj->GetTypeId());
2045 }
2046 
2048 {
2049  ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2050  // i_objectsToSwitch is iterated only in Map::RemoveAllObjectsInRemoveList() and it uses
2051  // the contained objects only if GetTypeId() == TYPEID_UNIT , so we can return in all other cases
2052  if (obj->GetTypeId() != TYPEID_UNIT)
2053  return;
2054 
2055  std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.find(obj);
2056  if (itr == i_objectsToSwitch.end())
2057  i_objectsToSwitch.insert(itr, std::make_pair(obj, on));
2058  else if (itr->second != on)
2059  i_objectsToSwitch.erase(itr);
2060  else
2061  ASSERT(false);
2062 }
2063 
2065 {
2066  while (!i_objectsToSwitch.empty())
2067  {
2068  std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.begin();
2069  WorldObject* obj = itr->first;
2070  bool on = itr->second;
2071  i_objectsToSwitch.erase(itr);
2072 
2073  if (obj->GetTypeId() == TYPEID_UNIT && !obj->IsPermanentWorldObject())
2074  SwitchGridContainers(obj->ToCreature(), on);
2075  }
2076 
2077  //sLog.outMap("Object remover 1 check.");
2078  while (!i_objectsToRemove.empty())
2079  {
2080  std::set<WorldObject*>::iterator itr = i_objectsToRemove.begin();
2081  WorldObject* obj = *itr;
2082 
2083  switch (obj->GetTypeId())
2084  {
2085  case TYPEID_CORPSE:
2086  {
2087  Corpse* corpse = ObjectAccessor::Instance().GetCorpse(*obj, obj->GetGUID());
2088  if (!corpse)
2089  sLog.outError("Tried to delete corpse/bones %u that is not in map.", obj->GetGUIDLow());
2090  else
2091  RemoveFromMap(corpse, true);
2092  break;
2093  }
2094  case TYPEID_DYNAMICOBJECT:
2095  RemoveFromMap((DynamicObject*)obj, true);
2096  break;
2097  case TYPEID_GAMEOBJECT:
2098  RemoveFromMap((GameObject*)obj, true);
2099  break;
2100  case TYPEID_UNIT:
2101  // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call
2102  // make sure that like sources auras/etc removed before destructor start
2103  obj->ToCreature()->CleanupsBeforeDelete();
2104  RemoveFromMap(obj->ToCreature(), true);
2105  break;
2106  default:
2107  sLog.outError("Non-grid object (TypeId: %u) is in grid object remove list, ignored.", obj->GetTypeId());
2108  break;
2109  }
2110 
2111  i_objectsToRemove.erase(itr);
2112  }
2113 
2114  //sLog.outMap("Object remover 2 check.");
2115 }
2116 
2118 {
2119  uint32 count = 0;
2121  if (!itr->GetSource()->IsGameMaster())
2122  ++count;
2123  return count;
2124 }
2125 
2126 void Map::SendToPlayers(WorldPacket const* data) const
2127 {
2129  itr->GetSource()->GetSession()->SendPacket(data);
2130 }
2131 
2132 bool Map::ActiveObjectsNearGrid(NGridType const& ngrid) const
2133 {
2134  CellCoord cell_min(ngrid.getX() * MAX_NUMBER_OF_CELLS, ngrid.getY() * MAX_NUMBER_OF_CELLS);
2135  CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord + MAX_NUMBER_OF_CELLS);
2136 
2137  //we must find visible range in cells so we unload only non-visible cells...
2138  float viewDist = GetVisibilityRange();
2139  int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1;
2140 
2141  cell_min << cell_range;
2142  cell_min -= cell_range;
2143  cell_max >> cell_range;
2144  cell_max += cell_range;
2145 
2146  for (MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
2147  {
2148  Player* plr = iter->GetSource();
2149 
2151  if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2152  (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2153  return true;
2154  }
2155 
2156  for (ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter)
2157  {
2158  WorldObject* obj = *iter;
2159 
2161  if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2162  (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2163  return true;
2164  }
2165 
2166  return false;
2167 }
2168 
2170 {
2171  AddToActiveHelper(c);
2172 
2173  // also not allow unloading spawn grid to prevent creating creature clone at load
2174  if (!c->IsPet() && c->GetDBTableGUIDLow())
2175  {
2176  float x, y, z;
2177  c->GetRespawnPosition(x, y, z);
2179  if (getNGrid(p.x_coord, p.y_coord))
2181  else
2182  {
2184  sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] not loaded.",
2185  c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2186  }
2187  }
2188 }
2189 
2191 {
2193 
2194  // also allow unloading spawn grid
2195  if (!c->IsPet() && c->GetDBTableGUIDLow())
2196  {
2197  float x, y, z;
2198  c->GetRespawnPosition(x, y, z);
2200  if (getNGrid(p.x_coord, p.y_coord))
2202  else
2203  {
2205  sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] not loaded.",
2206  c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2207  }
2208  }
2209 }
2210 
2211 template bool Map::AddToMap(Corpse*);
2212 template bool Map::AddToMap(Creature*);
2213 template bool Map::AddToMap(GameObject*);
2214 template bool Map::AddToMap(DynamicObject*);
2215 
2216 template void Map::RemoveFromMap(Corpse*, bool);
2217 template void Map::RemoveFromMap(Creature*, bool);
2218 template void Map::RemoveFromMap(GameObject*, bool);
2219 template void Map::RemoveFromMap(DynamicObject*, bool);
2220 
2221 /* ******* Dungeon Instance Maps ******* */
2222 
2223 InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
2224  : Map(id, expiry, InstanceId, SpawnMode, _parent),
2225  m_resetAfterUnload(false), m_unloadWhenEmpty(false),
2226  i_data(NULL)
2227 {
2228  //lets initialize visibility distance for dungeons
2230 
2231  // the timer is started by default, and stopped when the first player joins
2232  // this make sure it gets unloaded if for some reason no player joins
2234 }
2235 
2237 {
2238  delete i_data;
2239  i_data = NULL;
2240 }
2241 
2243 {
2244  //init visibility distance for instances
2245  m_VisibleDistance = sWorld.GetMaxVisibleDistanceInInstances();
2247 }
2248 
2249 /*
2250  Do map specific checks to see if the player can enter
2251 */
2253 {
2254  if (player->GetMapRef().getTarget() == this)
2255  {
2256  sLog.outError("InstanceMap::CannotEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
2257  ASSERT(false);
2259  }
2260 
2261  // allow GM's to enter
2262  if (player->IsGameMaster())
2263  return Map::CannotEnter(player);
2264 
2265  // cannot enter if the instance is full (player cap), GMs don't count
2266  InstanceTemplate const* iTemplate = sObjectMgr.GetInstanceTemplate(GetId());
2267  if (GetPlayersCountExceptGMs() >= iTemplate->maxPlayers)
2268  {
2269  sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName());
2270  return CANNOT_ENTER_MAX_PLAYERS;
2271  }
2272 
2273  // cannot enter while an encounter is in progress (unless this is a relog, in which case it is permitted)
2274  if (!player->IsLoading() && IsRaid() && GetInstanceData() && GetInstanceData()->IsEncounterInProgress())
2276 
2277  // cannot enter if player is permanent saved to a different instance id
2278  if (InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetDifficulty()))
2279  if (playerBind->perm && playerBind->save)
2280  if (playerBind->save->GetInstanceId() != GetInstanceId())
2282 
2283  return Map::CannotEnter(player);
2284 }
2285 
2286 /*
2287  Do map specific checks and add the player to the map if successful.
2288 */
2290 {
2291  // @todo Not sure about checking player level: already done in HandleAreaTriggerOpcode
2292  // GMs still can teleport player in instance.
2293  // Is it needed?
2294 
2295  {
2296  Guard guard(*this);
2297  //if (!CanEnter(player))
2298  //return false;
2299 
2300  // Dungeon only code
2301  if (IsDungeon())
2302  {
2303  // get or create an instance save for the map
2304  InstanceSave* mapSave = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2305  if (!mapSave)
2306  {
2307  sLog.outDetail("InstanceMap::AddToMap: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
2308  mapSave = sInstanceSaveMgr.AddInstanceSave(GetId(), GetInstanceId(), DungeonDifficulty(GetSpawnMode()), 0, true);
2309  }
2310 
2311  // check for existing instance binds
2312  InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), GetSpawnMode());
2313  if (playerBind && playerBind->perm)
2314  {
2315  // cannot enter other instances if bound permanently
2316  if (playerBind->save != mapSave)
2317  {
2318  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());
2319  return false;
2320  }
2321  }
2322  else
2323  {
2324  Group* pGroup = player->GetGroup();
2325  if (pGroup)
2326  {
2327  // solo saves should be reset when entering a group
2328  InstanceGroupBind* groupBind = pGroup->GetBoundInstance(this);
2329  if (playerBind)
2330  {
2331  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());
2332  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());
2333  //ASSERT(false);
2334  return false;
2335  }
2336  // bind to the group or keep using the group save
2337  if (!groupBind)
2338  pGroup->BindToInstance(mapSave, false);
2339  else
2340  {
2341  // cannot jump to a different instance without resetting it
2342  if (groupBind->save != mapSave)
2343  {
2344  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());
2345  if (mapSave)
2346  sLog.outError("MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount());
2347  else
2348  sLog.outError("MapSave NULL");
2349 
2350  if (groupBind->save)
2351  sLog.outError("GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount());
2352  else
2353  sLog.outError("GroupBind save NULL");
2354  return false;
2355  }
2356  // if the group/leader is permanently bound to the instance
2357  // players also become permanently bound when they enter
2358  if (groupBind->perm)
2359  {
2361  data << uint32(0);
2362  player->GetSession()->SendPacket(&data);
2363  player->BindToInstance(mapSave, true);
2364  }
2365  }
2366  }
2367  else
2368  {
2369  // set up a solo bind or continue using it
2370  if (!playerBind)
2371  player->BindToInstance(mapSave, false);
2372  else
2373  // cannot jump to a different instance without resetting it
2374  ASSERT(playerBind->save == mapSave);
2375  }
2376  }
2377  }
2378 
2379  // for normal instances cancel the reset schedule when the
2380  // first player enters (no players yet)
2381  SetResetSchedule(false);
2382 
2383  player->SendInitWorldStates();
2384  sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName());
2385  // initialize unload state
2386  m_unloadTimer = 0;
2387  m_resetAfterUnload = false;
2388  m_unloadWhenEmpty = false;
2389  }
2390 
2391  // this will acquire the same mutex so it cannot be in the previous block
2392  Map::AddPlayerToMap(player);
2393 
2394  if (i_data)
2395  i_data->OnPlayerEnter(player);
2396 
2397  return true;
2398 }
2399 
2400 void InstanceMap::Update(const uint32& t_diff)
2401 {
2402  Map::Update(t_diff);
2403 
2404  if (i_data)
2405  i_data->Update(t_diff);
2406 }
2407 
2408 void InstanceMap::RemovePlayerFromMap(Player* player, bool remove)
2409 {
2410  sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName());
2411  //if last player set unload timer
2412  if (!m_unloadTimer && m_mapRefManager.getSize() == 1)
2414  Map::RemovePlayerFromMap(player, remove);
2415  // for normal instances schedule the reset after all players have left
2416  SetResetSchedule(true);
2417 }
2418 
2420 {
2421  if (i_data != NULL)
2422  return;
2423 
2424  InstanceTemplate const* mInstance = sObjectMgr.GetInstanceTemplate(GetId());
2425  if (mInstance)
2426  {
2427  i_script_id = mInstance->script_id;
2428  i_data = sScriptMgr.CreateInstanceData(this);
2429  }
2430 
2431  if (!i_data)
2432  return;
2433 
2434  i_data->Initialize();
2435 
2436  if (load)
2437  {
2438  // @todo make a global storage for this
2439  QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT data FROM instance WHERE map = '%u' AND id = '%u'", GetId(), i_InstanceId);
2440  if (result)
2441  {
2442  Field* fields = result->Fetch();
2443  const char* data = fields[0].GetString();
2444  if (data && *data)
2445  {
2446  sLog.outMap("Loading instance data for %s with id %u", sObjectMgr.GetScriptName(i_script_id), i_InstanceId);
2447  i_data->Load(data);
2448  }
2449  }
2450  }
2451 }
2452 
2453 /*
2454  Returns true if there are no players in the instance
2455 */
2457 {
2458  // note: since the map may not be loaded when the instance needs to be reset
2459  // the instance must be deleted from the DB by InstanceSaveManager
2460 
2461  if (HavePlayers())
2462  {
2463  if (method == INSTANCE_RESET_ALL)
2464  {
2465  // notify the players to leave the instance so it can be reset
2466  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2467  itr->GetSource()->SendResetFailedNotify(GetId());
2468  }
2469  else
2470  {
2471  if (method == INSTANCE_RESET_GLOBAL)
2472  // set the homebind timer for players inside (1 minute)
2473  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2474  itr->GetSource()->m_InstanceValid = false;
2475 
2476  // the unload timer is not started
2477  // instead the map will unload immediately after the players have left
2478  m_unloadWhenEmpty = true;
2479  m_resetAfterUnload = true;
2480  }
2481  }
2482  else
2483  {
2484  // unloaded at next update
2486  m_resetAfterUnload = true;
2487  }
2488 
2489  return m_mapRefManager.isEmpty();
2490 }
2491 
2493 {
2494  if (!IsDungeon())
2495  return;
2496 
2497  InstanceSave* save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2498  if (!save)
2499  {
2500  sLog.outError("Cannot bind players, no instance save available for map!");
2501  return;
2502  }
2503 
2504  Group* group = player->GetGroup();
2505  // group members outside the instance group don't get bound
2506  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2507  {
2508  Player* plr = itr->GetSource();
2509  // players inside an instance cannot be bound to other instances
2510  // some players may already be permanently bound, in this case nothing happens
2511  InstancePlayerBind* bind = plr->GetBoundInstance(save->GetMapId(), save->GetDifficulty());
2512  if (!bind || !bind->perm)
2513  {
2514  plr->BindToInstance(save, true);
2516  data << uint32(0);
2517  plr->GetSession()->SendPacket(&data);
2518  }
2519 
2520  // if the leader is not in the instance the group will not get a perm bind
2521  if (group && group->GetLeaderGUID() == plr->GetGUID())
2522  group->BindToInstance(save, true);
2523  }
2524 }
2525 
2527 {
2528  InstanceSave* save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2529  return time_t(save ? save->GetDifficulty() : DIFFICULTY_NORMAL);
2530 }
2531 
2533 {
2534  ASSERT(!HavePlayers());
2535 
2536  if (m_resetAfterUnload == true)
2537  sObjectMgr.DeleteRespawnTimeForInstance(GetInstanceId());
2538 
2539  Map::UnloadAll();
2540 }
2541 
2543 {
2545  itr->GetSource()->SendInstanceResetWarning(GetId(), timeLeft);
2546 }
2547 
2549 {
2550  // only for normal instances
2551  // the reset time is only scheduled when there are no payers inside
2552  // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
2553  if (IsDungeon() && !HavePlayers() && !IsRaid() && !IsHeroic())
2554  {
2555  InstanceSave* save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
2556  if (!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId());
2557  else sInstanceSaveMgr.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), GetInstanceId()));
2558  }
2559 }
2560 
2561 /* ******* Battleground Instance Maps ******* */
2562 
2563 BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent)
2564  : Map(id, expiry, InstanceId, DIFFICULTY_NORMAL, _parent)
2565 {
2566  //lets initialize visibility distance for BG/Arenas
2568 }
2569 
2571 {
2572 }
2573 
2575 {
2576  //init visibility distance for BG/Arenas
2577  m_VisibleDistance = sWorld.GetMaxVisibleDistanceInBGArenas();
2579 }
2580 
2582 {
2583  if (player->GetMapRef().getTarget() == this)
2584  {
2585  sLog.outError("BGMap::CannotEnter - player %u is already in map!", player->GetGUIDLow());
2586  ASSERT(false);
2588  }
2589 
2590  if (player->GetBattlegroundId() != GetInstanceId())
2592 
2593  // player number limit is checked in bgmgr, no need to do it here
2594 
2595  return Map::CannotEnter(player);
2596 }
2597 
2599 {
2600  {
2601  Guard guard(*this);
2602  //if (!CanEnter(player))
2603  //return false;
2604  // reset instance validity, battleground maps do not homebind
2605  player->m_InstanceValid = true;
2606  }
2607  return Map::AddPlayerToMap(player);
2608 }
2609 
2611 {
2612  sLog.outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName());
2613  Map::RemovePlayerFromMap(player, remove);
2614 }
2615 
2617 {
2619 }
2620 
2622 {
2623  if (HavePlayers())
2624  for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
2625  if (Player* plr = itr->GetSource())
2626  if (!plr->IsBeingTeleportedFar())
2627  plr->TeleportTo(plr->GetBattlegroundEntryPoint());
2628 
2629 }
2630 
2631 Creature*
2633 {
2634  return ObjectAccessor::GetObjectInMap(guid, this, (Creature*)NULL);
2635 }
2636 
2637 GameObject*
2639 {
2640  return ObjectAccessor::GetObjectInMap(guid, this, (GameObject*)NULL);
2641 }
2642 
2645 {
2646  return ObjectAccessor::GetObjectInMap(guid, this, (DynamicObject*)NULL);
2647 }
2648 
2650 {
2651  if (m_mapRefIter == player->GetMapRef())
2653 }
2654 
std::multimap< time_t, ScriptAction > m_scriptSchedule
Definition: Map.h:644
float GetGridActivationRange() const
Definition: Object.cpp:1528
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:2223
InstanceSave * save
Definition: Group.h:145
EnterState CannotEnter(Player *player) override
Definition: Map.cpp:2252
Definition: NGrid.h:75
bool GetAreaInfo(float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId) const
Definition: Map.cpp:1662
virtual void ResetMap()
Definition: Object.cpp:1969
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:1844
#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:1985
ClientGUIDs m_clientGUIDs
Definition: Player.h:2471
Group * GetGroup()
Definition: Player.h:2589
#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:2456
uint8 GetSpawnMode() const
Definition: Map.h:394
float getHeightFromUint8(float x, float y) const
Definition: Map.cpp:1300
void InitVisibilityDistance() override
Definition: Map.cpp:2242
void RemoveFromGrid()
Definition: Object.h:599
uint8 height
Definition: Map.h:122
bool EnsureGridLoaded(Cell const &)
Definition: Map.cpp:363
std::set< WorldObject * > i_objectsToRemove
Definition: Map.h:641
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:1434
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:2058
virtual void RemovePlayerFromMap(Player *, bool)
Definition: Map.cpp:672
MapEntry const * i_mapEntry
Definition: Map.h:600
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:604
#define MAPID_INVALID
Definition: Object.h:565
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:626
Map * GetMap() const
Definition: Object.h:829
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:878
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:2570
grid_state_t GetGridState(void) const
Definition: NGrid.h:99
void RemoveAllPlayers() override
Definition: Map.cpp:2621
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:20676
GridMap * GetGrid(float x, float y)
Definition: Map.cpp:1560
void AddToWorld() override
Definition: Player.cpp:1906
bool IsRaid() const
Definition: Map.h:431
void RemoveFromActiveHelper(T *obj)
Definition: Map.h:660
void SendInitWorldStates(bool force=false, uint32 forceZoneId=0)
Definition: Player.cpp:7721
Map * m_parentMap
Definition: Map.h:630
void SetResetSchedule(bool on)
Definition: Map.cpp:2548
void SendInitTransports(Player *player)
Definition: Map.cpp:1955
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:2454
EnterState CannotEnter(Player *player) override
Definition: Map.cpp:2581
#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:2649
#define MAX_NUMBER_OF_CELLS
Definition: GridDefines.h:43
void RemovePlayerFromMap(Player *, bool) override
Definition: Map.cpp:2408
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:2001
bool IsInCombat() const
Definition: Unit.h:1318
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:642
void Update(const uint32 &) override
Definition: Map.cpp:2400
#define DEFAULT_VISIBILITY_NOTIFY_PERIOD
Definition: NGrid.h:28
void unloadData()
Definition: Map.cpp:1086
float GetHeight(float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const
Definition: Map.cpp:1590
uint32 m_homebindMapId
Definition: Player.h:2451
void SetCurrentCell(Cell const &cell)
Definition: Creature.h:717
#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:1549
uint32 fourcc
Definition: Map.h:116
~InstanceMap() override
Definition: Map.cpp:2236
void UnloadAll() override
Definition: Map.cpp:2532
#define MAX_NUMBER_OF_GRIDS
Definition: GridDefines.h:33
uint32 GetMapId()
virtual void CleanupsBeforeDelete()
Definition: Object.cpp:1155
Transport * GetTransport() const
Definition: Player.h:2403
ZLiquidStatus
Definition: Map.h:126
ACE_INT32 int32
Definition: Define.h:67
uint8 GetGroupCount()
void UpdateObjectVisibility(bool forced=true) override
Definition: Unit.cpp:13418
void Update(uint32 time) override
Definition: Player.cpp:1043
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:654
Definition: Grid.h:45
void AddObjectToRemoveList(WorldObject *obj)
Definition: Map.cpp:2037
bool IsWorldObject() const
Definition: Object.cpp:1111
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:2610
uint32 GetGUIDLow() const
Definition: Object.h:160
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:1572
void RemoveFromActive(T *obj)
Definition: Map.h:511
DynamicObject * ToDynObject()
Definition: Object.h:401
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:1824
bool ActiveObjectsNearGrid(NGridType const &ngrid) const
Definition: Map.cpp:2132
void RemoveAllObjectsInRemoveList()
Definition: Map.cpp:2064
uint16 gridArea
Definition: Map.h:96
DungeonDifficulty
iterator begin()
Definition: MapRefManager.h:48
uint8 i_spawnMode
Definition: Map.h:601
#define sObjectMgr
Definition: ObjectMgr.h:1285
uint32 i_script_id
Definition: Map.h:717
void SendPacket(WorldPacket const *packet)
bool IsInGrid() const
Definition: Object.h:597
ActiveNonPlayers m_activeNonPlayers
Definition: Map.h:612
bool i_scriptLock
Definition: Map.h:640
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:1918
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:625
GridMap * GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition: Map.h:633
void UpdateObjectVisibility(WorldObject *obj, Cell cell, CellCoord cellpair)
Definition: Map.cpp:1897
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:2563
void setNGrid(NGridType *grid, uint32 x, uint32 y)
Definition: Map.cpp:2008
time_t GetResetTime()
Definition: Map.cpp:2526
void CreateInstanceData(bool load)
Definition: Map.cpp:2419
#define MAP_LIQUID_TYPE_MAGMA
Definition: Map.h:137
uint8 GetTypeId() const
Definition: Object.h:204
bool isGridObjectDataLoaded(uint32 x, uint32 y) const
Definition: Map.h:579
float getHeightFromUint16(float x, float y) const
Definition: Map.cpp:1367
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition: Player.cpp:1556
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:2632
void PermBindAllPlayers(Player *player)
Definition: Map.cpp:2492
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:2047
void Relocate(float x, float y)
Definition: Position.h:65
void markCell(uint32 pCellId)
Definition: Map.h:467
bool m_resetAfterUnload
Definition: Map.h:714
Definition: Cell.h:29
void EnsureGridCreated(const GridCoord &)
Definition: Map.cpp:319
const bool & IsInWorld() const
Definition: Object.h:129
void resetMarkedCells()
Definition: Map.h:459
uint32 m_unloadTimer
Definition: Map.h:603
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:701
DynamicObject * GetDynamicObject(uint64 guid)
Definition: Map.cpp:2644
static int32 GetVisibilityNotifyPeriodInInstances()
Definition: World.h:724
HostileRefManager & getHostileRefManager()
Definition: Unit.h:1842
float GetWaterLevel(float x, float y) const
Definition: Map.cpp:1796
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:1727
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:1213
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:1167
void UpdateObjectsVisibilityFor(Player *player, Cell cell, CellCoord cellpair)
Definition: Map.cpp:1905
const char * GetMapName() const
Definition: Map.cpp:1892
float getHeightFromFloat(float x, float y) const
Definition: Map.cpp:1218
HostileReference * next()
float level
Definition: Map.h:151
CellCoord low_bound
Definition: Cell.h:42
virtual void RemoveFromWorld() override
Definition: Object.cpp:1166
static int32 GetVisibilityNotifyPeriodOnContinents()
Definition: World.h:720
#define VMAP_INVALID_HEIGHT_VALUE
Definition: IVMapManager.h:41
uint32 GetInstanceId() const
Definition: Object.h:682
bool isActiveObject() const
Definition: Object.h:899
virtual void Initialize()
Definition: InstanceData.h:98
void SendToPlayers(WorldPacket const *data) const
Definition: Map.cpp:2126
void LoadMapAndVMap(int gx, int gy)
Definition: Map.cpp:175
void CombatStop(bool cast=false)
Definition: Unit.cpp:7442
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:1834
#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:2555
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:18873
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:15838
uint32 GetMapId() const
Definition: Object.h:585
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:1851
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:2574
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:643
uint32 entry
Definition: Map.h:150
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2) const
Definition: Map.cpp:1804
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:15879
#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:1201
virtual void RemoveAllPlayers()
Definition: Map.cpp:978
InstanceData * i_data
Definition: Map.h:716
void EnsureGridLoadedForActiveObject(Cell const &, WorldObject *object)
Definition: Map.cpp:347
bool IsPet() const
Definition: Unit.h:1020
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:692
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:1874
uint8 GetTerrainType(float x, float y) const
Definition: Map.cpp:1719
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:713
virtual void UnloadAll()
Definition: Map.cpp:995
uint32 GetBattlegroundId() const
Definition: Player.h:2212
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:3751
const uint64 & GetLeaderGUID() const
Definition: Group.h:222
bool HaveAtClient(WorldObject const *u) const
Definition: Player.cpp:18670
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:613
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:609
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:2649
bool CreatureRespawnRelocation(Creature *c)
Definition: Map.cpp:873
bool AddPlayerToMap(Player *) override
Definition: Map.cpp:2289
uint32 fourcc
Definition: Map.h:94
Creature * ToCreature()
Definition: Object.h:389
PeriodicTimer & getRelocationTimer()
Definition: NGrid.h:49
uint8 getTerrainType(float x, float y)
Definition: Map.cpp:1453
void AddToActive(T *obj)
Definition: Map.h:502
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data=0)
Definition: Map.cpp:1466
void MoveAllCreaturesInMoveList()
Definition: Map.cpp:770
void CleanupsBeforeDelete() override
Definition: Unit.cpp:11086
NGridType * i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition: Map.h:632
uint32 maxPlayers
Definition: Map.h:234
void SetUnload()
Definition: Map.cpp:2616
uint32 i_InstanceId
Definition: Map.h:602
virtual void DelayedUpdate(const uint32 diff)
Definition: Map.cpp:2018
iterator begin()
void Visit(GridRefManager< T > &)
Definition: Map.cpp:582
static IVMapManager * createOrGetVMapManager()
void SetMap(Map *map) override
Definition: Player.cpp:20670
bool loadAreaData(FILE *in, uint32 offset, uint32 size)
Definition: Map.cpp:1103
#define ASSERT
Definition: Errors.h:33
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:1636
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:186
bool IsOutdoors(float x, float y, float z) const
Definition: Map.cpp:1650
bool IsPositionValid() const
Definition: Position.cpp:40
WorldSession * GetSession() const
Definition: Player.h:1959
#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:607
float getHeight(float x, float y, float z, float maxSearchDist) const
WorldObject * m_seer
Definition: Player.h:2363
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:2307
void Initialize()
float GetPositionX() const
Definition: Position.h:97
void SendResetWarnings(uint32 timeLeft) const
Definition: Map.cpp:2542
static void InitStateMachine()
Definition: Map.cpp:186
GameObject * GetGameObject(uint64 guid)
Definition: Map.cpp:2638
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:1810
Definition: Unit.h:884
void ResetGridExpiry(NGridType &grid, float factor=1) const
Definition: Map.h:324
bool m_unloadWhenEmpty
Definition: Map.h:715
bool isGridObjectDataLoaded() const
Definition: NGrid.h:108
float y
Definition: Map.h:220
MapRefManager m_mapRefManager
Definition: Map.h:606
void ScriptsProcess()
Definition: MapScripts.cpp:288
MapReference const * nocheck_prev() const
Definition: MapReference.h:61
void SendInitSelf(Player *player)
Definition: Map.cpp:1919
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:2453
bool AddPlayerToMap(Player *) override
Definition: Map.cpp:2598
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:2117
#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:1861
virtual bool IsEncounterInProgress() const
iterator end()
Definition: MapRefManager.h:52
bool IsPermanentWorldObject() const
Definition: Object.h:905
Definition: Pet.h:146
WorldObject * GetViewpoint() const
Definition: Player.cpp:20446
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:1121
float m_homebindZ
Definition: Player.h:2455
void AddWorldObject(SPECIFIC_OBJECT *obj)
Definition: Grid.h:58
uint16 GetAreaFlag(float x, float y, float z, bool *isOutdoors=0) const
Definition: Map.cpp:1681
const uint64 & GetGUID() const
Definition: Object.h:156
#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