diff options
24 files changed, 574 insertions, 81 deletions
diff --git a/sql/updates/world/master/2021_12_28_00_world_trinity_string_phaseshift_status.sql b/sql/updates/world/master/2021_12_28_00_world_trinity_string_phaseshift_status.sql new file mode 100644 index 00000000000..19d0727572c --- /dev/null +++ b/sql/updates/world/master/2021_12_28_00_world_trinity_string_phaseshift_status.sql @@ -0,0 +1,6 @@ +-- Add Name placeholder for phaseshift + +DELETE FROM `trinity_string` WHERE `entry` = 179; +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(179, "PhaseShift: +* Flags %u, PersonalGuid: %s (%s)"); diff --git a/src/server/game/Entities/Player/CinematicMgr.cpp b/src/server/game/Entities/Player/CinematicMgr.cpp index 5a3888220b5..2d3adb01542 100644 --- a/src/server/game/Entities/Player/CinematicMgr.cpp +++ b/src/server/game/Entities/Player/CinematicMgr.cpp @@ -66,7 +66,7 @@ void CinematicMgr::NextCinematicCamera() if (!pos.IsPositionValid()) return; - player->GetMap()->LoadGrid(pos.GetPositionX(), pos.GetPositionY()); + player->GetMap()->LoadGridForActiveObject(pos.GetPositionX(), pos.GetPositionY(), player); m_CinematicObject = player->SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 5 * MINUTE * IN_MILLISECONDS); if (m_CinematicObject) { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index a77afdfd8af..96091a7ebb6 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1239,7 +1239,6 @@ void Player::Update(uint32 p_time) //because we don't want player's ghost teleported from graveyard if (IsHasDelayedTeleport() && IsAlive()) TeleportTo(m_teleport_dest, m_teleport_options); - } void Player::setDeathState(DeathState s) @@ -29173,6 +29172,13 @@ void Player::UpdateWarModeAuras() } } +void Player::OnPhaseChange() +{ + Unit::OnPhaseChange(); + + GetMap()->UpdatePersonalPhasesForPlayer(this); +} + std::string Player::GetDebugInfo() const { std::stringstream sstr; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index b16d0903e1e..aac7c3ace91 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2423,6 +2423,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> bool IsVisibleGloballyFor(Player const* player) const; void SendInitialVisiblePackets(Unit* target) const; + void OnPhaseChange() override; void UpdateObjectVisibility(bool forced = true) override; void UpdateVisibilityForPlayer(); void UpdateVisibilityOf(WorldObject* target); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 1de368514a1..f85f43731e7 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1601,7 +1601,7 @@ class TC_GAME_API Unit : public WorldObject void SetVisible(bool x); // common function for visibility checks for player/creatures with detection code - void OnPhaseChange(); + virtual void OnPhaseChange(); void UpdateObjectVisibility(bool forced = true) override; SpellImmuneContainer m_spellImmune[MAX_SPELL_IMMUNITY]; diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 7e22c76f2f5..374522ae237 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -1231,7 +1231,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) // Add to correct cell if (CreatureData const* data = sObjectMgr->GetCreatureData(*itr)) { - sObjectMgr->AddCreatureToGrid(*itr, data); + sObjectMgr->AddCreatureToGrid(data); // Spawn if necessary (loaded grids only) Map* map = sMapMgr->CreateBaseMap(data->mapId); @@ -1254,7 +1254,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) // Add to correct cell if (GameObjectData const* data = sObjectMgr->GetGameObjectData(*itr)) { - sObjectMgr->AddGameobjectToGrid(*itr, data); + sObjectMgr->AddGameobjectToGrid(data); // Spawn if necessary (loaded grids only) // this base map checked as non-instanced and then only existed Map* map = sMapMgr->CreateBaseMap(data->mapId); @@ -1305,7 +1305,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) // Remove the creature from grid if (CreatureData const* data = sObjectMgr->GetCreatureData(*itr)) { - sObjectMgr->RemoveCreatureFromGrid(*itr, data); + sObjectMgr->RemoveCreatureFromGrid(data); sMapMgr->DoForAllMapsWithMapId(data->mapId, [&itr](Map* map) { @@ -1336,7 +1336,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) // Remove the gameobject from grid if (GameObjectData const* data = sObjectMgr->GetGameObjectData(*itr)) { - sObjectMgr->RemoveGameobjectFromGrid(*itr, data); + sObjectMgr->RemoveGameobjectFromGrid(data); sMapMgr->DoForAllMapsWithMapId(data->mapId, [&itr](Map* map) { diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index ec2bf4b499b..e665fc71aeb 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2300,33 +2300,70 @@ void ObjectMgr::LoadCreatures() // Add to grid if not managed by the game event or pool system if (gameEvent == 0 && PoolId == 0) - AddCreatureToGrid(guid, &data); + AddCreatureToGrid(&data); } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " creatures in %u ms", _creatureDataStore.size(), GetMSTimeDiffToNow(oldMSTime)); } -void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* data) +bool ObjectMgr::HasPersonalSpawns(uint32 mapid, Difficulty spawnMode, uint32 phaseId) const { - for (Difficulty difficulty : data->spawnDifficulties) + return Trinity::Containers::MapGetValuePtr(_mapPersonalObjectGuidsStore, { mapid, spawnMode, phaseId }) != nullptr; +} + +CellObjectGuids const* ObjectMgr::GetCellPersonalObjectGuids(uint32 mapid, Difficulty spawnMode, uint32 phaseId, uint32 cell_id) const +{ + if (CellObjectGuidsMap const* guids = Trinity::Containers::MapGetValuePtr(_mapPersonalObjectGuidsStore, { mapid, spawnMode, phaseId })) + return Trinity::Containers::MapGetValuePtr(*guids, cell_id); + + return nullptr; +} + +template<CellGuidSet CellObjectGuids::*guids> +void ObjectMgr::AddSpawnDataToGrid(SpawnData const* data) +{ + uint32 cellId = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()).GetId(); + bool isPersonalPhase = PhasingHandler::IsPersonalPhase(data->phaseId); + if (!isPersonalPhase) + { + for (Difficulty difficulty : data->spawnDifficulties) + (_mapObjectGuidsStore[{ data->mapId, difficulty }][cellId].*guids).insert(data->spawnId); + } + else { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[{ data->mapId, difficulty }][cellCoord.GetId()]; - cell_guids.creatures.insert(guid); + for (Difficulty difficulty : data->spawnDifficulties) + (_mapPersonalObjectGuidsStore[{ data->mapId, difficulty, data->phaseId }][cellId].*guids).insert(data->spawnId); } } -void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData const* data) +template<CellGuidSet CellObjectGuids::*guids> +void ObjectMgr::RemoveSpawnDataFromGrid(SpawnData const* data) { - for (Difficulty difficulty : data->spawnDifficulties) + uint32 cellId = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()).GetId(); + bool isPersonalPhase = PhasingHandler::IsPersonalPhase(data->phaseId); + if (!isPersonalPhase) + { + for (Difficulty difficulty : data->spawnDifficulties) + (_mapObjectGuidsStore[{ data->mapId, difficulty }][cellId].*guids).erase(data->spawnId); + } + else { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[{ data->mapId, difficulty }][cellCoord.GetId()]; - cell_guids.creatures.erase(guid); + for (Difficulty difficulty : data->spawnDifficulties) + (_mapPersonalObjectGuidsStore[{ data->mapId, difficulty, data->phaseId }][cellId].*guids).erase(data->spawnId); } } +void ObjectMgr::AddCreatureToGrid(CreatureData const* data) +{ + AddSpawnDataToGrid<&CellObjectGuids::creatures>(data); +} + +void ObjectMgr::RemoveCreatureFromGrid(CreatureData const* data) +{ + RemoveSpawnDataFromGrid<&CellObjectGuids::creatures>(data); +} + ObjectGuid::LowType ObjectMgr::AddGameObjectData(uint32 entry, uint32 mapId, Position const& pos, QuaternionData const& rot, uint32 spawntimedelay /*= 0*/) { GameObjectTemplate const* goinfo = GetGameObjectTemplate(entry); @@ -2352,7 +2389,7 @@ ObjectGuid::LowType ObjectMgr::AddGameObjectData(uint32 entry, uint32 mapId, Pos data.dbData = false; data.spawnGroupData = GetLegacySpawnGroup(); - AddGameobjectToGrid(spawnId, &data); + AddGameobjectToGrid(&data); // Spawn if necessary (loaded grids only) // We use spawn coords to spawn @@ -2407,7 +2444,7 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, Posit data.dynamicflags = cInfo->dynamicflags; data.spawnGroupData = GetLegacySpawnGroup(); - AddCreatureToGrid(spawnId, &data); + AddCreatureToGrid(&data); // We use spawn coords to spawn if (!map->Instanceable() && !map->IsRemovalGrid(data.spawnPoint)) @@ -2663,7 +2700,7 @@ void ObjectMgr::LoadGameObjects() } if (gameEvent == 0 && PoolId == 0) // if not this is to be managed by GameEvent System or Pool system - AddGameobjectToGrid(guid, &data); + AddGameobjectToGrid(&data); } while (result->NextRow()); @@ -2885,24 +2922,14 @@ void ObjectMgr::OnDeleteSpawnData(SpawnData const* data) ASSERT(false, "Spawn data (%u," UI64FMTD ") being removed is member of spawn group %u, but not actually listed in the lookup table for that group!", uint32(data->type), data->spawnId, data->spawnGroupData->groupId); } -void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data) +void ObjectMgr::AddGameobjectToGrid(GameObjectData const* data) { - for (Difficulty difficulty : data->spawnDifficulties) - { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[{ data->mapId, difficulty }][cellCoord.GetId()]; - cell_guids.gameobjects.insert(guid); - } + AddSpawnDataToGrid<&CellObjectGuids::gameobjects>(data); } -void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data) +void ObjectMgr::RemoveGameobjectFromGrid(GameObjectData const* data) { - for (Difficulty difficulty : data->spawnDifficulties) - { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[{ data->mapId, difficulty }][cellCoord.GetId()]; - cell_guids.gameobjects.erase(guid); - } + RemoveSpawnDataFromGrid<&CellObjectGuids::gameobjects>(data); } uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventoryType, uint32 quality, uint32 itemLevel) @@ -8431,7 +8458,7 @@ void ObjectMgr::DeleteCreatureData(ObjectGuid::LowType guid) CreatureData const* data = GetCreatureData(guid); if (data) { - RemoveCreatureFromGrid(guid, data); + RemoveCreatureFromGrid(data); OnDeleteSpawnData(data); } @@ -8444,7 +8471,7 @@ void ObjectMgr::DeleteGameObjectData(ObjectGuid::LowType guid) GameObjectData const* data = GetGameObjectData(guid); if (data) { - RemoveGameobjectFromGrid(guid, data); + RemoveGameobjectFromGrid(data); OnDeleteSpawnData(data); } diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 52eefdec97c..4443d8ba018 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -487,6 +487,7 @@ struct CellObjectGuids }; typedef std::unordered_map<uint32/*cell_id*/, CellObjectGuids> CellObjectGuidsMap; typedef std::unordered_map<std::pair<uint32 /*mapId*/, Difficulty>, CellObjectGuidsMap> MapObjectGuids; +typedef std::map<std::tuple<uint32/*mapId*/, Difficulty, uint32 /*phaseId*/>, CellObjectGuidsMap> MapPersonalObjectGuids; struct TrinityString { @@ -1454,16 +1455,19 @@ class TC_GAME_API ObjectMgr return nullptr; } - CellObjectGuids const& GetCellObjectGuids(uint16 mapid, Difficulty spawnMode, uint32 cell_id) + CellObjectGuids const& GetCellObjectGuids(uint32 mapid, Difficulty spawnMode, uint32 cell_id) { return _mapObjectGuidsStore[{ mapid, spawnMode }][cell_id]; } - CellObjectGuidsMap const& GetMapObjectGuids(uint16 mapid, Difficulty spawnMode) + CellObjectGuidsMap const& GetMapObjectGuids(uint32 mapid, Difficulty spawnMode) { return _mapObjectGuidsStore[{ mapid, spawnMode }]; } + bool HasPersonalSpawns(uint32 mapid, Difficulty spawnMode, uint32 phaseId) const; + CellObjectGuids const* GetCellPersonalObjectGuids(uint32 mapid, Difficulty spawnMode, uint32 phaseId, uint32 cell_id) const; + /** * Gets temp summon data for all creatures of specified group. * @@ -1589,10 +1593,10 @@ class TC_GAME_API ObjectMgr void SetDBCLocaleIndex(LocaleConstant locale) { DBCLocaleIndex = locale; } // grid objects - void AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* data); - void RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData const* data); - void AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data); - void RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data); + void AddCreatureToGrid(CreatureData const* data); + void RemoveCreatureFromGrid(CreatureData const* data); + void AddGameobjectToGrid(GameObjectData const* data); + void RemoveGameobjectFromGrid(GameObjectData const* data); ObjectGuid::LowType AddGameObjectData(uint32 entry, uint32 map, Position const& pos, QuaternionData const& rot, uint32 spawntimedelay = 0); ObjectGuid::LowType AddCreatureData(uint32 entry, uint32 map, Position const& pos, uint32 spawntimedelay = 0); @@ -1839,6 +1843,12 @@ class TC_GAME_API ObjectMgr QuestRelationResult GetQuestRelationsFrom(QuestRelations const& map, uint32 key, bool onlyActive) const { return { map.equal_range(key), onlyActive }; } void PlayerCreateInfoAddItemHelper(uint32 race_, uint32 class_, uint32 itemId, int32 count); + template<CellGuidSet CellObjectGuids::*guids> + void AddSpawnDataToGrid(SpawnData const* data); + + template<CellGuidSet CellObjectGuids::*guids> + void RemoveSpawnDataFromGrid(SpawnData const* data); + MailLevelRewardContainer _mailLevelRewardStore; CreatureBaseStatsContainer _creatureBaseStatsStore; @@ -1865,6 +1875,7 @@ class TC_GAME_API ObjectMgr HalfNameContainer _petHalfName1; MapObjectGuids _mapObjectGuidsStore; + MapPersonalObjectGuids _mapPersonalObjectGuidsStore; CreatureDataContainer _creatureDataStore; CreatureTemplateContainer _creatureTemplateStore; CreatureModelContainer _creatureModelStore; diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index a718f455dab..9d2f16e13b1 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -84,15 +84,16 @@ class ObjectWorldLoader uint32& i_corpses; }; -template<class T> void ObjectGridLoader::SetObjectCell(T* /*obj*/, CellCoord const& /*cellCoord*/) { } +template<class T> +void ObjectGridLoaderBase::SetObjectCell(T* /*obj*/, CellCoord const& /*cellCoord*/) { } -template<> void ObjectGridLoader::SetObjectCell(Creature* obj, CellCoord const& cellCoord) +template<> void ObjectGridLoaderBase::SetObjectCell(Creature* obj, CellCoord const& cellCoord) { Cell cell(cellCoord); obj->SetCurrentCell(cell); } -template<> void ObjectGridLoader::SetObjectCell(GameObject* obj, CellCoord const& cellCoord) +template<> void ObjectGridLoaderBase::SetObjectCell(GameObject* obj, CellCoord const& cellCoord) { Cell cell(cellCoord); obj->SetCurrentCell(cell); @@ -120,7 +121,7 @@ void AddObjectHelper(CellCoord &cell, CreatureMapType &m, uint32 &count, Map* ma } template <class T> -void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T> &m, uint32 &count, Map* map) +void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefManager<T>& m, uint32& count, Map* map, uint32 phaseId = 0, Optional<ObjectGuid> phaseOwner = {}) { for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) { @@ -131,11 +132,18 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T> T* obj = new T; //TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: " UI64FMTD ") Loading", table, guid); - if (!obj->LoadFromDB(guid, map, false, false)) + if (!obj->LoadFromDB(guid, map, false, phaseOwner.is_initialized() /*allowDuplicate*/)) { delete obj; continue; } + + if (phaseOwner) + { + PhasingHandler::InitDbPersonalOwnership(obj->GetPhaseShift(), *phaseOwner); + map->GetMultiPersonalPhaseTracker().RegisterTrackedObject(phaseId, *phaseOwner, obj); + } + AddObjectHelper(cell, m, count, map, obj); } } @@ -206,7 +214,40 @@ void ObjectGridLoader::LoadN(void) } } } - TC_LOG_DEBUG("maps", "%u GameObjects, %u Creatures, and %u Corpses/Bones loaded for grid %u on map %u", i_gameObjects, i_creatures, i_corpses, i_grid.GetGridId(), i_map->GetId()); + TC_LOG_DEBUG("maps", "%u GameObjects, %u Creatures, %u AreaTrriggers, and %u Corpses/Bones loaded for grid %u on map %u", + i_gameObjects, i_creatures, i_areaTriggers, i_corpses, i_grid.GetGridId(), i_map->GetId()); +} + +void PersonalPhaseGridLoader::Visit(GameObjectMapType& m) +{ + CellCoord cellCoord = i_cell.GetCellCoord(); + if (CellObjectGuids const* cell_guids = sObjectMgr->GetCellPersonalObjectGuids(i_map->GetId(), i_map->GetDifficultyID(), _phaseId, cellCoord.GetId())) + LoadHelper(cell_guids->gameobjects, cellCoord, m, i_gameObjects, i_map, _phaseId, _phaseOwner); +} + +void PersonalPhaseGridLoader::Visit(CreatureMapType& m) +{ + CellCoord cellCoord = i_cell.GetCellCoord(); + if (CellObjectGuids const* cell_guids = sObjectMgr->GetCellPersonalObjectGuids(i_map->GetId(), i_map->GetDifficultyID(), _phaseId, cellCoord.GetId())) + LoadHelper(cell_guids->creatures, cellCoord, m, i_creatures, i_map, _phaseId, _phaseOwner); +} + +void PersonalPhaseGridLoader::Load(uint32 phaseId) +{ + _phaseId = phaseId; + i_cell.data.Part.cell_y = 0; + for (uint32 x = 0; x < MAX_NUMBER_OF_CELLS; ++x) + { + i_cell.data.Part.cell_x = x; + for (uint32 y = 0; y < MAX_NUMBER_OF_CELLS; ++y) + { + i_cell.data.Part.cell_y = y; + + //Load creatures and game objects + TypeContainerVisitor<PersonalPhaseGridLoader, GridTypeMapContainer> visitor(*this); + i_grid.VisitGrid(x, y, visitor); + } + } } template<class T> diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h index dfd02011001..c9f2de1ccb3 100644 --- a/src/server/game/Grids/ObjectGridLoader.h +++ b/src/server/game/Grids/ObjectGridLoader.h @@ -24,15 +24,41 @@ #include "GridDefines.h" #include "Cell.h" +class ObjectGuid; class ObjectWorldLoader; -class TC_GAME_API ObjectGridLoader +class TC_GAME_API ObjectGridLoaderBase +{ + public: + ObjectGridLoaderBase(NGridType& grid, Map* map, Cell const& cell) + : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses(0), i_areaTriggers(0) + { } + + template<class T> + static void SetObjectCell(T* obj, CellCoord const& cellCoord); + + uint32 GetLoadedCreatures() const { return i_creatures; } + uint32 GetLoadedGameObjects() const { return i_gameObjects; } + uint32 GetLoadedCorpses() const { return i_corpses; } + uint32 GetLoadedAreaTriggers() const { return i_areaTriggers; } + + protected: + Cell i_cell; + NGridType &i_grid; + Map* i_map; + uint32 i_gameObjects; + uint32 i_creatures; + uint32 i_corpses; + uint32 i_areaTriggers; +}; + +class TC_GAME_API ObjectGridLoader : public ObjectGridLoaderBase { friend class ObjectWorldLoader; public: ObjectGridLoader(NGridType& grid, Map* map, Cell const& cell) - : i_cell(cell), i_grid(grid), i_map(map), i_gameObjects(0), i_creatures(0), i_corpses(0), i_areaTriggers(0) + : ObjectGridLoaderBase(grid, map, cell) { } void Visit(GameObjectMapType &m); @@ -43,18 +69,29 @@ class TC_GAME_API ObjectGridLoader void Visit(SceneObjectMapType&) const { } void Visit(ConversationMapType&) const { } - void LoadN(void); + void LoadN(); +}; - template<class T> static void SetObjectCell(T* obj, CellCoord const& cellCoord); +class TC_GAME_API PersonalPhaseGridLoader : public ObjectGridLoaderBase +{ + public: + PersonalPhaseGridLoader(NGridType& grid, Map* map, Cell const& cell, ObjectGuid const& phaseOwner) + : ObjectGridLoaderBase(grid, map, cell), _phaseId(0), _phaseOwner(phaseOwner) + { } + + void Visit(GameObjectMapType &m); + void Visit(CreatureMapType &m); + void Visit(AreaTriggerMapType&) const { } + void Visit(CorpseMapType&) const { } + void Visit(DynamicObjectMapType&) const { } + void Visit(SceneObjectMapType&) const { } + void Visit(ConversationMapType&) const { } + + void Load(uint32 phaseId); private: - Cell i_cell; - NGridType &i_grid; - Map* i_map; - uint32 i_gameObjects; - uint32 i_creatures; - uint32 i_corpses; - uint32 i_areaTriggers; + uint32 _phaseId; + ObjectGuid const& _phaseOwner; }; //Stop the creatures before unloading the NGrid diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 5e1b17d9d0d..9e553dd19e3 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -564,12 +564,15 @@ void Map::EnsureGridCreated_i(GridCoord const& p) } //Load NGrid and make it active -void Map::EnsureGridLoadedForActiveObject(Cell const& cell, WorldObject* object) +void Map::EnsureGridLoadedForActiveObject(Cell const& cell, WorldObject const* object) { EnsureGridLoaded(cell); NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); ASSERT(grid != nullptr); + if (object->IsPlayer()) + GetMultiPersonalPhaseTracker().LoadGrid(object->GetPhaseShift(), *grid, this, cell); + // refresh grid state & timer if (grid->GetGridState() != GRID_STATE_ACTIVE) { @@ -635,6 +638,11 @@ void Map::LoadGrid(float x, float y) EnsureGridLoaded(Cell(x, y)); } +void Map::LoadGridForActiveObject(float x, float y, WorldObject const* object) +{ + EnsureGridLoadedForActiveObject(Cell(x, y), object); +} + bool Map::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) { CellCoord cellCoord = Trinity::ComputeCellCoord(player->GetPositionX(), player->GetPositionY()); @@ -671,6 +679,12 @@ bool Map::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) return true; } +void Map::UpdatePersonalPhasesForPlayer(Player const* player) +{ + Cell cell(player->GetPositionX(), player->GetPositionY()); + GetMultiPersonalPhaseTracker().OnOwnerPhaseChanged(player, getNGrid(cell.GridX(), cell.GridY()), this, cell); +} + template<class T> void Map::InitializeObject(T* /*obj*/) { } @@ -939,6 +953,9 @@ void Map::Update(uint32 t_diff) _weatherUpdateTimer.Reset(); } + // update phase shift objects + GetMultiPersonalPhaseTracker().Update(this, t_diff); + MoveAllCreaturesInMoveList(); MoveAllGameObjectsInMoveList(); MoveAllAreaTriggersInMoveList(); @@ -1044,6 +1061,8 @@ void Map::RemovePlayerFromMap(Player* player, bool remove) player->UpdateZone(MAP_INVALID_ZONE, 0); sScriptMgr->OnPlayerLeaveMap(this, player); + GetMultiPersonalPhaseTracker().MarkAllPhasesForDeletion(player->GetGUID()); + player->CombatStop(); bool const inWorld = player->IsInWorld(); @@ -1070,6 +1089,8 @@ void Map::RemoveFromMap(T *obj, bool remove) if (obj->isActiveObject()) RemoveFromActive(obj); + GetMultiPersonalPhaseTracker().UnregisterTrackedObject(obj); + if (!inWorld) // if was in world, RemoveFromWorld() called DestroyForNearbyPlayers() obj->DestroyForNearbyPlayers(); // previous obj->UpdateObjectVisibility(true) @@ -1735,6 +1756,9 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) RemoveAllObjectsInRemoveList(); + // After removing all objects from the map, purge empty tracked phases + GetMultiPersonalPhaseTracker().UnloadGrid(ngrid); + { ObjectGridUnloader worker; TypeContainerVisitor<ObjectGridUnloader, GridTypeMapContainer> visitor(worker); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index e8a1a4d8a00..e5319376181 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -30,6 +30,7 @@ #include "MPSCQueue.h" #include "ObjectGuid.h" #include "Optional.h" +#include "PersonalPhaseTracker.h" #include "SharedDefines.h" #include "SpawnData.h" #include "Timer.h" @@ -313,6 +314,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType> bool GetUnloadLock(GridCoord const& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); } void SetUnloadLock(GridCoord const& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); } void LoadGrid(float x, float y); + void LoadGridForActiveObject(float x, float y, WorldObject const* object); void LoadAllCells(); bool UnloadGrid(NGridType& ngrid, bool pForce); void GridMarkNoUnload(uint32 x, uint32 y); @@ -656,7 +658,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType> void EnsureGridCreated(GridCoord const&); void EnsureGridCreated_i(GridCoord const&); bool EnsureGridLoaded(Cell const&); - void EnsureGridLoadedForActiveObject(Cell const&, WorldObject* object); + void EnsureGridLoadedForActiveObject(Cell const&, WorldObject const* object); void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } @@ -881,6 +883,16 @@ class TC_GAME_API Map : public GridRefManager<NGridType> std::unordered_set<Object*> _updateObjects; MPSCQueue<FarSpellCallback> _farSpellCallbacks; + + /*********************************************************/ + /*** Phasing ***/ + /*********************************************************/ + public: + MultiPersonalPhaseTracker& GetMultiPersonalPhaseTracker() { return _multiPersonalPhaseTracker; } + void UpdatePersonalPhasesForPlayer(Player const* player); + + private: + MultiPersonalPhaseTracker _multiPersonalPhaseTracker; }; enum InstanceResetMethod diff --git a/src/server/game/Maps/MapObject.h b/src/server/game/Maps/MapObject.h index 94b88155f5c..6481fc87cc0 100644 --- a/src/server/game/Maps/MapObject.h +++ b/src/server/game/Maps/MapObject.h @@ -35,7 +35,7 @@ enum MapObjectCellMoveState class TC_GAME_API MapObject { friend class Map; //map for moving creatures - friend class ObjectGridLoader; //grid loader for loading creatures + friend class ObjectGridLoaderBase; //grid loader for loading creatures protected: MapObject() : _moveState(MAP_OBJECT_CELL_MOVE_NONE) diff --git a/src/server/game/Phasing/PersonalPhaseTracker.cpp b/src/server/game/Phasing/PersonalPhaseTracker.cpp new file mode 100644 index 00000000000..db73485b352 --- /dev/null +++ b/src/server/game/Phasing/PersonalPhaseTracker.cpp @@ -0,0 +1,203 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "PersonalPhaseTracker.h" +#include "Containers.h" +#include "Log.h" +#include "Map.h" +#include "Object.h" +#include "ObjectGridLoader.h" +#include "ObjectMgr.h" +#include "PhasingHandler.h" + + /*********************************************************/ + /*** PlayerPersonalPhasesTracker ***/ + /*********************************************************/ + +void PlayerPersonalPhasesTracker::RegisterTrackedObject(uint32 phaseId, WorldObject* object) +{ + _spawns[phaseId].Objects.insert(object); +} + +void PlayerPersonalPhasesTracker::UnregisterTrackedObject(WorldObject* object) +{ + for (auto& [_, spawns] : _spawns) + spawns.Objects.erase(object); +} + +void PlayerPersonalPhasesTracker::OnOwnerPhasesChanged(WorldObject const* owner) +{ + PhaseShift const& phaseShift = owner->GetPhaseShift(); + + // Loop over all our tracked phases. If any don't exist - delete them + for (auto& [phaseId, spawns] : _spawns) + if (!spawns.DurationRemaining && !phaseShift.HasPhase(phaseId)) + spawns.DurationRemaining = PersonalPhaseSpawns::DELETE_TIME_DEFAULT; + + // loop over all owner phases. If any exist and marked for deletion - reset delete + for (PhaseShift::PhaseRef const& phaseRef : phaseShift.GetPhases()) + if (PersonalPhaseSpawns* spawns = Trinity::Containers::MapGetValuePtr(_spawns, phaseRef.Id)) + spawns->DurationRemaining.reset(); +} + +void PlayerPersonalPhasesTracker::MarkAllPhasesForDeletion() +{ + for (auto& [_, spawns] : _spawns) + spawns.DurationRemaining = PersonalPhaseSpawns::DELETE_TIME_DEFAULT; +} + +void PlayerPersonalPhasesTracker::Update(Map* map, uint32 diff) +{ + for (auto itr = _spawns.begin(); itr != _spawns.end(); ) + { + if (itr->second.DurationRemaining) + { + itr->second.DurationRemaining = *itr->second.DurationRemaining - Milliseconds(diff); + if (itr->second.DurationRemaining <= Milliseconds::zero()) + { + DespawnPhase(map, itr->second); + itr = _spawns.erase(itr); + continue; + } + } + ++itr; + } +} + +bool PlayerPersonalPhasesTracker::IsGridLoadedForPhase(uint32 gridId, uint32 phaseId) const +{ + if (PersonalPhaseSpawns const* spawns = Trinity::Containers::MapGetValuePtr(_spawns, phaseId)) + return spawns->Grids.find(gridId) != spawns->Grids.cend(); + + return false; +} + +void PlayerPersonalPhasesTracker::SetGridLoadedForPhase(uint32 gridId, uint32 phaseId) +{ + PersonalPhaseSpawns& group = _spawns[phaseId]; + group.Grids.insert(gridId); +} + +void PlayerPersonalPhasesTracker::SetGridUnloaded(uint32 gridId) +{ + for (auto itr = _spawns.begin(); itr != _spawns.end(); ) + { + itr->second.Grids.erase(gridId); + if (itr->second.IsEmpty()) + itr = _spawns.erase(itr); + else + ++itr; + } +} + +void PlayerPersonalPhasesTracker::DespawnPhase(Map* map, PersonalPhaseSpawns& spawns) +{ + for (WorldObject* obj : spawns.Objects) + map->AddObjectToRemoveList(obj); + + spawns.Objects.clear(); + spawns.Grids.clear(); +} + +/*********************************************************/ +/*** MultiPersonalPhaseTracker ***/ +/*********************************************************/ + +void MultiPersonalPhaseTracker::LoadGrid(PhaseShift const& phaseShift, NGridType& grid, Map* map, Cell const& cell) +{ + if (!phaseShift.HasPersonalPhase()) + return; + + PersonalPhaseGridLoader loader(grid, map, cell, phaseShift.GetPersonalGuid()); + PlayerPersonalPhasesTracker& playerTracker = _playerData[phaseShift.GetPersonalGuid()]; + + for (PhaseShift::PhaseRef const& phaseRef : phaseShift.GetPhases()) + { + if (!phaseRef.IsPersonal()) + continue; + + if (!sObjectMgr->HasPersonalSpawns(map->GetId(), map->GetDifficultyID(), phaseRef.Id)) + continue; + + if (playerTracker.IsGridLoadedForPhase(grid.GetGridId(), phaseRef.Id)) + continue; + + TC_LOG_DEBUG("maps", "Loading personal phase objects (phase %u) in grid[%u, %u] for map %u instance %u", + phaseRef.Id, cell.GridX(), cell.GridY(), map->GetId(), map->GetInstanceId()); + + loader.Load(phaseRef.Id); + + playerTracker.SetGridLoadedForPhase(grid.GetGridId(), phaseRef.Id); + } + + if (loader.GetLoadedGameObjects()) + map->Balance(); +} + +void MultiPersonalPhaseTracker::UnloadGrid(NGridType& grid) +{ + for (auto itr = _playerData.begin(); itr != _playerData.end(); ) + { + itr->second.SetGridUnloaded(grid.GetGridId()); + if (itr->second.IsEmpty()) + itr = _playerData.erase(itr); + else + ++itr; + } +} + +void MultiPersonalPhaseTracker::RegisterTrackedObject(uint32 phaseId, ObjectGuid const& phaseOwner, WorldObject* object) +{ + ASSERT(phaseId); + ASSERT(!phaseOwner.IsEmpty()); + ASSERT(object); + + _playerData[phaseOwner].RegisterTrackedObject(phaseId, object); +} + +void MultiPersonalPhaseTracker::UnregisterTrackedObject(WorldObject* object) +{ + if (PlayerPersonalPhasesTracker* playerTracker = Trinity::Containers::MapGetValuePtr(_playerData, object->GetPhaseShift().GetPersonalGuid())) + playerTracker->UnregisterTrackedObject(object); +} + +void MultiPersonalPhaseTracker::OnOwnerPhaseChanged(WorldObject const* phaseOwner, NGridType* grid, Map* map, Cell const& cell) +{ + if (PlayerPersonalPhasesTracker* playerTracker = Trinity::Containers::MapGetValuePtr(_playerData, phaseOwner->GetGUID())) + playerTracker->OnOwnerPhasesChanged(phaseOwner); + + if (grid) + LoadGrid(phaseOwner->GetPhaseShift(), *grid, map, cell); +} + +void MultiPersonalPhaseTracker::MarkAllPhasesForDeletion(ObjectGuid const& phaseOwner) +{ + if (PlayerPersonalPhasesTracker* playerTracker = Trinity::Containers::MapGetValuePtr(_playerData, phaseOwner)) + playerTracker->MarkAllPhasesForDeletion(); +} + +void MultiPersonalPhaseTracker::Update(Map* map, uint32 diff) +{ + for (auto itr = _playerData.begin(); itr != _playerData.end(); ) + { + itr->second.Update(map, diff); + if (itr->second.IsEmpty()) + itr = _playerData.erase(itr); + else + ++itr; + } +} diff --git a/src/server/game/Phasing/PersonalPhaseTracker.h b/src/server/game/Phasing/PersonalPhaseTracker.h new file mode 100644 index 00000000000..641cbece9fa --- /dev/null +++ b/src/server/game/Phasing/PersonalPhaseTracker.h @@ -0,0 +1,85 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef PersonalPhaseTracker_h__ +#define PersonalPhaseTracker_h__ + +#include "Common.h" +#include "Duration.h" +#include "GridDefines.h" +#include "ObjectGuid.h" +#include "Optional.h" + +class Map; +class PhaseShift; +class WorldObject; +struct Cell; + +struct PersonalPhaseSpawns +{ + static constexpr Milliseconds DELETE_TIME_DEFAULT = 1min; + + std::unordered_set<WorldObject*> Objects; + std::unordered_set<uint16> Grids; + Optional<Milliseconds> DurationRemaining; + + bool IsEmpty() const { return Objects.empty() && Grids.empty(); } +}; + +/* Tracks personal phases for a single owner */ +struct PlayerPersonalPhasesTracker +{ +public: + void RegisterTrackedObject(uint32 phaseId, WorldObject* object); + void UnregisterTrackedObject(WorldObject* object); + + void OnOwnerPhasesChanged(WorldObject const* owner); + void MarkAllPhasesForDeletion(); + + void Update(Map* map, uint32 diff); + + bool IsGridLoadedForPhase(uint32 gridId, uint32 phaseId) const; + void SetGridLoadedForPhase(uint32 gridId, uint32 phaseId); + void SetGridUnloaded(uint32 gridId); + + bool IsEmpty() const { return _spawns.empty(); } + +private: + void DespawnPhase(Map* map, PersonalPhaseSpawns& spawns); + + std::unordered_map<uint32 /*phaseId*/, PersonalPhaseSpawns> _spawns; +}; + +/* Handles personal phase trackers for all owners */ +struct MultiPersonalPhaseTracker +{ + void LoadGrid(PhaseShift const& phaseShift, NGridType& grid, Map* map, Cell const& cell); + void UnloadGrid(NGridType& grid); + + void RegisterTrackedObject(uint32 phaseId, ObjectGuid const& phaseOwner, WorldObject* object); + void UnregisterTrackedObject(WorldObject* object); + + void OnOwnerPhaseChanged(WorldObject const* phaseOwner, NGridType* grid, Map* map, Cell const& cell); + void MarkAllPhasesForDeletion(ObjectGuid const& phaseOwner); + + void Update(Map* map, uint32 diff); + +private: + std::unordered_map<ObjectGuid /*owner*/, PlayerPersonalPhasesTracker> _playerData; +}; + +#endif // PersonalPhaseTracker_h__ diff --git a/src/server/game/Phasing/PhaseShift.cpp b/src/server/game/Phasing/PhaseShift.cpp index f9753226918..f0655bf01fa 100644 --- a/src/server/game/Phasing/PhaseShift.cpp +++ b/src/server/game/Phasing/PhaseShift.cpp @@ -186,3 +186,11 @@ void PhaseShift::UpdatePersonalGuid() if (!PersonalReferences) PersonalGuid.Clear(); } + +bool PhaseShift::HasPersonalPhase() const +{ + for (PhaseRef const& phaseRef : GetPhases()) + if (phaseRef.IsPersonal()) + return true; + return false; +} diff --git a/src/server/game/Phasing/PhaseShift.h b/src/server/game/Phasing/PhaseShift.h index 133f58056a2..32fc4455877 100644 --- a/src/server/game/Phasing/PhaseShift.h +++ b/src/server/game/Phasing/PhaseShift.h @@ -65,6 +65,7 @@ public: std::vector<Condition*> const* AreaConditions; bool operator<(PhaseRef const& right) const { return Id < right.Id; } bool operator==(PhaseRef const& right) const { return Id == right.Id; } + bool IsPersonal() const { return Flags.HasFlag(PhaseFlags::Personal); } }; struct VisibleMapIdRef { @@ -85,6 +86,8 @@ public: using VisibleMapIdContainer = std::map<uint32, VisibleMapIdRef>; using UiMapPhaseIdContainer = std::map<uint32, UiMapPhaseIdRef>; + ObjectGuid GetPersonalGuid() const { return PersonalGuid; } + bool AddPhase(uint32 phaseId, PhaseFlags flags, std::vector<Condition*> const* areaConditions, int32 references = 1); EraseResult<PhaseContainer> RemovePhase(uint32 phaseId); bool HasPhase(uint32 phaseId) const { return Phases.find(PhaseRef(phaseId, PhaseFlags::None, nullptr)) != Phases.end(); } @@ -105,6 +108,8 @@ public: bool CanSee(PhaseShift const& other) const; + bool HasPersonalPhase() const; + protected: friend class PhasingHandler; diff --git a/src/server/game/Phasing/PhasingHandler.cpp b/src/server/game/Phasing/PhasingHandler.cpp index e1432b49351..31a28010c71 100644 --- a/src/server/game/Phasing/PhasingHandler.cpp +++ b/src/server/game/Phasing/PhasingHandler.cpp @@ -496,6 +496,13 @@ void PhasingHandler::InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlag phaseShift.Flags = flags; } +void PhasingHandler::InitDbPersonalOwnership(PhaseShift& phaseShift, ObjectGuid const& personalGuid) +{ + ASSERT(phaseShift.IsDbPhaseShift); + ASSERT(phaseShift.HasPersonalPhase()); + phaseShift.PersonalGuid = personalGuid; +} + void PhasingHandler::InitDbVisibleMapId(PhaseShift& phaseShift, int32 visibleMapId) { phaseShift.VisibleMapIds.clear(); @@ -551,9 +558,18 @@ void PhasingHandler::SetInversed(WorldObject* object, bool apply, bool updateVis UpdateVisibilityIfNeeded(object, updateVisibility, true); } -void PhasingHandler::PrintToChat(ChatHandler* chat, PhaseShift const& phaseShift) +void PhasingHandler::PrintToChat(ChatHandler* chat, WorldObject const* target) { - chat->PSendSysMessage(LANG_PHASESHIFT_STATUS, phaseShift.Flags.AsUnderlyingType(), phaseShift.PersonalGuid.ToString().c_str()); + PhaseShift const& phaseShift = target->GetPhaseShift(); + + std::string phaseOwnerName = "N/A"; + if (phaseShift.HasPersonalPhase()) + if (WorldObject* personalGuid = ObjectAccessor::GetWorldObject(*target, phaseShift.PersonalGuid)) + phaseOwnerName = personalGuid->GetName(); + + chat->PSendSysMessage(LANG_PHASESHIFT_STATUS, phaseShift.Flags.AsUnderlyingType(), + phaseShift.PersonalGuid.ToString().c_str(), phaseOwnerName.c_str()); + if (!phaseShift.Phases.empty()) { std::ostringstream phases; @@ -601,6 +617,14 @@ std::string PhasingHandler::FormatPhases(PhaseShift const& phaseShift) return phases.str(); } +bool PhasingHandler::IsPersonalPhase(uint32 phaseId) +{ + if (PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId)) + return phase->GetFlags().HasFlag(PhaseEntryFlags::Personal); + + return false; +} + void PhasingHandler::UpdateVisibilityIfNeeded(WorldObject* object, bool updateVisibility, bool changed) { if (changed && object->IsInWorld()) diff --git a/src/server/game/Phasing/PhasingHandler.h b/src/server/game/Phasing/PhasingHandler.h index 73003029cfc..17d40977e56 100644 --- a/src/server/game/Phasing/PhasingHandler.h +++ b/src/server/game/Phasing/PhasingHandler.h @@ -59,6 +59,7 @@ public: static PhaseShift const& GetEmptyPhaseShift(); static void InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId); + static void InitDbPersonalOwnership(PhaseShift& phaseShift, ObjectGuid const& personalGuid); static void InitDbVisibleMapId(PhaseShift& phaseShift, int32 visibleMapId); static bool InDbPhaseShift(WorldObject const* object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId); @@ -67,9 +68,11 @@ public: static void SetAlwaysVisible(WorldObject* object, bool apply, bool updateVisibility); static void SetInversed(WorldObject* object, bool apply, bool updateVisibility); - static void PrintToChat(ChatHandler* chat, PhaseShift const& phaseShift); + static void PrintToChat(ChatHandler* chat, WorldObject const* target); static std::string FormatPhases(PhaseShift const& phaseShift); + static bool IsPersonalPhase(uint32 phaseId); + private: static void AddPhase(WorldObject* object, uint32 phaseId, ObjectGuid const& personalGuid, bool updateVisibility); static void AddPhaseGroup(WorldObject* object, uint32 phaseGroupId, ObjectGuid const& personalGuid, bool updateVisibility); diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index d9402f7797a..070323fc99d 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -175,7 +175,7 @@ void PoolGroup<Creature>::Despawn1Object(uint64 guid) { if (CreatureData const* data = sObjectMgr->GetCreatureData(guid)) { - sObjectMgr->RemoveCreatureFromGrid(guid, data); + sObjectMgr->RemoveCreatureFromGrid(data); Map* map = sMapMgr->FindMap(data->mapId, 0); if (map && !map->Instanceable()) @@ -200,7 +200,7 @@ void PoolGroup<GameObject>::Despawn1Object(uint64 guid) { if (GameObjectData const* data = sObjectMgr->GetGameObjectData(guid)) { - sObjectMgr->RemoveGameobjectFromGrid(guid, data); + sObjectMgr->RemoveGameobjectFromGrid(data); Map* map = sMapMgr->FindMap(data->mapId, 0); if (map && !map->Instanceable()) @@ -320,7 +320,7 @@ void PoolGroup<Creature>::Spawn1Object(PoolObject* obj) { if (CreatureData const* data = sObjectMgr->GetCreatureData(obj->guid)) { - sObjectMgr->AddCreatureToGrid(obj->guid, data); + sObjectMgr->AddCreatureToGrid(data); // Spawn if necessary (loaded grids only) Map* map = sMapMgr->FindMap(data->mapId, 0); @@ -336,7 +336,7 @@ void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj) { if (GameObjectData const* data = sObjectMgr->GetGameObjectData(obj->guid)) { - sObjectMgr->AddGameobjectToGrid(obj->guid, data); + sObjectMgr->AddGameobjectToGrid(data); // Spawn if necessary (loaded grids only) // this base map checked as non-instanced and then only existed Map* map = sMapMgr->FindMap(data->mapId, 0); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 6de82fcd0eb..e66fbe3e573 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -1453,7 +1453,7 @@ public: else if (target->GetDBPhase() < 0) handler->PSendSysMessage("Target creature's PhaseGroup in DB: %d", abs(target->GetDBPhase())); - PhasingHandler::PrintToChat(handler, target->GetPhaseShift()); + PhasingHandler::PrintToChat(handler, target); return true; } diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 3bf6b0ba3f2..debd992ebec 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -183,7 +183,7 @@ public: return false; /// @todo is it really necessary to add both the real and DB table guid here ? - sObjectMgr->AddGameobjectToGrid(spawnId, ASSERT_NOTNULL(sObjectMgr->GetGameObjectData(spawnId))); + sObjectMgr->AddGameobjectToGrid(ASSERT_NOTNULL(sObjectMgr->GetGameObjectData(spawnId))); handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), std::to_string(spawnId).c_str(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); return true; @@ -487,9 +487,9 @@ public: object->Relocate(x, y, z, object->GetOrientation()); // update which cell has this gameobject registered for loading - sObjectMgr->RemoveGameobjectFromGrid(guidLow, object->GetGameObjectData()); + sObjectMgr->RemoveGameobjectFromGrid(object->GetGameObjectData()); object->SaveToDB(); - sObjectMgr->AddGameobjectToGrid(guidLow, object->GetGameObjectData()); + sObjectMgr->AddGameobjectToGrid(object->GetGameObjectData()); // Generate a completely new spawn with new guid // 3.3.5a client caches recently deleted objects and brings them back to life diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 7bf851699ca..d7515aa40aa 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -302,7 +302,7 @@ public: if (status) handler->PSendSysMessage(LANG_LIQUID_STATUS, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, uint32(liquidStatus.type_flags.AsUnderlyingType()), status); - PhasingHandler::PrintToChat(handler, object->GetPhaseShift()); + PhasingHandler::PrintToChat(handler, object); return true; } @@ -1905,7 +1905,7 @@ public: // Output XIII. phases if (target) - PhasingHandler::PrintToChat(handler, target->GetPhaseShift()); + PhasingHandler::PrintToChat(handler, target); // Output XIV. LANG_PINFO_CHR_MONEY uint32 gold = money / GOLD; diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 06c092f9de2..2c32d1b6687 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -225,7 +225,7 @@ public: if (Creature* creature = trans->CreateNPCPassenger(guid, &data)) { creature->SaveToDB(trans->GetGOInfo()->moTransport.SpawnMap, { map->GetDifficultyID() }); - sObjectMgr->AddCreatureToGrid(guid, &data); + sObjectMgr->AddCreatureToGrid(&data); } return true; } @@ -248,7 +248,7 @@ public: if (!creature) return false; - sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid)); + sObjectMgr->AddCreatureToGrid(sObjectMgr->GetCreatureData(db_guid)); return true; } @@ -697,7 +697,7 @@ public: if (CreatureData const* data = sObjectMgr->GetCreatureData(target->GetSpawnId())) { handler->PSendSysMessage(LANG_NPCINFO_PHASES, data->phaseId, data->phaseGroup); - PhasingHandler::PrintToChat(handler, target->GetPhaseShift()); + PhasingHandler::PrintToChat(handler, target); } handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); @@ -812,9 +812,9 @@ public: } // update position in memory - sObjectMgr->RemoveCreatureFromGrid(lowguid, data); + sObjectMgr->RemoveCreatureFromGrid(data); const_cast<CreatureData*>(data)->spawnPoint.Relocate(*player); - sObjectMgr->AddCreatureToGrid(lowguid, data); + sObjectMgr->AddCreatureToGrid(data); // update position in DB WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_POSITION); |