diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 869278407..edc8e4065 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4467,7 +4467,7 @@ void Player::OfflineResurrect(ObjectGuid const& guid, CharacterDatabaseTransacti Corpse* Player::CreateCorpse() { // prevent existence 2 corpse for player - SpawnCorpseBones(); + SpawnCorpseBones(); // TODO: We'd love to allow for several corpses in the world per player but it might break things... [ElderShell] uint32 _uf, _pb, _pb2, _cfb1, _cfb2; @@ -4499,7 +4499,7 @@ Corpse* Player::CreateCorpse() corpse->SetUInt32Value(CORPSE_FIELD_BYTES_1, _cfb1); corpse->SetUInt32Value(CORPSE_FIELD_BYTES_2, _cfb2); - uint32 flags = CORPSE_FLAG_UNK2; + uint32 flags = CORPSE_FLAG_UNK2 | CORPSE_FLAG_LOOTABLE; if (HasPlayerFlag(PLAYER_FLAGS_HIDE_HELM)) flags |= CORPSE_FLAG_HIDE_HELM; if (HasPlayerFlag(PLAYER_FLAGS_HIDE_CLOAK)) @@ -4518,6 +4518,9 @@ Corpse* Player::CreateCorpse() corpse->SetUInt32Value(CORPSE_FIELD_GUILD, GetGuildId()); + corpse->lootRecipient = this; + corpse->SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); + uint32 iDisplayID; uint32 iIventoryType; uint32 _cfi; @@ -4542,6 +4545,120 @@ Corpse* Player::CreateCorpse() if (!GetMap()->IsBattlegroundOrArena()) corpse->SaveToDB(); + uint64 playerGuid = GetGUID().GetCounter(); + uint64 corpseGuid = corpse->GetGUID().GetCounter(); + + // Insert corpse + CharacterDatabase.DirectExecute( + "INSERT INTO lost_corpses " + "(player_guid, corpse_guid, map_id, zone_id, position_x, position_y, position_z, orientation, money) " + "VALUES ({}, {}, {}, {}, {}, {}, {}, {}, {})", + playerGuid, + corpseGuid, + GetMapId(), + GetZoneId(), + GetPositionX(), + GetPositionY(), + GetPositionZ(), + GetOrientation(), + GetMoney() + ); + + QueryResult result = CharacterDatabase.Query( + "SELECT lost_corpse_id " + "FROM lost_corpses " + "WHERE player_guid = {} " + "ORDER BY lost_corpse_id DESC " + "LIMIT 1", + playerGuid); + + if (!result) + return corpse; + + Field* fields = result->Fetch(); + uint32 lostCorpseId = fields[0].Get(); + + auto insertItem = [&](Item* item) + { + if (!item) + return; + + CharacterDatabase.Execute( + "INSERT INTO lost_corpse_items " + "(lost_corpse_id, item_entry, count, randomPropertyId, durability, enchantments, looted) " + "VALUES ({}, {}, {}, {}, {}, '{}', 0)", + lostCorpseId, + item->GetEntry(), + item->GetCount(), + item->GetItemRandomPropertyId(), + item->GetUInt32Value(ITEM_FIELD_DURABILITY), + "" + ); + }; + + // EQUIPPED ITEMS + for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) + { + if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + insertItem(item); + } + + // INVENTORY + BAGS + for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; ++slot) + { + if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + insertItem(item); + } + + // BAGS + for (uint8 bag = INVENTORY_SLOT_BAG_START; bag < INVENTORY_SLOT_BAG_END; ++bag) + { + if (Bag* b = GetBagByPos(bag)) + { + for (uint32 slot = 0; slot < b->GetBagSize(); ++slot) + { + if (Item* item = b->GetItemByPos(slot)) + insertItem(item); + } + } + } + + // Remove items and bags from player + for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) + { + if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + { + RemoveItem(INVENTORY_SLOT_BAG_0, i, true); + } + } + + for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + { + if (Bag* bag = GetBagByPos(i)) + { + for (uint32 slot = 0; slot < bag->GetBagSize(); ++slot) + { + if (Item* item = bag->GetItemByPos(slot)) + { + bag->RemoveItem(slot, true); + } + } + } + } + + CharacterDatabase.Execute( + "DELETE ii FROM item_instance ii " + "JOIN character_inventory ci ON ci.item = ii.guid " + "WHERE ci.guid = {}", + GetGUID().GetCounter()); + + CharacterDatabase.Execute( + "DELETE FROM character_inventory " + "WHERE guid = {}", + GetGUID().GetCounter()); + + SetMoney(0); + return corpse; }