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))
|
if (Bag* b = GetBagByPos(bag))
|
||||||
{
|
{
|
||||||
|
insertItem(b);
|
||||||
|
|
||||||
for (uint32 slot = 0; slot < b->GetBagSize(); ++slot)
|
for (uint32 slot = 0; slot < b->GetBagSize(); ++slot)
|
||||||
{
|
{
|
||||||
if (Item* item = b->GetItemByPos(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);
|
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);
|
SendLootRelease(guid);
|
||||||
return;
|
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;
|
loot = &bones->loot;
|
||||||
|
|
||||||
if (loot->loot_type == LOOT_NONE)
|
if (loot->loot_type == LOOT_NONE)
|
||||||
|
|
@ -8278,6 +8292,71 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
||||||
SendLootError(guid, LOOT_ERROR_DIDNT_KILL);
|
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)
|
void Player::SendLootError(ObjectGuid guid, LootError error)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_LOOT_RESPONSE, 10);
|
WorldPacket data(SMSG_LOOT_RESPONSE, 10);
|
||||||
|
|
@ -13692,6 +13771,62 @@ LootItem* Player::StoreLootItem(uint8 lootSlot, Loot* loot, InventoryResult& msg
|
||||||
AllowedLooterSet looters = item->GetAllowedLooters();
|
AllowedLooterSet looters = item->GetAllowedLooters();
|
||||||
Item* newitem = StoreNewItem(dest, item->itemid, true, item->randomPropertyId, looters);
|
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)
|
if (qitem)
|
||||||
{
|
{
|
||||||
qitem->is_looted = true;
|
qitem->is_looted = true;
|
||||||
|
|
|
||||||
|
|
@ -1082,6 +1082,17 @@ struct PendingSpellCastRequest
|
||||||
|
|
||||||
class Player : public Unit, public GridObject<Player>
|
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 WorldSession;
|
||||||
friend class CinematicMgr;
|
friend class CinematicMgr;
|
||||||
friend void Item::AddToUpdateQueueOf(Player* player);
|
friend void Item::AddToUpdateQueueOf(Player* player);
|
||||||
|
|
@ -2586,6 +2597,7 @@ public:
|
||||||
[[nodiscard]] bool CanSeeTrainer(Creature const* creature) const;
|
[[nodiscard]] bool CanSeeTrainer(Creature const* creature) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void LoadLostCorpseLoot(ObjectGuid playerGuid, Loot& loot);
|
||||||
[[nodiscard]] bool AnyVendorOptionAvailable(uint32 menuId, Creature const* creature) const;
|
[[nodiscard]] bool AnyVendorOptionAvailable(uint32 menuId, Creature const* creature) const;
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] uint32 GetChampioningFaction() const { return m_ChampioningFaction; }
|
[[nodiscard]] uint32 GetChampioningFaction() const { return m_ChampioningFaction; }
|
||||||
|
|
|
||||||
|
|
@ -243,7 +243,7 @@ void WorldSession::HandleLootOpcode(WorldPacket& recvData)
|
||||||
recvData >> guid;
|
recvData >> guid;
|
||||||
|
|
||||||
// Check possible cheat
|
// Check possible cheat
|
||||||
if (!GetPlayer()->IsAlive() || !guid.IsCreatureOrVehicle())
|
if (!GetPlayer()->IsAlive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// interrupt cast
|
// interrupt cast
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue