diff options
| author | Shauren <shauren.trinity@gmail.com> | 2015-09-28 17:20:27 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2015-09-28 17:20:27 +0200 |
| commit | cd27fd38b93884797c094a82dc7beb0498e2f124 (patch) | |
| tree | f4bb0ff6baf13e90bfb51697ceb3161253437d06 /src/server/game/Maps | |
| parent | 3bc3b67a8fae059e1019446b09882dfa7fcd11a0 (diff) | |
Core/Maps: Moved corpse management to map level
Diffstat (limited to 'src/server/game/Maps')
| -rw-r--r-- | src/server/game/Maps/Map.cpp | 113 | ||||
| -rw-r--r-- | src/server/game/Maps/Map.h | 25 | ||||
| -rw-r--r-- | src/server/game/Maps/MapManager.cpp | 7 |
3 files changed, 131 insertions, 14 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index ccfd3ce33f7..1e35722202c 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -57,9 +57,9 @@ ZoneDynamicInfo::ZoneDynamicInfo() : MusicId(0), WeatherId(WEATHER_STATE_FINE), Map::~Map() { - sScriptMgr->OnDestroyMap(this); + // UnloadAll must be called before deleting the map - UnloadAll(); + sScriptMgr->OnDestroyMap(this); while (!i_worldObjects.empty()) { @@ -399,7 +399,7 @@ void Map::DeleteFromWorld(T* obj) template<> void Map::DeleteFromWorld(Player* player) { - sObjectAccessor->RemoveObject(player); + ObjectAccessor::RemoveObject(player); RemoveUpdateObject(player); /// @todo I do not know why we need this, it should be removed in ~Object anyway delete player; } @@ -466,8 +466,6 @@ bool Map::EnsureGridLoaded(const Cell &cell) LoadGridObjects(grid, cell); - // Add resurrectable corpses to world object list in grid - sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this); Balance(); return true; } @@ -516,6 +514,9 @@ bool Map::AddPlayerToMap(Player* player, bool initPlayer /*= true*/) player->UpdateObjectVisibility(false); player->SendUpdatePhasing(); + if (player->IsAlive()) + ConvertCorpseToBones(player->GetGUID()); + sScriptMgr->OnPlayerEnterMap(this, player); return true; } @@ -3580,7 +3581,7 @@ time_t Map::GetLinkedRespawnTime(ObjectGuid guid) const void Map::LoadCorpseData() { - std::unordered_map<uint64, std::unordered_set<uint32>> phases; + std::unordered_map<ObjectGuid::LowType, std::unordered_set<uint32>> phases; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_PHASES); stmt->setUInt32(0, GetId()); @@ -3594,7 +3595,7 @@ void Map::LoadCorpseData() do { Field* fields = phaseResult->Fetch(); - uint64 guid = fields[0].GetUInt64(); + ObjectGuid::LowType guid = fields[0].GetUInt64(); uint32 phaseId = fields[1].GetUInt32(); phases[guid].insert(phaseId); @@ -3612,7 +3613,6 @@ void Map::LoadCorpseData() if (!result) return; - uint32 count = 0; do { Field* fields = result->Fetch(); @@ -3634,8 +3634,8 @@ void Map::LoadCorpseData() for (auto phaseId : phases[guid]) corpse->SetInPhase(phaseId, false, true); - sObjectAccessor->AddCorpse(corpse); - ++count; + AddCorpse(corpse); + } while (result->NextRow()); } @@ -3648,6 +3648,99 @@ void Map::DeleteCorpseData() CharacterDatabase.Execute(stmt); } +void Map::AddCorpse(Corpse* corpse) +{ + corpse->SetMap(this); + + CellCoord cellCoord = Trinity::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY()); + _corpsesByCell[cellCoord.GetId()].insert(corpse); + _corpsesByPlayer[corpse->GetOwnerGUID()] = corpse; +} + +void Map::RemoveCorpse(Corpse* corpse) +{ + ASSERT(corpse && corpse->GetType() != CORPSE_BONES); + + corpse->DestroyForNearbyPlayers(); + if (corpse->IsInGrid()) + RemoveFromMap(corpse, false); + else + { + corpse->RemoveFromWorld(); + corpse->ResetMap(); + } + + CellCoord cellCoord = Trinity::ComputeCellCoord(corpse->GetPositionX(), corpse->GetPositionY()); + _corpsesByCell[cellCoord.GetId()].erase(corpse); + _corpsesByPlayer.erase(corpse->GetOwnerGUID()); +} + +Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= false*/) +{ + Corpse* corpse = GetCorpseByPlayer(ownerGuid); + if (!corpse) + return nullptr; + + RemoveCorpse(corpse); + + // remove corpse from DB + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + corpse->DeleteFromDB(trans); + CharacterDatabase.CommitTransaction(trans); + + Corpse* bones = NULL; + + // create the bones only if the map and the grid is loaded at the corpse's location + // ignore bones creating option in case insignia + if ((insignia || + (IsBattlegroundOrArena() ? sWorld->getBoolConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld->getBoolConfig(CONFIG_DEATH_BONES_WORLD))) && + !IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) + { + // Create bones, don't change Corpse + bones = new Corpse(); + bones->Create(corpse->GetGUID().GetCounter(), this); + + for (uint8 i = OBJECT_FIELD_GUID + 4; i < CORPSE_END; ++i) // don't overwrite guid + bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); + + bones->SetGridCoord(corpse->GetGridCoord()); + bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); + + bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); + bones->SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Empty); + bones->SetGuidValue(OBJECT_FIELD_DATA, corpse->GetGuidValue(OBJECT_FIELD_DATA)); + + for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) + if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) + bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); + + bones->CopyPhaseFrom(corpse); + + // add bones in grid store if grid loaded where corpse placed + AddToMap(bones); + } + + // all references to the corpse should be removed at this point + delete corpse; + + return bones; +} + +void Map::RemoveOldCorpses() +{ + time_t now = time(nullptr); + + std::vector<ObjectGuid> corpses; + corpses.reserve(_corpsesByPlayer.size()); + + for (auto const& p : _corpsesByPlayer) + if (p.second->IsExpired(now)) + corpses.push_back(p.first); + + for (ObjectGuid const& ownerGuid : corpses) + ConvertCorpseToBones(ownerGuid); +} + void Map::SendZoneDynamicInfo(Player* player) { uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 9331815bb39..596a753ad34 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -464,6 +464,24 @@ class Map : public GridRefManager<NGridType> typedef std::unordered_multimap<ObjectGuid::LowType, GameObject*> GameObjectBySpawnIdContainer; GameObjectBySpawnIdContainer& GetGameObjectBySpawnIdStore() { return _gameobjectBySpawnIdStore; } + std::unordered_set<Corpse*> const* GetCorpsesInCell(uint32 cellId) const + { + auto itr = _corpsesByCell.find(cellId); + if (itr != _corpsesByCell.end()) + return &itr->second; + + return nullptr; + } + + Corpse* GetCorpseByPlayer(ObjectGuid const& ownerGuid) const + { + auto itr = _corpsesByPlayer.find(ownerGuid); + if (itr != _corpsesByPlayer.end()) + return itr->second; + + return nullptr; + } + MapInstanced* ToMapInstanced() { if (Instanceable()) return reinterpret_cast<MapInstanced*>(this); return NULL; } MapInstanced const* ToMapInstanced() const { if (Instanceable()) return reinterpret_cast<MapInstanced const*>(this); return NULL; } @@ -511,8 +529,13 @@ class Map : public GridRefManager<NGridType> void RemoveGORespawnTime(ObjectGuid::LowType dbGuid); void LoadRespawnTimes(); void DeleteRespawnTimes(); + void LoadCorpseData(); void DeleteCorpseData(); + void AddCorpse(Corpse* corpse); + void RemoveCorpse(Corpse* corpse); + Corpse* ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia = false); + void RemoveOldCorpses(); static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId); @@ -708,6 +731,8 @@ class Map : public GridRefManager<NGridType> MapStoredObjectTypesContainer _objectsStore; CreatureBySpawnIdContainer _creatureBySpawnIdStore; GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore; + std::unordered_map<uint32/*cellId*/, std::unordered_set<Corpse*>> _corpsesByCell; + std::unordered_map<ObjectGuid, Corpse*> _corpsesByPlayer; std::unordered_set<Object*> _updateObjects; }; diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index 5cb3a2c26c5..bfaa9c588b9 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -163,10 +163,10 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) if (!player->IsAlive()) { - if (Corpse* corpse = player->GetCorpse()) + if (player->HasCorpse()) { // let enter in ghost mode in instance that connected to inner instance with corpse - uint32 corpseMap = corpse->GetMapId(); + uint32 corpseMap = player->GetCorpseLocation().GetMapId(); do { if (corpseMap == mapid) @@ -183,9 +183,8 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) TC_LOG_DEBUG("maps", "MAP: Player '%s' does not have a corpse in instance '%s' and cannot enter.", player->GetName().c_str(), mapName); return false; } + TC_LOG_DEBUG("maps", "MAP: Player '%s' has corpse in instance '%s' and can enter.", player->GetName().c_str(), mapName); - player->ResurrectPlayer(0.5f, false); - player->SpawnCorpseBones(); } else TC_LOG_DEBUG("maps", "Map::CanPlayerEnter - player '%s' is dead but does not have a corpse!", player->GetName().c_str()); |
