TrinityCore
Loading...
Searching...
No Matches
Map.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore 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 "Battleground.h"
20#include "BattlegroundMgr.h"
21#include "BattlegroundScript.h"
22#include "CellImpl.h"
23#include "CharacterPackets.h"
24#include "ChatPackets.h"
25#include "Conversation.h"
26#include "DB2Stores.h"
27#include "DatabaseEnv.h"
28#include "DynamicTree.h"
30#include "GameObjectModel.h"
31#include "GameTime.h"
32#include "GridNotifiers.h"
33#include "GridNotifiersImpl.h"
34#include "GridStates.h"
35#include "Group.h"
36#include "InstanceLockMgr.h"
37#include "InstancePackets.h"
38#include "InstanceScenario.h"
39#include "InstanceScript.h"
40#include "Log.h"
41#include "MMapManager.h"
42#include "MapManager.h"
43#include "MapUtils.h"
44#include "Metric.h"
45#include "MiscPackets.h"
46#include "MotionMaster.h"
47#include "ObjectAccessor.h"
48#include "ObjectGridLoader.h"
49#include "ObjectMgr.h"
50#include "Pet.h"
51#include "PhasingHandler.h"
52#include "PoolMgr.h"
53#include "ScriptMgr.h"
54#include "SpellAuras.h"
55#include "TerrainMgr.h"
56#include "Transport.h"
57#include "VMapFactory.h"
58#include "VMapManager.h"
59#include "Vehicle.h"
60#include "Vignette.h"
61#include "VignettePackets.h"
62#include "Weather.h"
63#include "WeatherMgr.h"
64#include "World.h"
65#include "WorldSession.h"
66#include "WorldStateMgr.h"
67#include "WorldStatePackets.h"
68#include <boost/heap/fibonacci_heap.hpp>
69#include <sstream>
70
71#define DEFAULT_GRID_EXPIRY 300
72#define MAX_GRID_LOAD_TIME 50
73#define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld->getRate(RATE_CREATURE_AGGRO))
74
76
77ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), DefaultWeather(nullptr), WeatherId(WEATHER_STATE_FINE),
78 Intensity(0.0f) { }
79
81
83struct RespawnListContainer : boost::heap::fibonacci_heap<RespawnInfoWithHandle*, boost::heap::compare<CompareRespawnInfo>>
84{
85};
86
88{
89 explicit RespawnInfoWithHandle(RespawnInfo const& other) : RespawnInfo(other) { }
90
91 RespawnListContainer::handle_type handle;
92};
93
95{
96 // Delete all waiting spawns, else there will be a memory leak
97 // This doesn't delete from database.
99
100 while (!i_worldObjects.empty())
101 {
102 WorldObject* obj = *i_worldObjects.begin();
104 //ASSERT(obj->GetTypeId() == TYPEID_CORPSE);
105 obj->RemoveFromWorld();
106 obj->ResetMap();
107 }
108
109 if (!m_scriptSchedule.empty())
110 sMapMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size());
111
112 m_terrain->UnloadMMapInstance(GetId(), GetInstanceId());
113}
114
116{
117 for (uint32 gridX = 0; gridX < MAX_NUMBER_OF_GRIDS; ++gridX)
118 for (uint32 gridY = 0; gridY < MAX_NUMBER_OF_GRIDS; ++gridY)
119 EnsureGridLoaded(GridCoord(gridX, gridY));
120}
121
129
137
138Map::Map(uint32 id, time_t expiry, uint32 InstanceId, Difficulty SpawnMode) :
139_creatureToMoveLock(false), _gameObjectsToMoveLock(false), _dynamicObjectsToMoveLock(false), _areaTriggersToMoveLock(false),
140i_mapEntry(sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
141m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE), m_mapRefIter(m_mapRefManager.end()),
142m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD),
143m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transports.end()),
144i_gridExpiry(expiry), m_terrain(sTerrainMgr.LoadTerrain(id)), m_forceEnabledNavMeshFilterFlags(0), m_forceDisabledNavMeshFilterFlags(0), i_grids(),
145i_scriptLock(false), _respawnTimes(std::make_unique<RespawnListContainer>()), _respawnCheckTimer(0), _vignetteUpdateTimer(5200, 5200)
146{
147 //lets initialize visibility distance for map
149
151
152 GetGuidSequenceGenerator(HighGuid::Transport).Set(sObjectMgr->GetGenerator<HighGuid::Transport>().GetNextAfterMaxUsed());
153
154 _poolData = sPoolMgr->InitPoolsForMap(this);
155
156 sTransportMgr->CreateTransportsForMap(this);
157
158 m_terrain->LoadMMapInstance(GetId(), GetInstanceId());
159
161 m_mmapTileRebuilder = std::make_shared<MMAP::DynamicTileBuilder>(this, MMAP::MMapManager::instance()->GetNavMesh(GetId(), GetInstanceId()));
162
164}
165
172
173// Template specialization of utility methods
174template<class T>
175void Map::AddToGrid(T* obj, Cell const& cell)
176{
177 NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
178 if constexpr (WorldTypeMapContainer::TypeExists<T> && GridTypeMapContainer::TypeExists<T>)
179 {
180 NGridType::GridType& cellType = grid->GetGridType(cell.CellX(), cell.CellY());
181 if (obj->IsStoredInWorldObjectGridContainer())
182 cellType.AddWorldObject<T>(obj);
183 else
184 cellType.AddGridObject<T>(obj);
185 }
186 else if constexpr (WorldTypeMapContainer::TypeExists<T>)
187 grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject<T>(obj);
188 else if constexpr (GridTypeMapContainer::TypeExists<T>)
189 grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject<T>(obj);
190
191 if constexpr (std::is_base_of_v<MapObject, T>)
192 obj->SetCurrentCell(cell);
193}
194
195template<>
196void Map::AddToGrid(Corpse* obj, Cell const& cell)
197{
198 NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
199 // Corpses are a special object type - they can be added to grid via a call to AddToMap
200 // or loaded through ObjectGridLoader.
201 // Both corpses loaded from database and these freshly generated by Player::CreateCoprse are added to _corpsesByCell
202 // ObjectGridLoader loads all corpses from _corpsesByCell even if they were already added to grid before it was loaded
203 // so we need to explicitly check it here (Map::AddToGrid is only called from Player::BuildPlayerRepop, not from ObjectGridLoader)
204 // to avoid failing an assertion in GridObject::AddToGrid
205 if (grid->isGridObjectDataLoaded())
206 {
207 NGridType::GridType& cellType = grid->GetGridType(cell.CellX(), cell.CellY());
209 cellType.AddWorldObject(obj);
210 else
211 cellType.AddGridObject(obj);
212 }
213}
214
215template<class T>
216void Map::SwitchGridContainers(T* /*obj*/, bool /*on*/) { }
217
218template<>
220{
223 if (!p.IsCoordValid())
224 {
225 TC_LOG_ERROR("maps", "Map::SwitchGridContainers: Object {} has invalid coordinates X:{} Y:{} grid cell [{}:{}]", obj->GetGUID().ToString(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
226 return;
227 }
228
229 Cell cell(p);
231 return;
232
233 if (sLog->ShouldLog("maps", LOG_LEVEL_DEBUG))
234 {
235 // Extract bitfield values
236 uint32 const grid_x = cell.data.Part.grid_x;
237 uint32 const grid_y = cell.data.Part.grid_y;
238
239 TC_LOG_DEBUG("maps", "Switch object {} from grid[{}, {}] {}", obj->GetGUID().ToString(), grid_x, grid_y, on);
240 }
241
242 NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY());
243 ASSERT(ngrid != nullptr);
244
245 GridType &grid = ngrid->GetGridType(cell.CellX(), cell.CellY());
246
247 obj->RemoveFromGrid(); //This step is not really necessary but we want to do ASSERT in remove/add
248
249 if (on)
250 {
251 grid.AddWorldObject(obj);
252 AddWorldObject(obj);
253 }
254 else
255 {
256 grid.AddGridObject(obj);
258 }
259
260 obj->m_isTempWorldObject = on;
261}
262
263template<class T>
265{
266 // Note: In case resurrectable corpse and pet its removed from global lists in own destructor
267 delete obj;
268}
269
270template<>
272{
274 RemoveUpdateObject(player);
275 delete player;
276}
277
278//Create NGrid so the object can be added to it
279//But object data is not loaded here
281{
282 if (!getNGrid(p.x_coord, p.y_coord))
283 {
284 TC_LOG_DEBUG("maps", "Creating grid[{}, {}] for map {} instance {}", p.x_coord, p.y_coord, GetId(), i_InstanceId);
285
286 NGridType* ngrid = new NGridType(p.GetId(), p.x_coord, p.y_coord, i_gridExpiry, sWorld->getBoolConfig(CONFIG_GRID_UNLOAD));
287 setNGrid(ngrid, p.x_coord, p.y_coord);
288
289 // build a linkage between this map and NGridType
290 buildNGridLinkage(ngrid);
291
293
294 //z coord
295 int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord;
296 int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord;
297
298 m_terrain->LoadMapAndVMap(gx, gy);
299 m_terrain->LoadMMap(GetInstanceId(), gx, gy);
300 }
301}
302
303//Load NGrid and make it active
305{
307 NGridType *grid = getNGrid(p.x_coord, p.y_coord);
308 ASSERT(grid != nullptr);
309
310 if (object->IsPlayer())
311 GetMultiPersonalPhaseTracker().LoadGrid(object->GetPhaseShift(), *grid, this);
312
313 // refresh grid state & timer
314 if (grid->GetGridState() != GRID_STATE_ACTIVE)
315 {
316 TC_LOG_DEBUG("maps", "Active object {} triggers loading of grid [{}, {}] on map {}", object->GetGUID().ToString(), p.x_coord, p.y_coord, GetId());
317 ResetGridExpiry(*grid, 0.1f);
319 }
320}
321
322//Create NGrid and load the object data in it
324{
326 NGridType *grid = getNGrid(p.x_coord, p.y_coord);
327
328 ASSERT(grid != nullptr);
329 if (!grid->isGridObjectDataLoaded())
330 {
331 TC_LOG_DEBUG("maps", "Loading grid[{}, {}] for map {} instance {}", p.x_coord, p.y_coord, GetId(), i_InstanceId);
332
333 grid->setGridObjectDataLoaded(true);
334
335 LoadGridObjects(grid);
336
337 Balance();
338 return true;
339 }
340
341 return false;
342}
343
345{
346 ObjectGridLoader loader(*grid, this);
347 loader.LoadN();
348}
349
351{
352 // First make sure this grid is loaded
354
355 // Mark as don't unload
356 NGridType* grid = getNGrid(x, y);
357 grid->setUnloadExplicitLock(true);
358}
359
361{
362 // If grid is loaded, clear unload lock
363 if (IsGridLoaded(GridCoord(x, y)))
364 {
365 NGridType* grid = getNGrid(x, y);
366 grid->setUnloadExplicitLock(false);
367 }
368}
369
370void Map::LoadGrid(float x, float y)
371{
373}
374
375void Map::LoadGridForActiveObject(float x, float y, WorldObject const* object)
376{
378}
379
380void Map::LoadGridsInRange(float x, float y, float radius)
381{
382 radius = std::min(radius, SIZE_OF_GRIDS);
383
384 GridCoord gridAreaLow = Trinity::ComputeGridCoord(x - radius, y - radius);
385 GridCoord gridAreaHigh = Trinity::ComputeGridCoord(x + radius, y + radius);
386
387 for (uint32 gx = gridAreaLow.x_coord; gx <= gridAreaHigh.x_coord; ++gx)
388 for (uint32 gy = gridAreaLow.y_coord; gy <= gridAreaHigh.y_coord; ++gy)
390}
391
392bool Map::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
393{
394 CellCoord cellCoord = Trinity::ComputeCellCoord(player->GetPositionX(), player->GetPositionY());
395 if (!cellCoord.IsCoordValid())
396 {
397 TC_LOG_ERROR("maps", "Map::Add: Player {} has invalid coordinates X:{} Y:{} grid cell [{}:{}]", player->GetGUID().ToString(), player->GetPositionX(), player->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
398 return false;
399 }
400
401 Cell cell(cellCoord);
402 EnsureGridLoadedForActiveObject(GridCoord(cell.GridX(), cell.GridY()), player);
403 AddToGrid(player, cell);
404
405 // Check if we are adding to correct map
406 ASSERT (player->GetMap() == this);
407 player->SetMap(this);
408 player->AddToWorld();
409
410 if (initPlayer)
411 SendInitSelf(player);
412
413 SendInitTransports(player);
414
415 if (initPlayer)
416 player->m_clientGUIDs.clear();
417
418 player->UpdateObjectVisibility(false);
420
421 if (Instanceable())
423
424 if (player->IsAlive())
425 ConvertCorpseToBones(player->GetGUID());
426
427 sScriptMgr->OnPlayerEnterMap(this, player);
428 return true;
429}
430
432{
433 GridCoord gridCoord = Trinity::ComputeGridCoord(player->GetPositionX(), player->GetPositionY());
434 GetMultiPersonalPhaseTracker().OnOwnerPhaseChanged(player, getNGrid(gridCoord.x_coord, gridCoord.y_coord), this);
435}
436
438{
439 if (int32 const* value = Trinity::Containers::MapGetValuePtr(_worldStateValues, worldStateId))
440 return *value;
441
442 return 0;
443}
444
445void Map::SetWorldStateValue(int32 worldStateId, int32 value, bool hidden)
446{
447 auto [itr, inserted] = _worldStateValues.try_emplace(worldStateId, 0);
448 int32 oldValue = itr->second;
449 if (oldValue == value && !inserted)
450 return;
451
452 itr->second = value;
453
454 WorldStateTemplate const* worldStateTemplate = WorldStateMgr::GetWorldStateTemplate(worldStateId);
455 if (worldStateTemplate)
456 sScriptMgr->OnWorldStateValueChange(worldStateTemplate, oldValue, value, this);
457
458 // Broadcast update to all players on the map
460 updateWorldState.VariableID = worldStateId;
461 updateWorldState.Value = value;
462 updateWorldState.Hidden = hidden;
463 updateWorldState.Write();
464
465 for (MapReference const& mapReference : m_mapRefManager)
466 {
467 if (worldStateTemplate && !worldStateTemplate->AreaIds.empty())
468 {
469 bool isInAllowedArea = std::any_of(worldStateTemplate->AreaIds.begin(), worldStateTemplate->AreaIds.end(),
470 [playerAreaId = mapReference.GetSource()->GetAreaId()](uint32 requiredAreaId) { return DB2Manager::IsInArea(playerAreaId, requiredAreaId); });
471 if (!isInAllowedArea)
472 continue;
473 }
474
475 mapReference.GetSource()->SendDirectMessage(updateWorldState.GetRawPacket());
476 }
477}
478
480{
481 _infiniteAOIVignettes.push_back(vignette);
482
484 vignette->FillPacket(vignetteUpdate.Added);
485 vignetteUpdate.Write();
486
487 for (MapReference const& ref : m_mapRefManager)
488 if (Vignettes::CanSee(ref.GetSource(), *vignette))
489 ref.GetSource()->SendDirectMessage(vignetteUpdate.GetRawPacket());
490}
491
493{
494 if (!std::erase(_infiniteAOIVignettes, vignette))
495 return;
496
498 vignetteUpdate.Removed.push_back(vignette->Guid);
499 vignetteUpdate.Write();
500
501 if (vignette->Data->GetFlags().HasFlag(VignetteFlags::ZoneInfiniteAOI))
502 {
503 for (MapReference const& ref : m_mapRefManager)
504 if (ref.GetSource()->GetZoneId() == vignette->ZoneID)
505 ref.GetSource()->SendDirectMessage(vignetteUpdate.GetRawPacket());
506 }
507 else
508 SendToPlayers(vignetteUpdate.GetRawPacket());
509}
510
511template<class T>
512void Map::InitializeObject(T* /*obj*/) { }
513
514template<>
519
520template<>
525
526template<class T>
527bool Map::AddToMap(T* obj)
528{
530 if (obj->IsInWorld())
531 {
532 ASSERT(obj->IsInGrid());
533 obj->UpdateObjectVisibility(true);
534 return true;
535 }
536
537 CellCoord cellCoord = Trinity::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
538 //It will create many problems (including crashes) if an object is not added to grid after creation
539 //The correct way to fix it is to make AddToMap return false and delete the object if it is not added to grid
540 //But now AddToMap is used in too many places, I will just see how many ASSERT failures it will cause
541 ASSERT(cellCoord.IsCoordValid());
542 if (!cellCoord.IsCoordValid())
543 {
544 TC_LOG_ERROR("maps", "Map::Add: Object {} has invalid coordinates X:{} Y:{} grid cell [{}:{}]", obj->GetGUID().ToString(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
545 return false; //Should delete object
546 }
547
548 if (IsAlwaysActive())
549 obj->setActive(true);
550
551 Cell cell(cellCoord);
552 if (obj->isActiveObject())
554 else
555 EnsureGridCreated(GridCoord(cell.GridX(), cell.GridY()));
556 AddToGrid(obj, cell);
557 TC_LOG_DEBUG("maps", "Object {} enters grid[{}, {}]", obj->GetGUID().ToString(), cell.GridX(), cell.GridY());
558
559 //Must already be set before AddToMap. Usually during obj->Create.
560 //obj->SetMap(this);
561 obj->AddToWorld();
562
563 InitializeObject(obj);
564
565 if (obj->isActiveObject())
566 AddToActive(obj);
567
568 //something, such as vehicle, needs to be update immediately
569 //also, trigger needs to cast spell, if not update, cannot see visual
570 obj->SetIsNewObject(true);
571 obj->UpdateObjectVisibilityOnCreate();
572 obj->SetIsNewObject(false);
573 return true;
574}
575
576template<>
578{
579 //TODO: Needs clean up. An object should not be added to map twice.
580 if (obj->IsInWorld())
581 return true;
582
584 if (!cellCoord.IsCoordValid())
585 {
586 TC_LOG_ERROR("maps", "Map::Add: Object {} has invalid coordinates X:{} Y:{} grid cell [{}:{}]", obj->GetGUID().ToString(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
587 return false; //Should delete object
588 }
589
590 _transports.insert(obj);
591
592 if (obj->GetExpectedMapId() == GetId())
593 {
594 obj->AddToWorld();
595
596 // Broadcast creation to players
597 for (Map::PlayerList::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
598 {
599 if (itr->GetSource()->GetTransport() != obj && itr->GetSource()->InSamePhase(obj))
600 {
601 UpdateData data(GetId());
602 obj->BuildCreateUpdateBlockForPlayer(&data, itr->GetSource());
603 itr->GetSource()->m_visibleTransports.insert(obj->GetGUID());
604 WorldPacket packet;
605 data.BuildPacket(&packet);
606 itr->GetSource()->SendDirectMessage(&packet);
607 }
608 }
609 }
610
611 return true;
612}
613
614bool Map::IsGridLoaded(GridCoord const& p) const
615{
616 NGridType* grid = getNGrid(p.x_coord, p.y_coord);
617 return grid && grid->isGridObjectDataLoaded();
618}
619
621{
622 // Check for valid position
623 if (!obj->IsPositionValid())
624 return;
625
626 // Update mobs/objects in ALL visible cells around object!
628
629 for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
630 {
631 for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
632 {
633 // marked cells are those that have been visited
634 // don't visit the same cell twice
635 uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
636 if (isCellMarked(cell_id))
637 continue;
638
639 markCell(cell_id);
640 CellCoord pair(x, y);
641 Cell cell(pair);
642 Visit(cell, gridVisitor);
643 Visit(cell, worldVisitor);
644 }
645 }
646}
647
649{
650 // Nothing to do if no change
651 if (oldZone == newZone)
652 return;
653
654 if (oldZone != MAP_INVALID_ZONE)
655 {
656 uint32& oldZoneCount = _zonePlayerCountMap[oldZone];
657 ASSERT(oldZoneCount, "A player left zone %u (went to %u) - but there were no players in the zone!", oldZone, newZone);
658 --oldZoneCount;
659 }
660 ++_zonePlayerCountMap[newZone];
661}
662
663void Map::Update(uint32 t_diff)
664{
665 _dynamicTree.update(t_diff);
667 m_mmapTileRebuilder->Update(Milliseconds(t_diff));
668
671 {
672 Player* player = m_mapRefIter->GetSource();
673 if (player && player->IsInWorld())
674 {
675 //player->Update(t_diff);
676 WorldSession* session = player->GetSession();
677 MapSessionFilter updater(session);
678 session->Update(t_diff, updater);
679 }
680 }
681
683 if (_respawnCheckTimer <= t_diff)
684 {
688 }
689 else
690 _respawnCheckTimer -= t_diff;
691
694
695 Trinity::ObjectUpdater updater(t_diff);
696 // for creature
698 // for pets
700
701 // the player iterator is stored in the map object
702 // to make sure calls to Map::Remove don't invalidate it
704 {
705 Player* player = m_mapRefIter->GetSource();
706
707 if (!player || !player->IsInWorld())
708 continue;
709
710 // update players at tick
711 player->Update(t_diff);
712
713 VisitNearbyCellsOf(player, grid_object_update, world_object_update);
714
715 // If player is using far sight or mind vision, visit that object too
716 if (WorldObject* viewPoint = player->GetViewpoint())
717 VisitNearbyCellsOf(viewPoint, grid_object_update, world_object_update);
718
719 // Handle updates for creatures in combat with player and are more than 60 yards away
720 if (player->IsInCombat())
721 {
722 std::vector<Unit*> toVisit;
723 for (auto const& pair : player->GetCombatManager().GetPvECombatRefs())
724 if (Creature* unit = pair.second->GetOther(player)->ToCreature())
725 if (unit->GetMapId() == player->GetMapId() && !unit->IsWithinDistInMap(player, GetVisibilityRange(), false))
726 toVisit.push_back(unit);
727 for (Unit* unit : toVisit)
728 VisitNearbyCellsOf(unit, grid_object_update, world_object_update);
729 }
730
731 { // Update any creatures that own auras the player has applications of
732 std::unordered_set<Unit*> toVisit;
733 for (std::pair<uint32, AuraApplication*> pair : player->GetAppliedAuras())
734 {
735 if (Unit* caster = pair.second->GetBase()->GetCaster())
736 if (caster->GetTypeId() != TYPEID_PLAYER && !caster->IsWithinDistInMap(player, GetVisibilityRange(), false))
737 toVisit.insert(caster);
738 }
739 for (Unit* unit : toVisit)
740 VisitNearbyCellsOf(unit, grid_object_update, world_object_update);
741 }
742
743 { // Update player's summons
744 std::vector<Unit*> toVisit;
745
746 // Totems
747 for (ObjectGuid const& summonGuid : player->m_SummonSlot)
748 if (!summonGuid.IsEmpty())
749 if (Creature* unit = GetCreature(summonGuid))
750 if (unit->GetMapId() == player->GetMapId() && !unit->IsWithinDistInMap(player, GetVisibilityRange(), false))
751 toVisit.push_back(unit);
752
753 for (Unit* unit : toVisit)
754 VisitNearbyCellsOf(unit, grid_object_update, world_object_update);
755 }
756 }
757
758 // non-player active objects, increasing iterator in the loop in case of object removal
760 {
763
764 if (!obj || !obj->IsInWorld())
765 continue;
766
767 VisitNearbyCellsOf(obj, grid_object_update, world_object_update);
768 }
769
771 {
774 obj->Update(t_diff);
775 }
776
777 if (_vignetteUpdateTimer.Update(t_diff))
778 {
780 {
781 if (vignette->NeedUpdate)
782 {
784 vignette->FillPacket(vignetteUpdate.Updated);
785 vignetteUpdate.Write();
786 for (MapReference const& ref : m_mapRefManager)
787 if (Vignettes::CanSee(ref.GetSource(), *vignette))
788 ref.GetSource()->SendDirectMessage(vignetteUpdate.GetRawPacket());
789
790 vignette->NeedUpdate = false;
791 }
792 }
793 }
794
796
798 if (!m_scriptSchedule.empty())
799 {
800 i_scriptLock = true;
802 i_scriptLock = false;
803 }
804
807 {
808 for (auto&& zoneInfo : _zoneDynamicInfo)
809 if (zoneInfo.second.DefaultWeather && !zoneInfo.second.DefaultWeather->Update(_weatherUpdateTimer.GetInterval()))
810 zoneInfo.second.DefaultWeather.reset();
811
813 }
814
815 // update phase shift objects
816 GetMultiPersonalPhaseTracker().Update(this, t_diff);
817
821
822 if (!m_mapRefManager.empty() || !m_activeNonPlayers.empty())
824
825 sScriptMgr->OnMapUpdate(this, t_diff);
826
827 TC_METRIC_VALUE("map_creatures", uint64(GetObjectsStore().Size<Creature>()),
828 TC_METRIC_TAG("map_id", std::to_string(GetId())),
829 TC_METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
830
831 TC_METRIC_VALUE("map_gameobjects", uint64(GetObjectsStore().Size<GameObject>()),
832 TC_METRIC_TAG("map_id", std::to_string(GetId())),
833 TC_METRIC_TAG("map_instanceid", std::to_string(GetInstanceId())));
834}
835
837{
838 template<class T>inline void resetNotify(GridRefManager<T> &m)
839 {
840 for (typename GridRefManager<T>::iterator iter=m.begin(); iter != m.end(); ++iter)
841 iter->GetSource()->ResetAllNotifies();
842 }
843 template<class T> void Visit(GridRefManager<T> &) { }
844 void Visit(CreatureMapType &m) { resetNotify<Creature>(m);}
845 void Visit(PlayerMapType &m) { resetNotify<Player>(m);}
846};
847
849{
851 {
852 NGridType *grid = i->GetSource();
853
854 if (grid->GetGridState() != GRID_STATE_ACTIVE)
855 continue;
856
858 if (!grid->getGridInfoRef()->getRelocationTimer().TPassed())
859 continue;
860
861 uint32 gx = grid->getX(), gy = grid->getY();
862
864 CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
865
866 for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x)
867 {
868 for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y)
869 {
870 uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
871 if (!isCellMarked(cell_id))
872 continue;
873
874 CellCoord pair(x, y);
875 Cell cell(pair);
876
877 Trinity::DelayedUnitRelocation cell_relocation(cell, pair, *this, MAX_VISIBILITY_DISTANCE);
880 Visit(cell, grid_object_relocation);
881 Visit(cell, world_object_relocation);
882 }
883 }
884 }
885
886 ResetNotifier reset;
890 {
891 NGridType *grid = i->GetSource();
892
893 if (grid->GetGridState() != GRID_STATE_ACTIVE)
894 continue;
895
896 if (!grid->getGridInfoRef()->getRelocationTimer().TPassed())
897 continue;
898
900
901 uint32 gx = grid->getX(), gy = grid->getY();
902
904 CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
905
906 for (uint32 x = cell_min.x_coord; x < cell_max.x_coord; ++x)
907 {
908 for (uint32 y = cell_min.y_coord; y < cell_max.y_coord; ++y)
909 {
910 uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x;
911 if (!isCellMarked(cell_id))
912 continue;
913
914 CellCoord pair(x, y);
915 Cell cell(pair);
916 Visit(cell, grid_notifier);
917 Visit(cell, world_notifier);
918 }
919 }
920 }
921}
922
923void Map::RemovePlayerFromMap(Player* player, bool remove)
924{
925 // Before leaving map, update zone/area for stats
926 player->UpdateZone(MAP_INVALID_ZONE, 0);
927 sScriptMgr->OnPlayerLeaveMap(this, player);
928
930
931 player->CombatStop();
932
933 bool const inWorld = player->IsInWorld();
934 player->RemoveFromWorld();
935 SendRemoveTransports(player);
936
937 if (!inWorld) // if was in world, RemoveFromWorld() called DestroyForNearbyPlayers()
939
940 if (player->IsInGrid())
941 player->RemoveFromGrid();
942 else
943 ASSERT(remove); //maybe deleted in logoutplayer when player is not in a map
944
945 if (remove)
946 DeleteFromWorld(player);
947}
948
949template<class T>
950void Map::RemoveFromMap(T *obj, bool remove)
951{
952 bool const inWorld = obj->IsInWorld() && obj->GetTypeId() >= TYPEID_UNIT && obj->GetTypeId() <= TYPEID_GAMEOBJECT;
953 obj->RemoveFromWorld();
954 if (obj->isActiveObject())
955 RemoveFromActive(obj);
956
958
959 if (!inWorld) // if was in world, RemoveFromWorld() called DestroyForNearbyPlayers()
960 obj->UpdateObjectVisibilityOnDestroy();
961
962 obj->RemoveFromGrid();
963
964 obj->ResetMap();
965
966 if (remove)
967 DeleteFromWorld(obj);
968}
969
970template<>
971void Map::RemoveFromMap(Transport* obj, bool remove)
972{
973 if (obj->IsInWorld())
974 {
975 obj->RemoveFromWorld();
976
977 UpdateData data(GetId());
978 if (obj->IsDestroyedObject())
979 obj->BuildDestroyUpdateBlock(&data);
980 else
981 obj->BuildOutOfRangeUpdateBlock(&data);
982
983 WorldPacket packet;
984 data.BuildPacket(&packet);
985 for (Map::PlayerList::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
986 {
987 if (itr->GetSource()->GetTransport() != obj && itr->GetSource()->m_visibleTransports.count(obj->GetGUID()))
988 {
989 itr->GetSource()->SendDirectMessage(&packet);
990 itr->GetSource()->m_visibleTransports.erase(obj->GetGUID());
991 }
992 }
993 }
994
996 {
997 TransportsContainer::iterator itr = _transports.find(obj);
998 if (itr == _transports.end())
999 return;
1000 if (itr == _transportsUpdateIter)
1002 _transports.erase(itr);
1003 }
1004 else
1005 _transports.erase(obj);
1006
1007 obj->ResetMap();
1008
1009 if (remove)
1010 DeleteFromWorld(obj);
1011}
1012
1013template <typename T>
1014/*static*/ bool Map::CheckGridIntegrity(T* object, bool moved, char const* objType)
1015{
1016 Cell const& cur_cell = object->GetCurrentCell();
1017 Cell xy_cell(object->GetPositionX(), object->GetPositionY());
1018 if (xy_cell != cur_cell)
1019 {
1020 TC_LOG_DEBUG("maps", "{} {} X: {} Y: {} ({}) is in grid[{}, {}]cell[{}, {}] instead of grid[{}, {}]cell[{}, {}]",
1021 objType, object->GetGUID().ToString(),
1022 object->GetPositionX(), object->GetPositionY(), (moved ? "final" : "original"),
1023 cur_cell.GridX(), cur_cell.GridY(), cur_cell.CellX(), cur_cell.CellY(),
1024 xy_cell.GridX(), xy_cell.GridY(), xy_cell.CellX(), xy_cell.CellY());
1025 return true; // not crash at error, just output error in debug mode
1026 }
1027
1028 return true;
1029}
1030
1031void Map::PlayerRelocation(Player* player, float x, float y, float z, float orientation)
1032{
1033 ASSERT(player);
1034
1035 Cell old_cell(player->GetPositionX(), player->GetPositionY());
1036 Cell new_cell(x, y);
1037
1038 player->Relocate(x, y, z, orientation);
1039 if (player->IsVehicle())
1040 player->GetVehicleKit()->RelocatePassengers();
1041
1042 if (old_cell.DiffGrid(new_cell) || old_cell.DiffCell(new_cell))
1043 {
1044 TC_LOG_DEBUG("maps", "Player {} relocation grid[{}, {}]cell[{}, {}]->grid[{}, {}]cell[{}, {}]", 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());
1045
1046 player->RemoveFromGrid();
1047
1048 if (old_cell.DiffGrid(new_cell))
1049 EnsureGridLoadedForActiveObject(GridCoord(new_cell.GridX(), new_cell.GridY()), player);
1050
1051 AddToGrid(player, new_cell);
1052 }
1053
1054 player->UpdatePositionData();
1055 player->UpdateObjectVisibility(false);
1056}
1057
1058void Map::CreatureRelocation(Creature* creature, float x, float y, float z, float ang, bool respawnRelocationOnFail)
1059{
1060 ASSERT(CheckGridIntegrity(creature, false, "Creature"));
1061
1062 Cell new_cell(x, y);
1063
1064 if (!respawnRelocationOnFail && !getNGrid(new_cell.GridX(), new_cell.GridY()))
1065 return;
1066
1067 Cell old_cell = creature->GetCurrentCell();
1068 // delay creature move for grid/cell to grid/cell moves
1069 if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
1070 {
1071#ifdef TRINITY_DEBUG
1072 TC_LOG_DEBUG("maps", "Creature {} added to moving list from grid[{}, {}]cell[{}, {}] to grid[{}, {}]cell[{}, {}].", creature->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
1073#endif
1074 AddCreatureToMoveList(creature, x, y, z, ang);
1075 // in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList
1076 }
1077 else
1078 {
1079 creature->Relocate(x, y, z, ang);
1080 if (creature->IsVehicle())
1081 creature->GetVehicleKit()->RelocatePassengers();
1082 creature->UpdateObjectVisibility(false);
1083 creature->UpdatePositionData();
1085 }
1086
1087 ASSERT(CheckGridIntegrity(creature, true, "Creature"));
1088}
1089
1090void Map::GameObjectRelocation(GameObject* go, float x, float y, float z, float orientation, bool respawnRelocationOnFail)
1091{
1092 ASSERT(CheckGridIntegrity(go, false, "GameObject"));
1093 Cell new_cell(x, y);
1094
1095 if (!respawnRelocationOnFail && !getNGrid(new_cell.GridX(), new_cell.GridY()))
1096 return;
1097
1098 Cell old_cell = go->GetCurrentCell();
1099
1100 // delay creature move for grid/cell to grid/cell moves
1101 if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
1102 {
1103#ifdef TRINITY_DEBUG
1104 TC_LOG_DEBUG("maps", "GameObject {} added to moving list from grid[{}, {}]cell[{}, {}] to grid[{}, {}]cell[{}, {}].", go->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
1105#endif
1106 AddGameObjectToMoveList(go, x, y, z, orientation);
1107 // in diffcell/diffgrid case notifiers called at finishing move go in Map::MoveAllGameObjectsInMoveList
1108 }
1109 else
1110 {
1111 go->Relocate(x, y, z, orientation);
1112 go->AfterRelocation();
1114 }
1115
1116 ASSERT(CheckGridIntegrity(go, true, "GameObject"));
1117}
1118
1119void Map::DynamicObjectRelocation(DynamicObject* dynObj, float x, float y, float z, float orientation)
1120{
1121 ASSERT(CheckGridIntegrity(dynObj, false, "DynamicObject"));
1122 Cell new_cell(x, y);
1123
1124 if (!getNGrid(new_cell.GridX(), new_cell.GridY()))
1125 return;
1126
1127 Cell old_cell = dynObj->GetCurrentCell();
1128
1129 // delay creature move for grid/cell to grid/cell moves
1130 if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
1131 {
1132#ifdef TRINITY_DEBUG
1133 TC_LOG_DEBUG("maps", "GameObject {} added to moving list from grid[{}, {}]cell[{}, {}] to grid[{}, {}]cell[{}, {}].", dynObj->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
1134#endif
1135 AddDynamicObjectToMoveList(dynObj, x, y, z, orientation);
1136 // in diffcell/diffgrid case notifiers called at finishing move dynObj in Map::MoveAllGameObjectsInMoveList
1137 }
1138 else
1139 {
1140 dynObj->Relocate(x, y, z, orientation);
1141 dynObj->UpdatePositionData();
1142 dynObj->UpdateObjectVisibility(false);
1144 }
1145
1146 ASSERT(CheckGridIntegrity(dynObj, true, "DynamicObject"));
1147}
1148
1149void Map::AreaTriggerRelocation(AreaTrigger* at, float x, float y, float z, float orientation)
1150{
1151 ASSERT(CheckGridIntegrity(at, false, "AreaTrigger"));
1152 Cell new_cell(x, y);
1153
1154 if (!getNGrid(new_cell.GridX(), new_cell.GridY()))
1155 return;
1156
1157 Cell old_cell = at->GetCurrentCell();
1158
1159 // delay areatrigger move for grid/cell to grid/cell moves
1160 if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell))
1161 {
1162#ifdef TRINITY_DEBUG
1163 TC_LOG_DEBUG("maps", "AreaTrigger ({}) added to moving list from grid[{}, {}]cell[{}, {}] to grid[{}, {}]cell[{}, {}].", at->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
1164#endif
1165 AddAreaTriggerToMoveList(at, x, y, z, orientation);
1166 // in diffcell/diffgrid case notifiers called at finishing move at in Map::MoveAllAreaTriggersInMoveList
1167 }
1168 else
1169 {
1170 at->Relocate(x, y, z, orientation);
1171 at->UpdateShape();
1172 at->UpdateObjectVisibility(false);
1174 }
1175
1176 ASSERT(CheckGridIntegrity(at, true, "AreaTrigger"));
1177}
1178
1179void Map::AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang)
1180{
1181 if (_creatureToMoveLock) //can this happen?
1182 return;
1183
1185 _creaturesToMove.push_back(c);
1186 c->SetNewCellPosition(x, y, z, ang);
1187}
1188
1190{
1191 if (_creatureToMoveLock) //can this happen?
1192 return;
1193
1196}
1197
1198void Map::AddGameObjectToMoveList(GameObject* go, float x, float y, float z, float ang)
1199{
1200 if (_gameObjectsToMoveLock) //can this happen?
1201 return;
1202
1204 _gameObjectsToMove.push_back(go);
1205 go->SetNewCellPosition(x, y, z, ang);
1206}
1207
1209{
1210 if (_gameObjectsToMoveLock) //can this happen?
1211 return;
1212
1215}
1216
1217void Map::AddDynamicObjectToMoveList(DynamicObject* dynObj, float x, float y, float z, float ang)
1218{
1219 if (_dynamicObjectsToMoveLock) //can this happen?
1220 return;
1221
1223 _dynamicObjectsToMove.push_back(dynObj);
1224 dynObj->SetNewCellPosition(x, y, z, ang);
1225}
1226
1228{
1229 if (_dynamicObjectsToMoveLock) //can this happen?
1230 return;
1231
1234}
1235
1236void Map::AddAreaTriggerToMoveList(AreaTrigger* at, float x, float y, float z, float ang)
1237{
1238 if (_areaTriggersToMoveLock) //can this happen?
1239 return;
1240
1242 _areaTriggersToMove.push_back(at);
1243 at->SetNewCellPosition(x, y, z, ang);
1244}
1245
1247{
1248 if (_areaTriggersToMoveLock) //can this happen?
1249 return;
1250
1253}
1254
1256{
1257 _creatureToMoveLock = true;
1258 for (std::vector<Creature*>::iterator itr = _creaturesToMove.begin(); itr != _creaturesToMove.end(); ++itr)
1259 {
1260 Creature* c = *itr;
1261 if (c->FindMap() != this) //pet is teleported to another map
1262 continue;
1263
1265 {
1267 continue;
1268 }
1269
1271 if (!c->IsInWorld())
1272 continue;
1273
1274 // do move or do move to respawn or remove creature if previous all fail
1276 {
1277 // update pos
1278 c->Relocate(c->_newPosition);
1279 if (c->IsVehicle())
1281 //CreatureRelocationNotify(c, new_cell, new_cell.cellCoord());
1282 c->UpdatePositionData();
1283 c->UpdateObjectVisibility(false);
1284 }
1285 else
1286 {
1287 // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid
1288 // creature coordinates will be updated and notifiers send
1289 if (!CreatureRespawnRelocation(c, false))
1290 {
1291 // ... or unload (if respawn grid also not loaded)
1292#ifdef TRINITY_DEBUG
1293 TC_LOG_DEBUG("maps", "Creature {} cannot be move to unloaded respawn grid.", c->GetGUID().ToString());
1294#endif
1295 //AddObjectToRemoveList(Pet*) should only be called in Pet::Remove
1296 //This may happen when a player just logs in and a pet moves to a nearby unloaded cell
1297 //To avoid this, we can load nearby cells when player log in
1298 //But this check is always needed to ensure safety
1300 //need to check why pet is frequently relocated to an unloaded cell
1301 if (c->IsPet())
1302 ((Pet*)c)->Remove(PET_SAVE_NOT_IN_SLOT, true);
1303 else
1305 }
1306 }
1307 }
1308 _creaturesToMove.clear();
1309 _creatureToMoveLock = false;
1310}
1311
1313{
1315 for (std::vector<GameObject*>::iterator itr = _gameObjectsToMove.begin(); itr != _gameObjectsToMove.end(); ++itr)
1316 {
1317 GameObject* go = *itr;
1318 if (go->FindMap() != this) //transport is teleported to another map
1319 continue;
1320
1322 {
1324 continue;
1325 }
1326
1328 if (!go->IsInWorld())
1329 continue;
1330
1331 // do move or do move to respawn or remove creature if previous all fail
1333 {
1334 // update pos
1335 go->Relocate(go->_newPosition);
1336 go->AfterRelocation();
1337 }
1338 else
1339 {
1340 // if GameObject can't be move in new cell/grid (not loaded) move it to repawn cell/grid
1341 // GameObject coordinates will be updated and notifiers send
1342 if (!GameObjectRespawnRelocation(go, false))
1343 {
1344 // ... or unload (if respawn grid also not loaded)
1345#ifdef TRINITY_DEBUG
1346 TC_LOG_DEBUG("maps", "GameObject {} cannot be move to unloaded respawn grid.", go->GetGUID().ToString());
1347#endif
1349 }
1350 }
1351 }
1352 _gameObjectsToMove.clear();
1353 _gameObjectsToMoveLock = false;
1354}
1355
1357{
1359 for (std::vector<DynamicObject*>::iterator itr = _dynamicObjectsToMove.begin(); itr != _dynamicObjectsToMove.end(); ++itr)
1360 {
1361 DynamicObject* dynObj = *itr;
1362 if (dynObj->FindMap() != this) //transport is teleported to another map
1363 continue;
1364
1366 {
1368 continue;
1369 }
1370
1372 if (!dynObj->IsInWorld())
1373 continue;
1374
1375 // do move or do move to respawn or remove creature if previous all fail
1377 {
1378 // update pos
1379 dynObj->Relocate(dynObj->_newPosition);
1380 dynObj->UpdatePositionData();
1381 dynObj->UpdateObjectVisibility(false);
1382 }
1383 else
1384 {
1385#ifdef TRINITY_DEBUG
1386 TC_LOG_DEBUG("maps", "DynamicObject {} cannot be moved to unloaded grid.", dynObj->GetGUID().ToString());
1387#endif
1388 }
1389 }
1390
1391 _dynamicObjectsToMove.clear();
1393}
1394
1396{
1398 for (std::vector<AreaTrigger*>::iterator itr = _areaTriggersToMove.begin(); itr != _areaTriggersToMove.end(); ++itr)
1399 {
1400 AreaTrigger* at = *itr;
1401 if (at->FindMap() != this) //transport is teleported to another map
1402 continue;
1403
1405 {
1407 continue;
1408 }
1409
1411 if (!at->IsInWorld())
1412 continue;
1413
1414 // do move or do move to respawn or remove creature if previous all fail
1416 {
1417 // update pos
1418 at->Relocate(at->_newPosition);
1419 at->UpdateShape();
1420 at->UpdateObjectVisibility(false);
1421 }
1422 else
1423 {
1424#ifdef TRINITY_DEBUG
1425 TC_LOG_DEBUG("maps", "AreaTrigger {} cannot be moved to unloaded grid.", at->GetGUID().ToString());
1426#endif
1427 }
1428 }
1429
1430 _areaTriggersToMove.clear();
1432}
1433
1434template <typename T>
1435bool Map::MapObjectCellRelocation(T* object, Cell new_cell, [[maybe_unused]] char const* objType)
1436{
1437 Cell const& old_cell = object->GetCurrentCell();
1438 if (!old_cell.DiffGrid(new_cell)) // in same grid
1439 {
1440 // if in same cell then none do
1441 if (old_cell.DiffCell(new_cell))
1442 {
1443#ifdef TRINITY_DEBUG
1444 TC_LOG_DEBUG("maps", "{} {} moved in grid[{}, {}] from cell[{}, {}] to cell[{}, {}].", objType, object->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
1445#endif
1446
1447 object->RemoveFromGrid();
1448 AddToGrid(object, new_cell);
1449 }
1450 else
1451 {
1452#ifdef TRINITY_DEBUG
1453 TC_LOG_DEBUG("maps", "{} {} moved in same grid[{}, {}]cell[{}, {}].", objType, object->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY());
1454#endif
1455 }
1456
1457 return true;
1458 }
1459
1460 GridCoord new_grid(new_cell.GridX(), new_cell.GridY());
1461
1462 // in diff. grids but active creature
1463 if (object->isActiveObject())
1464 {
1465 EnsureGridLoadedForActiveObject(new_grid, object);
1466
1467#ifdef TRINITY_DEBUG
1468 TC_LOG_DEBUG("maps", "Active {} {} moved from grid[{}, {}]cell[{}, {}] to grid[{}, {}]cell[{}, {}].", objType, object->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
1469#endif
1470
1471 object->RemoveFromGrid();
1472 AddToGrid(object, new_cell);
1473
1474 return true;
1475 }
1476
1477 if (Creature* c = object->ToCreature())
1478 if (c->GetCharmerOrOwnerGUID().IsPlayer())
1479 EnsureGridLoaded(new_grid);
1480
1481 // in diff. loaded grid normal object
1482 if (IsGridLoaded(new_grid))
1483 {
1484#ifdef TRINITY_DEBUG
1485 TC_LOG_DEBUG("maps", "{} {} moved from grid[{}, {}]cell[{}, {}] to grid[{}, {}]cell[{}, {}].", objType, object->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
1486#endif
1487
1488 object->RemoveFromGrid();
1489 EnsureGridCreated(new_grid);
1490 AddToGrid(object, new_cell);
1491
1492 return true;
1493 }
1494
1495 // fail to move: normal object attempt move to unloaded grid
1496#ifdef TRINITY_DEBUG
1497 TC_LOG_DEBUG("maps", "{} {} attempted to move from grid[{}, {}]cell[{}, {}] to unloaded grid[{}, {}]cell[{}, {}].", objType, object->GetGUID().ToString(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
1498#endif
1499 return false;
1500}
1501
1503{
1504 return MapObjectCellRelocation(c, new_cell, "Creature");
1505}
1506
1508{
1509 return MapObjectCellRelocation(go, new_cell, "GameObject");
1510}
1511
1513{
1514 return MapObjectCellRelocation(go, new_cell, "DynamicObject");
1515}
1516
1518{
1519 return MapObjectCellRelocation(at, new_cell, "AreaTrigger");
1520}
1521
1522bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly)
1523{
1524 Position resp = c->GetRespawnPosition();
1525 Cell resp_cell(resp.GetPositionX(), resp.GetPositionY());
1526
1527 //creature will be unloaded with grid
1528 if (diffGridOnly && !c->GetCurrentCell().DiffGrid(resp_cell))
1529 return true;
1530
1531 c->CombatStop();
1532 c->GetMotionMaster()->Clear();
1533
1534#ifdef TRINITY_DEBUG
1535 TC_LOG_DEBUG("maps", "Creature {} moved from grid[{}, {}]cell[{}, {}] to respawn grid[{}, {}]cell[{}, {}].", c->GetGUID().ToString(), c->GetCurrentCell().GridX(), c->GetCurrentCell().GridY(), c->GetCurrentCell().CellX(), c->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
1536#endif
1537
1538 // teleport it to respawn point (like normal respawn if player see)
1539 if (CreatureCellRelocation(c, resp_cell))
1540 {
1541 c->Relocate(resp);
1542 c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators
1543 //CreatureRelocationNotify(c, resp_cell, resp_cell.GetCellCoord());
1544 c->UpdatePositionData();
1545 c->UpdateObjectVisibility(false);
1546 return true;
1547 }
1548
1549 return false;
1550}
1551
1553{
1554 Position resp = go->GetRespawnPosition();
1555 Cell resp_cell(resp.GetPositionX(), resp.GetPositionY());
1556
1557 //GameObject will be unloaded with grid
1558 if (diffGridOnly && !go->GetCurrentCell().DiffGrid(resp_cell))
1559 return true;
1560
1561#ifdef TRINITY_DEBUG
1562 TC_LOG_DEBUG("maps", "GameObject {} moved from grid[{}, {}]cell[{}, {}] to respawn grid[{}, {}]cell[{}, {}].", go->GetGUID().ToString(), go->GetCurrentCell().GridX(), go->GetCurrentCell().GridY(), go->GetCurrentCell().CellX(), go->GetCurrentCell().CellY(), resp_cell.GridX(), resp_cell.GridY(), resp_cell.CellX(), resp_cell.CellY());
1563#endif
1564
1565 // teleport it to respawn point (like normal respawn if player see)
1566 if (GameObjectCellRelocation(go, resp_cell))
1567 {
1568 go->Relocate(resp);
1569 go->UpdatePositionData();
1570 go->UpdateObjectVisibility(false);
1571 return true;
1572 }
1573
1574 return false;
1575}
1576
1577bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll)
1578{
1579 const uint32 x = ngrid.getX();
1580 const uint32 y = ngrid.getY();
1581
1582 {
1583 if (!unloadAll)
1584 {
1585 //pets, possessed creatures (must be active), transport passengers
1586 if (ngrid.HasWorldObjectsInNGrid<Creature>())
1587 return false;
1588
1589 if (ActiveObjectsNearGrid(ngrid))
1590 return false;
1591 }
1592
1593 TC_LOG_DEBUG("maps", "Unloading grid[{}, {}] for map {}", x, y, GetId());
1594
1595 if (!unloadAll)
1596 {
1597 // Finish creature moves, remove and delete all creatures with delayed remove before moving to respawn grids
1598 // Must know real mob position before move
1602
1603 // move creatures to respawn grids if this is diff.grid or to remove list
1604 ObjectGridEvacuator worker;
1606 ngrid.VisitAllGrids(visitor);
1607
1608 // Finish creature moves, remove and delete all creatures with delayed remove before unload
1612 }
1613
1614 {
1615 ObjectGridCleaner worker;
1617 ngrid.VisitAllGrids(visitor);
1618 }
1619
1621
1622 // After removing all objects from the map, purge empty tracked phases
1624
1625 {
1626 ObjectGridUnloader worker;
1628 ngrid.VisitAllGrids(visitor);
1629 }
1630
1631 ASSERT(i_objectsToRemove.empty());
1632
1633 delete &ngrid;
1634 setNGrid(nullptr, x, y);
1635 }
1636 int gx = (MAX_NUMBER_OF_GRIDS - 1) - x;
1637 int gy = (MAX_NUMBER_OF_GRIDS - 1) - y;
1638
1639 m_terrain->UnloadMap(gx, gy);
1640
1641 TC_LOG_DEBUG("maps", "Unloading grid[{}, {}] for map {} finished", x, y, GetId());
1642 return true;
1643}
1644
1646{
1647 if (HavePlayers())
1648 {
1649 for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
1650 {
1651 Player* player = itr->GetSource();
1652 if (!player->IsBeingTeleportedFar())
1653 {
1654 // this is happening for bg
1655 TC_LOG_ERROR("maps", "Map::UnloadAll: player {} is still in map {} during unload, this should not happen!", player->GetName(), GetId());
1656 player->TeleportTo(player->m_homebind);
1657 }
1658 }
1659 }
1660}
1661
1663{
1664 // clear all delayed moves, useless anyway do this moves before map unload.
1665 _creaturesToMove.clear();
1666 _gameObjectsToMove.clear();
1667
1669 {
1670 NGridType &grid(*i->GetSource());
1671 ++i;
1672 UnloadGrid(grid, true); // deletes the grid and removes it from the GridRefManager
1673 }
1674
1675 for (TransportsContainer::iterator itr = _transports.begin(); itr != _transports.end();)
1676 {
1677 Transport* transport = *itr;
1678 ++itr;
1679
1680 RemoveFromMap<Transport>(transport, true);
1681 }
1682
1683 for (auto& [gridId, corpses] : _corpsesByGrid)
1684 {
1685 for (Corpse* corpse : corpses)
1686 {
1687 corpse->RemoveFromWorld();
1688 corpse->ResetMap();
1689 delete corpse;
1690 }
1691 }
1692
1693 _corpsesByGrid.clear();
1694 _corpsesByPlayer.clear();
1695 _corpseBones.clear();
1696}
1697
1698void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data,
1699 Optional<map_liquidHeaderTypeFlags> reqLiquidType, float collisionHeight)
1700{
1701 m_terrain->GetFullTerrainStatusForPosition(phaseShift, GetId(), x, y, z, data, reqLiquidType, collisionHeight, &_dynamicTree);
1702}
1703
1704ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, Optional<map_liquidHeaderTypeFlags> ReqLiquidType, LiquidData* data,
1705 float collisionHeight)
1706{
1707 return m_terrain->GetLiquidStatus(phaseShift, GetId(), x, y, z, ReqLiquidType, data, collisionHeight);
1708}
1709
1710uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z)
1711{
1712 return m_terrain->GetAreaId(phaseShift, GetId(), x, y, z, &_dynamicTree);
1713}
1714
1715uint32 Map::GetZoneId(PhaseShift const& phaseShift, float x, float y, float z)
1716{
1717 return m_terrain->GetZoneId(phaseShift, GetId(), x, y, z, &_dynamicTree);
1718}
1719
1720void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z)
1721{
1722 return m_terrain->GetZoneAndAreaId(phaseShift, GetId(), zoneid, areaid, x, y, z, &_dynamicTree);
1723}
1724
1725float Map::GetMinHeight(PhaseShift const& phaseShift, float x, float y)
1726{
1727 return m_terrain->GetMinHeight(phaseShift, GetId(), x, y);
1728}
1729
1730float Map::GetGridHeight(PhaseShift const& phaseShift, float x, float y)
1731{
1732 return m_terrain->GetGridHeight(phaseShift, GetId(), x, y);
1733}
1734
1735float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap, float maxSearchDist)
1736{
1737 return m_terrain->GetStaticHeight(phaseShift, GetId(), x, y, z, checkVMap, maxSearchDist);
1738}
1739
1740float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y)
1741{
1742 return m_terrain->GetWaterLevel(phaseShift, GetId(), x, y);
1743}
1744
1745bool Map::IsInWater(PhaseShift const& phaseShift, float x, float y, float z, LiquidData* data)
1746{
1747 return m_terrain->IsInWater(phaseShift, GetId(), x, y, z, data);
1748}
1749
1750bool Map::IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z)
1751{
1752 return m_terrain->IsUnderWater(phaseShift, GetId(), x, y, z);
1753}
1754
1755float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground, bool swim, float collisionHeight)
1756{
1757 return m_terrain->GetWaterOrGroundLevel(phaseShift, GetId(), x, y, z, ground, swim, collisionHeight, &_dynamicTree);
1758}
1759
1760bool Map::isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
1761{
1762 if ((checks & LINEOFSIGHT_CHECK_VMAP)
1763 && !VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(phaseShift, GetId(), m_terrain.get(), x1, y1), x1, y1, z1, x2, y2, z2, ignoreFlags))
1764 return false;
1765 if (sWorld->getBoolConfig(CONFIG_CHECK_GOBJECT_LOS) && (checks & LINEOFSIGHT_CHECK_GOBJECT)
1766 && !_dynamicTree.isInLineOfSight({ x1, y1, z1 }, { x2, y2, z2 }, phaseShift))
1767 return false;
1768 return true;
1769}
1770
1771bool Map::getObjectHitPos(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist)
1772{
1773 G3D::Vector3 startPos(x1, y1, z1);
1774 G3D::Vector3 dstPos(x2, y2, z2);
1775
1776 G3D::Vector3 resultPos;
1777 bool result = _dynamicTree.getObjectHitPos(startPos, dstPos, resultPos, modifyDist, phaseShift);
1778
1779 rx = resultPos.x;
1780 ry = resultPos.y;
1781 rz = resultPos.z;
1782 return result;
1783}
1784
1786{
1788 return;
1789
1790 uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, GetId(), m_terrain.get(), model.GetPosition().x, model.GetPosition().y);
1791
1792 G3D::AABox const& bounds = model.getBounds();
1793
1794 GridCoord low = Trinity::ComputeGridCoord(bounds.high().x, bounds.high().y);
1795 low.x_coord = (MAX_NUMBER_OF_GRIDS - 1) - low.x_coord;
1796 low.y_coord = (MAX_NUMBER_OF_GRIDS - 1) - low.y_coord;
1797
1798 GridCoord high = Trinity::ComputeGridCoord(bounds.low().x, bounds.low().y);
1799 high.x_coord = (MAX_NUMBER_OF_GRIDS - 1) - high.x_coord;
1800 high.y_coord = (MAX_NUMBER_OF_GRIDS - 1) - high.y_coord;
1801
1802 for (uint32 x = low.x_coord; x <= high.x_coord; ++x)
1803 for (uint32 y = low.y_coord; y <= high.y_coord; ++y)
1804 m_mmapTileRebuilder->AddTile(terrainMapId, x, y);
1805}
1806
1808{
1809 MapEntry const* entry = sMapStore.LookupEntry(mapid);
1810 if (!entry)
1812
1813 if (!entry->IsDungeon())
1814 return TRANSFER_ABORT_NONE;
1815
1816 Group* group = player->GetGroup();
1817 Difficulty targetDifficulty = group ? group->GetDifficultyID(entry) : player->GetDifficultyID(entry);
1818 // Get the highest available difficulty if current setting is higher than the instance allows
1819 MapDifficultyEntry const* mapDiff = sDB2Manager.GetDownscaledMapDifficultyData(mapid, targetDifficulty);
1820 if (!mapDiff)
1822
1823 //Bypass checks for GMs
1824 if (player->IsGameMaster())
1825 return TRANSFER_ABORT_NONE;
1826
1827 //Other requirements
1828 {
1830 if (!player->Satisfy(sObjectMgr->GetAccessRequirement(mapid, Difficulty(mapDiff->DifficultyID)), mapid, &params, true))
1831 return params;
1832 }
1833
1834 if (entry->IsRaid() && entry->Expansion() >= sWorld->getIntConfig(CONFIG_EXPANSION)) // can only enter in a raid group but raids from old expansion don't need a group
1835 if ((!group || !group->isRaidGroup()) && !sWorld->getBoolConfig(CONFIG_INSTANCE_IGNORE_RAID))
1837
1838 if (entry->Instanceable())
1839 {
1840 //Get instance where player's group is bound & its map
1841 uint32 instanceIdToCheck = sMapMgr->FindInstanceIdForPlayer(mapid, player);
1842 if (Map* boundMap = sMapMgr->FindMap(mapid, instanceIdToCheck))
1843 if (TransferAbortParams denyReason = boundMap->CannotEnter(player))
1844 return denyReason;
1845
1846 // players are only allowed to enter 10 instances per hour
1847 if (!entry->GetFlags2().HasFlag(MapFlags2::IgnoreInstanceFarmLimit) && entry->IsDungeon() && !player->GetSession()->UpdateAndCheckInstanceCount(instanceIdToCheck) && !player->isDead())
1849 }
1850
1851 return TRANSFER_ABORT_NONE;
1852}
1853
1854char const* Map::GetMapName() const
1855{
1856 return i_mapEntry->MapName[sWorld->GetDefaultDbcLocale()];
1857}
1858
1860{
1861 TC_LOG_DEBUG("maps", "Creating player data for himself {}", player->GetGUID().ToString());
1862
1863 UpdateData data(player->GetMapId());
1864
1865 // attach to player data current transport data
1866 if (Transport* transport = dynamic_cast<Transport*>(player->GetTransport()))
1867 {
1868 transport->BuildCreateUpdateBlockForPlayer(&data, player);
1869 player->m_visibleTransports.insert(transport->GetGUID());
1870 }
1871
1872 // build data for self presence in world at own client (one time for map)
1873 player->BuildCreateUpdateBlockForPlayer(&data, player);
1874
1875 // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map
1876 if (Transport* transport = dynamic_cast<Transport*>(player->GetTransport()))
1877 for (WorldObject* passenger : transport->GetPassengers())
1878 if (player != passenger && player->HaveAtClient(passenger))
1879 passenger->BuildCreateUpdateBlockForPlayer(&data, player);
1880
1881 WorldPacket packet;
1882 data.BuildPacket(&packet);
1883 player->SendDirectMessage(&packet);
1884
1885 // client will respond to SMSG_UPDATE_OBJECT that contains ThisIsYou = true with CMSG_MOVE_INIT_ACTIVE_MOVER_COMPLETE
1887}
1888
1890{
1891 // Hack to send out transports
1892 UpdateData transData(GetId());
1893 for (Transport* transport : _transports)
1894 {
1895 if (transport->IsInWorld() && transport != player->GetTransport() && player->InSamePhase(transport))
1896 {
1897 transport->BuildCreateUpdateBlockForPlayer(&transData, player);
1898 player->m_visibleTransports.insert(transport->GetGUID());
1899 }
1900 }
1901
1902 if (!transData.HasData())
1903 return;
1904
1905 WorldPacket packet;
1906 transData.BuildPacket(&packet);
1907 player->SendDirectMessage(&packet);
1908}
1909
1911{
1912 // Hack to send out transports
1913 UpdateData transData(player->GetMapId());
1914 for (Transport* transport : _transports)
1915 {
1916 if (player->m_visibleTransports.count(transport->GetGUID()) && transport != player->GetTransport())
1917 {
1918 transport->BuildOutOfRangeUpdateBlock(&transData);
1919 player->m_visibleTransports.erase(transport->GetGUID());
1920 }
1921 }
1922
1923 if (!transData.HasData())
1924 return;
1925
1926 WorldPacket packet;
1927 transData.BuildPacket(&packet);
1928 player->SendDirectMessage(&packet);
1929}
1930
1932{
1933 // Hack to send out transports
1934 UpdateData transData(player->GetMapId());
1935 for (Transport* transport : _transports)
1936 {
1937 if (!transport->IsInWorld())
1938 continue;
1939
1940 auto transportItr = player->m_visibleTransports.find(transport->GetGUID());
1941 if (player->InSamePhase(transport))
1942 {
1943 if (transportItr == player->m_visibleTransports.end())
1944 {
1945 transport->BuildCreateUpdateBlockForPlayer(&transData, player);
1946 player->m_visibleTransports.insert(transport->GetGUID());
1947 }
1948 }
1949 else if (transportItr != player->m_visibleTransports.end())
1950 {
1951 transport->BuildOutOfRangeUpdateBlock(&transData);
1952 player->m_visibleTransports.erase(transportItr);
1953 }
1954 }
1955
1956 if (!transData.HasData())
1957 return;
1958
1959 WorldPacket packet;
1960 transData.BuildPacket(&packet);
1961 player->GetSession()->SendPacket(&packet);
1962}
1963
1964inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y)
1965{
1967 {
1968 TC_LOG_ERROR("maps", "map::setNGrid() Invalid grid coordinates found: {}, {}!", x, y);
1969 ABORT();
1970 }
1971 i_grids[x][y] = grid;
1972}
1973
1975{
1976 UpdateDataMapType update_players;
1977
1978 while (!_updateObjects.empty())
1979 {
1980 BaseEntity* obj = *_updateObjects.begin();
1981 ASSERT(obj->IsInWorld());
1982 _updateObjects.erase(_updateObjects.begin());
1983 obj->BuildUpdate(update_players);
1984 }
1985
1986 WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
1987 for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
1988 {
1989 iter->second.BuildPacket(&packet);
1990 iter->first->SendDirectMessage(&packet);
1991 packet.clear(); // clean the string
1992 }
1993}
1994
1995// CheckRespawn MUST do one of the following:
1996// -) return true
1997// -) set info->respawnTime to zero, which indicates the respawn time should be deleted (and will never be processed again without outside intervention)
1998// -) set info->respawnTime to a new respawn time, which must be strictly GREATER than the current time (GameTime::GetGameTime())
2000{
2001 SpawnData const* data = sObjectMgr->GetSpawnData(info->type, info->spawnId);
2002 ASSERT(data, "Invalid respawn info with type %u, spawnID " UI64FMTD " in respawn queue.", info->type, info->spawnId);
2003
2004 // First, check if this creature's spawn group is inactive
2006 {
2007 info->respawnTime = 0;
2008 return false;
2009 }
2010
2011 // Next, check if there's already an instance of this object that would block the respawn
2012 bool alreadyExists = false;
2013 switch (info->type)
2014 {
2016 {
2017 // escort check for creatures only (if the world config boolean is set)
2018 bool const isEscort = (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && data->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC);
2019
2020 auto range = _creatureBySpawnIdStore.equal_range(info->spawnId);
2021 for (auto it = range.first; it != range.second; ++it)
2022 {
2023 Creature* creature = it->second;
2024 if (!creature->IsAlive())
2025 continue;
2026 // escort NPCs are allowed to respawn as long as all other instances are already escorting
2027 if (isEscort && creature->IsEscorted())
2028 continue;
2029 alreadyExists = true;
2030 break;
2031 }
2032 break;
2033 }
2035 // gameobject check is simpler - they cannot be dead or escorting
2037 alreadyExists = true;
2038 break;
2039 default:
2040 ABORT_MSG("Invalid spawn type %u with spawnId " UI64FMTD " on map %u", uint32(info->type), info->spawnId, GetId());
2041 return true;
2042 }
2043 if (alreadyExists)
2044 {
2045 info->respawnTime = 0;
2046 return false;
2047 }
2048
2049 // next, check linked respawn time
2050 ObjectGuid thisGUID = info->type == SPAWN_TYPE_GAMEOBJECT
2051 ? ObjectGuid::Create<HighGuid::GameObject>(GetId(), info->entry, info->spawnId)
2052 : ObjectGuid::Create<HighGuid::Creature>(GetId(), info->entry, info->spawnId);
2053 if (time_t linkedTime = GetLinkedRespawnTime(thisGUID))
2054 {
2055 time_t now = GameTime::GetGameTime();
2056 time_t respawnTime;
2057 if (linkedTime == std::numeric_limits<time_t>::max())
2058 respawnTime = linkedTime;
2059 else if (sObjectMgr->GetLinkedRespawnGuid(thisGUID) == thisGUID) // never respawn, save "something" in DB
2060 respawnTime = now + WEEK;
2061 else // set us to check again shortly after linked unit
2062 respawnTime = std::max<time_t>(now, linkedTime) + urand(5, 15);
2063 info->respawnTime = respawnTime;
2064 return false;
2065 }
2066 // everything ok, let's spawn
2067 return true;
2068}
2069
2071{
2072 if (info->respawnTime <= GameTime::GetGameTime())
2073 return;
2075 _respawnTimes->increase(static_cast<RespawnInfoWithHandle*>(info)->handle);
2076 SaveRespawnInfoDB(*info, dbTrans);
2077}
2078
2080{
2081 std::vector<WorldObject*> toUnload;
2082 switch (type)
2083 {
2085 for (auto const& pair : Trinity::Containers::MapEqualRange(GetCreatureBySpawnIdStore(), spawnId))
2086 toUnload.push_back(pair.second);
2087 break;
2089 for (auto const& pair : Trinity::Containers::MapEqualRange(GetGameObjectBySpawnIdStore(), spawnId))
2090 toUnload.push_back(pair.second);
2091 break;
2092 default:
2093 break;
2094 }
2095
2096 for (WorldObject* o : toUnload)
2098
2099 return toUnload.size();
2100}
2101
2103{
2104 if (!info.spawnId)
2105 {
2106 TC_LOG_ERROR("maps", "Attempt to insert respawn info for zero spawn id (type {})", uint32(info.type));
2107 return false;
2108 }
2109
2110 RespawnInfoMap* bySpawnIdMap = GetRespawnMapForType(info.type);
2111 if (!bySpawnIdMap)
2112 return false;
2113
2114 // check if we already have the maximum possible number of respawns scheduled
2115 if (SpawnData::TypeHasData(info.type))
2116 {
2117 auto it = bySpawnIdMap->find(info.spawnId);
2118 if (it != bySpawnIdMap->end()) // spawnid already has a respawn scheduled
2119 {
2120 RespawnInfo* const existing = it->second;
2121 if (info.respawnTime < existing->respawnTime) // delete existing in this case
2122 DeleteRespawnInfo(existing);
2123 else
2124 return false;
2125 }
2126 ASSERT(bySpawnIdMap->find(info.spawnId) == bySpawnIdMap->end(), "Insertion of respawn info with id (%u," UI64FMTD ") into spawn id map failed - state desync.", uint32(info.type), info.spawnId);
2127 }
2128 else
2129 ABORT_MSG("Invalid respawn info for spawn id (%u," UI64FMTD ") being inserted", uint32(info.type), info.spawnId);
2130
2132 ri->handle = _respawnTimes->push(ri);
2133 bySpawnIdMap->emplace(ri->spawnId, ri);
2134 return true;
2135}
2136
2137static void PushRespawnInfoFrom(std::vector<RespawnInfo const*>& data, RespawnInfoMap const& map)
2138{
2139 data.reserve(data.size() + map.size());
2140 for (auto const& pair : map)
2141 data.push_back(pair.second);
2142}
2143
2144void Map::GetRespawnInfo(std::vector<RespawnInfo const*>& respawnData, SpawnObjectTypeMask types) const
2145{
2146 if (types & SPAWN_TYPEMASK_CREATURE)
2148 if (types & SPAWN_TYPEMASK_GAMEOBJECT)
2150}
2151
2153{
2154 RespawnInfoMap const* map = GetRespawnMapForType(type);
2155 if (!map)
2156 return nullptr;
2157 auto it = map->find(spawnId);
2158 if (it == map->end())
2159 return nullptr;
2160 return it->second;
2161}
2162
2163void Map::UnloadAllRespawnInfos() // delete everything from memory
2164{
2165 for (RespawnInfo* info : *_respawnTimes)
2166 delete info;
2167 _respawnTimes->clear();
2170}
2171
2173{
2174 // Delete from all relevant containers to ensure consistency
2175 ASSERT(info);
2176
2177 // spawnid store
2178 auto spawnMap = GetRespawnMapForType(info->type);
2179 if (!spawnMap)
2180 return;
2181
2182 auto range = spawnMap->equal_range(info->spawnId);
2183 auto it = std::find_if(range.first, range.second, [info](RespawnInfoMap::value_type const& pair) { return (pair.second == info); });
2184 ASSERT(it != range.second, "Respawn stores inconsistent for map %u, spawnid " UI64FMTD " (type %u)", GetId(), info->spawnId, uint32(info->type));
2185 spawnMap->erase(it);
2186
2187 // respawn heap
2188 _respawnTimes->erase(static_cast<RespawnInfoWithHandle*>(info)->handle);
2189
2190 // database
2191 DeleteRespawnInfoFromDB(info->type, info->spawnId, dbTrans);
2192
2193 // then cleanup the object
2194 delete info;
2195}
2196
2198{
2199 if (Instanceable())
2200 return;
2201
2203 stmt->setUInt16(0, type);
2204 stmt->setUInt64(1, spawnId);
2205 stmt->setUInt16(2, GetId());
2206 stmt->setUInt32(3, GetInstanceId());
2207 CharacterDatabase.ExecuteOrAppend(dbTrans, stmt);
2208}
2209
2211{
2212 if (!IsGridLoaded(gridId)) // if grid isn't loaded, this will be processed in grid load handler
2213 return;
2214
2215 switch (type)
2216 {
2218 {
2219 Creature* obj = new Creature();
2220 if (!obj->LoadFromDB(spawnId, this, true, true))
2221 delete obj;
2222 break;
2223 }
2225 {
2226 GameObject* obj = new GameObject();
2227 if (!obj->LoadFromDB(spawnId, this, true))
2228 delete obj;
2229 break;
2230 }
2231 default:
2232 ABORT_MSG("Invalid spawn type %u (spawnid " UI64FMTD ") on map %u", uint32(type), spawnId, GetId());
2233 }
2234}
2235
2237{
2238 time_t now = GameTime::GetGameTime();
2239 while (!_respawnTimes->empty())
2240 {
2241 RespawnInfoWithHandle* next = _respawnTimes->top();
2242 if (now < next->respawnTime) // done for this tick
2243 break;
2244
2245 if (uint32 poolId = sPoolMgr->IsPartOfAPool(next->type, next->spawnId)) // is this part of a pool?
2246 { // if yes, respawn will be handled by (external) pooling logic, just delete the respawn time
2247 // step 1: remove entry from maps to avoid it being reachable by outside logic
2248 _respawnTimes->pop();
2249 ASSERT_NOTNULL(GetRespawnMapForType(next->type))->erase(next->spawnId);
2250
2251 // step 2: tell pooling logic to do its thing
2252 sPoolMgr->UpdatePool(GetPoolData(), poolId, next->type, next->spawnId);
2253
2254 // step 3: get rid of the actual entry
2255 RemoveRespawnTime(next->type, next->spawnId, nullptr, true);
2256 delete next;
2257 }
2258 else if (CheckRespawn(next)) // see if we're allowed to respawn
2259 { // ok, respawn
2260 // step 1: remove entry from maps to avoid it being reachable by outside logic
2261 _respawnTimes->pop();
2262 ASSERT_NOTNULL(GetRespawnMapForType(next->type))->erase(next->spawnId);
2263
2264 // step 2: do the respawn, which involves external logic
2265 DoRespawn(next->type, next->spawnId, next->gridId);
2266
2267 // step 3: get rid of the actual entry
2268 RemoveRespawnTime(next->type, next->spawnId, nullptr, true);
2269 delete next;
2270 }
2271 else if (!next->respawnTime)
2272 { // just remove this respawn entry without rescheduling
2273 _respawnTimes->pop();
2274 ASSERT_NOTNULL(GetRespawnMapForType(next->type))->erase(next->spawnId);
2275 RemoveRespawnTime(next->type, next->spawnId, nullptr, true);
2276 delete next;
2277 }
2278 else
2279 { // new respawn time, update heap position
2280 ASSERT(now < next->respawnTime); // infinite loop guard
2281 _respawnTimes->decrease(next->handle);
2282 SaveRespawnInfoDB(*next);
2283 }
2284 }
2285}
2286
2287void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::LowType spawnId, uint32& respawnDelay, uint32 mode) const
2288{
2289 ASSERT(mode == 1);
2290 ASSERT(obj->GetMap() == this);
2291
2293 return;
2294
2295 SpawnObjectType type;
2296 switch (obj->GetTypeId())
2297 {
2298 case TYPEID_UNIT:
2299 type = SPAWN_TYPE_CREATURE;
2300 break;
2301 case TYPEID_GAMEOBJECT:
2302 type = SPAWN_TYPE_GAMEOBJECT;
2303 break;
2304 default:
2305 return;
2306 }
2307
2308 SpawnMetadata const* data = sObjectMgr->GetSpawnMetadata(type, spawnId);
2309 if (!data)
2310 return;
2311
2313 return;
2314
2315 auto it = _zonePlayerCountMap.find(obj->GetZoneId());
2316 if (it == _zonePlayerCountMap.end())
2317 return;
2318 uint32 const playerCount = it->second;
2319 if (!playerCount)
2320 return;
2321 double const adjustFactor = sWorld->getFloatConfig(type == SPAWN_TYPE_GAMEOBJECT ? CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT : CONFIG_RESPAWN_DYNAMICRATE_CREATURE) / playerCount;
2322 if (adjustFactor >= 1.0) // nothing to do here
2323 return;
2325 if (respawnDelay <= timeMinimum)
2326 return;
2327
2328 respawnDelay = std::max<uint32>(ceil(respawnDelay * adjustFactor), timeMinimum);
2329}
2330
2332{
2334 // check if the object is on its respawn timer
2335 if (GetRespawnTime(type, spawnId))
2336 return false;
2337
2338 SpawnMetadata const* spawnData = ASSERT_NOTNULL(sObjectMgr->GetSpawnMetadata(type, spawnId));
2339 // check if the object is part of a spawn group
2340 SpawnGroupTemplateData const* spawnGroup = ASSERT_NOTNULL(spawnData->spawnGroupData);
2341 if (!(spawnGroup->flags & SPAWNGROUP_FLAG_SYSTEM))
2342 if (!IsSpawnGroupActive(spawnGroup->groupId))
2343 return false;
2344
2345 if (spawnData->ToSpawnData()->poolId)
2346 if (!GetPoolData().IsSpawnedObject(type, spawnId))
2347 return false;
2348
2349 return true;
2350}
2351
2353{
2354 SpawnGroupTemplateData const* data = sObjectMgr->GetSpawnGroupData(groupId);
2355 if (data && (data->flags & SPAWNGROUP_FLAG_SYSTEM || data->mapId == GetId()))
2356 return data;
2357 return nullptr;
2358}
2359
2360bool Map::SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn, bool force, std::vector<WorldObject*>* spawnedObjects)
2361{
2362 SpawnGroupTemplateData const* groupData = GetSpawnGroupData(groupId);
2363 if (!groupData || groupData->flags & SPAWNGROUP_FLAG_SYSTEM)
2364 {
2365 TC_LOG_ERROR("maps", "Tried to spawn non-existing (or system) spawn group {} on map {}. Blocked.", groupId, GetId());
2366 return false;
2367 }
2368
2369 SetSpawnGroupActive(groupId, true); // start processing respawns for the group
2370
2371 std::vector<SpawnData const*> toSpawn;
2372 for (auto& pair : sObjectMgr->GetSpawnMetadataForGroup(groupId))
2373 {
2374 SpawnMetadata const* data = pair.second;
2375 ASSERT(groupData->mapId == data->mapId);
2376
2377 auto respawnMap = GetRespawnMapForType(data->type);
2378 if (!respawnMap)
2379 continue;
2380
2381 if (force || ignoreRespawn)
2382 RemoveRespawnTime(data->type, data->spawnId);
2383
2384 uint32 nRespawnTimers = respawnMap->count(data->spawnId);
2385 if (SpawnData::TypeHasData(data->type))
2386 {
2387 // has a respawn timer
2388 if (nRespawnTimers)
2389 continue;
2390
2391 // has a spawn already active
2392 if (!force)
2393 if (WorldObject* obj = GetWorldObjectBySpawnId(data->type, data->spawnId))
2394 if ((data->type != SPAWN_TYPE_CREATURE) || obj->ToCreature()->IsAlive())
2395 continue;
2396
2397 toSpawn.push_back(ASSERT_NOTNULL(data->ToSpawnData()));
2398 }
2399 }
2400
2401 for (SpawnData const* data : toSpawn)
2402 {
2403 // don't spawn if the current map difficulty is not used by the spawn
2404 if (std::find(data->spawnDifficulties.begin(), data->spawnDifficulties.end(), GetDifficultyID()) == data->spawnDifficulties.end())
2405 continue;
2406
2407 // don't spawn if the grid isn't loaded (will be handled in grid loader)
2408 if (!IsGridLoaded(data->spawnPoint))
2409 continue;
2410
2411 // now do the actual (re)spawn
2412 switch (data->type)
2413 {
2415 {
2416 Creature* creature = new Creature();
2417 if (!creature->LoadFromDB(data->spawnId, this, true, force))
2418 delete creature;
2419 else if (spawnedObjects)
2420 spawnedObjects->push_back(creature);
2421 break;
2422 }
2424 {
2425 GameObject* gameobject = new GameObject();
2426 if (!gameobject->LoadFromDB(data->spawnId, this, true))
2427 delete gameobject;
2428 else if (spawnedObjects)
2429 spawnedObjects->push_back(gameobject);
2430 break;
2431 }
2433 {
2434 AreaTrigger* areaTrigger = new AreaTrigger();
2435 if (!areaTrigger->LoadFromDB(data->spawnId, this, true, false))
2436 delete areaTrigger;
2437 else if (spawnedObjects)
2438 spawnedObjects->push_back(areaTrigger);
2439 break;
2440 }
2441 default:
2442 ABORT_MSG("Invalid spawn type %u with spawnId " UI64FMTD, uint32(data->type), data->spawnId);
2443 return false;
2444 }
2445 }
2446 return true;
2447}
2448
2449bool Map::SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes, size_t* count)
2450{
2451 SpawnGroupTemplateData const* groupData = GetSpawnGroupData(groupId);
2452 if (!groupData || groupData->flags & SPAWNGROUP_FLAG_SYSTEM)
2453 {
2454 TC_LOG_ERROR("maps", "Tried to despawn non-existing (or system) spawn group {} on map {}. Blocked.", groupId, GetId());
2455 return false;
2456 }
2457
2458 for (auto const& pair : sObjectMgr->GetSpawnMetadataForGroup(groupId))
2459 {
2460 SpawnMetadata const* data = pair.second;
2461 ASSERT(groupData->mapId == data->mapId);
2462 if (deleteRespawnTimes)
2463 RemoveRespawnTime(data->type, data->spawnId);
2464 size_t c = DespawnAll(data->type, data->spawnId);
2465 if (count)
2466 *count += c;
2467 }
2468 SetSpawnGroupActive(groupId, false); // stop processing respawns for the group, too
2469 return true;
2470}
2471
2472void Map::SetSpawnGroupActive(uint32 groupId, bool state)
2473{
2474 SpawnGroupTemplateData const* const data = GetSpawnGroupData(groupId);
2475 if (!data || data->flags & SPAWNGROUP_FLAG_SYSTEM)
2476 {
2477 TC_LOG_ERROR("maps", "Tried to set non-existing (or system) spawn group {} to {} on map {}. Blocked.", groupId, state ? "active" : "inactive", GetId());
2478 return;
2479 }
2480 if (state != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN)) // toggled
2481 _toggledSpawnGroupIds.insert(groupId);
2482 else
2483 _toggledSpawnGroupIds.erase(groupId);
2484}
2485
2487{
2488 SpawnGroupTemplateData const* const data = GetSpawnGroupData(groupId);
2489 if (!data)
2490 {
2491 TC_LOG_ERROR("maps", "Tried to query state of non-existing spawn group {} on map {}.", groupId, GetId());
2492 return false;
2493 }
2494 if (data->flags & SPAWNGROUP_FLAG_SYSTEM)
2495 return true;
2496 // either manual spawn group and toggled, or not manual spawn group and not toggled...
2497 return (_toggledSpawnGroupIds.find(groupId) != _toggledSpawnGroupIds.end()) != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN);
2498}
2499
2501{
2502 std::vector<uint32> const* spawnGroups = sObjectMgr->GetSpawnGroupsForMap(GetId());
2503 if (!spawnGroups)
2504 return;
2505
2506 for (uint32 spawnGroupId : *spawnGroups)
2507 {
2508 SpawnGroupTemplateData const* spawnGroupTemplate = ASSERT_NOTNULL(GetSpawnGroupData(spawnGroupId));
2509 if (spawnGroupTemplate->flags & (SPAWNGROUP_FLAG_SYSTEM | SPAWNGROUP_FLAG_MANUAL_SPAWN))
2510 continue;
2511
2512 SetSpawnGroupActive(spawnGroupId, sConditionMgr->IsMapMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPAWN_GROUP, spawnGroupId, this));
2513 }
2514}
2515
2517{
2518 std::vector<uint32> const* spawnGroups = sObjectMgr->GetSpawnGroupsForMap(GetId());
2519 if (!spawnGroups)
2520 return;
2521
2522 for (uint32 spawnGroupId : *spawnGroups)
2523 {
2524 SpawnGroupTemplateData const* spawnGroupTemplate = ASSERT_NOTNULL(GetSpawnGroupData(spawnGroupId));
2525
2526 bool isActive = IsSpawnGroupActive(spawnGroupId);
2527 bool shouldBeActive = sConditionMgr->IsMapMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_SPAWN_GROUP, spawnGroupId, this);
2528
2529 if (spawnGroupTemplate->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN)
2530 {
2531 // Only despawn the group if it isn't meeting conditions
2532 if (isActive && !shouldBeActive && spawnGroupTemplate->flags & SPAWNGROUP_FLAG_DESPAWN_ON_CONDITION_FAILURE)
2533 SpawnGroupDespawn(spawnGroupId, true);
2534
2535 continue;
2536 }
2537
2538 if (isActive == shouldBeActive)
2539 continue;
2540
2541 if (shouldBeActive)
2542 SpawnGroupSpawn(spawnGroupId);
2543 else if (spawnGroupTemplate->flags & SPAWNGROUP_FLAG_DESPAWN_ON_CONDITION_FAILURE)
2544 SpawnGroupDespawn(spawnGroupId, true);
2545 else
2546 SetSpawnGroupInactive(spawnGroupId);
2547 }
2548}
2549
2551{
2552 return _guidGenerators.try_emplace(high, high).first->second;
2553}
2554
2556{
2557 _farSpellCallbacks.Enqueue(new FarSpellCallback(std::move(callback)));
2558}
2559
2561{
2562 {
2563 FarSpellCallback* callback;
2564 while (_farSpellCallbacks.Dequeue(callback))
2565 {
2566 (*callback)(this);
2567 delete callback;
2568 }
2569 }
2570
2572
2573 // 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 !
2574 // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended
2575 if (!IsBattlegroundOrArena())
2576 {
2578 {
2579 NGridType *grid = i->GetSource();
2580 GridInfo* info = i->GetSource()->getGridInfoRef();
2581 ++i; // The update might delete the map and we need the next map before the iterator gets invalid
2582 ASSERT(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE);
2583 si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, t_diff);
2584 }
2585 }
2586}
2587
2589{
2590 ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2591
2592 obj->SetDestroyedObject(true);
2593 obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links
2594
2595 i_objectsToRemove.insert(obj);
2596}
2597
2599{
2600 ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId());
2601 // i_objectsToSwitch is iterated only in Map::RemoveAllObjectsInRemoveList() and it uses
2602 // the contained objects only if GetTypeId() == TYPEID_UNIT , so we can return in all other cases
2603 if (obj->GetTypeId() != TYPEID_UNIT)
2604 return;
2605
2606 std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.find(obj);
2607 if (itr == i_objectsToSwitch.end())
2608 i_objectsToSwitch.insert(itr, std::make_pair(obj, on));
2609 else if (itr->second != on)
2610 i_objectsToSwitch.erase(itr);
2611 else
2612 ABORT();
2613}
2614
2616{
2617 while (!i_objectsToSwitch.empty())
2618 {
2619 std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.begin();
2620 WorldObject* obj = itr->first;
2621 bool on = itr->second;
2622 i_objectsToSwitch.erase(itr);
2623
2625 {
2626 switch (obj->GetTypeId())
2627 {
2628 case TYPEID_UNIT:
2629 SwitchGridContainers<Creature>(obj->ToCreature(), on);
2630 break;
2631 default:
2632 break;
2633 }
2634 }
2635 }
2636
2637 //TC_LOG_DEBUG("maps", "Object remover 1 check.");
2638 while (!i_objectsToRemove.empty())
2639 {
2640 std::set<WorldObject*>::iterator itr = i_objectsToRemove.begin();
2641 WorldObject* obj = *itr;
2642
2643 switch (obj->GetTypeId())
2644 {
2645 case TYPEID_CORPSE:
2646 {
2647 Corpse* corpse = ObjectAccessor::GetCorpse(*obj, obj->GetGUID());
2648 if (!corpse)
2649 TC_LOG_ERROR("maps", "Tried to delete corpse/bones {} that is not in map.", obj->GetGUID().ToString());
2650 else
2651 RemoveFromMap(corpse, true);
2652 break;
2653 }
2655 RemoveFromMap(obj->ToDynObject(), true);
2656 break;
2657 case TYPEID_AREATRIGGER:
2658 RemoveFromMap((AreaTrigger*)obj, true);
2659 break;
2661 RemoveFromMap((Conversation*)obj, true);
2662 break;
2663 case TYPEID_GAMEOBJECT:
2664 {
2665 GameObject* go = obj->ToGameObject();
2666 if (Transport* transport = go->ToTransport())
2667 RemoveFromMap(transport, true);
2668 else
2669 RemoveFromMap(go, true);
2670 break;
2671 }
2672 case TYPEID_UNIT:
2673 // in case triggered sequence some spell can continue casting after prev CleanupsBeforeDelete call
2674 // make sure that like sources auras/etc removed before destructor start
2676 RemoveFromMap(obj->ToCreature(), true);
2677 break;
2678 default:
2679 TC_LOG_ERROR("maps", "Non-grid object (TypeId: {}) is in grid object remove list, ignored.", obj->GetTypeId());
2680 break;
2681 }
2682
2683 i_objectsToRemove.erase(itr);
2684 }
2685
2686 //TC_LOG_DEBUG("maps", "Object remover 2 check.");
2687}
2688
2690{
2691 uint32 count = 0;
2693 if (!itr->GetSource()->IsGameMaster())
2694 ++count;
2695 return count;
2696}
2697
2698void Map::SendToPlayers(WorldPacket const* data) const
2699{
2701 itr->GetSource()->SendDirectMessage(data);
2702}
2703
2705bool Map::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession const* self, Optional<Team> team) const
2706{
2707 bool foundPlayerToSend = false;
2708
2709 for (MapReference const& ref : GetPlayers())
2710 {
2711 Player* player = ref.GetSource();
2712 if (player->IsInWorld() &&
2713 player->GetZoneId() == zone &&
2714 player->GetSession() != self &&
2715 (!team || player->GetTeam() == *team))
2716 {
2717 player->SendDirectMessage(packet);
2718 foundPlayerToSend = true;
2719 }
2720 }
2721
2722 return foundPlayerToSend;
2723}
2724
2726{
2727 CellCoord cell_min(ngrid.getX() * MAX_NUMBER_OF_CELLS, ngrid.getY() * MAX_NUMBER_OF_CELLS);
2728 CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
2729
2730 //we must find visible range in cells so we unload only non-visible cells...
2731 float viewDist = GetVisibilityRange();
2732 int cell_range = (int)ceilf(viewDist / SIZE_OF_GRID_CELL) + 1;
2733
2734 cell_min.dec_x(cell_range);
2735 cell_min.dec_y(cell_range);
2736 cell_max.inc_x(cell_range);
2737 cell_max.inc_y(cell_range);
2738
2740 {
2741 Player* player = iter->GetSource();
2742
2744 if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2745 (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2746 return true;
2747 }
2748
2749 for (ActiveNonPlayers::const_iterator iter = m_activeNonPlayers.begin(); iter != m_activeNonPlayers.end(); ++iter)
2750 {
2751 WorldObject* obj = *iter;
2752
2754 if ((cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
2755 (cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord))
2756 return true;
2757 }
2758
2759 return false;
2760}
2761
2763{
2764 i_worldObjects.insert(obj);
2765}
2766
2768{
2769 i_worldObjects.erase(obj);
2770}
2771
2773{
2774 m_activeNonPlayers.insert(obj);
2775
2776 Optional<Position> respawnLocation;
2777 switch (obj->GetTypeId())
2778 {
2779 case TYPEID_UNIT:
2780 if (Creature* creature = obj->ToCreature(); !creature->IsPet() && creature->GetSpawnId())
2781 respawnLocation = creature->GetRespawnPosition();
2782 break;
2783 case TYPEID_GAMEOBJECT:
2784 if (GameObject* gameObject = obj->ToGameObject(); gameObject->GetSpawnId())
2785 respawnLocation = gameObject->GetRespawnPosition();
2786 break;
2787 default:
2788 break;
2789 }
2790
2791 if (respawnLocation)
2792 {
2793 GridCoord p = Trinity::ComputeGridCoord(respawnLocation->GetPositionX(), respawnLocation->GetPositionY());
2794 if (getNGrid(p.x_coord, p.y_coord))
2796 else
2797 {
2799 TC_LOG_ERROR("maps", "Active object {} added to grid[{}, {}] but spawn grid[{}, {}] was not loaded.",
2800 obj->GetGUID().ToString(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2801 }
2802 }
2803}
2804
2806{
2807 // Map::Update for active object in proccess
2809 {
2810 ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj);
2811 if (itr != m_activeNonPlayers.end())
2812 {
2813 if (itr == m_activeNonPlayersIter)
2815 m_activeNonPlayers.erase(itr);
2816 }
2817 }
2818 else
2819 m_activeNonPlayers.erase(obj);
2820
2821 Optional<Position> respawnLocation;
2822 switch (obj->GetTypeId())
2823 {
2824 case TYPEID_UNIT:
2825 if (Creature* creature = obj->ToCreature(); !creature->IsPet() && creature->GetSpawnId())
2826 respawnLocation = creature->GetRespawnPosition();
2827 break;
2828 case TYPEID_GAMEOBJECT:
2829 if (GameObject* gameObject = obj->ToGameObject(); gameObject->GetSpawnId())
2830 respawnLocation = gameObject->GetRespawnPosition();
2831 break;
2832 default:
2833 break;
2834 }
2835
2836 if (respawnLocation)
2837 {
2838 GridCoord p = Trinity::ComputeGridCoord(respawnLocation->GetPositionX(), respawnLocation->GetPositionY());
2839 if (getNGrid(p.x_coord, p.y_coord))
2841 else
2842 {
2844 TC_LOG_ERROR("maps", "Active object {} removed from to grid[{}, {}] but spawn grid[{}, {}] was not loaded.",
2845 obj->GetGUID().ToString(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
2846 }
2847 }
2848}
2849
2850template TC_GAME_API bool Map::AddToMap(Corpse*);
2851template TC_GAME_API bool Map::AddToMap(Creature*);
2852template TC_GAME_API bool Map::AddToMap(GameObject*);
2854template TC_GAME_API bool Map::AddToMap(AreaTrigger*);
2855template TC_GAME_API bool Map::AddToMap(SceneObject*);
2856template TC_GAME_API bool Map::AddToMap(Conversation*);
2857
2858template TC_GAME_API void Map::RemoveFromMap(Corpse*, bool);
2859template TC_GAME_API void Map::RemoveFromMap(Creature*, bool);
2860template TC_GAME_API void Map::RemoveFromMap(GameObject*, bool);
2861template TC_GAME_API void Map::RemoveFromMap(DynamicObject*, bool);
2862template TC_GAME_API void Map::RemoveFromMap(AreaTrigger*, bool);
2863template TC_GAME_API void Map::RemoveFromMap(SceneObject*, bool);
2864template TC_GAME_API void Map::RemoveFromMap(Conversation*, bool);
2865
2866/* ******* Dungeon Instance Maps ******* */
2867
2868InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, Difficulty SpawnMode, TeamId InstanceTeam, InstanceLock* instanceLock,
2869 Optional<uint32> lfgDungeonsId)
2870 : Map(id, expiry, InstanceId, SpawnMode),
2871 i_data(nullptr), i_script_id(0), i_instanceLock(instanceLock), i_lfgDungeonsId(lfgDungeonsId)
2872{
2873 //lets initialize visibility distance for dungeons
2875
2876 // the timer is started by default, and stopped when the first player joins
2877 // this make sure it gets unloaded if for some reason no player joins
2879
2881 WorldStateMgr::SetValue(WS_TEAM_IN_INSTANCE_HORDE, InstanceTeam == TEAM_HORDE, false, this);
2882
2883 if (i_instanceLock)
2884 {
2885 i_instanceLock->SetInUse(true);
2886 i_instanceExpireEvent = i_instanceLock->GetExpiryTime(); // ignore extension state for reset event (will ask players to accept extended save on expiration)
2887 }
2888}
2889
2891{
2892 if (i_instanceLock)
2893 i_instanceLock->SetInUse(false);
2894
2895 delete i_data;
2896}
2897
2899{
2900 //init visibility distance for instances
2903}
2904
2905/*
2906 Do map specific checks to see if the player can enter
2907*/
2909{
2910 if (player->GetMapRef().getTarget() == this)
2911 {
2912 TC_LOG_ERROR("maps", "InstanceMap::CannotEnter - player {} {} already in map {}, {}, {}!", player->GetName(), player->GetGUID().ToString(), GetId(), GetInstanceId(), GetDifficultyID());
2913 ABORT();
2914 return TRANSFER_ABORT_ERROR;
2915 }
2916
2917 // allow GM's to enter
2918 if (player->IsGameMaster())
2919 return Map::CannotEnter(player);
2920
2921 // cannot enter if the instance is full (player cap), GMs don't count
2922 uint32 maxPlayers = GetMaxPlayers();
2923 if (GetPlayersCountExceptGMs() >= maxPlayers)
2924 {
2925 TC_LOG_WARN("maps", "MAP: Instance '{}' of map '{}' cannot have more than '{}' players. Player '{}' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName());
2927 }
2928
2929 // cannot enter while an encounter is in progress (unless this is a relog, in which case it is permitted)
2930 if (!player->IsLoading() && IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress())
2932
2933 if (i_instanceLock)
2934 {
2935 // cannot enter if player is permanent saved to a different instance id
2936 TransferAbortReason lockError = sInstanceLockMgr.CanJoinInstanceLock(player->GetGUID(), { GetEntry(), GetMapDifficulty() }, i_instanceLock);
2937 if (lockError != TRANSFER_ABORT_NONE)
2938 return lockError;
2939 }
2940
2941 if (Group* owningGroup = GetOwningGroup())
2942 if (!player->IsInGroup(owningGroup->GetGUID()))
2944
2945 return Map::CannotEnter(player);
2946}
2947
2948/*
2949 Do map specific checks and add the player to the map if successful.
2950*/
2951bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
2952{
2953 // increase current instances (hourly limit)
2955
2956 MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
2957 if (entries.MapDifficulty->HasResetSchedule() && i_instanceLock && !i_instanceLock->IsNew() && i_data)
2958 {
2959 if (!entries.MapDifficulty->IsUsingEncounterLocks())
2960 {
2961 InstanceLock const* playerLock = sInstanceLockMgr.FindActiveInstanceLock(player->GetGUID(), entries);
2962 if (!playerLock || (playerLock->IsExpired() && playerLock->IsExtended()) ||
2964 {
2966 pendingRaidLock.TimeUntilLock = 60000;
2968 pendingRaidLock.Extending = playerLock && playerLock->IsExtended();
2969 pendingRaidLock.WarningOnly = entries.Map->IsFlexLocking(); // events it triggers: 1 : INSTANCE_LOCK_WARNING 0 : INSTANCE_LOCK_STOP / INSTANCE_LOCK_START
2970 player->GetSession()->SendPacket(pendingRaidLock.Write());
2971 if (!entries.Map->IsFlexLocking())
2972 player->SetPendingBind(GetInstanceId(), 60000);
2973 }
2974 }
2975 }
2976
2977 TC_LOG_DEBUG("maps", "MAP: Player '{}' entered instance '{}' of map '{}'", player->GetName(), GetInstanceId(), GetMapName());
2978 // initialize unload state
2979 m_unloadTimer = 0;
2980
2981 // this will acquire the same mutex so it cannot be in the previous block
2982 Map::AddPlayerToMap(player, initPlayer);
2983
2984 if (i_data)
2985 i_data->OnPlayerEnter(player);
2986
2987 if (i_scenario)
2988 i_scenario->OnPlayerEnter(player);
2989
2990 return true;
2991}
2992
2994{
2995 Map::Update(t_diff);
2996
2997 if (i_data)
2998 {
2999 i_data->Update(t_diff);
3001 }
3002
3003 if (i_scenario)
3004 i_scenario->Update(t_diff);
3005
3007 {
3010 }
3011}
3012
3014{
3015 TC_LOG_DEBUG("maps", "MAP: Removing player '{}' from instance '{}' of map '{}' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName());
3016
3017 if (i_data)
3018 i_data->OnPlayerLeave(player);
3019
3020 // if last player set unload timer
3021 if (!m_unloadTimer && m_mapRefManager.size() == 1)
3023
3024 if (i_scenario)
3025 i_scenario->OnPlayerExit(player);
3026
3027 Map::RemovePlayerFromMap(player, remove);
3028}
3029
3031{
3032 if (i_data != nullptr)
3033 return;
3034
3035 InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(GetId());
3036 if (mInstance)
3037 {
3038 i_script_id = mInstance->ScriptId;
3039 i_data = sScriptMgr->CreateInstanceData(this);
3040 }
3041
3042 if (!i_data)
3043 return;
3044
3046 {
3047 i_data->Create();
3048 return;
3049 }
3050
3051 MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
3052 if (!entries.IsInstanceIdBound() && !IsRaid() && !entries.MapDifficulty->IsRestoringDungeonState() && i_owningGroupRef.isValid())
3053 {
3054 i_data->Create();
3055 return;
3056 }
3057
3060 if (!lockData->Data.empty())
3061 {
3062 TC_LOG_DEBUG("maps", "Loading instance data for `{}` with id {}", sObjectMgr->GetScriptName(i_script_id), i_InstanceId);
3063 i_data->Load(lockData->Data.c_str());
3064 }
3065 else
3066 i_data->Create();
3067}
3068
3070{
3072 i_owningGroupRef.link(group, this);
3073}
3074
3075/*
3076 Returns true if there are no players in the instance
3077*/
3079{
3080 // raids can be reset if no boss was killed
3083
3084 if (HavePlayers())
3085 {
3086 switch (method)
3087 {
3089 // notify the players to leave the instance so it can be reset
3090 for (MapReference const& ref : m_mapRefManager)
3091 ref.GetSource()->SendResetFailedNotify(GetId());
3092 break;
3094 // no client notification
3095 break;
3097 {
3099 raidInstanceMessage.Type = RAID_INSTANCE_EXPIRED;
3100 raidInstanceMessage.MapID = GetId();
3101 raidInstanceMessage.DifficultyID = GetDifficultyID();
3102 raidInstanceMessage.Write();
3103
3104 for (MapReference const& ref : m_mapRefManager)
3105 ref.GetSource()->SendDirectMessage(raidInstanceMessage.GetRawPacket());
3106
3107 if (i_data)
3108 {
3110 pendingRaidLock.TimeUntilLock = 60000;
3112 pendingRaidLock.Extending = true;
3113 pendingRaidLock.WarningOnly = GetEntry()->IsFlexLocking();
3114 pendingRaidLock.Write();
3115
3116 for (MapReference const& ref : m_mapRefManager)
3117 {
3118 ref.GetSource()->SendDirectMessage(pendingRaidLock.GetRawPacket());
3119
3120 if (!pendingRaidLock.WarningOnly)
3121 ref.GetSource()->SetPendingBind(GetInstanceId(), 60000);
3122 }
3123 }
3124 break;
3125 }
3126 default:
3127 break;
3128 }
3129
3131 }
3132 else
3133 {
3134 // unloaded at next update
3136 }
3137
3139}
3140
3141std::string const& InstanceMap::GetScriptName() const
3142{
3143 return sObjectMgr->GetScriptName(i_script_id);
3144}
3145
3147{
3148 i_scenario.reset(); // sends exit packets to all players
3149
3150 if (scenario)
3151 {
3152 i_scenario.reset(scenario);
3153
3154 scenario->LoadInstanceData();
3155
3156 DoOnPlayers([scenario](Player* player)
3157 {
3158 scenario->OnPlayerEnter(player);
3159 });
3160 }
3161}
3162
3164{
3165 if (i_instanceLock)
3166 {
3167 uint32 instanceCompletedEncounters = i_instanceLock->GetData()->CompletedEncountersMask | (1u << updateSaveDataEvent.DungeonEncounter->Bit);
3168
3169 MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
3170
3171 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
3172
3173 if (entries.IsInstanceIdBound())
3174 sInstanceLockMgr.UpdateSharedInstanceLock(trans, InstanceLockUpdateEvent(GetInstanceId(), i_data->GetSaveData(),
3175 instanceCompletedEncounters, updateSaveDataEvent.DungeonEncounter, i_data->GetEntranceLocationForCompletedEncounters(instanceCompletedEncounters)));
3176
3177 for (MapReference& mapReference : m_mapRefManager)
3178 {
3179 Player* player = mapReference.GetSource();
3180 // never instance bind GMs with GM mode enabled
3181 if (player->IsGameMaster())
3182 continue;
3183
3184 InstanceLock const* playerLock = sInstanceLockMgr.FindActiveInstanceLock(player->GetGUID(), entries);
3185 std::string const* oldData = nullptr;
3186 uint32 playerCompletedEncounters = 0;
3187 if (playerLock)
3188 {
3189 oldData = &playerLock->GetData()->Data;
3190 playerCompletedEncounters = playerLock->GetData()->CompletedEncountersMask | (1u << updateSaveDataEvent.DungeonEncounter->Bit);
3191 }
3192
3193 bool isNewLock = !playerLock || playerLock->IsNew() || playerLock->IsExpired();
3194
3195 InstanceLock const* newLock = sInstanceLockMgr.UpdateInstanceLockForPlayer(trans, player->GetGUID(), entries,
3196 InstanceLockUpdateEvent(GetInstanceId(), i_data->UpdateBossStateSaveData(oldData ? *oldData : "", updateSaveDataEvent),
3197 instanceCompletedEncounters, updateSaveDataEvent.DungeonEncounter, i_data->GetEntranceLocationForCompletedEncounters(playerCompletedEncounters)));
3198
3199 if (isNewLock)
3200 {
3202 data.Gm = player->IsGameMaster();
3203 player->SendDirectMessage(data.Write());
3204
3205 player->GetSession()->SendCalendarRaidLockoutAdded(newLock);
3206 }
3207 }
3208
3209 CharacterDatabase.CommitTransaction(trans);
3210 }
3211}
3212
3214{
3215 if (i_instanceLock)
3216 {
3217 uint32 instanceCompletedEncounters = i_instanceLock->GetData()->CompletedEncountersMask;
3218
3219 MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
3220
3221 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
3222
3223 if (entries.IsInstanceIdBound())
3224 sInstanceLockMgr.UpdateSharedInstanceLock(trans, InstanceLockUpdateEvent(GetInstanceId(), i_data->GetSaveData(),
3225 instanceCompletedEncounters, nullptr, {}));
3226
3227 for (MapReference& mapReference : m_mapRefManager)
3228 {
3229 Player* player = mapReference.GetSource();
3230 // never instance bind GMs with GM mode enabled
3231 if (player->IsGameMaster())
3232 continue;
3233
3234 InstanceLock const* playerLock = sInstanceLockMgr.FindActiveInstanceLock(player->GetGUID(), entries);
3235 std::string const* oldData = nullptr;
3236 if (playerLock)
3237 oldData = &playerLock->GetData()->Data;
3238
3239 bool isNewLock = !playerLock || playerLock->IsNew() || playerLock->IsExpired();
3240
3241 InstanceLock const* newLock = sInstanceLockMgr.UpdateInstanceLockForPlayer(trans, player->GetGUID(), entries,
3242 InstanceLockUpdateEvent(GetInstanceId(), i_data->UpdateAdditionalSaveData(oldData ? *oldData : "", updateSaveDataEvent),
3243 instanceCompletedEncounters, nullptr, {}));
3244
3245 if (isNewLock)
3246 {
3248 data.Gm = player->IsGameMaster();
3249 player->SendDirectMessage(data.Write());
3250
3251 player->GetSession()->SendCalendarRaidLockoutAdded(newLock);
3252 }
3253 }
3254
3255 CharacterDatabase.CommitTransaction(trans);
3256 }
3257}
3258
3260{
3261 MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
3262 InstanceLock const* playerLock = sInstanceLockMgr.FindActiveInstanceLock(player->GetGUID(), entries);
3263
3264 bool isNewLock = !playerLock || playerLock->IsNew() || playerLock->IsExpired();
3265
3266 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
3267
3268 InstanceLock const* newLock = sInstanceLockMgr.UpdateInstanceLockForPlayer(trans, player->GetGUID(), entries,
3270
3271 CharacterDatabase.CommitTransaction(trans);
3272
3273 if (isNewLock)
3274 {
3276 data.Gm = player->IsGameMaster();
3277 player->SendDirectMessage(data.Write());
3278
3279 player->GetSession()->SendCalendarRaidLockoutAdded(newLock);
3280 }
3281}
3282
3284{
3285 return sDB2Manager.GetMapDifficultyData(GetId(), GetDifficultyID());
3286}
3287
3289{
3290 return i_mapEntry->ID;
3291}
3292
3294{
3295 return i_mapEntry && i_mapEntry->Instanceable();
3296}
3297
3299{
3300 return i_mapEntry && i_mapEntry->IsWorldMap();
3301}
3302
3303bool Map::IsDungeon() const
3304{
3305 return i_mapEntry && i_mapEntry->IsDungeon();
3306}
3307
3309{
3311}
3312
3313bool Map::IsRaid() const
3314{
3315 return i_mapEntry && i_mapEntry->IsRaid();
3316}
3317
3318bool Map::IsLFR() const
3319{
3320 switch (i_spawnMode)
3321 {
3322 case DIFFICULTY_LFR:
3323 case DIFFICULTY_LFR_NEW:
3325 return true;
3326 default:
3327 return false;
3328 }
3329}
3330
3331bool Map::IsNormal() const
3332{
3333 switch (i_spawnMode)
3334 {
3335 case DIFFICULTY_NORMAL:
3336 case DIFFICULTY_10_N:
3337 case DIFFICULTY_25_N:
3341 return true;
3342 default:
3343 return false;
3344 }
3345}
3346
3347bool Map::IsHeroic() const
3348{
3349 if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(i_spawnMode))
3350 {
3351 if (difficulty->Flags & DIFFICULTY_FLAG_DISPLAY_HEROIC)
3352 return true;
3353 }
3354
3355 // compatibility purposes of old difficulties
3356 switch (i_spawnMode)
3357 {
3358 case DIFFICULTY_10_HC:
3359 case DIFFICULTY_25_HC:
3360 case DIFFICULTY_HEROIC:
3362 return true;
3363 default:
3364 return false;
3365 }
3366}
3367
3368bool Map::IsMythic() const
3369{
3370 if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(i_spawnMode))
3371 return difficulty->Flags & DIFFICULTY_FLAG_DISPLAY_MYTHIC;
3372 return false;
3373}
3374
3376{
3378}
3379
3381{
3382 return IsHeroic() || IsMythic() || IsMythicPlus();
3383}
3384
3386{
3388}
3389
3394
3396{
3398}
3399
3401{
3402 return i_mapEntry && i_mapEntry->IsBattleArena();
3403}
3404
3406{
3408}
3409
3411{
3412 return i_mapEntry && i_mapEntry->IsScenario();
3413}
3414
3416{
3417 return i_mapEntry && i_mapEntry->IsGarrison();
3418}
3419
3421{
3422 return IsBattlegroundOrArena();
3423}
3424
3425bool Map::GetEntrancePos(int32 &mapid, float &x, float &y)
3426{
3427 if (!i_mapEntry)
3428 return false;
3429 return i_mapEntry->GetEntrancePos(mapid, x, y);
3430}
3431
3433{
3434 MapDifficultyEntry const* mapDiff = GetMapDifficulty();
3435 if (mapDiff && mapDiff->MaxPlayers)
3436 return mapDiff->MaxPlayers;
3437
3438 return GetEntry()->MaxPlayers;
3439}
3440
3449
3450/* ******* Battleground Instance Maps ******* */
3451
3452BattlegroundMap::BattlegroundMap(uint32 id, time_t expiry, uint32 InstanceId, Difficulty spawnMode)
3453 : Map(id, expiry, InstanceId, spawnMode), m_bg(nullptr), _battlegroundScript(nullptr), _scriptId(0)
3454{
3455 //lets initialize visibility distance for BG/Arenas
3457}
3458
3460{
3461 if (m_bg)
3462 {
3463 //unlink to prevent crash, always unlink all pointer reference before destruction
3464 m_bg->SetBgMap(nullptr);
3465 m_bg = nullptr;
3466 }
3467}
3468
3475
3476std::string const& BattlegroundMap::GetScriptName() const
3477{
3478 return sObjectMgr->GetScriptName(_scriptId);
3479}
3480
3482{
3484 return;
3485
3486 ASSERT(GetBG(), "Battleground not set yet!");
3487
3488 if (BattlegroundScriptTemplate const* scriptTemplate = sBattlegroundMgr->FindBattlegroundScriptTemplate(GetId(), GetBG()->GetTypeID()))
3489 {
3490 _scriptId = scriptTemplate->ScriptId;
3491 _battlegroundScript.reset(sScriptMgr->CreateBattlegroundData(this));
3492 }
3493
3494 // Make sure every battleground has a default script
3496 {
3497 if (IsBattleArena())
3498 _battlegroundScript = std::make_unique<ArenaScript>(this);
3499 else
3500 _battlegroundScript = std::make_unique<BattlegroundScript>(this);
3501 }
3502}
3503
3505{
3506 if (player->GetMapRef().getTarget() == this)
3507 {
3508 TC_LOG_ERROR("maps", "BGMap::CannotEnter - player {} is already in map!", player->GetGUID().ToString());
3509 ABORT();
3510 return TRANSFER_ABORT_ERROR;
3511 }
3512
3513 if (player->GetBattlegroundId() != GetInstanceId())
3515
3516 // player number limit is checked in bgmgr, no need to do it here
3517
3518 return Map::CannotEnter(player);
3519}
3520
3521bool BattlegroundMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
3522{
3523 player->m_InstanceValid = true;
3524 return Map::AddPlayerToMap(player, initPlayer);
3525}
3526
3528{
3529 TC_LOG_DEBUG("maps", "MAP: Removing player '{}' from bg '{}' of map '{}' before relocating to another map", player->GetName(), GetInstanceId(), GetMapName());
3530 Map::RemovePlayerFromMap(player, remove);
3531}
3532
3537
3539{
3540 if (HavePlayers())
3541 for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
3542 if (Player* player = itr->GetSource())
3543 if (!player->IsBeingTeleportedFar())
3544 player->TeleportTo(player->GetBattlegroundEntryPoint());
3545}
3546
3548{
3549 Map::Update(diff);
3550 _battlegroundScript->OnUpdate(diff);
3551}
3552
3554{
3555 return _objectsStore.Find<AreaTrigger>(guid);
3556}
3557
3559{
3560 return _objectsStore.Find<SceneObject>(guid);
3561}
3562
3564{
3565 return _objectsStore.Find<Conversation>(guid);
3566}
3567
3569{
3570 return ObjectAccessor::GetPlayer(this, guid);
3571}
3572
3574{
3575 return _objectsStore.Find<Corpse>(guid);
3576}
3577
3579{
3580 return _objectsStore.Find<Creature>(guid);
3581}
3582
3587
3589{
3590 return _objectsStore.Find<GameObject>(guid);
3591}
3592
3594{
3595 return _objectsStore.Find<Pet>(guid);
3596}
3597
3599{
3600 if (!guid.IsMOTransport())
3601 return nullptr;
3602
3603 GameObject* go = GetGameObject(guid);
3604 return go ? go->ToTransport() : nullptr;
3605}
3606
3608{
3609 auto const bounds = GetCreatureBySpawnIdStore().equal_range(spawnId);
3610 if (bounds.first == bounds.second)
3611 return nullptr;
3612
3613 std::unordered_multimap<ObjectGuid::LowType, Creature*>::const_iterator creatureItr = std::find_if(bounds.first, bounds.second, [](Map::CreatureBySpawnIdContainer::value_type const& pair)
3614 {
3615 return pair.second->IsAlive();
3616 });
3617
3618 return creatureItr != bounds.second ? creatureItr->second : bounds.first->second;
3619}
3620
3622{
3623 auto const bounds = GetGameObjectBySpawnIdStore().equal_range(spawnId);
3624 if (bounds.first == bounds.second)
3625 return nullptr;
3626
3627 std::unordered_multimap<ObjectGuid::LowType, GameObject*>::const_iterator creatureItr = std::find_if(bounds.first, bounds.second, [](Map::GameObjectBySpawnIdContainer::value_type const& pair)
3628 {
3629 return pair.second->isSpawned();
3630 });
3631
3632 return creatureItr != bounds.second ? creatureItr->second : bounds.first->second;
3633}
3634
3636{
3637 auto const bounds = GetAreaTriggerBySpawnIdStore().equal_range(spawnId);
3638 if (bounds.first == bounds.second)
3639 return nullptr;
3640
3641 return bounds.first->second;
3642}
3643
3645{
3646 if (&*m_mapRefIter == &player->GetMapRef())
3647 --m_mapRefIter;
3648}
3649
3650void Map::SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, CharacterDatabaseTransaction dbTrans, bool startup)
3651{
3652 SpawnMetadata const* data = sObjectMgr->GetSpawnMetadata(type, spawnId);
3653 if (!data)
3654 {
3655 TC_LOG_ERROR("maps", "Map {} attempt to save respawn time for nonexistant spawnid ({},{}).", GetId(), type, spawnId);
3656 return;
3657 }
3658
3659 if (!respawnTime)
3660 {
3661 // Delete only
3662 RemoveRespawnTime(data->type, data->spawnId, dbTrans);
3663 return;
3664 }
3665
3666 RespawnInfo ri;
3667 ri.type = data->type;
3668 ri.spawnId = data->spawnId;
3669 ri.entry = entry;
3670 ri.respawnTime = respawnTime;
3671 ri.gridId = gridId;
3672 bool success = AddRespawnInfo(ri);
3673
3674 if (startup)
3675 {
3676 if (!success)
3677 TC_LOG_ERROR("maps", "Attempt to load saved respawn {} for ({},{}) failed - duplicate respawn? Skipped.", respawnTime, uint32(type), spawnId);
3678 }
3679 else if (success)
3680 SaveRespawnInfoDB(ri, dbTrans);
3681}
3682
3684{
3685 if (Instanceable())
3686 return;
3687
3689 stmt->setUInt16(0, info.type);
3690 stmt->setUInt64(1, info.spawnId);
3691 stmt->setInt64(2, info.respawnTime);
3692 stmt->setUInt16(3, GetId());
3693 stmt->setUInt32(4, GetInstanceId());
3694 CharacterDatabase.ExecuteOrAppend(dbTrans, stmt);
3695}
3696
3698{
3699 if (Instanceable())
3700 return;
3701
3703 stmt->setUInt16(0, GetId());
3704 stmt->setUInt32(1, GetInstanceId());
3705 if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
3706 {
3707 do
3708 {
3709 Field* fields = result->Fetch();
3710 SpawnObjectType type = SpawnObjectType(fields[0].GetUInt16());
3711 ObjectGuid::LowType spawnId = fields[1].GetUInt64();
3712 time_t respawnTime = fields[2].GetInt64();
3713
3714 if (SpawnData::TypeHasData(type))
3715 {
3716 if (SpawnData const* data = sObjectMgr->GetSpawnData(type, spawnId))
3717 SaveRespawnTime(type, spawnId, data->id, time_t(respawnTime), Trinity::ComputeGridCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()).GetId(), nullptr, true);
3718 else
3719 TC_LOG_ERROR("maps", "Loading saved respawn time of {} for spawnid ({},{}) - spawn does not exist, ignoring", respawnTime, uint32(type), spawnId);
3720 }
3721 else
3722 {
3723 TC_LOG_ERROR("maps", "Loading saved respawn time of {} for spawnid ({},{}) - invalid spawn type, ignoring", respawnTime, uint32(type), spawnId);
3724 }
3725
3726 } while (result->NextRow());
3727 }
3728}
3729
3731{
3732 if (Instanceable())
3733 return;
3734
3736 stmt->setUInt16(0, GetId());
3737 stmt->setUInt32(1, GetInstanceId());
3738 CharacterDatabase.Execute(stmt);
3739}
3740
3742{
3743 ObjectGuid linkedGuid = sObjectMgr->GetLinkedRespawnGuid(guid);
3744 switch (linkedGuid.GetHigh())
3745 {
3746 case HighGuid::Creature:
3747 return GetCreatureRespawnTime(linkedGuid.GetCounter());
3749 return GetGORespawnTime(linkedGuid.GetCounter());
3750 default:
3751 break;
3752 }
3753
3754 return time_t(0);
3755}
3756
3758{
3760 stmt->setUInt32(0, GetId());
3761 stmt->setUInt32(1, GetInstanceId());
3762
3763 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
3764 // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, race, class, gender, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ?
3765 PreparedQueryResult result = CharacterDatabase.Query(stmt);
3766 if (!result)
3767 return;
3768
3769 std::unordered_map<ObjectGuid::LowType, std::unordered_set<uint32>> phases;
3770 std::unordered_map<ObjectGuid::LowType, std::vector<UF::ChrCustomizationChoice>> customizations;
3771
3772 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_PHASES);
3773 stmt->setUInt32(0, GetId());
3774 stmt->setUInt32(1, GetInstanceId());
3775
3776 // 0 1
3777 // SELECT OwnerGuid, PhaseId FROM corpse_phases cp LEFT JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ?
3778 if (PreparedQueryResult phaseResult = CharacterDatabase.Query(stmt))
3779 {
3780 do
3781 {
3782 Field* fields = phaseResult->Fetch();
3783 ObjectGuid::LowType guid = fields[0].GetUInt64();
3784 uint32 phaseId = fields[1].GetUInt32();
3785
3786 phases[guid].insert(phaseId);
3787
3788 } while (phaseResult->NextRow());
3789 }
3790
3791 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_CUSTOMIZATIONS);
3792 stmt->setUInt32(0, GetId());
3793 stmt->setUInt32(1, GetInstanceId());
3794
3795 // 0 1 2
3796 // SELECT cc.ownerGuid, cc.chrCustomizationOptionID, cc.chrCustomizationChoiceID FROM corpse_customizations cc LEFT JOIN corpse c ON cc.ownerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ?
3797 if (PreparedQueryResult customizationResult = CharacterDatabase.Query(stmt))
3798 {
3799 do
3800 {
3801 Field* fields = customizationResult->Fetch();
3802 ObjectGuid::LowType guid = fields[0].GetUInt64();
3803 std::vector<UF::ChrCustomizationChoice>& customizationsForCorpse = customizations[guid];
3804
3805 customizationsForCorpse.emplace_back();
3806 UF::ChrCustomizationChoice& choice = customizationsForCorpse.back();
3807 choice.ChrCustomizationOptionID = fields[1].GetUInt32();
3808 choice.ChrCustomizationChoiceID = fields[2].GetUInt32();
3809
3810 } while (customizationResult->NextRow());
3811 }
3812
3813 do
3814 {
3815 Field* fields = result->Fetch();
3816 CorpseType type = CorpseType(fields[13].GetUInt8());
3817 ObjectGuid::LowType guid = fields[15].GetUInt64();
3818 if (type >= MAX_CORPSE_TYPE || type == CORPSE_BONES)
3819 {
3820 TC_LOG_ERROR("misc", "Corpse (guid: {}) have wrong corpse type ({}), not loading.", guid, type);
3821 continue;
3822 }
3823
3824 Corpse* corpse = new Corpse(type);
3825 if (!corpse->LoadCorpseFromDB(GenerateLowGuid<HighGuid::Corpse>(), fields))
3826 {
3827 delete corpse;
3828 continue;
3829 }
3830
3831 for (uint32 phaseId : phases[guid])
3832 PhasingHandler::AddPhase(corpse, phaseId, false);
3833
3834 corpse->SetCustomizations(Trinity::Containers::MakeIteratorPair(customizations[guid].begin(), customizations[guid].end()));
3835
3836 AddCorpse(corpse);
3837
3838 } while (result->NextRow());
3839}
3840
3842{
3843 // DELETE cp, c FROM corpse_phases cp INNER JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ?
3845 stmt->setUInt32(0, GetId());
3846 stmt->setUInt32(1, GetInstanceId());
3847 CharacterDatabase.Execute(stmt);
3848}
3849
3851{
3852 GridCoord gridCoord = Trinity::ComputeGridCoord(corpse->GetPositionX(), corpse->GetPositionY());
3853 corpse->SetMap(this);
3854
3855 _corpsesByGrid[gridCoord.GetId()].insert(corpse);
3856 if (corpse->GetType() != CORPSE_BONES)
3857 _corpsesByPlayer[corpse->GetOwnerGUID()] = corpse;
3858 else
3859 _corpseBones.insert(corpse);
3860}
3861
3863{
3864 GridCoord gridCoord = Trinity::ComputeGridCoord(corpse->GetPositionX(), corpse->GetPositionY());
3865 ASSERT(corpse);
3866
3868 if (corpse->IsInGrid())
3869 RemoveFromMap(corpse, false);
3870 else
3871 {
3872 corpse->RemoveFromWorld();
3873 corpse->ResetMap();
3874 }
3875
3876 _corpsesByGrid[gridCoord.GetId()].erase(corpse);
3877 if (corpse->GetType() != CORPSE_BONES)
3878 _corpsesByPlayer.erase(corpse->GetOwnerGUID());
3879 else
3880 _corpseBones.erase(corpse);
3881}
3882
3883Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= false*/)
3884{
3885 Corpse* corpse = GetCorpseByPlayer(ownerGuid);
3886 if (!corpse)
3887 return nullptr;
3888
3889 RemoveCorpse(corpse);
3890
3891 // remove corpse from DB
3892 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
3893 corpse->DeleteFromDB(trans);
3894 CharacterDatabase.CommitTransaction(trans);
3895
3896 Corpse* bones = nullptr;
3897
3898 // create the bones only if the map and the grid is loaded at the corpse's location
3899 // ignore bones creating option in case insignia
3900 if ((insignia ||
3902 !IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
3903 {
3904 // Create bones, don't change Corpse
3905 bones = new Corpse();
3906 bones->Create(corpse->GetGUID().GetCounter(), this);
3907
3909 bones->SetOwnerGUID(corpse->GetOwnerGUID());
3910 bones->SetPartyGUID(corpse->GetPartyGUID());
3911 bones->SetGuildGUID(corpse->GetGuildGUID());
3912 bones->SetDisplayId(corpse->GetDisplayId());
3913 bones->SetRace(corpse->GetRace());
3914 bones->SetSex(corpse->GetSex());
3915 bones->SetClass(corpse->GetClass());
3916 bones->SetCustomizations(corpse->GetCustomizations());
3918 bones->SetFactionTemplate(corpse->GetFactionTemplate());
3919
3920 bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
3921
3922 PhasingHandler::InheritPhaseShift(bones, corpse);
3923
3924 AddCorpse(bones);
3925
3926 bones->UpdatePositionData();
3927 bones->SetZoneScript();
3928
3929 // add bones in grid store if grid loaded where corpse placed
3930 AddToMap(bones);
3931 }
3932
3933 // all references to the corpse should be removed at this point
3934 delete corpse;
3935
3936 return bones;
3937}
3938
3940{
3941 time_t now = GameTime::GetGameTime();
3942
3943 std::vector<ObjectGuid> corpses;
3944 corpses.reserve(_corpsesByPlayer.size());
3945
3946 for (auto const& p : _corpsesByPlayer)
3947 if (p.second->IsExpired(now))
3948 corpses.push_back(p.first);
3949
3950 for (ObjectGuid const& ownerGuid : corpses)
3951 ConvertCorpseToBones(ownerGuid);
3952
3953 std::vector<Corpse*> expiredBones;
3954 for (Corpse* bones : _corpseBones)
3955 if (bones->IsExpired(now))
3956 expiredBones.push_back(bones);
3957
3958 for (Corpse* bones : expiredBones)
3959 {
3960 RemoveCorpse(bones);
3961 delete bones;
3962 }
3963}
3964
3965void Map::SendZoneDynamicInfo(uint32 zoneId, Player* player) const
3966{
3967 auto itr = _zoneDynamicInfo.find(zoneId);
3968 if (itr == _zoneDynamicInfo.end())
3969 return;
3970
3971 if (uint32 music = itr->second.MusicId)
3972 player->SendDirectMessage(WorldPackets::Misc::PlayMusic(music).Write());
3973
3974 SendZoneWeather(itr->second, player);
3975
3976 for (ZoneDynamicInfo::LightOverride const& lightOverride : itr->second.LightOverrides)
3977 {
3979 overrideLight.AreaLightID = lightOverride.AreaLightId;
3980 overrideLight.OverrideLightID = lightOverride.OverrideLightId;
3981 overrideLight.TransitionMilliseconds = lightOverride.TransitionMilliseconds;
3982 player->SendDirectMessage(overrideLight.Write());
3983 }
3984}
3985
3986void Map::SendZoneWeather(uint32 zoneId, Player* player) const
3987{
3989 {
3990 auto itr = _zoneDynamicInfo.find(zoneId);
3991 if (itr == _zoneDynamicInfo.end())
3992 return;
3993
3994 SendZoneWeather(itr->second, player);
3995 }
3996}
3997
3998void Map::SendZoneWeather(ZoneDynamicInfo const& zoneDynamicInfo, Player* player) const
3999{
4000 if (WeatherState weatherId = zoneDynamicInfo.WeatherId)
4001 {
4002 WorldPackets::Misc::Weather weather(weatherId, zoneDynamicInfo.Intensity);
4003 player->SendDirectMessage(weather.Write());
4004 }
4005 else if (zoneDynamicInfo.DefaultWeather)
4006 {
4007 zoneDynamicInfo.DefaultWeather->SendWeatherUpdateToPlayer(player);
4008 }
4009 else
4011}
4012
4014void Map::SendZoneText(uint32 zoneId, char const* text, WorldSession const* self, Optional<Team> team) const
4015{
4017 packet.Initialize(CHAT_MSG_SYSTEM, LANG_UNIVERSAL, nullptr, nullptr, text);
4018 SendZoneMessage(zoneId, packet.Write(), self, team);
4019}
4020
4021void Map::SetZoneMusic(uint32 zoneId, uint32 musicId)
4022{
4023 _zoneDynamicInfo[zoneId].MusicId = musicId;
4024
4025 WorldPackets::Misc::PlayMusic playMusic(musicId);
4026 SendZoneMessage(zoneId, WorldPackets::Misc::PlayMusic(musicId).Write());
4027}
4028
4030{
4031 WeatherData const* weatherData = WeatherMgr::GetWeatherData(zoneId);
4032 if (!weatherData)
4033 return nullptr;
4034
4035 ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
4036 if (!info.DefaultWeather)
4037 {
4038 info.DefaultWeather = std::make_unique<Weather>(this, zoneId, weatherData);
4039 info.DefaultWeather->ReGenerate();
4040 info.DefaultWeather->UpdateWeather();
4041 }
4042
4043 return info.DefaultWeather.get();
4044}
4045
4047{
4049 if (zoneDynamicInfo)
4050 {
4051 if (WeatherState weatherId = zoneDynamicInfo->WeatherId)
4052 return weatherId;
4053
4054 if (zoneDynamicInfo->DefaultWeather)
4055 return zoneDynamicInfo->DefaultWeather->GetWeatherState();
4056 }
4057
4058 return WEATHER_STATE_FINE;
4059}
4060
4061void Map::SetZoneWeather(uint32 zoneId, WeatherState weatherId, float intensity)
4062{
4063 ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
4064 info.WeatherId = weatherId;
4065 info.Intensity = intensity;
4066
4067 Map::PlayerList const& players = GetPlayers();
4068 if (!players.empty())
4069 {
4070 WorldPackets::Misc::Weather weather(weatherId, intensity);
4071 weather.Write();
4072
4073 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
4074 if (Player* player = itr->GetSource())
4075 if (player->GetZoneId() == zoneId && !player->HasAuraType(SPELL_AURA_FORCE_WEATHER))
4076 player->SendDirectMessage(weather.GetRawPacket());
4077 }
4078}
4079
4080void Map::SetZoneOverrideLight(uint32 zoneId, uint32 areaLightId, uint32 overrideLightId, Milliseconds transitionTime)
4081{
4082 ZoneDynamicInfo& info = _zoneDynamicInfo[zoneId];
4083 // client can support only one override for each light (zone independent)
4084 info.LightOverrides.erase(std::remove_if(info.LightOverrides.begin(), info.LightOverrides.end(), [areaLightId](ZoneDynamicInfo::LightOverride const& lightOverride)
4085 {
4086 return lightOverride.AreaLightId == areaLightId;
4087 }), info.LightOverrides.end());
4088
4089 // set new override (if any)
4090 if (overrideLightId)
4091 {
4092 ZoneDynamicInfo::LightOverride& lightOverride = info.LightOverrides.emplace_back();
4093 lightOverride.AreaLightId = areaLightId;
4094 lightOverride.OverrideLightId = overrideLightId;
4095 lightOverride.TransitionMilliseconds = static_cast<uint32>(transitionTime.count());
4096 }
4097
4099 overrideLight.AreaLightID = areaLightId;
4100 overrideLight.OverrideLightID = overrideLightId;
4101 overrideLight.TransitionMilliseconds = static_cast<uint32>(transitionTime.count());
4102 SendZoneMessage(zoneId, overrideLight.Write());
4103}
4104
4106{
4107 Map::PlayerList const& players = GetPlayers();
4108 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
4109 {
4110 if (Player* player = itr->GetSource())
4111 {
4112 if (player->IsInWorld())
4113 {
4114 player->UpdateAreaDependentAuras(player->GetAreaId());
4115 player->UpdateZoneDependentAuras(player->GetZoneId());
4116 }
4117 }
4118 }
4119}
4120
4121std::string Map::GetDebugInfo() const
4122{
4123 std::stringstream sstr;
4124 sstr << std::boolalpha
4125 << "Id: " << GetId() << " InstanceId: " << GetInstanceId() << " Difficulty: " << AsUnderlyingType(GetDifficultyID())
4126 << " HasPlayers: " << HavePlayers();
4127 return sstr.str();
4128}
4129
4130std::string InstanceMap::GetDebugInfo() const
4131{
4132 std::stringstream sstr;
4133 sstr << Map::GetDebugInfo() << "\n"
4134 << std::boolalpha
4135 << "ScriptId: " << GetScriptId() << " ScriptName: " << GetScriptName();
4136 return sstr.str();
4137}
4138
std::unordered_map< Player *, UpdateData > UpdateDataMapType
Definition BaseEntity.h:32
#define sBattlegroundMgr
@ CHAR_SEL_CORPSE_CUSTOMIZATIONS
@ CHAR_DEL_ALL_RESPAWNS
@ CHAR_REP_RESPAWN
@ CHAR_SEL_CORPSE_PHASES
@ CHAR_DEL_RESPAWN
@ CHAR_SEL_CORPSES
@ CHAR_DEL_CORPSES_FROM_MAP
@ CHAR_SEL_RESPAWNS
@ IN_MILLISECONDS
Definition Common.h:38
@ WEEK
Definition Common.h:35
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_SPAWN_GROUP
CorpseType
Definition Corpse.h:30
@ CORPSE_BONES
Definition Corpse.h:31
@ CORPSE_FLAG_BONES
Definition Corpse.h:43
#define MAX_CORPSE_TYPE
Definition Corpse.h:35
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
#define sDB2Manager
Definition DB2Stores.h:579
@ DIFFICULTY_FLAG_DISPLAY_MYTHIC
Definition DBCEnums.h:985
@ DIFFICULTY_FLAG_DISPLAY_HEROIC
Definition DBCEnums.h:984
Difficulty
Definition DBCEnums.h:935
@ DIFFICULTY_25_HC
Definition DBCEnums.h:942
@ DIFFICULTY_NORMAL_RAID
Definition DBCEnums.h:948
@ DIFFICULTY_NORMAL
Definition DBCEnums.h:937
@ DIFFICULTY_LFR_15TH_ANNIVERSARY
Definition DBCEnums.h:971
@ DIFFICULTY_HEROIC
Definition DBCEnums.h:938
@ DIFFICULTY_MYTHIC_KEYSTONE
Definition DBCEnums.h:944
@ DIFFICULTY_3_MAN_SCENARIO_HC
Definition DBCEnums.h:946
@ DIFFICULTY_TIMEWALKING_RAID
Definition DBCEnums.h:963
@ DIFFICULTY_TIMEWALKING
Definition DBCEnums.h:956
@ DIFFICULTY_10_N
Definition DBCEnums.h:939
@ DIFFICULTY_25_N
Definition DBCEnums.h:940
@ DIFFICULTY_NORMAL_WARFRONT
Definition DBCEnums.h:969
@ DIFFICULTY_NORMAL_ISLAND
Definition DBCEnums.h:965
@ DIFFICULTY_LFR_NEW
Definition DBCEnums.h:951
@ DIFFICULTY_10_HC
Definition DBCEnums.h:941
@ DIFFICULTY_LFR
Definition DBCEnums.h:943
@ IgnoreInstanceFarmLimit
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
#define UI64FMTD
Definition Define.h:138
#define TC_GAME_API
Definition Define.h:129
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint32_t uint32
Definition Define.h:154
std::unordered_set< uint32 > params[2]
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ABORT_MSG
Definition Errors.h:80
#define ABORT
Definition Errors.h:79
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:74
#define ASSERT
Definition Errors.h:72
#define MAX_NUMBER_OF_CELLS
Definition GridDefines.h:36
#define TOTAL_NUMBER_OF_CELLS_PER_MAP
Definition GridDefines.h:53
#define SIZE_OF_GRIDS
Definition GridDefines.h:40
CoordPair< MAX_NUMBER_OF_GRIDS > GridCoord
#define MAX_NUMBER_OF_GRIDS
Definition GridDefines.h:38
#define SIZE_OF_GRID_CELL
Definition GridDefines.h:48
NGrid< MAX_NUMBER_OF_CELLS, WorldTypeMapContainer, GridTypeMapContainer > NGridType
Definition GridDefines.h:98
#define sInstanceLockMgr
@ LOG_LEVEL_DEBUG
Definition LogCommon.h:28
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:173
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:182
#define sLog
Definition Log.h:156
#define TC_LOG_WARN(filterType__, message__,...)
Definition Log.h:179
ZLiquidStatus
Definition MapDefines.h:133
#define sMapMgr
Definition MapManager.h:186
@ MAP_OBJECT_CELL_MOVE_INACTIVE
Definition MapObject.h:32
@ MAP_OBJECT_CELL_MOVE_ACTIVE
Definition MapObject.h:31
@ MAP_OBJECT_CELL_MOVE_NONE
Definition MapObject.h:30
static void PushRespawnInfoFrom(std::vector< RespawnInfo const * > &data, RespawnInfoMap const &map)
Definition Map.cpp:2137
GridState * si_GridStates[MAX_GRID_STATE]
Definition Map.cpp:75
#define MIN_UNLOAD_DELAY
Definition Map.h:158
InstanceResetMethod
Definition Map.h:869
std::unordered_map< ObjectGuid::LowType, RespawnInfo * > RespawnInfoMap
Definition Map.h:168
InstanceResetResult
Definition Map.h:876
#define MAP_INVALID_ZONE
Definition Map.h:159
TransferAbortReason
Definition Map.h:91
@ TRANSFER_ABORT_TOO_MANY_INSTANCES
Definition Map.h:96
@ TRANSFER_ABORT_DIFFICULTY
Definition Map.h:100
@ TRANSFER_ABORT_MAP_NOT_ALLOWED
Definition Map.h:108
@ TRANSFER_ABORT_MAX_PLAYERS
Definition Map.h:94
@ TRANSFER_ABORT_ZONE_IN_COMBAT
Definition Map.h:98
@ TRANSFER_ABORT_NONE
Definition Map.h:92
@ TRANSFER_ABORT_LOCKED_TO_DIFFERENT_INSTANCE
Definition Map.h:109
@ TRANSFER_ABORT_NEED_GROUP
Definition Map.h:103
@ TRANSFER_ABORT_ERROR
Definition Map.h:93
#define TC_METRIC_VALUE(category, value,...)
Definition Metric.h:206
#define TC_METRIC_TAG(name, value)
Definition Metric.h:187
@ GRID_STATE_REMOVAL
Definition NGrid.h:59
@ GRID_STATE_INVALID
Definition NGrid.h:56
@ GRID_STATE_IDLE
Definition NGrid.h:58
@ GRID_STATE_ACTIVE
Definition NGrid.h:57
@ MAX_GRID_STATE
Definition NGrid.h:60
#define DEFAULT_VISIBILITY_NOTIFY_PERIOD
Definition NGrid.h:29
#define MAX_VISIBILITY_DISTANCE
#define DEFAULT_VISIBILITY_DISTANCE
@ TYPEID_AREATRIGGER
Definition ObjectGuid.h:49
@ TYPEID_DYNAMICOBJECT
Definition ObjectGuid.h:47
@ TYPEID_GAMEOBJECT
Definition ObjectGuid.h:46
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_CORPSE
Definition ObjectGuid.h:48
@ TYPEID_CONVERSATION
Definition ObjectGuid.h:51
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
HighGuid
Definition ObjectGuid.h:109
#define sObjectMgr
Definition ObjectMgr.h:1873
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ PET_SAVE_NOT_IN_SLOT
Definition PetDefines.h:48
@ RAID_INSTANCE_EXPIRED
Definition Player.h:875
#define sPoolMgr
Definition PoolMgr.h:179
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:43
#define sScriptMgr
Definition ScriptMgr.h:1449
@ LANG_UNIVERSAL
@ TEAM_NEUTRAL
@ TEAM_ALLIANCE
@ TEAM_HORDE
LineOfSightChecks
@ LINEOFSIGHT_CHECK_VMAP
@ LINEOFSIGHT_CHECK_GOBJECT
@ CHAT_MSG_SYSTEM
@ WS_TEAM_IN_INSTANCE_ALLIANCE
@ WS_TEAM_IN_INSTANCE_HORDE
@ SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE
Definition SpawnData.h:59
@ SPAWNGROUP_FLAG_MANUAL_SPAWN
Definition SpawnData.h:58
@ SPAWNGROUP_FLAG_DESPAWN_ON_CONDITION_FAILURE
Definition SpawnData.h:61
@ SPAWNGROUP_FLAG_SYSTEM
Definition SpawnData.h:56
@ SPAWNGROUP_FLAG_ESCORTQUESTNPC
Definition SpawnData.h:60
SpawnObjectTypeMask
Definition SpawnData.h:44
@ SPAWN_TYPEMASK_CREATURE
Definition SpawnData.h:45
@ SPAWN_TYPEMASK_GAMEOBJECT
Definition SpawnData.h:46
SpawnObjectType
Definition SpawnData.h:35
@ SPAWN_TYPE_GAMEOBJECT
Definition SpawnData.h:37
@ SPAWN_TYPE_AREATRIGGER
Definition SpawnData.h:38
@ SPAWN_TYPE_CREATURE
Definition SpawnData.h:36
@ SPELL_AURA_FORCE_WEATHER
#define sTerrainMgr
Definition TerrainMgr.h:167
#define sTransportMgr
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
bool LoadFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap, bool allowDuplicate)
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void SetDestroyedObject(bool destroyed)
Definition BaseEntity.h:199
bool IsInWorld() const
Definition BaseEntity.h:158
void BuildDestroyUpdateBlock(UpdateData *data) const
virtual void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
bool IsPlayer() const
Definition BaseEntity.h:173
bool IsDestroyedObject() const
Definition BaseEntity.h:198
TypeID GetTypeId() const
Definition BaseEntity.h:166
void BuildOutOfRangeUpdateBlock(UpdateData *data) const
virtual void BuildUpdate(UpdateDataMapType &data_map)
Definition BaseEntity.h:200
TransferAbortParams CannotEnter(Player *player) override
Definition Map.cpp:3504
BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Difficulty spawnMode)
Definition Map.cpp:3452
void SetUnload()
Definition Map.cpp:3533
void RemoveAllPlayers() override
Definition Map.cpp:3538
std::unique_ptr< BattlegroundScript > _battlegroundScript
Definition Map.h:953
Battleground * GetBG() const
Definition Map.h:942
void InitScriptData()
Definition Map.cpp:3481
std::string const & GetScriptName() const
Definition Map.cpp:3476
bool AddPlayerToMap(Player *player, bool initPlayer=true) override
Definition Map.cpp:3521
Battleground * m_bg
Definition Map.h:952
void RemovePlayerFromMap(Player *, bool) override
Definition Map.cpp:3527
virtual void InitVisibilityDistance() override
Definition Map.cpp:3469
uint32 _scriptId
Definition Map.h:954
void Update(uint32 diff) override
Definition Map.cpp:3547
void SetBgMap(BattlegroundMap *map)
void clear()
Definition ByteBuffer.h:121
std::unordered_map< ObjectGuid, CombatReference * > const & GetPvECombatRefs() const
uint32 GetDisplayId() const
Definition Corpse.h:114
void SetRace(uint8 race)
Definition Corpse.h:117
ObjectGuid GetPartyGUID() const
Definition Corpse.h:110
void SetClass(uint8 playerClass)
Definition Corpse.h:119
uint8 GetRace() const
Definition Corpse.h:116
uint8 GetClass() const
Definition Corpse.h:118
void SetSex(uint8 sex)
Definition Corpse.h:121
ObjectGuid GetGuildGUID() const
Definition Corpse.h:112
void SetGuildGUID(ObjectGuid guildGuid)
Definition Corpse.h:113
void SetDisplayId(uint32 displayId)
Definition Corpse.h:115
CorpseDynFlags GetCorpseDynamicFlags() const
Definition Corpse.h:101
void ReplaceAllCorpseFlags(CorpseFlags flags)
Definition Corpse.h:99
void SetFactionTemplate(int32 factionTemplate)
Definition Corpse.h:123
void RemoveFromWorld() override
Definition Corpse.cpp:58
void SetOwnerGUID(ObjectGuid owner)
Definition Corpse.h:109
void SetPartyGUID(ObjectGuid partyGuid)
Definition Corpse.h:111
void ReplaceAllCorpseDynamicFlags(CorpseDynFlags dynamicFlags)
Definition Corpse.h:105
CorpseFlags GetCorpseFlags() const
Definition Corpse.h:95
ObjectGuid GetOwnerGUID() const override
Definition Corpse.h:108
bool LoadCorpseFromDB(ObjectGuid::LowType guid, Field *fields)
Definition Corpse.cpp:181
std::span< UF::ChrCustomizationChoice const > GetCustomizations() const
Definition Corpse.h:129
uint8 GetSex() const
Definition Corpse.h:120
void SetCustomizations(std::span< UF::ChrCustomizationChoice const > customizations)
Definition Corpse.h:130
bool Create(ObjectGuid::LowType guidlow, Map *map)
Definition Corpse.cpp:67
uint32 GetFactionTemplate() const
Definition Corpse.h:122
CorpseType GetType() const
Definition Corpse.h:139
void DeleteFromDB(CharacterDatabaseTransaction trans)
Definition Corpse.cpp:156
bool LoadFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap, bool allowDuplicate)
bool IsEscorted() const
Position GetRespawnPosition(float *dist=nullptr) const
bool m_isTempWorldObject
Definition Creature.h:437
bool isInLineOfSight(G3D::Vector3 const &startPos, G3D::Vector3 const &endPos, PhaseShift const &phaseShift) const
bool getObjectHitPos(G3D::Vector3 const &startPos, G3D::Vector3 const &endPos, G3D::Vector3 &resultHitPos, float modifyDist, PhaseShift const &phaseShift) const
void update(uint32 diff)
Class used to access individual fields of database query result.
Definition Field.h:94
uint64 GetUInt64() const noexcept
Definition Field.cpp:71
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
int64 GetInt64() const noexcept
Definition Field.cpp:78
const G3D::AABox & getBounds() const
G3D::Vector3 const & GetPosition() const
bool LoadFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap, bool=true)
void RemoveFromWorld() override
ObjectGuid::LowType GetSpawnId() const
Definition GameObject.h:218
void AfterRelocation()
Transport * ToTransport()
Definition GameObject.h:412
void AddToWorld() override
Position GetRespawnPosition() const
PeriodicTimer & getRelocationTimer()
Definition NGrid.h:45
void RemoveFromGrid()
Definition GridObject.h:32
bool IsInGrid() const
Definition GridObject.h:30
virtual void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const =0
Definition Grid.h:42
void AddWorldObject(SPECIFIC_OBJECT *obj)
Definition Grid.h:53
void AddGridObject(SPECIFIC_OBJECT *obj)
Definition Grid.h:95
Definition Group.h:209
Difficulty GetDifficultyID(MapEntry const *mapEntry) const
Definition Group.cpp:1318
bool isRaidGroup() const
Definition Group.cpp:1598
virtual InstanceLockData const * GetInstanceInitializationData() const
bool IsExtended() const
void SetInUse(bool inUse)
InstanceResetTimePoint GetExpiryTime() const
bool IsNew() const
bool IsExpired() const
InstanceLockData * GetData()
Optional< SystemTimePoint > i_instanceExpireEvent
Definition Map.h:918
InstanceLock * i_instanceLock
Definition Map.h:922
TransferAbortParams CannotEnter(Player *player) override
Definition Map.cpp:2908
void Update(uint32) override
Definition Map.cpp:2993
InstanceResetResult Reset(InstanceResetMethod method)
Definition Map.cpp:3078
TeamId GetTeamIdInInstance() const
Definition Map.cpp:3441
std::unique_ptr< InstanceScenario > i_scenario
Definition Map.h:921
void TrySetOwningGroup(Group *group)
Definition Map.cpp:3069
void CreateInstanceLockForPlayer(Player *player)
Definition Map.cpp:3259
uint32 GetMaxPlayers() const
Definition Map.cpp:3432
virtual void InitVisibilityDistance() override
Definition Map.cpp:2898
uint32 GetScriptId() const
Definition Map.h:893
void RemovePlayerFromMap(Player *, bool) override
Definition Map.cpp:3013
InstanceMap(uint32 id, time_t, uint32 InstanceId, Difficulty SpawnMode, TeamId InstanceTeam, InstanceLock *instanceLock, Optional< uint32 > lfgDungeonsId)
Definition Map.cpp:2868
GroupInstanceReference i_owningGroupRef
Definition Map.h:923
bool AddPlayerToMap(Player *player, bool initPlayer=true) override
Definition Map.cpp:2951
InstanceScript * i_data
Definition Map.h:919
std::string const & GetScriptName() const
Definition Map.cpp:3141
void SetInstanceScenario(InstanceScenario *scenario)
Definition Map.cpp:3146
std::string GetDebugInfo() const override
Definition Map.cpp:4130
void CreateInstanceData()
Definition Map.cpp:3030
uint32 i_script_id
Definition Map.h:920
Group * GetOwningGroup() const
Definition Map.h:913
InstanceScript * GetInstanceScript()
Definition Map.h:895
void UpdateInstanceLock(UpdateBossStateSaveDataEvent const &updateSaveDataEvent)
Definition Map.cpp:3163
~InstanceMap()
Definition Map.cpp:2890
std::string GetSaveData()
Optional< uint32 > GetEntranceLocationForCompletedEncounters(uint32 completedEncountersMask) const
void Load(char const *data)
virtual void OnPlayerLeave(Player *)
void UpdateCombatResurrection(uint32 diff)
virtual void Create()
void SetEntranceLocation(uint32 worldSafeLocationId)
std::string UpdateAdditionalSaveData(std::string const &oldData, UpdateAdditionalSaveDataEvent const &event)
virtual void OnPlayerEnter(Player *)
virtual void Update(uint32)
std::string UpdateBossStateSaveData(std::string const &oldData, UpdateBossStateSaveDataEvent const &event)
uint32 size() const
Definition LinkedList.h:129
bool empty() const
Definition LinkedList.h:107
static bool isRebuildingTilesEnabledOnMap(uint32 mapId)
static MMapManager * instance()
MapObjectCellMoveState _moveState
Definition MapObject.h:51
Position _newPosition
Definition MapObject.h:52
void SetNewCellPosition(float x, float y, float z, float o)
Definition MapObject.h:53
Cell const & GetCurrentCell() const
Definition MapObject.h:48
Definition Map.h:227
MapEntry const * i_mapEntry
Definition Map.h:651
void DynamicObjectRelocation(DynamicObject *go, float x, float y, float z, float orientation)
Definition Map.cpp:1119
bool _creatureToMoveLock
Definition Map.h:618
std::map< WorldObject *, bool > i_objectsToSwitch
Definition Map.h:700
WorldObject * GetWorldObjectBySpawnId(SpawnObjectType type, ObjectGuid::LowType spawnId) const
Definition Map.h:448
std::unordered_map< uint32, uint32 > _zonePlayerCountMap
Definition Map.h:813
std::vector< Creature * > _creaturesToMove
Definition Map.h:619
void AddFarSpellCallback(FarSpellCallback &&callback)
Definition Map.cpp:2555
void GameObjectRelocation(GameObject *go, float x, float y, float z, float orientation, bool respawnRelocationOnFail=true)
Definition Map.cpp:1090
void AddGameObjectToMoveList(GameObject *go, float x, float y, float z, float ang)
Definition Map.cpp:1198
void RemoveDynamicObjectFromMoveList(DynamicObject *go)
Definition Map.cpp:1227
bool IsDungeon() const
Definition Map.cpp:3303
void CreatureRelocation(Creature *creature, float x, float y, float z, float ang, bool respawnRelocationOnFail=true)
Definition Map.cpp:1058
ZLiquidStatus GetLiquidStatus(PhaseShift const &phaseShift, float x, float y, float z, Optional< map_liquidHeaderTypeFlags > ReqLiquidType={}, LiquidData *data=nullptr, float collisionHeight=2.03128f)
Definition Map.cpp:1704
void SetZoneMusic(uint32 zoneId, uint32 musicId)
Definition Map.cpp:4021
bool IsBattlegroundOrArena() const
Definition Map.cpp:3405
void LoadAllGrids()
Definition Map.cpp:115
void RemoveInfiniteAOIVignette(Vignettes::VignetteData *vignette)
Definition Map.cpp:492
bool UnloadGrid(NGridType &ngrid, bool pForce)
Definition Map.cpp:1577
void SetSpawnGroupInactive(uint32 groupId)
Definition Map.h:756
std::unordered_map< ObjectGuid, Corpse * > _corpsesByPlayer
Definition Map.h:827
void UpdateSpawnGroupConditions()
Definition Map.cpp:2516
void SetZoneWeather(uint32 zoneId, WeatherState weatherId, float intensity)
Definition Map.cpp:4061
Pet * GetPet(ObjectGuid const &guid)
Definition Map.cpp:3593
MapStoredObjectTypesContainer & GetObjectsStore()
Definition Map.h:463
TransportsContainer::iterator _transportsUpdateIter
Definition Map.h:672
bool IsNormal() const
Definition Map.cpp:3331
void InitializeObject(T *obj)
Definition Map.cpp:512
bool IsWorldMap() const
Definition Map.cpp:3298
bool SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn=false, bool force=false, std::vector< WorldObject * > *spawnedObjects=nullptr)
Definition Map.cpp:2360
void SwitchGridContainers(T *obj, bool on)
Definition Map.cpp:216
void AddObjectToRemoveList(WorldObject *obj)
Definition Map.cpp:2588
std::map< HighGuid, ObjectGuidGenerator > _guidGenerators
Definition Map.h:820
void SendZoneWeather(uint32 zoneId, Player *player) const
Definition Map.cpp:3986
virtual void RemovePlayerFromMap(Player *, bool)
Definition Map.cpp:923
virtual bool AddPlayerToMap(Player *player, bool initPlayer=true)
Definition Map.cpp:392
void MoveAllGameObjectsInMoveList()
Definition Map.cpp:1312
bool SendZoneMessage(uint32 zone, WorldPacket const *packet, WorldSession const *self=nullptr, Optional< Team > team={ }) const
Send a packet to all players (or players selected team) in the zone (except self if mentioned)
Definition Map.cpp:2705
void EnsureGridCreated(GridCoord const &p)
Definition Map.cpp:280
Creature * GetCreatureBySpawnId(ObjectGuid::LowType spawnId) const
Definition Map.cpp:3607
void RemoveAreaTriggerFromMoveList(AreaTrigger *at)
Definition Map.cpp:1246
void DeleteRespawnInfoFromDB(SpawnObjectType type, ObjectGuid::LowType spawnId, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:2197
size_t DespawnAll(SpawnObjectType type, ObjectGuid::LowType spawnId)
Definition Map.cpp:2079
void AddAreaTriggerToMoveList(AreaTrigger *at, float x, float y, float z, float ang)
Definition Map.cpp:1236
std::function< void(Map *)> FarSpellCallback
Definition Map.h:761
void SetSpawnGroupActive(uint32 groupId, bool state)
Definition Map.cpp:2472
void LoadGrid(float x, float y)
Definition Map.cpp:370
bool IsUnderWater(PhaseShift const &phaseShift, float x, float y, float z)
Definition Map.cpp:1750
void SendZoneDynamicInfo(uint32 zoneId, Player *player) const
Definition Map.cpp:3965
void RemoveFromActive(WorldObject *obj)
Definition Map.cpp:2805
MapDifficultyEntry const * GetMapDifficulty() const
Definition Map.cpp:3283
PeriodicTimer _vignetteUpdateTimer
Definition Map.h:865
std::shared_ptr< MMAP::DynamicTileBuilder > m_mmapTileRebuilder
Definition Map.h:658
bool AddToMap(T *)
Definition Map.cpp:527
void DeleteCorpseData()
Definition Map.cpp:3841
void AddInfiniteAOIVignette(Vignettes::VignetteData *vignette)
Definition Map.cpp:479
RespawnInfoMap * GetRespawnMapForType(SpawnObjectType type)
Definition Map.h:780
virtual TransferAbortParams CannotEnter(Player *)
Definition Map.h:359
RespawnInfoMap _gameObjectRespawnTimesBySpawnId
Definition Map.h:779
NGridType * i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]
Definition Map.h:691
void UpdatePersonalPhasesForPlayer(Player const *player)
Definition Map.cpp:431
void ProcessRespawns()
Definition Map.cpp:2236
Weather * GetOrGenerateZoneDefaultWeather(uint32 zoneId)
Definition Map.cpp:4029
void SendZoneText(uint32 zoneId, const char *text, WorldSession const *self=nullptr, Optional< Team > team={ }) const
Send a System Message to all players in the zone (except self if mentioned)
Definition Map.cpp:4014
uint32 m_unloadTimer
Definition Map.h:655
virtual void DelayedUpdate(uint32 diff)
Definition Map.cpp:2560
Player * GetPlayer(ObjectGuid const &guid)
Definition Map.cpp:3568
AreaTriggerBySpawnIdContainer & GetAreaTriggerBySpawnIdStore()
Definition Map.h:474
bool IsLFR() const
Definition Map.cpp:3318
void RemoveUpdateObject(BaseEntity *obj)
Definition Map.h:582
void EnsureGridLoadedForActiveObject(GridCoord const &p, WorldObject const *object)
Definition Map.cpp:304
bool isInLineOfSight(PhaseShift const &phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
Definition Map.cpp:1760
bool IsNonRaidDungeon() const
Definition Map.cpp:3308
time_t GetLinkedRespawnTime(ObjectGuid guid) const
Definition Map.cpp:3741
void AddCorpse(Corpse *corpse)
Definition Map.cpp:3850
bool IsBattleground() const
Definition Map.cpp:3395
void UpdatePlayerZoneStats(uint32 oldZone, uint32 newZone)
Definition Map.cpp:648
WorldStateValueContainer _worldStateValues
Definition Map.h:853
IntervalTimer _weatherUpdateTimer
Definition Map.h:816
bool CheckRespawn(RespawnInfo *info)
Definition Map.cpp:1999
std::unordered_set< BaseEntity * > _updateObjects
Definition Map.h:830
bool IsRaid() const
Definition Map.cpp:3313
void ProcessRelocationNotifies(const uint32 diff)
Definition Map.cpp:848
void UnloadAllRespawnInfos()
Definition Map.cpp:2163
void UnloadAll()
Definition Map.cpp:1662
void RemoveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, CharacterDatabaseTransaction dbTrans=nullptr, bool alwaysDeleteFromDB=false)
Definition Map.h:730
bool GetEntrancePos(int32 &mapid, float &x, float &y)
Definition Map.cpp:3425
bool _dynamicObjectsToMoveLock
Definition Map.h:624
NGridType * getNGrid(uint32 x, uint32 y) const
Definition Map.h:637
std::shared_ptr< TerrainInfo > m_terrain
Definition Map.h:687
bool Is25ManRaid() const
Definition Map.cpp:3385
bool _gameObjectsToMoveLock
Definition Map.h:621
void RemoveOldCorpses()
Definition Map.cpp:3939
bool IsMythicPlus() const
Definition Map.cpp:3375
uint32 _respawnCheckTimer
Definition Map.h:812
Corpse * ConvertCorpseToBones(ObjectGuid const &ownerGuid, bool insignia=false)
Definition Map.cpp:3883
bool HavePlayers() const
Definition Map.h:397
bool IsRemovalGrid(float x, float y) const
Definition Map.h:270
MapRefManager m_mapRefManager
Definition Map.h:660
void resetMarkedCells()
Definition Map.h:393
bool ActiveObjectsNearGrid(NGridType const &ngrid) const
Definition Map.cpp:2725
void RemoveCreatureFromMoveList(Creature *c)
Definition Map.cpp:1189
void GetZoneAndAreaId(PhaseShift const &phaseShift, uint32 &zoneid, uint32 &areaid, float x, float y, float z)
Definition Map.cpp:1720
bool getObjectHitPos(PhaseShift const &phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist)
Definition Map.cpp:1771
void ScriptsProcess()
Process queued scripts.
void Visit(Cell const &cell, TypeContainerVisitor< T, CONTAINER > &visitor)
Definition Map.h:958
ScriptScheduleMap m_scriptSchedule
Definition Map.h:704
void AddWorldObject(WorldObject *obj)
Definition Map.cpp:2762
void GetFullTerrainStatusForPosition(PhaseShift const &phaseShift, float x, float y, float z, PositionFullTerrainStatus &data, Optional< map_liquidHeaderTypeFlags > reqLiquidType={}, float collisionHeight=2.03128f)
Definition Map.cpp:1698
void ResetGridExpiry(NGridType &grid, float factor=1) const
Definition Map.h:292
DynamicMapTree _dynamicTree
Definition Map.h:657
std::vector< GameObject * > _gameObjectsToMove
Definition Map.h:622
void DeleteRespawnInfo(RespawnInfo *info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:2172
bool IsTimewalking() const
Definition Map.cpp:3390
void ApplyDynamicModeRespawnScaling(WorldObject const *obj, ObjectGuid::LowType spawnId, uint32 &respawnDelay, uint32 mode) const
Definition Map.cpp:2287
void LoadRespawnTimes()
Definition Map.cpp:3697
bool GameObjectRespawnRelocation(GameObject *go, bool diffGridOnly)
Definition Map.cpp:1552
void DoOnPlayers(T &&fn)
Definition Map.h:411
float GetWaterOrGroundLevel(PhaseShift const &phaseShift, float x, float y, float z, float *ground=nullptr, bool swim=false, float collisionHeight=2.03128f)
Definition Map.cpp:1755
SceneObject * GetSceneObject(ObjectGuid const &guid)
Definition Map.cpp:3558
time_t i_gridExpiry
Definition Map.h:685
void DeleteRespawnTimesInDB()
Definition Map.cpp:3730
int32 m_VisibilityNotifyPeriod
Definition Map.h:663
float GetMinHeight(PhaseShift const &phaseShift, float x, float y)
Definition Map.cpp:1725
std::unordered_set< Corpse * > _corpseBones
Definition Map.h:828
void RequestRebuildNavMeshOnGameObjectModelChange(GameObjectModel const &model, PhaseShift const &phaseShift)
Definition Map.cpp:1785
void SetWorldStateValue(int32 worldStateId, int32 value, bool hidden)
Definition Map.cpp:445
void AreaTriggerRelocation(AreaTrigger *at, float x, float y, float z, float orientation)
Definition Map.cpp:1149
MPSCQueue< FarSpellCallback > _farSpellCallbacks
Definition Map.h:832
Difficulty i_spawnMode
Definition Map.h:652
int32 GetWorldStateValue(int32 worldStateId) const
Definition Map.cpp:437
AreaTrigger * GetAreaTriggerBySpawnId(ObjectGuid::LowType spawnId) const
Definition Map.cpp:3635
time_t GetGORespawnTime(ObjectGuid::LowType spawnId) const
Definition Map.h:530
bool i_scriptLock
Definition Map.h:698
static bool CheckGridIntegrity(T *object, bool moved, char const *objType)
Definition Map.cpp:1014
void SendInitSelf(Player *player)
Definition Map.cpp:1859
void DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId)
Definition Map.cpp:2210
virtual void RemoveAllPlayers()
Definition Map.cpp:1645
std::unordered_set< uint32 > _toggledSpawnGroupIds
Definition Map.h:810
bool isCellMarked(uint32 pCellId)
Definition Map.h:394
SpawnGroupTemplateData const * GetSpawnGroupData(uint32 groupId) const
Definition Map.cpp:2352
bool GameObjectCellRelocation(GameObject *go, Cell new_cell)
Definition Map.cpp:1507
void SendToPlayers(WorldPacket const *data) const
Definition Map.cpp:2698
bool AreaTriggerCellRelocation(AreaTrigger *at, Cell new_cell)
Definition Map.cpp:1517
time_t GetCreatureRespawnTime(ObjectGuid::LowType spawnId) const
Definition Map.h:529
MultiPersonalPhaseTracker & GetMultiPersonalPhaseTracker()
Definition Map.h:838
static TransferAbortParams PlayerCannotEnter(uint32 mapid, Player *player)
Definition Map.cpp:1807
bool IsHeroicOrHigher() const
Definition Map.cpp:3380
GameObject * GetGameObject(ObjectGuid const &guid)
Definition Map.cpp:3588
void SetZoneOverrideLight(uint32 zoneId, uint32 areaLightId, uint32 overrideLightId, Milliseconds transitionTime)
Definition Map.cpp:4080
virtual std::string GetDebugInfo() const
Definition Map.cpp:4121
static void DeleteStateMachine()
Definition Map.cpp:130
void SaveRespawnInfoDB(RespawnInfo const &info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:3683
bool IsSpawnGroupActive(uint32 groupId) const
Definition Map.cpp:2486
MapRefManager::iterator m_mapRefIter
Definition Map.h:661
bool CreatureCellRelocation(Creature *creature, Cell new_cell)
Definition Map.cpp:1502
void LoadCorpseData()
Definition Map.cpp:3757
std::unique_ptr< RespawnListContainer > _respawnTimes
Definition Map.h:777
Corpse * GetCorpse(ObjectGuid const &guid)
Definition Map.cpp:3573
time_t GetRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId) const
Definition Map.h:520
void Balance()
Definition Map.h:502
virtual void Update(uint32)
Definition Map.cpp:663
uint32 GetZoneId(PhaseShift const &phaseShift, float x, float y, float z)
Definition Map.cpp:1715
ZoneDynamicInfoMap _zoneDynamicInfo
Definition Map.h:815
bool _areaTriggersToMoveLock
Definition Map.h:627
virtual ~Map()
Definition Map.cpp:94
DynamicObject * GetDynamicObject(ObjectGuid const &guid)
Definition Map.cpp:3583
std::vector< Vignettes::VignetteData * > _infiniteAOIVignettes
Definition Map.h:864
std::vector< AreaTrigger * > _areaTriggersToMove
Definition Map.h:628
void RemoveGameObjectFromMoveList(GameObject *go)
Definition Map.cpp:1208
void LoadGridForActiveObject(float x, float y, WorldObject const *object)
Definition Map.cpp:375
Conversation * GetConversation(ObjectGuid const &guid)
Definition Map.cpp:3563
void RemoveWorldObject(WorldObject *obj)
Definition Map.cpp:2767
std::set< WorldObject * > i_worldObjects
Definition Map.h:701
Difficulty GetDifficultyID() const
Definition Map.h:363
ActiveNonPlayers m_activeNonPlayers
Definition Map.h:666
void SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, CharacterDatabaseTransaction dbTrans=nullptr, bool startup=false)
Definition Map.cpp:3650
void SendUpdateTransportVisibility(Player *player)
Definition Map.cpp:1931
virtual void LoadGridObjects(NGridType *grid)
Definition Map.cpp:344
bool MapObjectCellRelocation(T *object, Cell new_cell, char const *objType)
Definition Map.cpp:1435
void UpdateIteratorBack(Player *player)
Definition Map.cpp:3644
GameObjectBySpawnIdContainer & GetGameObjectBySpawnIdStore()
Definition Map.h:470
bool Instanceable() const
Definition Map.cpp:3293
ObjectGuidGenerator & GetGuidSequenceGenerator(HighGuid high)
Definition Map.cpp:2550
void AddDynamicObjectToMoveList(DynamicObject *go, float x, float y, float z, float ang)
Definition Map.cpp:1217
bool IsScenario() const
Definition Map.cpp:3410
void buildNGridLinkage(NGridType *pNGridType)
Definition Map.h:635
MapEntry const * GetEntry() const
Definition Map.h:233
std::set< WorldObject * > i_objectsToRemove
Definition Map.h:699
bool SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes=false, size_t *count=nullptr)
Definition Map.cpp:2449
MapStoredObjectTypesContainer _objectsStore
Definition Map.h:822
void AddToGrid(T *object, Cell const &cell)
Definition Map.cpp:175
void MoveAllDynamicObjectsInMoveList()
Definition Map.cpp:1356
uint32 GetPlayersCountExceptGMs() const
Definition Map.cpp:2689
void DeleteFromWorld(T *)
Definition Map.cpp:264
void UpdateAreaDependentAuras()
Definition Map.cpp:4105
uint32 GetId() const
Definition Map.cpp:3288
void SendInitTransports(Player *player)
Definition Map.cpp:1889
float m_VisibleDistance
Definition Map.h:656
float GetVisibilityRange() const
Definition Map.h:257
char const * GetMapName() const
Definition Map.cpp:1854
float GetWaterLevel(PhaseShift const &phaseShift, float x, float y)
Definition Map.cpp:1740
Corpse * GetCorpseByPlayer(ObjectGuid const &ownerGuid) const
Definition Map.h:486
void RemoveAllObjectsInRemoveList()
Definition Map.cpp:2615
void MoveAllCreaturesInMoveList()
Definition Map.cpp:1255
bool IsGridLoaded(uint32 gridId) const
Definition Map.h:277
uint32 GetAreaId(PhaseShift const &phaseShift, float x, float y, float z)
Definition Map.cpp:1710
void InitSpawnGroupState()
Definition Map.cpp:2500
bool EnsureGridLoaded(GridCoord const &p)
Definition Map.cpp:323
void markCell(uint32 pCellId)
Definition Map.h:395
void LoadGridsInRange(float x, float y, float radius)
Definition Map.cpp:380
void VisitNearbyCellsOf(WorldObject *obj, TypeContainerVisitor< Trinity::ObjectUpdater, GridTypeMapContainer > &gridVisitor, TypeContainerVisitor< Trinity::ObjectUpdater, WorldTypeMapContainer > &worldVisitor)
Definition Map.cpp:620
WeatherState GetZoneWeather(uint32 zoneId) const
Definition Map.cpp:4046
void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang)
Definition Map.cpp:1179
void GridUnmarkNoUnload(uint32 x, uint32 y)
Definition Map.cpp:360
void MoveAllAreaTriggersInMoveList()
Definition Map.cpp:1395
CreatureBySpawnIdContainer & GetCreatureBySpawnIdStore()
Definition Map.h:466
float GetGridHeight(PhaseShift const &phaseShift, float x, float y)
Definition Map.cpp:1730
virtual void InitVisibilityDistance()
Definition Map.cpp:166
Map(uint32 id, time_t, uint32 InstanceId, Difficulty SpawnMode)
Definition Map.cpp:138
float GetStaticHeight(PhaseShift const &phaseShift, float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH)
Definition Map.cpp:1735
bool IsHeroic() const
Definition Map.cpp:3347
RespawnInfo * GetRespawnInfo(SpawnObjectType type, ObjectGuid::LowType spawnId) const
Definition Map.cpp:2152
void SendObjectUpdates()
Definition Map.cpp:1974
void RemoveFromMap(T *, bool)
Definition Map.cpp:950
std::vector< DynamicObject * > _dynamicObjectsToMove
Definition Map.h:625
uint32 GetInstanceId() const
Definition Map.h:353
TransportsContainer _transports
Definition Map.h:671
void SendRemoveTransports(Player *player)
Definition Map.cpp:1910
std::unordered_map< uint32, std::unordered_set< Corpse * > > _corpsesByGrid
Definition Map.h:826
PlayerList const & GetPlayers() const
Definition Map.h:408
void AddToActive(WorldObject *obj)
Definition Map.cpp:2772
static void InitStateMachine()
Definition Map.cpp:122
SpawnedPoolData & GetPoolData()
Definition Map.h:758
AreaTrigger * GetAreaTrigger(ObjectGuid const &guid)
Definition Map.cpp:3553
void PlayerRelocation(Player *, float x, float y, float z, float orientation)
Definition Map.cpp:1031
RespawnInfoMap _creatureRespawnTimesBySpawnId
Definition Map.h:778
bool CreatureRespawnRelocation(Creature *c, bool diffGridOnly)
Definition Map.cpp:1522
CreatureBySpawnIdContainer _creatureBySpawnIdStore
Definition Map.h:823
void AddObjectToSwitchList(WorldObject *obj, bool on)
Definition Map.cpp:2598
uint32 i_InstanceId
Definition Map.h:653
bool AddRespawnInfo(RespawnInfo const &info)
Definition Map.cpp:2102
ActiveNonPlayers::iterator m_activeNonPlayersIter
Definition Map.h:667
bool IsMythic() const
Definition Map.cpp:3368
bool IsInWater(PhaseShift const &phaseShift, float x, float y, float z, LiquidData *data=nullptr)
Definition Map.cpp:1745
void RemoveCorpse(Corpse *corpse)
Definition Map.cpp:3862
Creature * GetCreature(ObjectGuid const &guid)
Definition Map.cpp:3578
Transport * GetTransport(ObjectGuid const &guid)
Definition Map.cpp:3598
GameObject * GetGameObjectBySpawnId(ObjectGuid::LowType spawnId) const
Definition Map.cpp:3621
void GridMarkNoUnload(uint32 x, uint32 y)
Definition Map.cpp:350
bool IsGarrison() const
Definition Map.cpp:3415
bool DynamicObjectCellRelocation(DynamicObject *go, Cell new_cell)
Definition Map.cpp:1512
bool IsAlwaysActive() const
Definition Map.cpp:3420
GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore
Definition Map.h:824
void Respawn(RespawnInfo *info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:2070
void setNGrid(NGridType *grid, uint32 x, uint32 y)
Definition Map.cpp:1964
std::unique_ptr< SpawnedPoolData > _poolData
Definition Map.h:821
bool IsBattleArena() const
Definition Map.cpp:3400
bool ShouldBeSpawnedOnGridLoad(SpawnObjectType type, ObjectGuid::LowType spawnId) const
Definition Map.cpp:2331
Definition NGrid.h:70
void decUnloadActiveLock()
Definition NGrid.h:108
void setUnloadExplicitLock(bool on)
Definition NGrid.h:106
void SetGridState(grid_state_t s)
Definition NGrid.h:92
grid_state_t GetGridState(void) const
Definition NGrid.h:91
void VisitAllGrids(TypeContainerVisitor< VISITOR, WORLD_OBJECT_CONTAINER > &visitor)
Definition NGrid.h:136
GridType & GetGridType(const uint32 x, const uint32 y)
Definition NGrid.h:78
bool HasWorldObjectsInNGrid() const
Definition NGrid.h:185
void setGridObjectDataLoaded(bool pLoaded)
Definition NGrid.h:101
bool isGridObjectDataLoaded() const
Definition NGrid.h:100
int32 getX() const
Definition NGrid.h:93
GridInfo * getGridInfoRef()
Definition NGrid.h:103
int32 getY() const
Definition NGrid.h:94
void incUnloadActiveLock()
Definition NGrid.h:107
void Set(ObjectGuid::LowType val)
LowType GetCounter() const
Definition ObjectGuid.h:336
bool IsMOTransport() const
Definition ObjectGuid.h:376
std::string ToString() const
uint64 LowType
Definition ObjectGuid.h:321
HighGuid GetHigh() const
Definition ObjectGuid.h:331
DynamicObject * ToDynObject()
Definition Object.h:141
GameObject * ToGameObject()
Definition Object.h:131
Creature * ToCreature()
Definition Object.h:121
Definition Pet.h:40
static uint32 GetTerrainMapId(PhaseShift const &phaseShift, uint32 mapId, TerrainInfo const *terrain, float x, float y)
static void AddPhase(WorldObject *object, uint32 phaseId, bool updateVisibility)
static void InheritPhaseShift(WorldObject *target, WorldObject const *source)
static void SendToPlayer(Player const *player, PhaseShift const &phaseShift)
bool Satisfy(AccessRequirement const *ar, uint32 target_map, TransferAbortParams *params=nullptr, bool report=false)
Definition Player.cpp:20033
bool m_InstanceValid
Definition Player.h:2748
bool IsBeingTeleportedFar() const
Definition Player.h:2388
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6193
void Update(uint32 time) override
Definition Player.cpp:886
void UpdateZone(uint32 newZone, uint32 newArea)
Definition Player.cpp:7492
GuidUnorderedSet m_clientGUIDs
Definition Player.h:2686
bool IsLoading() const override
Definition Player.cpp:17925
bool HaveAtClient(BaseEntity const *u) const
Definition Player.cpp:24425
WorldLocation m_homebind
Definition Player.h:2679
WorldSession * GetSession() const
Definition Player.h:2256
void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const override
Definition Player.cpp:3484
WorldObject * GetViewpoint() const
Definition Player.cpp:26922
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, TeleportToOptions options=TELE_TO_NONE, Optional< uint32 > instanceId={}, uint32 teleportSpellId=0)
Definition Player.cpp:1181
bool IsGameMaster() const
Definition Player.h:1293
void SetPendingBind(uint32 instanceId, uint32 bindTimer)
Definition Player.cpp:20000
GuidUnorderedSet m_visibleTransports
Definition Player.h:2687
bool IsInGroup(ObjectGuid groupGuid) const
Definition Player.cpp:24860
MapReference & GetMapRef()
Definition Player.h:2808
uint32 GetBattlegroundId() const
Definition Player.h:2572
void AddToWorld() override
Definition Player.cpp:1485
Group * GetGroup(Optional< uint8 > partyIndex)
Definition Player.h:2781
void UpdateObjectVisibility(bool forced=true) override
Definition Player.cpp:24772
void SetMap(Map *map) override
Definition Player.cpp:28402
void RemoveFromWorld() override
Definition Player.cpp:1499
Team GetTeam() const
Definition Player.h:2406
Difficulty GetDifficultyID(MapEntry const *mapEntry) const
Definition Player.cpp:30544
void setUInt16(uint8 index, uint16 value)
void setUInt32(uint8 index, uint32 value)
void setInt64(uint8 index, int64 value)
void setUInt64(uint8 index, uint64 value)
iterator end()
Definition RefManager.h:36
iterator begin()
Definition RefManager.h:35
bool isValid() const
Definition Reference.h:79
TO * getTarget() const
Definition Reference.h:85
void link(TO *toObj, FROM *fromObj)
Definition Reference.h:47
virtual void OnPlayerEnter(Player *player)
Definition Scenario.cpp:118
uint32 GetExpectedMapId() const
Returns id of the map that transport is expected to be on, according to current path progress.
Definition Unit.h:647
bool IsVehicle() const
Definition Unit.h:766
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6031
void UpdateObjectVisibility(bool forced=true) override
Definition Unit.cpp:12563
std::array< ObjectGuid, MAX_SUMMON_SLOT > m_SummonSlot
Definition Unit.h:1524
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
bool IsPet() const
Definition Unit.h:763
void CleanupsBeforeDelete(bool finalCleanup=true) override
Definition Unit.cpp:10396
bool IsAlive() const
Definition Unit.h:1205
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4832
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const *source=nullptr)
Definition Unit.cpp:4259
CombatManager & GetCombatManager()
Definition Unit.h:1053
AuraApplicationMap & GetAppliedAuras()
Definition Unit.h:1315
Vehicle * GetVehicleKit() const
Definition Unit.h:1798
bool IsInCombat() const
Definition Unit.h:1073
bool isDead() const
Definition Unit.h:1207
bool HasData() const
Definition UpdateData.h:49
bool BuildPacket(WorldPacket *packet)
static VMapManager * createOrGetVMapManager()
void RelocatePassengers()
Relocate passengers. Must be called after m_base::Relocate.
Definition Vehicle.cpp:579
Weather for one zone.
Definition Weather.h:67
constexpr uint32 GetMapId() const
Definition Position.h:216
bool InSamePhase(PhaseShift const &phaseShift) const
Definition Object.h:314
Map * GetMap() const
Definition Object.h:411
virtual void ResetMap()
Definition Object.cpp:1167
Map * FindMap() const
Definition Object.h:412
void RemoveFromWorld() override
Definition Object.cpp:369
virtual void UpdateObjectVisibilityOnDestroy()
Definition Object.h:511
float GetGridActivationRange() const
Definition Object.cpp:769
PhaseShift & GetPhaseShift()
Definition Object.h:310
void SetZoneScript()
Definition Object.cpp:1389
TransportBase * GetTransport() const
Definition Object.h:537
uint32 GetInstanceId() const
Definition Object.h:308
std::string const & GetName() const
Definition Object.h:342
virtual void SetMap(Map *map)
Definition Object.cpp:1149
void UpdatePositionData()
Definition Object.cpp:344
bool IsStoredInWorldObjectGridContainer() const
Definition Object.cpp:263
uint32 GetZoneId() const
Definition Object.h:332
bool IsAlwaysStoredInWorldObjectGridContainer() const
Definition Object.h:531
virtual void Update(uint32 diff)
Definition Object.cpp:243
virtual void UpdateObjectVisibility(bool forced=true)
Definition Object.cpp:3050
virtual void CleanupsBeforeDelete(bool finalCleanup=true)
Definition Object.cpp:333
void Initialize(ChatMsg chatType, Language language, WorldObject const *sender, WorldObject const *receiver, std::string_view message, uint32 achievementId=0, std::string_view channelName="", LocaleConstant locale=DEFAULT_LOCALE, std::string_view addonPrefix="")
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * GetRawPacket() const
Definition Packet.h:38
WorldPacket const * Write() override
Player session in the World.
bool Update(uint32 diff, PacketFilter &updater)
Update the WorldSession (triggered by World update)
static constexpr uint32 SPECIAL_INIT_ACTIVE_MOVER_TIME_SYNC_COUNTER
void SendCalendarRaidLockoutAdded(InstanceLock const *lock)
void RegisterTimeSync(uint32 counter)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
bool UpdateAndCheckInstanceCount(uint32 instanceId)
void AddInstanceEnterTime(uint32 instanceId, SystemTimePoint enterTime)
#define sWorld
Definition World.h:919
WeatherState
Definition Weather.h:47
WeatherData const * GetWeatherData(uint32 zone_id)
static void SendFineWeatherUpdateToPlayer(Player *player)
Definition Weather.cpp:200
@ CONFIG_VISIBILITY_NOTIFY_PERIOD_CONTINENT
Definition World.h:431
@ CONFIG_VISIBILITY_NOTIFY_PERIOD_BATTLEGROUND
Definition World.h:433
@ CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE
Definition World.h:424
@ CONFIG_VISIBILITY_NOTIFY_PERIOD_ARENA
Definition World.h:434
@ CONFIG_INSTANCE_UNLOAD_DELAY
Definition World.h:276
@ CONFIG_EXPANSION
Definition World.h:306
@ CONFIG_VISIBILITY_NOTIFY_PERIOD_INSTANCE
Definition World.h:432
@ CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT
Definition World.h:425
@ CONFIG_RESPAWN_MINCHECKINTERVALMS
Definition World.h:419
@ WEATHER_STATE_FINE
Definition Weather.h:48
@ CONFIG_RESPAWN_DYNAMICRATE_CREATURE
Definition World.h:224
@ CONFIG_MAX_VISIBILITY_DISTANCE_ARENA
Definition World.h:232
@ CONFIG_MAX_VISIBILITY_DISTANCE_INSTANCE
Definition World.h:230
@ CONFIG_MAX_VISIBILITY_DISTANCE_BATTLEGROUND
Definition World.h:231
@ CONFIG_MAX_VISIBILITY_DISTANCE_CONTINENT
Definition World.h:229
@ CONFIG_RESPAWN_DYNAMICRATE_GAMEOBJECT
Definition World.h:225
@ CONFIG_CHECK_GOBJECT_LOS
Definition World.h:193
@ CONFIG_GRID_UNLOAD
Definition World.h:108
@ CONFIG_DEATH_BONES_BG_OR_ARENA
Definition World.h:134
@ CONFIG_INSTANCE_IGNORE_RAID
Definition World.h:119
@ CONFIG_RESPAWN_DYNAMIC_ESCORTNPC
Definition World.h:194
@ CONFIG_DEATH_BONES_WORLD
Definition World.h:133
SystemTimePoint GetSystemTime()
Current chrono system_clock time point.
Definition GameTime.cpp:62
time_t GetGameTime()
Definition GameTime.cpp:52
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
void RemoveObject(T *object)
TC_GAME_API Corpse * GetCorpse(WorldObject const &u, ObjectGuid const &guid)
auto MapEqualRange(M &map, typename M::key_type const &key)
constexpr IteratorPair< iterator, end_iterator > MakeIteratorPair(iterator first, end_iterator second)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
constexpr CellCoord ComputeCellCoord(float x, float y)
constexpr GridCoord ComputeGridCoord(float x, float y)
bool CanSee(Player const *player, VignetteData const &vignette)
Definition Vignette.cpp:125
TC_GAME_API void SetValue(int32 worldStateId, int32 value, bool hidden, Map *map)
TC_GAME_API WorldStateTemplate const * GetWorldStateTemplate(int32 worldStateId)
TC_GAME_API int32 GetValue(int32 worldStateId, Map const *map)
WorldStateValueContainer GetInitialWorldStatesForMap(Map const *map)
STL namespace.
CellCoord high_bound
Definition Cell.h:34
CellCoord low_bound
Definition Cell.h:33
Definition Cell.h:38
uint32 GridX() const
Definition Cell.h:63
struct Cell::@301::@302 Part
uint8 grid_x
Definition Cell.h:85
uint32 GridY() const
Definition Cell.h:64
bool DiffGrid(Cell const &cell) const
Definition Cell.h:55
bool DiffCell(Cell const &cell) const
Definition Cell.h:49
uint32 CellX() const
Definition Cell.h:61
uint32 CellY() const
Definition Cell.h:62
static CellArea CalculateCellArea(float x, float y, float radius)
Definition CellImpl.h:33
union Cell::@301 data
uint8 grid_y
Definition Cell.h:86
uint32 x_coord
constexpr void inc_y(uint32 val)
constexpr void dec_y(uint32 val)
constexpr void dec_x(uint32 val)
constexpr uint32 GetId() const
constexpr bool IsCoordValid() const
uint32 y_coord
constexpr void inc_x(uint32 val)
uint32 EntranceWorldSafeLocId
uint32 CompletedEncountersMask
void SetInterval(time_t interval)
Definition Timer.h:94
time_t GetInterval() const
Definition Timer.h:99
bool Passed()
Definition Timer.h:78
void Update(time_t diff)
Definition Timer.h:71
void Reset()
Definition Timer.h:83
bool IsBattleground() const
bool IsScenario() const
bool GetEntrancePos(int32 &mapid, float &x, float &y) const
bool IsNonRaidDungeon() const
bool IsFlexLocking() const
bool IsWorldMap() const
bool IsBattlegroundOrArena() const
EnumFlag< MapFlags2 > GetFlags2() const
LocalizedString MapName
bool IsGarrison() const
uint8 Expansion() const
bool IsDungeon() const
bool IsRaid() const
bool IsBattleArena() const
bool Instanceable() const
uint8 MaxPlayers
void Update(Map *map, uint32 diff)
void MarkAllPhasesForDeletion(ObjectGuid const &phaseOwner)
void LoadGrid(PhaseShift const &phaseShift, NGridType &grid, Map *map)
void OnOwnerPhaseChanged(WorldObject const *phaseOwner, NGridType *grid, Map *map)
void UnregisterTrackedObject(WorldObject *object)
void TUpdate(int32 diff)
Definition Timer.h:180
bool TPassed() const
Definition Timer.h:181
bool Update(const uint32 diff)
Definition Timer.h:164
void TReset(int32 diff, int32 period)
Definition Timer.h:182
constexpr float GetPositionX() const
Definition Position.h:87
constexpr float GetPositionY() const
Definition Position.h:88
float m_positionX
Definition Position.h:64
float m_positionY
Definition Position.h:65
bool IsPositionValid() const
Definition Position.cpp:42
constexpr void Relocate(float x, float y)
Definition Position.h:74
constexpr float GetOrientation() const
Definition Position.h:90
constexpr float GetPositionZ() const
Definition Position.h:89
void resetNotify(GridRefManager< T > &m)
Definition Map.cpp:838
void Visit(PlayerMapType &m)
Definition Map.cpp:845
void Visit(GridRefManager< T > &)
Definition Map.cpp:843
void Visit(CreatureMapType &m)
Definition Map.cpp:844
RespawnInfoWithHandle(RespawnInfo const &other)
Definition Map.cpp:89
RespawnListContainer::handle_type handle
Definition Map.cpp:91
uint32 gridId
Definition Map.h:177
ObjectGuid::LowType spawnId
Definition Map.h:174
time_t respawnTime
Definition Map.h:176
virtual ~RespawnInfo()
uint32 entry
Definition Map.h:175
SpawnObjectType type
Definition Map.h:173
uint32 poolId
Definition SpawnData.h:141
SpawnGroupFlags flags
Definition SpawnData.h:72
SpawnObjectType const type
Definition SpawnData.h:120
static constexpr bool TypeHasData(SpawnObjectType type)
Definition SpawnData.h:113
SpawnGroupTemplateData const * spawnGroupData
Definition SpawnData.h:124
uint64 spawnId
Definition SpawnData.h:121
SpawnData const * ToSpawnData() const
Definition SpawnData.h:118
ValueType< ObjectType > Find(typename UnderlyingContainer< ObjectType >::KeyType const &key) const
DungeonEncounterEntry const * DungeonEncounter
EnumFlag< VignetteFlags > GetFlags() const
VignetteEntry const * Data
Definition Vignette.h:41
void FillPacket(WorldPackets::Vignette::VignetteDataSet &dataSet) const
Definition Vignette.cpp:67
std::unordered_set< uint32 > AreaIds
ZoneDynamicInfo()
Definition Map.cpp:77
std::vector< LightOverride > LightOverrides
Definition Map.h:155
WeatherState WeatherId
Definition Map.h:146
std::unique_ptr< Weather > DefaultWeather
Definition Map.h:145
float Intensity
Definition Map.h:147