aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Maps
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2015-09-28 17:20:27 +0200
committerShauren <shauren.trinity@gmail.com>2015-09-28 17:20:27 +0200
commitcd27fd38b93884797c094a82dc7beb0498e2f124 (patch)
treef4bb0ff6baf13e90bfb51697ceb3161253437d06 /src/server/game/Maps
parent3bc3b67a8fae059e1019446b09882dfa7fcd11a0 (diff)
Core/Maps: Moved corpse management to map level
Diffstat (limited to 'src/server/game/Maps')
-rw-r--r--src/server/game/Maps/Map.cpp113
-rw-r--r--src/server/game/Maps/Map.h25
-rw-r--r--src/server/game/Maps/MapManager.cpp7
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());