diff options
Diffstat (limited to 'src/server/game/Maps/Map.cpp')
-rw-r--r-- | src/server/game/Maps/Map.cpp | 109 |
1 files changed, 100 insertions, 9 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index b50099b9787..7acafb3c341 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -50,9 +50,9 @@ GridState* si_GridStates[MAX_GRID_STATE]; Map::~Map() { - sScriptMgr->OnDestroyMap(this); + // UnloadAll must be called before deleting the map - UnloadAll(); + sScriptMgr->OnDestroyMap(this); while (!i_worldObjects.empty()) { @@ -400,7 +400,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; } @@ -468,8 +468,6 @@ bool Map::EnsureGridLoaded(const Cell &cell) ObjectGridLoader loader(*grid, this, cell); loader.LoadN(); - // 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; } @@ -507,6 +505,9 @@ bool Map::AddPlayerToMap(Player* player) player->m_clientGUIDs.clear(); player->UpdateObjectVisibility(false); + if (player->IsAlive()) + ConvertCorpseToBones(player->GetGUID()); + sScriptMgr->OnPlayerEnterMap(this, player); return true; } @@ -2610,7 +2611,7 @@ void Map::SendObjectUpdates() _updateObjects.erase(_updateObjects.begin()); obj->BuildUpdate(update_players); } - + WorldPacket packet; // here we allocate a std::vector with a size of 0x10000 for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter) { @@ -3530,7 +3531,6 @@ void Map::LoadCorpseData() if (!result) return; - uint32 count = 0; do { Field* fields = result->Fetch(); @@ -3550,8 +3550,8 @@ void Map::LoadCorpseData() continue; } - sObjectAccessor->AddCorpse(corpse); - ++count; + AddCorpse(corpse); + } while (result->NextRow()); } @@ -3564,6 +3564,97 @@ 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_TYPE + 1; i < CORPSE_END; ++i) // don't overwrite guid and object type + bones->SetUInt32Value(i, corpse->GetUInt32Value(i)); + + bones->SetGridCoord(corpse->GetGridCoord()); + bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); + bones->SetPhaseMask(corpse->GetPhaseMask(), false); + + bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); + bones->SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Empty); + + for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) + if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) + bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); + + // 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()); |