fix(Core/Item): prevent possible items dupe (#6943)
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
INSERT INTO `version_db_characters` (`sql_rev`) VALUES ('1626271703991541000');
|
||||||
|
ALTER TABLE `item_loot_storage`
|
||||||
|
ADD COLUMN `item_index` INT UNSIGNED NOT NULL DEFAULT 0 AFTER `count`;
|
||||||
@@ -510,9 +510,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
|||||||
PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC);
|
||||||
|
|
||||||
// Items that hold loot or money
|
// Items that hold loot or money
|
||||||
PrepareStatement(CHAR_SEL_ITEMCONTAINER_ITEMS, "SELECT containerGUID, itemid, count, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest, conditionLootId FROM item_loot_storage", CONNECTION_SYNCH);
|
PrepareStatement(CHAR_SEL_ITEMCONTAINER_ITEMS, "SELECT containerGUID, itemid, count, item_index, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest, conditionLootId FROM item_loot_storage", CONNECTION_SYNCH);
|
||||||
PrepareStatement(CHAR_DEL_ITEMCONTAINER_SINGLE_ITEM, "DELETE FROM item_loot_storage WHERE containerGUID = ? AND itemid = ? AND count = ? LIMIT 1", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_DEL_ITEMCONTAINER_SINGLE_ITEM, "DELETE FROM item_loot_storage WHERE containerGUID = ? AND itemid = ? AND count = ? AND item_index = ? LIMIT 1", CONNECTION_ASYNC);
|
||||||
PrepareStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM, "INSERT INTO item_loot_storage (containerGUID, itemid, count, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest, conditionLootId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM, "INSERT INTO item_loot_storage (containerGUID, itemid, item_index, count, randomPropertyId, randomSuffix, follow_loot_rules, freeforall, is_blocked, is_counted, is_underthreshold, needs_quest, conditionLootId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||||
PrepareStatement(CHAR_DEL_ITEMCONTAINER_CONTAINER, "DELETE FROM item_loot_storage WHERE containerGUID = ?", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_DEL_ITEMCONTAINER_CONTAINER, "DELETE FROM item_loot_storage WHERE containerGUID = ?", CONNECTION_ASYNC);
|
||||||
|
|
||||||
// Calendar
|
// Calendar
|
||||||
|
|||||||
@@ -12616,7 +12616,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
|
|||||||
|
|
||||||
// LootItem is being removed (looted) from the container, delete it from the DB.
|
// LootItem is being removed (looted) from the container, delete it from the DB.
|
||||||
if (loot->containerGUID)
|
if (loot->containerGUID)
|
||||||
sLootItemStorage->RemoveStoredLootItem(loot->containerGUID, item->itemid, item->count, loot);
|
sLootItemStorage->RemoveStoredLootItem(loot->containerGUID, item->itemid, item->count, loot, item->itemIndex);
|
||||||
|
|
||||||
#ifdef ELUNA
|
#ifdef ELUNA
|
||||||
sEluna->OnLootItem(this, newitem, item->count, this->GetLootGUID());
|
sEluna->OnLootItem(this, newitem, item->count, this->GetLootGUID());
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ void LootItemStorage::LoadStorageFromDB()
|
|||||||
Field* fields = result->Fetch();
|
Field* fields = result->Fetch();
|
||||||
|
|
||||||
StoredLootItemList& itemList = lootItemStore[ObjectGuid::Create<HighGuid::Item>(fields[0].GetUInt32())];
|
StoredLootItemList& itemList = lootItemStore[ObjectGuid::Create<HighGuid::Item>(fields[0].GetUInt32())];
|
||||||
itemList.push_back(StoredLootItem(fields[1].GetUInt32(), fields[2].GetUInt32(), fields[3].GetInt32(), fields[4].GetUInt32(), fields[5].GetBool(),
|
itemList.push_back(StoredLootItem(fields[1].GetUInt32(), fields[2].GetUInt32(), fields[3].GetUInt32(), fields[4].GetInt32(), fields[5].GetUInt32(), fields[6].GetBool(),
|
||||||
fields[6].GetBool(), fields[7].GetBool(), fields[8].GetBool(), fields[9].GetBool(), fields[10].GetBool(), fields[11].GetUInt32()));
|
fields[7].GetBool(), fields[8].GetBool(), fields[9].GetBool(), fields[10].GetBool(), fields[11].GetBool(), fields[12].GetUInt32()));
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
} while (result->NextRow());
|
} while (result->NextRow());
|
||||||
@@ -51,7 +51,7 @@ void LootItemStorage::LoadStorageFromDB()
|
|||||||
LOG_INFO("server.loading", " ");
|
LOG_INFO("server.loading", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LootItemStorage::RemoveEntryFromDB(ObjectGuid containerGUID, uint32 itemid, uint32 count)
|
void LootItemStorage::RemoveEntryFromDB(ObjectGuid containerGUID, uint32 itemid, uint32 count, uint32 itemIndex)
|
||||||
{
|
{
|
||||||
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
||||||
|
|
||||||
@@ -59,6 +59,7 @@ void LootItemStorage::RemoveEntryFromDB(ObjectGuid containerGUID, uint32 itemid,
|
|||||||
stmt->setUInt32(0, containerGUID.GetCounter());
|
stmt->setUInt32(0, containerGUID.GetCounter());
|
||||||
stmt->setUInt32(1, itemid);
|
stmt->setUInt32(1, itemid);
|
||||||
stmt->setUInt32(2, count);
|
stmt->setUInt32(2, count);
|
||||||
|
stmt->setUInt32(3, itemIndex);
|
||||||
trans->Append(stmt);
|
trans->Append(stmt);
|
||||||
|
|
||||||
CharacterDatabase.CommitTransaction(trans);
|
CharacterDatabase.CommitTransaction(trans);
|
||||||
@@ -80,12 +81,13 @@ void LootItemStorage::AddNewStoredLoot(Loot* loot, Player* /*player*/)
|
|||||||
// Gold at first
|
// Gold at first
|
||||||
if (loot->gold)
|
if (loot->gold)
|
||||||
{
|
{
|
||||||
itemList.push_back(StoredLootItem(0, loot->gold, 0, 0, false, false, false, false, false, false, 0));
|
itemList.push_back(StoredLootItem(0, 0, loot->gold, 0, 0, false, false, false, false, false, false, 0));
|
||||||
|
|
||||||
uint8 index = 0;
|
uint8 index = 0;
|
||||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM);
|
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM);
|
||||||
stmt->setUInt32(index++, loot->containerGUID.GetCounter());
|
stmt->setUInt32(index++, loot->containerGUID.GetCounter());
|
||||||
stmt->setUInt32(index++, 0);
|
stmt->setUInt32(index++, 0);
|
||||||
|
stmt->setUInt32(index++, 0);
|
||||||
stmt->setUInt32(index++, loot->gold);
|
stmt->setUInt32(index++, loot->gold);
|
||||||
stmt->setInt32(index++, 0);
|
stmt->setInt32(index++, 0);
|
||||||
stmt->setUInt32(index++, 0);
|
stmt->setUInt32(index++, 0);
|
||||||
@@ -118,13 +120,14 @@ void LootItemStorage::AddNewStoredLoot(Loot* loot, Player* /*player*/)
|
|||||||
conditionLootId = li->conditions.front()->SourceGroup;
|
conditionLootId = li->conditions.front()->SourceGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemList.push_back(StoredLootItem(li->itemid, li->count, li->randomPropertyId, li->randomSuffix, li->follow_loot_rules, li->freeforall, li->is_blocked, li->is_counted,
|
itemList.push_back(StoredLootItem(li->itemid, li->itemIndex, li->count, li->randomPropertyId, li->randomSuffix, li->follow_loot_rules, li->freeforall, li->is_blocked, li->is_counted,
|
||||||
li->is_underthreshold, li->needs_quest, conditionLootId));
|
li->is_underthreshold, li->needs_quest, conditionLootId));
|
||||||
|
|
||||||
uint8 index = 0;
|
uint8 index = 0;
|
||||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM);
|
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ITEMCONTAINER_SINGLE_ITEM);
|
||||||
stmt->setUInt32(index++, loot->containerGUID.GetCounter());
|
stmt->setUInt32(index++, loot->containerGUID.GetCounter());
|
||||||
stmt->setUInt32(index++, li->itemid);
|
stmt->setUInt32(index++, li->itemid);
|
||||||
|
stmt->setUInt32(index++, li->itemIndex);
|
||||||
stmt->setUInt32(index++, li->count);
|
stmt->setUInt32(index++, li->count);
|
||||||
stmt->setInt32 (index++, li->randomPropertyId);
|
stmt->setInt32 (index++, li->randomPropertyId);
|
||||||
stmt->setUInt32(index++, li->randomSuffix);
|
stmt->setUInt32(index++, li->randomSuffix);
|
||||||
@@ -168,6 +171,7 @@ bool LootItemStorage::LoadStoredLoot(Item* item, Player* player)
|
|||||||
{
|
{
|
||||||
LootItem li;
|
LootItem li;
|
||||||
li.itemid = it2->itemid;
|
li.itemid = it2->itemid;
|
||||||
|
li.itemIndex = it2->itemIndex;
|
||||||
li.count = it2->count;
|
li.count = it2->count;
|
||||||
li.follow_loot_rules = it2->follow_loot_rules;
|
li.follow_loot_rules = it2->follow_loot_rules;
|
||||||
li.freeforall = it2->freeforall;
|
li.freeforall = it2->freeforall;
|
||||||
@@ -212,7 +216,7 @@ bool LootItemStorage::LoadStoredLoot(Item* item, Player* player)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LootItemStorage::RemoveStoredLootItem(ObjectGuid containerGUID, uint32 itemid, uint32 count, Loot* loot)
|
void LootItemStorage::RemoveStoredLootItem(ObjectGuid containerGUID, uint32 itemid, uint32 count, Loot* loot, uint32 itemIndex)
|
||||||
{
|
{
|
||||||
LootItemContainer::iterator itr = lootItemStore.find(containerGUID);
|
LootItemContainer::iterator itr = lootItemStore.find(containerGUID);
|
||||||
if (itr == lootItemStore.end())
|
if (itr == lootItemStore.end())
|
||||||
@@ -222,7 +226,7 @@ void LootItemStorage::RemoveStoredLootItem(ObjectGuid containerGUID, uint32 item
|
|||||||
for (StoredLootItemList::iterator it2 = itemList.begin(); it2 != itemList.end(); ++it2)
|
for (StoredLootItemList::iterator it2 = itemList.begin(); it2 != itemList.end(); ++it2)
|
||||||
if (it2->itemid == itemid && it2->count == count)
|
if (it2->itemid == itemid && it2->count == count)
|
||||||
{
|
{
|
||||||
RemoveEntryFromDB(containerGUID, itemid, count);
|
RemoveEntryFromDB(containerGUID, itemid, count, itemIndex);
|
||||||
itemList.erase(it2);
|
itemList.erase(it2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -243,7 +247,7 @@ void LootItemStorage::RemoveStoredLootMoney(ObjectGuid containerGUID, Loot* loot
|
|||||||
for (StoredLootItemList::iterator it2 = itemList.begin(); it2 != itemList.end(); ++it2)
|
for (StoredLootItemList::iterator it2 = itemList.begin(); it2 != itemList.end(); ++it2)
|
||||||
if (it2->itemid == 0)
|
if (it2->itemid == 0)
|
||||||
{
|
{
|
||||||
RemoveEntryFromDB(containerGUID, 0, it2->count);
|
RemoveEntryFromDB(containerGUID, 0, it2->count, 0);
|
||||||
itemList.erase(it2);
|
itemList.erase(it2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,14 @@ Xinef
|
|||||||
|
|
||||||
struct StoredLootItem
|
struct StoredLootItem
|
||||||
{
|
{
|
||||||
StoredLootItem(uint32 i, uint32 c, int32 ri, uint32 rs, bool follow_loot_rules, bool freeforall,
|
StoredLootItem(uint32 i, uint32 idx, uint32 c, int32 ri, uint32 rs, bool follow_loot_rules, bool freeforall,
|
||||||
bool is_blocked, bool is_counted, bool is_underthreshold, bool needs_quest, uint32 conditionLootId) :
|
bool is_blocked, bool is_counted, bool is_underthreshold, bool needs_quest, uint32 conditionLootId) : itemid(i), itemIndex(idx),
|
||||||
itemid(i), count(c), randomPropertyId(ri), randomSuffix(rs), follow_loot_rules(follow_loot_rules), freeforall(freeforall), is_blocked(is_blocked),
|
count(c), randomPropertyId(ri), randomSuffix(rs), follow_loot_rules(follow_loot_rules), freeforall(freeforall), is_blocked(is_blocked),
|
||||||
is_counted(is_counted), is_underthreshold(is_underthreshold), needs_quest(needs_quest), conditionLootId(conditionLootId) { }
|
is_counted(is_counted), is_underthreshold(is_underthreshold), needs_quest(needs_quest), conditionLootId(conditionLootId) { }
|
||||||
|
|
||||||
// If itemid == 0 - money amount is stored in count value
|
// If itemid == 0 - money amount is stored in count value
|
||||||
uint32 itemid;
|
uint32 itemid;
|
||||||
|
uint32 itemIndex;
|
||||||
uint32 count;
|
uint32 count;
|
||||||
int32 randomPropertyId;
|
int32 randomPropertyId;
|
||||||
uint32 randomSuffix;
|
uint32 randomSuffix;
|
||||||
@@ -45,12 +46,12 @@ public:
|
|||||||
static LootItemStorage* instance();
|
static LootItemStorage* instance();
|
||||||
|
|
||||||
void LoadStorageFromDB();
|
void LoadStorageFromDB();
|
||||||
void RemoveEntryFromDB(ObjectGuid containerGUID, uint32 itemid, uint32 count);
|
void RemoveEntryFromDB(ObjectGuid containerGUID, uint32 itemid, uint32 count, uint32 itemIndex);
|
||||||
|
|
||||||
void AddNewStoredLoot(Loot* loot, Player* player);
|
void AddNewStoredLoot(Loot* loot, Player* player);
|
||||||
bool LoadStoredLoot(Item* item, Player* player);
|
bool LoadStoredLoot(Item* item, Player* player);
|
||||||
|
|
||||||
void RemoveStoredLootItem(ObjectGuid containerGUID, uint32 itemid, uint32 count, Loot* loot);
|
void RemoveStoredLootItem(ObjectGuid containerGUID, uint32 itemid, uint32 count, Loot* loot, uint32 itemIndex);
|
||||||
void RemoveStoredLootMoney(ObjectGuid containerGUID, Loot* loot);
|
void RemoveStoredLootMoney(ObjectGuid containerGUID, Loot* loot);
|
||||||
void RemoveStoredLoot(ObjectGuid containerGUID);
|
void RemoveStoredLoot(ObjectGuid containerGUID);
|
||||||
|
|
||||||
|
|||||||
@@ -368,7 +368,8 @@ bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const
|
|||||||
// Constructor, copies most fields from LootStoreItem and generates random count
|
// Constructor, copies most fields from LootStoreItem and generates random count
|
||||||
LootItem::LootItem(LootStoreItem const& li)
|
LootItem::LootItem(LootStoreItem const& li)
|
||||||
{
|
{
|
||||||
itemid = li.itemid;
|
itemid = li.itemid;
|
||||||
|
itemIndex = 0;
|
||||||
conditions = li.conditions;
|
conditions = li.conditions;
|
||||||
|
|
||||||
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemid);
|
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemid);
|
||||||
@@ -466,6 +467,7 @@ void Loot::AddItem(LootStoreItem const& item)
|
|||||||
{
|
{
|
||||||
LootItem generatedLoot(item);
|
LootItem generatedLoot(item);
|
||||||
generatedLoot.count = std::min(count, proto->GetMaxStackSize());
|
generatedLoot.count = std::min(count, proto->GetMaxStackSize());
|
||||||
|
generatedLoot.itemIndex = lootItems.size();
|
||||||
lootItems.push_back(generatedLoot);
|
lootItems.push_back(generatedLoot);
|
||||||
count -= proto->GetMaxStackSize();
|
count -= proto->GetMaxStackSize();
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ typedef GuidSet AllowedLooterSet;
|
|||||||
struct LootItem
|
struct LootItem
|
||||||
{
|
{
|
||||||
uint32 itemid;
|
uint32 itemid;
|
||||||
|
uint32 itemIndex;
|
||||||
uint32 randomSuffix;
|
uint32 randomSuffix;
|
||||||
int32 randomPropertyId;
|
int32 randomPropertyId;
|
||||||
ConditionList conditions; // additional loot condition
|
ConditionList conditions; // additional loot condition
|
||||||
|
|||||||
Reference in New Issue
Block a user