diff --git a/src/game/Object/Creature.cpp b/src/game/Object/Creature.cpp index e76322f95..0ebeff039 100644 --- a/src/game/Object/Creature.cpp +++ b/src/game/Object/Creature.cpp @@ -92,13 +92,15 @@ bool VendorItemData::RemoveItem(uint32 item_id, uint8 type) return found; } -VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint8 type, uint32 extendedCost) const +VendorItem const* VendorItemData::FindItem(uint32 item_id) const { for (VendorItemList::const_iterator i = m_items.begin(); i != m_items.end(); ++i) { // Skip checking for conditions, condition system is powerfull enough to not require additional entries only for the conditions - if ((*i)->item == item_id && (*i)->ExtendedCost == extendedCost && (*i)->type == type) + if ((*i)->item == item_id) + { return *i; + } } return NULL; } diff --git a/src/game/Object/Creature.h b/src/game/Object/Creature.h index 342e2d57b..f0ba6ef9b 100644 --- a/src/game/Object/Creature.h +++ b/src/game/Object/Creature.h @@ -362,6 +362,7 @@ struct VendorItemData } bool RemoveItem(uint32 item_id, uint8 type); VendorItem const* FindItemCostPair(uint32 item_id, uint8 type, uint32 extendedCost) const; + VendorItem const* FindItem(uint32 item_id) const; void Clear() { diff --git a/src/game/Object/ObjectMgr.cpp b/src/game/Object/ObjectMgr.cpp index 38a4bd6cf..42fea20fa 100644 --- a/src/game/Object/ObjectMgr.cpp +++ b/src/game/Object/ObjectMgr.cpp @@ -9537,6 +9537,163 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry, uint32 item, uint8 type) return true; } +bool ObjectMgr::IsVendorItemValid(bool isTemplate, char const* tableName, uint32 vendor_entry, uint32 item_id, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, uint16 conditionId, Player* pl, std::set* skip_vendors) const +{ + char const* idStr = isTemplate ? "vendor template" : "vendor"; + CreatureInfo const* cInfo = NULL; + + if (!isTemplate) + { + cInfo = GetCreatureTemplate(vendor_entry); + if (!cInfo) + { + if (pl) + { + ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); + } + else + { + sLog.outErrorDb("Table `%s` has data for nonexistent creature (Entry: %u), ignoring", tableName, vendor_entry); + } + return false; + } + + if (!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR)) + { + if (!skip_vendors || skip_vendors->count(vendor_entry) == 0) + { + if (pl) + { + ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); + } + else + { + sLog.outErrorDb("Table `%s` has data for creature (Entry: %u) without vendor flag, ignoring", tableName, vendor_entry); + } + + if (skip_vendors) + { + skip_vendors->insert(vendor_entry); + } + } + return false; + } + } + + if (!GetItemPrototype(item_id)) + { + if (pl) + { + ChatHandler(pl).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id); + } + else + sLog.outErrorDb("Table `%s` for %s %u contain nonexistent item (%u), ignoring", + tableName, idStr, vendor_entry, item_id); + return false; + } + + if (ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost)) + { + if (pl) + ChatHandler(pl).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST, ExtendedCost); + else + sLog.outErrorDb("Table `%s` contain item (Entry: %u) with wrong ExtendedCost (%u) for %s %u, ignoring", + tableName, item_id, ExtendedCost, idStr, vendor_entry); + return false; + } + + if (maxcount > 0 && incrtime == 0) + { + if (pl) + { + ChatHandler(pl).PSendSysMessage("MaxCount!=0 (%u) but IncrTime==0", maxcount); + } + else + sLog.outErrorDb("Table `%s` has `maxcount` (%u) for item %u of %s %u but `incrtime`=0, ignoring", + tableName, maxcount, item_id, idStr, vendor_entry); + return false; + } + else if (maxcount == 0 && incrtime > 0) + { + if (pl) + { + ChatHandler(pl).PSendSysMessage("MaxCount==0 but IncrTime<>=0"); + } + else + sLog.outErrorDb("Table `%s` has `maxcount`=0 for item %u of %s %u but `incrtime`<>0, ignoring", + tableName, item_id, idStr, vendor_entry); + return false; + } + + if (conditionId && !sConditionStorage.LookupEntry(conditionId)) + { + sLog.outErrorDb("Table `%s` has `condition_id`=%u for item %u of %s %u but this condition is not valid, ignoring", tableName, conditionId, item_id, idStr, vendor_entry); + return false; + } + + VendorItemData const* vItems = isTemplate ? GetNpcVendorTemplateItemList(vendor_entry) : GetNpcVendorItemList(vendor_entry); + VendorItemData const* tItems = isTemplate ? NULL : GetNpcVendorTemplateItemList(vendor_entry); + + if (!vItems && !tItems) + { + return true; + } // later checks for non-empty lists + + if (vItems && vItems->FindItem(item_id)) + { + if (pl) + { + ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id); + } + else + sLog.outErrorDb("Table `%s` has duplicate items %u for %s %u, ignoring", + tableName, item_id, idStr, vendor_entry); + return false; + } + + if (!isTemplate) + { + if (tItems && tItems->GetItem(item_id)) + { + if (pl) + { + ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id); + } + else + { + if (!cInfo->vendorId) + sLog.outErrorDb("Table `%s` has duplicate items %u for %s %u, ignoring", + tableName, item_id, idStr, vendor_entry); + else + sLog.outErrorDb("Table `%s` has duplicate items %u for %s %u (or possible in vendor template %u), ignoring", + tableName, item_id, idStr, vendor_entry, cInfo->vendorId); + } + return false; + } + } + + uint32 countItems = vItems ? vItems->GetItemCount() : 0; + countItems += tItems ? tItems->GetItemCount() : 0; + + if (countItems >= MAX_VENDOR_ITEMS) + { + if (pl) + { + ChatHandler(pl).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS); + } + else + sLog.outErrorDb("Table `%s` has too many items (%u >= %i) for %s %u, ignoring", + tableName, countItems, MAX_VENDOR_ITEMS, idStr, vendor_entry); + return false; + } + + return true; +} + +/* + This is the Pre Dev21 version of the function + Delete this if the above works? +*/ bool ObjectMgr::IsVendorItemValid(bool isTemplate, char const* tableName, uint32 vendor_entry, uint32 item_id, uint8 type, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, uint16 conditionId, Player* pl, std::set* skip_vendors) const { char const* idStr = isTemplate ? "vendor template" : "vendor"; diff --git a/src/game/Object/ObjectMgr.h b/src/game/Object/ObjectMgr.h index 65cfe3840..6ebbb2d9b 100644 --- a/src/game/Object/ObjectMgr.h +++ b/src/game/Object/ObjectMgr.h @@ -1063,6 +1063,7 @@ class ObjectMgr void AddVendorItem(uint32 entry, uint32 item, uint8 type, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost); bool RemoveVendorItem(uint32 entry, uint32 item, uint8 type); bool IsVendorItemValid(bool isTemplate, char const* tableName, uint32 vendor_entry, uint32 item, uint8 type, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, uint16 conditionId, Player* pl = NULL, std::set* skip_vendors = NULL) const; + bool IsVendorItemValid(bool isTemplate, char const* tableName, uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, uint16 conditionId, Player* pl = NULL, std::set* skip_vendors = NULL) const; static inline void GetLocaleString(const StringVector& data, int loc_idx, std::string& value) { diff --git a/src/game/Object/Unit.cpp b/src/game/Object/Unit.cpp index b4d58edb7..836ca5a46 100644 --- a/src/game/Object/Unit.cpp +++ b/src/game/Object/Unit.cpp @@ -96,7 +96,7 @@ void MovementInfo::Read(ByteBuffer& data, uint16 opcode) MovementStatusElements element = sequence[i]; if (element == MSEEnd) break; - + if (element >= MSEGuidBit0 && element <= MSEGuidBit7) { guid[element - MSEGuidBit0] = data.ReadBit(); diff --git a/src/game/Server/DBCStructure.h b/src/game/Server/DBCStructure.h index 2e4badc2f..e58d579ab 100644 --- a/src/game/Server/DBCStructure.h +++ b/src/game/Server/DBCStructure.h @@ -1217,13 +1217,13 @@ struct ItemRandomPropertiesEntry uint32 ID; // 0 m_ID //char* internalName // 1 m_Name uint32 enchant_id[5]; // 2-6 m_Enchantment - DBCString nameSuffix; // 7 m_name_lang + char* nameSuffix; // 7 m_name_lang }; struct ItemRandomSuffixEntry { uint32 ID; // 0 m_ID - DBCString nameSuffix; // 1 m_name_lang + char* nameSuffix; // 1 m_name_lang // 2 m_internalName uint32 enchant_id[5]; // 3-7 m_enchantment uint32 prefix[5]; // 8-12 m_allocationPct diff --git a/src/game/WorldHandlers/Chat.cpp b/src/game/WorldHandlers/Chat.cpp index 5a2816434..92643ca85 100644 --- a/src/game/WorldHandlers/Chat.cpp +++ b/src/game/WorldHandlers/Chat.cpp @@ -2018,7 +2018,7 @@ bool ChatHandler::isValidChatMessage(const char* message) } else if (linkedItem) { - DBCString suffix = itemSuffix?itemSuffix->nameSuffix:(itemProperty?itemProperty->nameSuffix:NULL); + char* suffix = itemSuffix ? itemSuffix->nameSuffix : (itemProperty ? itemProperty->nameSuffix : NULL); std::string expectedName = std::string(linkedItem->Name1); if (suffix)