aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Globals/ObjectMgr.cpp
diff options
context:
space:
mode:
authorRoc13x <roc13x@gmail.com>2017-10-09 20:03:25 +0100
committerShauren <shauren.trinity@gmail.com>2017-10-09 21:03:25 +0200
commita6d1b3447209ba2203edd5d934f061228f1d1ae0 (patch)
tree4c25122fe52d45e19e473250791777439921571e /src/server/game/Globals/ObjectMgr.cpp
parent6d07f55c0077c1a41956bbfb10e0fcbc9a3c913c (diff)
Core/Creature: Refactor and improve vendor items (#20328)
* Implement item bonuses in vendors. * Implement the PlayerConditionID and IgnoreFiltering DB columns. * Fix loading referenced vendor items * Allow adding bonuses in .npc add item command
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp119
1 files changed, 73 insertions, 46 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 365b329f421..24a54057d0d 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -8666,12 +8666,11 @@ void ObjectMgr::LoadCreatureDefaultTrainers()
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " default trainers in %u ms", _creatureDefaultTrainers.size(), GetMSTimeDiffToNow(oldMSTime));
}
-int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, uint8 referenceType, std::set<uint32> *skip_vendors)
+int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *skip_vendors)
{
// find all items from the reference vendor
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_NPC_VENDOR_REF);
stmt->setUInt32(0, uint32(item));
- stmt->setUInt8(1, referenceType);
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
@@ -8686,20 +8685,27 @@ int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, uint8 referenceType
// if item is a negative, its a reference
if (item_id < 0)
- count += LoadReferenceVendor(vendor, -item_id, referenceType, skip_vendors);
+ count += LoadReferenceVendor(vendor, -item_id, skip_vendors);
else
{
- int32 maxcount = fields[1].GetUInt32();
- uint32 incrtime = fields[2].GetUInt32();
- uint32 ExtendedCost = fields[3].GetUInt32();
- uint8 type = fields[4].GetUInt8();
+ VendorItem vItem;
+ vItem.item = item_id;
+ vItem.maxcount = fields[1].GetUInt32();
+ vItem.incrtime = fields[2].GetUInt32();
+ vItem.ExtendedCost = fields[3].GetUInt32();
+ vItem.Type = fields[4].GetUInt8();
+ vItem.PlayerConditionId = fields[6].GetUInt32();
+ vItem.IgnoreFiltering = fields[7].GetBool();
- if (!IsVendorItemValid(vendor, item_id, maxcount, incrtime, ExtendedCost, type, nullptr, skip_vendors))
+ Tokenizer bonusListIDsTok(fields[5].GetString(), ' ');
+ for (char const* token : bonusListIDsTok)
+ vItem.BonusListIDs.push_back(int32(atol(token)));
+
+ if (!IsVendorItemValid(vendor, vItem, nullptr, skip_vendors))
continue;
VendorItemData& vList = _cacheVendorItemStore[vendor];
-
- vList.AddItem(item_id, maxcount, incrtime, ExtendedCost, type);
+ vList.AddItem(std::move(vItem));
++count;
}
} while (result->NextRow());
@@ -8718,10 +8724,9 @@ void ObjectMgr::LoadVendors()
std::set<uint32> skip_vendors;
- QueryResult result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost, type FROM npc_vendor ORDER BY entry, slot ASC");
+ QueryResult result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost, type, BonusListIDs, PlayerConditionID, IgnoreFiltering FROM npc_vendor ORDER BY entry, slot ASC");
if (!result)
{
-
TC_LOG_ERROR("server.loading", ">> Loaded 0 Vendors. DB table `npc_vendor` is empty!");
return;
}
@@ -8737,20 +8742,27 @@ void ObjectMgr::LoadVendors()
// if item is a negative, its a reference
if (item_id < 0)
- count += LoadReferenceVendor(entry, -item_id, 0, &skip_vendors);
+ count += LoadReferenceVendor(entry, -item_id, &skip_vendors);
else
{
- uint32 maxcount = fields[2].GetUInt32();
- uint32 incrtime = fields[3].GetUInt32();
- uint32 ExtendedCost = fields[4].GetUInt32();
- uint8 type = fields[5].GetUInt8();
+ VendorItem vItem;
+ vItem.item = item_id;
+ vItem.maxcount = fields[2].GetUInt32();
+ vItem.incrtime = fields[3].GetUInt32();
+ vItem.ExtendedCost = fields[4].GetUInt32();
+ vItem.Type = fields[5].GetUInt8();
+ vItem.PlayerConditionId = fields[7].GetUInt32();
+ vItem.IgnoreFiltering = fields[8].GetBool();
+
+ Tokenizer bonusListIDsTok(fields[6].GetString(), ' ');
+ for (char const* token : bonusListIDsTok)
+ vItem.BonusListIDs.push_back(int32(atol(token)));
- if (!IsVendorItemValid(entry, item_id, maxcount, incrtime, ExtendedCost, type, nullptr, &skip_vendors))
+ if (!IsVendorItemValid(entry, vItem, nullptr, &skip_vendors))
continue;
VendorItemData& vList = _cacheVendorItemStore[entry];
-
- vList.AddItem(item_id, maxcount, incrtime, ExtendedCost, type);
+ vList.AddItem(std::move(vItem));
++count;
}
}
@@ -8910,21 +8922,21 @@ uint32 ObjectMgr::GetCreatureDefaultTrainer(uint32 creatureId) const
return 0;
}
-void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, uint8 type, bool persist /*= true*/)
+void ObjectMgr::AddVendorItem(uint32 entry, VendorItem const& vItem, bool persist /*= true*/)
{
VendorItemData& vList = _cacheVendorItemStore[entry];
- vList.AddItem(item, maxcount, incrtime, extendedCost, type);
+ vList.AddItem(vItem);
if (persist)
{
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_NPC_VENDOR);
stmt->setUInt32(0, entry);
- stmt->setUInt32(1, item);
- stmt->setUInt8(2, maxcount);
- stmt->setUInt32(3, incrtime);
- stmt->setUInt32(4, extendedCost);
- stmt->setUInt8(5, type);
+ stmt->setUInt32(1, vItem.item);
+ stmt->setUInt8(2, vItem.maxcount);
+ stmt->setUInt32(3, vItem.incrtime);
+ stmt->setUInt32(4, vItem.ExtendedCost);
+ stmt->setUInt8(5, vItem.Type);
WorldDatabase.Execute(stmt);
}
@@ -8953,7 +8965,7 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, uint8 type, bool per
return true;
}
-bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 id, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, uint8 type, Player* player, std::set<uint32>* skip_vendors, uint32 ORnpcflag) const
+bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, VendorItem const& vItem, Player* player, std::set<uint32>* skip_vendors, uint32 ORnpcflag) const
{
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(vendor_entry);
if (!cInfo)
@@ -8980,61 +8992,76 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 id, int32 maxcount
return false;
}
- if ((type == ITEM_VENDOR_TYPE_ITEM && !sObjectMgr->GetItemTemplate(id)) ||
- (type == ITEM_VENDOR_TYPE_CURRENCY && !sCurrencyTypesStore.LookupEntry(id)))
+ if ((vItem.Type == ITEM_VENDOR_TYPE_ITEM && !sObjectMgr->GetItemTemplate(vItem.item)) ||
+ (vItem.Type == ITEM_VENDOR_TYPE_CURRENCY && !sCurrencyTypesStore.LookupEntry(vItem.item)))
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_NOT_FOUND, id, type);
+ ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_NOT_FOUND, vItem.item, vItem.Type);
else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u, type %u), ignore", vendor_entry, id, type);
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u, type %u), ignore", vendor_entry, vItem.item, vItem.Type);
+ return false;
+ }
+
+ if (vItem.PlayerConditionId && !sPlayerConditionStore.LookupEntry(vItem.PlayerConditionId))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has Item (Entry: %u) with invalid PlayerConditionId (%u) for vendor (%u), ignore", vItem.item, vItem.PlayerConditionId, vendor_entry);
return false;
}
- if (ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost))
+ if (vItem.ExtendedCost && !sItemExtendedCostStore.LookupEntry(vItem.ExtendedCost))
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST, ExtendedCost);
+ ChatHandler(player->GetSession()).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST, vItem.ExtendedCost);
else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore", id, ExtendedCost, vendor_entry);
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore", vItem.item, vItem.ExtendedCost, vendor_entry);
return false;
}
- if (type == ITEM_VENDOR_TYPE_ITEM) // not applicable to currencies
+ if (vItem.Type == ITEM_VENDOR_TYPE_ITEM) // not applicable to currencies
{
- if (maxcount > 0 && incrtime == 0)
+ if (vItem.maxcount > 0 && vItem.incrtime == 0)
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", maxcount);
+ ChatHandler(player->GetSession()).PSendSysMessage("MaxCount != 0 (%u) but IncrTime == 0", vItem.maxcount);
else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", maxcount, id, vendor_entry);
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore", vItem.maxcount, vItem.item, vendor_entry);
return false;
}
- else if (maxcount == 0 && incrtime > 0)
+ else if (vItem.maxcount == 0 && vItem.incrtime > 0)
{
if (player)
ChatHandler(player->GetSession()).PSendSysMessage("MaxCount == 0 but IncrTime<>= 0");
else
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", id, vendor_entry);
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore", vItem.item, vendor_entry);
return false;
}
+
+ for (int32 bonusList : vItem.BonusListIDs)
+ {
+ if (!sDB2Manager.GetItemBonusList(bonusList))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` have Item (Entry: %u) with invalid bonus %u for vendor (%u), ignore", vItem.item, bonusList, vendor_entry);
+ return false;
+ }
+ }
}
VendorItemData const* vItems = GetNpcVendorItemList(vendor_entry);
if (!vItems)
return true; // later checks for non-empty lists
- if (vItems->FindItemCostPair(id, ExtendedCost, type))
+ if (vItems->FindItemCostPair(vItem.item, vItem.ExtendedCost, vItem.Type))
{
if (player)
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, id, ExtendedCost, type);
+ ChatHandler(player->GetSession()).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, vItem.item, vItem.ExtendedCost, vItem.Type);
else
- TC_LOG_ERROR("sql.sql", "Table `npc_vendor` has duplicate items %u (with extended cost %u, type %u) for vendor (Entry: %u), ignoring", id, ExtendedCost, type, vendor_entry);
+ TC_LOG_ERROR("sql.sql", "Table `npc_vendor` has duplicate items %u (with extended cost %u, type %u) for vendor (Entry: %u), ignoring", vItem.item, vItem.ExtendedCost, vItem.Type, vendor_entry);
return false;
}
- if (type == ITEM_VENDOR_TYPE_CURRENCY && maxcount == 0)
+ if (vItem.Type == ITEM_VENDOR_TYPE_CURRENCY && vItem.maxcount == 0)
{
- TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` have Item (Entry: %u, type: %u) with missing maxcount for vendor (%u), ignore", id, type, vendor_entry);
+ TC_LOG_ERROR("sql.sql", "Table `(game_event_)npc_vendor` have Item (Entry: %u, type: %u) with missing maxcount for vendor (%u), ignore", vItem.item, vItem.Type, vendor_entry);
return false;
}