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/Entities | |
| parent | 3bc3b67a8fae059e1019446b09882dfa7fcd11a0 (diff) | |
Core/Maps: Moved corpse management to map level
Diffstat (limited to 'src/server/game/Entities')
| -rw-r--r-- | src/server/game/Entities/Corpse/Corpse.cpp | 17 | ||||
| -rw-r--r-- | src/server/game/Entities/Corpse/Corpse.h | 1 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/GossipDef.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 74 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 35 |
6 files changed, 80 insertions, 53 deletions
diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 4745a4d4e1b..4122c3a61c2 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -149,13 +149,18 @@ void Corpse::DeleteBonesFromWorld() void Corpse::DeleteFromDB(SQLTransaction& trans) { + DeleteFromDB(GetOwnerGUID(), trans); +} + +void Corpse::DeleteFromDB(ObjectGuid const& ownerGuid, SQLTransaction& trans) +{ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE); - stmt->setUInt64(0, GetOwnerGUID().GetCounter()); - trans->Append(stmt); + stmt->setUInt64(0, ownerGuid.GetCounter()); + CharacterDatabase.ExecuteOrAppend(trans, stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_PHASES); - stmt->setUInt64(0, GetOwnerGUID().GetCounter()); - trans->Append(stmt); + stmt->setUInt64(0, ownerGuid.GetCounter()); + CharacterDatabase.ExecuteOrAppend(trans, stmt); } bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) @@ -202,6 +207,10 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) bool Corpse::IsExpired(time_t t) const { + // Deleted character + if (!sWorld->GetCharacterInfo(GetOwnerGUID())) + return true; + if (m_type == CORPSE_BONES) return m_time < t - 60 * MINUTE; else diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h index 29ae2a79d84..be2cb435ac9 100644 --- a/src/server/game/Entities/Corpse/Corpse.h +++ b/src/server/game/Entities/Corpse/Corpse.h @@ -63,6 +63,7 @@ class Corpse : public WorldObject, public GridObject<Corpse> void DeleteBonesFromWorld(); void DeleteFromDB(SQLTransaction& trans); + static void DeleteFromDB(ObjectGuid const& ownerGuid, SQLTransaction& trans); ObjectGuid GetOwnerGUID() const { return GetGuidValue(CORPSE_FIELD_OWNER); } diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index ec1e7050732..60747974a13 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -635,7 +635,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI offer.QuestGiverGUID = npcGUID; // Is there a better way? what about game objects? - if (Creature const* creature = sObjectAccessor->GetCreature(*_session->GetPlayer(), npcGUID)) + if (Creature const* creature = ObjectAccessor::GetCreature(*_session->GetPlayer(), npcGUID)) offer.QuestGiverCreatureID = creature->GetCreatureTemplate()->Entry; offer.QuestID = quest->GetQuestId(); @@ -693,7 +693,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU packet.QuestGiverGUID = npcGUID; // Is there a better way? what about game objects? - if (Creature const* creature = sObjectAccessor->GetCreature(*_session->GetPlayer(), npcGUID)) + if (Creature const* creature = ObjectAccessor::GetCreature(*_session->GetPlayer(), npcGUID)) packet.QuestGiverCreatureID = creature->GetCreatureTemplate()->Entry; packet.QuestID = quest->GetQuestId(); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 15b40c36c4a..9a01eacbf7f 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2166,7 +2166,7 @@ void WorldObject::SendObjectDeSpawnAnim(ObjectGuid guid) void WorldObject::SetMap(Map* map) { ASSERT(map); - ASSERT(!IsInWorld() || GetTypeId() == TYPEID_CORPSE); + ASSERT(!IsInWorld()); if (m_currMap == map) // command add npc: first create, than loadfromdb return; if (m_currMap) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b52172afcc8..85c2869e72a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4129,10 +4129,6 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe charDeleteMethod = CHAR_DELETE_REMOVE; } - // convert corpse to bones if exist (to prevent exiting Corpse in World without DB entry) - // bones will be deleted by corpse/bones deleting thread shortly - sObjectAccessor->ConvertCorpseForPlayer(playerguid); - if (ObjectGuid::LowType guildId = GetGuildIdFromDB(playerguid)) if (Guild* guild = sGuildMgr->GetGuildById(guildId)) guild->DeleteMember(playerguid, false, false, true); @@ -4452,13 +4448,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe stmt->setUInt64(0, guid); trans->Append(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE); - stmt->setUInt64(0, guid); - trans->Append(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_PHASES); - stmt->setUInt64(0, guid); - trans->Append(stmt); + Corpse::DeleteFromDB(playerguid, trans); Garrison::DeleteFromDB(guid, trans); @@ -4544,18 +4534,17 @@ void Player::BuildPlayerRepop() // there must be SMSG.FORCE_RUN_SPEED_CHANGE, SMSG.FORCE_SWIM_SPEED_CHANGE, SMSG.MOVE_SET_WATER_WALK // there must be SMSG.STOP_MIRROR_TIMER - // there we must send 888 opcode - // the player cannot have a corpse already, only bones which are not returned by GetCorpse - if (GetCorpse()) + // the player cannot have a corpse already on current map, only bones which are not returned by GetCorpse + WorldLocation corpseLocation = GetCorpseLocation(); + if (corpseLocation.GetMapId() == GetMapId()) { TC_LOG_ERROR("entities.player", "BuildPlayerRepop: player %s (%s) already has a corpse", GetName().c_str(), GetGUID().ToString().c_str()); return; } // create a corpse and place it at the player's location - CreateCorpse(); - Corpse* corpse = GetCorpse(); + Corpse* corpse = CreateCorpse(); if (!corpse) { TC_LOG_ERROR("entities.player", "Error creating corpse for Player %s [%s]", GetName().c_str(), GetGUID().ToString().c_str()); @@ -4697,7 +4686,16 @@ void Player::KillPlayer() UpdateObjectVisibility(); } -void Player::CreateCorpse() +void Player::OfflineResurrect(ObjectGuid const& guid, SQLTransaction& trans) +{ + Corpse::DeleteFromDB(guid, trans); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_RESURRECT)); + stmt->setUInt64(1, guid.GetCounter()); + CharacterDatabase.ExecuteOrAppend(trans, stmt); +} + +Corpse* Player::CreateCorpse() { // prevent existence 2 corpse for player SpawnCorpseBones(); @@ -4710,9 +4708,11 @@ void Player::CreateCorpse() if (!corpse->Create(GetMap()->GenerateLowGuid<HighGuid::Corpse>(), this)) { delete corpse; - return; + return nullptr; } + _corpseLocation.WorldRelocate(*this); + uint8 skin = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID); uint8 face = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID); uint8 hairstyle = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID); @@ -4756,19 +4756,21 @@ void Player::CreateCorpse() corpse->SaveToDB(); // register for player, but not show - sObjectAccessor->AddCorpse(corpse); + GetMap()->AddCorpse(corpse); + return corpse; } -void Player::SpawnCorpseBones() +void Player::SpawnCorpseBones(bool triggerSave /*= true*/) { - if (sObjectAccessor->ConvertCorpseForPlayer(GetGUID())) - if (!GetSession()->PlayerLogoutWithSave()) // at logout we will already store the player - SaveToDB(); // prevent loading as ghost without corpse + _corpseLocation.WorldRelocate(); + if (GetMap()->ConvertCorpseToBones(GetGUID())) + if (triggerSave && !GetSession()->PlayerLogoutWithSave()) // at logout we will already store the player + SaveToDB(); // prevent loading as ghost without corpse } Corpse* Player::GetCorpse() const { - return sObjectAccessor->GetCorpseForPlayerGUID(GetGUID()); + return GetMap()->GetCorpseByPlayer(GetGUID()); } void Player::DurabilityLossAll(double percent, bool inventory) @@ -8315,9 +8317,11 @@ void Player::RemovedInsignia(Player* looterPlr) RepopAtGraveyard(); } + _corpseLocation.WorldRelocate(); + // We have to convert player corpse to bones, not to be able to resurrect there // SpawnCorpseBones isn't handy, 'cos it saves player while he in BG - Corpse* bones = sObjectAccessor->ConvertCorpseForPlayer(GetGUID(), true); + Corpse* bones = GetMap()->ConvertCorpseToBones(GetGUID(), true); if (!bones) return; @@ -17438,18 +17442,24 @@ void Player::_LoadGlyphAuras() } } -void Player::LoadCorpse() +void Player::LoadCorpse(PreparedQueryResult result) { - if (IsAlive()) - sObjectAccessor->ConvertCorpseForPlayer(GetGUID()); - else + if (IsAlive() || HasAtLoginFlag(AT_LOGIN_RESURRECT)) + SpawnCorpseBones(false); + + if (!IsAlive()) { - if (Corpse* corpse = GetCorpse()) - ApplyModFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_RELEASE_TIMER, corpse && !sMapStore.LookupEntry(corpse->GetMapId())->Instanceable()); + if (result && !HasAtLoginFlag(AT_LOGIN_RESURRECT)) + { + Field* fields = result->Fetch(); + _corpseLocation.WorldRelocate(fields[0].GetUInt16(), fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat()); + ApplyModFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_RELEASE_TIMER, !sMapStore.LookupEntry(_corpseLocation.GetMapId())->Instanceable()); + } else - //Prevent Dead Player login without corpse ResurrectPlayer(0.5f); } + + RemoveAtLoginFlag(AT_LOGIN_RESURRECT); } void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 05aa3d5bbf4..f139e8e3031 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -642,15 +642,16 @@ enum PlayerExtraFlags // 2^n values enum AtLoginFlags { - AT_LOGIN_NONE = 0x00, - AT_LOGIN_RENAME = 0x01, - AT_LOGIN_RESET_SPELLS = 0x02, - AT_LOGIN_RESET_TALENTS = 0x04, - AT_LOGIN_CUSTOMIZE = 0x08, - AT_LOGIN_RESET_PET_TALENTS = 0x10, - AT_LOGIN_FIRST = 0x20, - AT_LOGIN_CHANGE_FACTION = 0x40, - AT_LOGIN_CHANGE_RACE = 0x80 + AT_LOGIN_NONE = 0x000, + AT_LOGIN_RENAME = 0x001, + AT_LOGIN_RESET_SPELLS = 0x002, + AT_LOGIN_RESET_TALENTS = 0x004, + AT_LOGIN_CUSTOMIZE = 0x008, + AT_LOGIN_RESET_PET_TALENTS = 0x010, + AT_LOGIN_FIRST = 0x020, + AT_LOGIN_CHANGE_FACTION = 0x040, + AT_LOGIN_CHANGE_RACE = 0x080, + AT_LOGIN_RESURRECT = 0x100, }; typedef std::map<uint32, QuestStatusData> QuestStatusMap; @@ -986,6 +987,7 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE, PLAYER_LOGIN_QUERY_LOAD_CURRENCY, PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, + PLAYER_LOGIN_QUERY_LOAD_CORPSE_LOCATION, PLAYER_LOGIN_QUERY_LOAD_GARRISON, PLAYER_LOGIN_QUERY_LOAD_GARRISON_BLUEPRINTS, PLAYER_LOGIN_QUERY_LOAD_GARRISON_BUILDINGS, @@ -1546,7 +1548,7 @@ class Player : public Unit, public GridObject<Player> void AddItemDurations(Item* item); void RemoveItemDurations(Item* item); void SendItemDurations(); - void LoadCorpse(); + void LoadCorpse(PreparedQueryResult result); void LoadPet(); bool AddItem(uint32 itemId, uint32 count); @@ -2088,15 +2090,18 @@ class Player : public Unit, public GridObject<Player> bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); } void UpdateUnderwaterState(Map* m, float x, float y, float z) override; - void SendMessageToSet(WorldPacket const* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); }// overwrite Object::SendMessageToSet - void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) override; // overwrite Object::SendMessageToSetInRange + void SendMessageToSet(WorldPacket const* data, bool self) override { SendMessageToSetInRange(data, GetVisibilityRange(), self); } + void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self) override; void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool own_team_only); void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) override; Corpse* GetCorpse() const; - void SpawnCorpseBones(); - void CreateCorpse(); + void SpawnCorpseBones(bool triggerSave = true); + Corpse* CreateCorpse(); void KillPlayer(); + static void OfflineResurrect(ObjectGuid const& guid, SQLTransaction& trans); + bool HasCorpse() const { return _corpseLocation.GetMapId() != MAPID_INVALID; } + WorldLocation GetCorpseLocation() const { return _corpseLocation; } uint32 GetResurrectionSpellId() const; void ResurrectPlayer(float restore_percent, bool applySickness = false); void BuildPlayerRepop(); @@ -2913,6 +2918,8 @@ class Player : public Unit, public GridObject<Player> std::unique_ptr<Garrison> _garrison; bool _advancedCombatLoggingEnabled; + + WorldLocation _corpseLocation; }; void AddItemsSetItem(Player* player, Item* item); |
