aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
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/Entities
parent3bc3b67a8fae059e1019446b09882dfa7fcd11a0 (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.cpp17
-rw-r--r--src/server/game/Entities/Corpse/Corpse.h1
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp4
-rw-r--r--src/server/game/Entities/Object/Object.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp74
-rw-r--r--src/server/game/Entities/Player/Player.h35
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);