added corpse looting, also store player bags in db
This commit is contained in:
parent
70a5d07325
commit
9fb81f22c0
3 changed files with 149 additions and 2 deletions
|
|
@ -4615,6 +4615,8 @@ Corpse* Player::CreateCorpse()
|
|||
{
|
||||
if (Bag* b = GetBagByPos(bag))
|
||||
{
|
||||
insertItem(b);
|
||||
|
||||
for (uint32 slot = 0; slot < b->GetBagSize(); ++slot)
|
||||
{
|
||||
if (Item* item = b->GetItemByPos(slot))
|
||||
|
|
@ -8069,12 +8071,24 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
{
|
||||
Corpse* bones = ObjectAccessor::GetCorpse(*this, guid);
|
||||
|
||||
if (!bones || !(loot_type == LOOT_CORPSE || loot_type == LOOT_INSIGNIA) || bones->GetType() != CORPSE_BONES || !bones->HasFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE))
|
||||
if (!bones || !(loot_type == LOOT_CORPSE || loot_type == LOOT_INSIGNIA) || !bones->HasFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE))
|
||||
{
|
||||
SendLootRelease(guid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Corpse* bones = ObjectAccessor::GetCorpse(*this, guid))
|
||||
{
|
||||
if (bones->lootRecipient != this)
|
||||
{
|
||||
SendLootError(guid, LOOT_ERROR_DIDNT_KILL);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadLostCorpseLoot(bones->GetOwnerGUID(), bones->loot);
|
||||
bones->loot.loot_type = LOOT_CORPSE;
|
||||
}
|
||||
|
||||
loot = &bones->loot;
|
||||
|
||||
if (loot->loot_type == LOOT_NONE)
|
||||
|
|
@ -8278,6 +8292,71 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
|||
SendLootError(guid, LOOT_ERROR_DIDNT_KILL);
|
||||
}
|
||||
|
||||
void Player::LoadLostCorpseLoot(ObjectGuid playerGuid, Loot& loot)
|
||||
{
|
||||
loot.clear();
|
||||
m_lostCorpseItems.clear();
|
||||
|
||||
if (playerGuid.IsEmpty())
|
||||
return;
|
||||
|
||||
QueryResult corpseResult = CharacterDatabase.Query(
|
||||
"SELECT lost_corpse_id, money "
|
||||
"FROM lost_corpses "
|
||||
"WHERE player_guid = {} "
|
||||
"ORDER BY lost_corpse_id DESC LIMIT 1",
|
||||
playerGuid.GetCounter()
|
||||
);
|
||||
|
||||
if (!corpseResult)
|
||||
return;
|
||||
|
||||
Field* corpseFields = corpseResult->Fetch();
|
||||
|
||||
uint32 lostCorpseId = corpseFields[0].Get<uint32>();
|
||||
uint32 money = corpseFields[1].Get<uint32>();
|
||||
|
||||
loot.gold = money;
|
||||
|
||||
QueryResult result = CharacterDatabase.Query(
|
||||
"SELECT id, lost_corpse_id, item_entry, count, durability "
|
||||
"FROM lost_corpse_items "
|
||||
"WHERE lost_corpse_id = {} AND looted = 0 "
|
||||
"ORDER BY id ASC",
|
||||
lostCorpseId
|
||||
);
|
||||
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 dbId = fields[0].Get<uint32>();
|
||||
uint32 lostCorpseId = fields[1].Get<uint32>();
|
||||
uint32 itemId = fields[2].Get<uint32>();
|
||||
uint32 count = fields[3].Get<uint32>();
|
||||
uint32 durability = fields[4].Get<uint32>();
|
||||
|
||||
LostCorpseItemData data;
|
||||
data.id = dbId;
|
||||
data.lostCorpseId = lostCorpseId;
|
||||
data.itemId = itemId;
|
||||
data.count = count;
|
||||
data.durability = durability;
|
||||
|
||||
m_lostCorpseItems.push_back(data);
|
||||
|
||||
LootItem item;
|
||||
item.itemid = itemId;
|
||||
item.count = count;
|
||||
|
||||
loot.items.push_back(item);
|
||||
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
void Player::SendLootError(ObjectGuid guid, LootError error)
|
||||
{
|
||||
WorldPacket data(SMSG_LOOT_RESPONSE, 10);
|
||||
|
|
@ -13692,6 +13771,62 @@ LootItem* Player::StoreLootItem(uint8 lootSlot, Loot* loot, InventoryResult& msg
|
|||
AllowedLooterSet looters = item->GetAllowedLooters();
|
||||
Item* newitem = StoreNewItem(dest, item->itemid, true, item->randomPropertyId, looters);
|
||||
|
||||
// APPLY LOST CORPSE DURABILITY
|
||||
if (newitem && lootSlot < m_lostCorpseItems.size())
|
||||
{
|
||||
LostCorpseItemData const& data = m_lostCorpseItems[lootSlot];
|
||||
|
||||
// Safety check (important if something desyncs)
|
||||
if (data.itemId == item->itemid)
|
||||
{
|
||||
newitem->SetUInt32Value(ITEM_FIELD_DURABILITY, data.durability);
|
||||
|
||||
// clamp (prevents weird DB values breaking items)
|
||||
if (newitem->GetUInt32Value(ITEM_FIELD_DURABILITY) > newitem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
|
||||
{
|
||||
newitem->SetUInt32Value(
|
||||
ITEM_FIELD_DURABILITY,
|
||||
newitem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)
|
||||
);
|
||||
}
|
||||
|
||||
uint32 dbId = m_lostCorpseItems[lootSlot].id;
|
||||
uint32 corpseId = m_lostCorpseItems[lootSlot].lostCorpseId;
|
||||
|
||||
CharacterDatabase.DirectExecute(
|
||||
"UPDATE lost_corpse_items SET looted = 1 WHERE id = {}",
|
||||
dbId
|
||||
);
|
||||
|
||||
// Check if any items remain unlooted
|
||||
QueryResult remaining = CharacterDatabase.Query(
|
||||
"SELECT COUNT(*) FROM lost_corpse_items "
|
||||
"WHERE lost_corpse_id = {} AND looted = 0",
|
||||
corpseId
|
||||
);
|
||||
|
||||
if (remaining)
|
||||
{
|
||||
uint32 count = remaining->Fetch()[0].Get<uint32>();
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
// No items left, deactivate corpse
|
||||
CharacterDatabase.Execute(
|
||||
"UPDATE lost_corpses SET active = 0 WHERE lost_corpse_id = {}",
|
||||
corpseId
|
||||
);
|
||||
|
||||
// Remove lootability in-game
|
||||
if (Corpse* corpse = ObjectAccessor::GetCorpse(*this, GetLootGUID()))
|
||||
{
|
||||
corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (qitem)
|
||||
{
|
||||
qitem->is_looted = true;
|
||||
|
|
|
|||
|
|
@ -1082,6 +1082,17 @@ struct PendingSpellCastRequest
|
|||
|
||||
class Player : public Unit, public GridObject<Player>
|
||||
{
|
||||
struct LostCorpseItemData
|
||||
{
|
||||
uint32 id;
|
||||
uint32 lostCorpseId;
|
||||
uint32 itemId;
|
||||
uint32 count;
|
||||
uint32 durability;
|
||||
};
|
||||
|
||||
std::vector<LostCorpseItemData> m_lostCorpseItems;
|
||||
|
||||
friend class WorldSession;
|
||||
friend class CinematicMgr;
|
||||
friend void Item::AddToUpdateQueueOf(Player* player);
|
||||
|
|
@ -2586,6 +2597,7 @@ public:
|
|||
[[nodiscard]] bool CanSeeTrainer(Creature const* creature) const;
|
||||
|
||||
private:
|
||||
void LoadLostCorpseLoot(ObjectGuid playerGuid, Loot& loot);
|
||||
[[nodiscard]] bool AnyVendorOptionAvailable(uint32 menuId, Creature const* creature) const;
|
||||
public:
|
||||
[[nodiscard]] uint32 GetChampioningFaction() const { return m_ChampioningFaction; }
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ void WorldSession::HandleLootOpcode(WorldPacket& recvData)
|
|||
recvData >> guid;
|
||||
|
||||
// Check possible cheat
|
||||
if (!GetPlayer()->IsAlive() || !guid.IsCreatureOrVehicle())
|
||||
if (!GetPlayer()->IsAlive())
|
||||
return;
|
||||
|
||||
// interrupt cast
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue