diff options
| author | Shauren <shauren.trinity@gmail.com> | 2013-07-22 19:52:18 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2013-07-22 19:52:18 +0200 |
| commit | 21c42bf5a7e916bbb705b3195acaa890dc0126f8 (patch) | |
| tree | 3ac7dd795a2ec553601d984dbf29ebe5a50cf5c3 | |
| parent | 35799424389f578854149297b68b51f84a79dab1 (diff) | |
Core/Creatures: Implemented new extended cost requirements and fixed some items requiring too much honor/conquest points
| -rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 6 | ||||
| -rw-r--r-- | src/server/game/DataStores/DB2fmt.h | 2 | ||||
| -rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 10 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 86 | ||||
| -rw-r--r-- | src/server/game/Handlers/ItemHandler.cpp | 41 |
6 files changed, 126 insertions, 23 deletions
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 81b3301ade0..0a60d0b860f 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -135,7 +135,11 @@ struct ItemExtendedCostEntry //uint32 ItemPurchaseGroup; // 15 uint32 RequiredCurrency[MAX_ITEM_EXT_COST_CURRENCIES];// 16-20 required curency id uint32 RequiredCurrencyCount[MAX_ITEM_EXT_COST_CURRENCIES];// 21-25 required curency count - //uint32 Unknown[5]; // 26-30 + uint32 RequiredFactionId; + uint32 RequiredFactionStanding; + uint32 RequirementFlags; + uint32 RequiredGuildLevel; + uint32 RequiredAchievement; }; #define KEYCHAIN_SIZE 32 diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h index e4b6801f36c..e2904aed51e 100644 --- a/src/server/game/DataStores/DB2fmt.h +++ b/src/server/game/DataStores/DB2fmt.h @@ -21,7 +21,7 @@ char const Itemfmt[]="niiiiiii"; char const ItemCurrencyCostfmt[]="xn"; char const ItemSparsefmt[]="niiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisssssiiiiiiiiiiiiiiiiiiiiiifiiifii"; -char const ItemExtendedCostEntryfmt[]="nxxiiiiiiiiiiiixiiiiiiiiiixxxxx"; +char const ItemExtendedCostEntryfmt[]="nxxiiiiiiiiiiiixiiiiiiiiiiiiiii"; char const KeyChainfmt[]="nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; #endif diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 11ca372625a..fd8c6dfba42 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -405,6 +405,16 @@ enum ItemEnchantmentType ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET = 8 }; +enum ItemExtendedCostFlags +{ + ITEM_EXT_COST_FLAG_REQUIRE_GUILD = 0x01, + ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 = 0x02, + ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_2 = 0x04, + ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_3 = 0x08, + ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_4 = 0x10, + ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_5 = 0x20, +}; + enum ItemLimitCategoryMode { ITEM_LIMIT_CATEGORY_MODE_HAVE = 0, // limit applied to amount items in inventory/bank diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index bc7294a5f16..13ed277eda3 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -348,7 +348,7 @@ struct VendorItemData return m_items[slot]; } bool Empty() const { return m_items.empty(); } - uint8 GetItemCount() const { return m_items.size(); } + uint32 GetItemCount() const { return m_items.size(); } void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, uint8 type) { m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost, type)); @@ -412,7 +412,7 @@ typedef std::map<uint32, time_t> CreatureSpellCooldowns; // max different by z coordinate for creature aggro reaction #define CREATURE_Z_ATTACK_RANGE 3 -#define MAX_VENDOR_ITEMS 300 // Limitation in 4.x.x item count in SMSG_LIST_INVENTORY +#define MAX_VENDOR_ITEMS 150 // Limitation in 4.x.x item count in SMSG_LIST_INVENTORY enum CreatureCellMoveState { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 42d50e5a00b..2949cbc80df 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -21656,6 +21656,9 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c for (int i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i) { + if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i)) + continue; + if (iece->RequiredCurrency[i]) ModifyCurrency(iece->RequiredCurrency[i], -int32(iece->RequiredCurrencyCount[i] * stacks), true, true); } @@ -21774,7 +21777,13 @@ bool Player::BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uin return false; } - if (!HasCurrency(iece->RequiredCurrency[i], (iece->RequiredCurrencyCount[i] * stacks))) + if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i)) + { + // Not implemented + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } + else if (!HasCurrency(iece->RequiredCurrency[i], (iece->RequiredCurrencyCount[i] * stacks))) { SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error return false; @@ -21788,6 +21797,30 @@ bool Player::BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uin SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL); return false; } + + if (iece->RequiredFactionId && GetReputationRank(iece->RequiredFactionId) < iece->RequiredFactionStanding) + { + SendBuyError(BUY_ERR_REPUTATION_REQUIRE, creature, currency, 0); + return false; + } + + if (iece->RequirementFlags & ITEM_EXT_COST_FLAG_REQUIRE_GUILD && !GetGuildId()) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } + + if (iece->RequiredGuildLevel && iece->RequiredGuildLevel < GetGuildLevel()) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } + + if (iece->RequiredAchievement && !HasAchieved(iece->RequiredAchievement)) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } } else // currencies have no price defined, can only be bought with ExtendedCost { @@ -21811,6 +21844,9 @@ bool Player::BuyCurrencyFromVendorSlot(uint64 vendorGuid, uint32 vendorSlot, uin if (!iece->RequiredCurrency[i]) continue; + if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i)) + continue; + ModifyCurrency(iece->RequiredCurrency[i], -int32(iece->RequiredCurrencyCount[i]) * stacks, false, true); } } @@ -21921,7 +21957,12 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 return false; } - if (!HasCurrency(iece->RequiredCurrency[i], iece->RequiredCurrencyCount[i] * stacks)) + if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i)) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } + else if (!HasCurrency(iece->RequiredCurrency[i], iece->RequiredCurrencyCount[i] * stacks)) { SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); return false; @@ -21935,6 +21976,30 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 SendEquipError(EQUIP_ERR_CANT_EQUIP_RANK, NULL, NULL); return false; } + + if (iece->RequiredFactionId && GetReputationRank(iece->RequiredFactionId) < iece->RequiredFactionStanding) + { + SendBuyError(BUY_ERR_REPUTATION_REQUIRE, creature, item, 0); + return false; + } + + if (iece->RequirementFlags & ITEM_EXT_COST_FLAG_REQUIRE_GUILD && !GetGuildId()) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } + + if (iece->RequiredGuildLevel && iece->RequiredGuildLevel < GetGuildLevel()) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } + + if (iece->RequiredAchievement && !HasAchieved(iece->RequiredAchievement)) + { + SendEquipError(EQUIP_ERR_VENDOR_MISSING_TURNINS, NULL, NULL); // Find correct error + return false; + } } uint32 price = 0; @@ -26610,6 +26675,13 @@ void Player::SendRefundInfo(Item* item) data.WriteByteSeq(guid[2]); for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i) // currency cost data { + if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i)) + { + data << uint32(0); + data << uint32(0); + continue; + } + CurrencyTypesEntry const* currencyType = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]); uint32 precision = (currencyType && currencyType->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1; @@ -26667,6 +26739,13 @@ void Player::SendItemRefundResult(Item* item, ItemExtendedCostEntry const* iece, { for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i) { + if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i)) + { + data << uint32(0); + data << uint32(0); + continue; + } + CurrencyTypesEntry const* currencyType = sCurrencyTypesStore.LookupEntry(iece->RequiredCurrency[i]); uint32 precision = (currencyType && currencyType->Flags & CURRENCY_FLAG_HIGH_PRECISION) ? CURRENCY_PRECISION : 1; @@ -26780,6 +26859,9 @@ void Player::RefundItem(Item* item) // Grant back currencies for (uint8 i = 0; i < MAX_ITEM_EXT_COST_CURRENCIES; ++i) { + if (iece->RequirementFlags & (ITEM_EXT_COST_CURRENCY_REQ_IS_SEASON_EARNED_1 << i)) + continue; + uint32 count = iece->RequiredCurrencyCount[i]; uint32 currencyid = iece->RequiredCurrency[i]; if (count && currencyid) diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 86e5004332a..3b8659c7d6a 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -571,7 +571,7 @@ void WorldSession::SendListInventory(uint64 vendorGuid) vendor->StopMoving(); VendorItemData const* vendorItems = vendor->GetVendorItems(); - uint8 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0; + uint32 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0; //if (rawItemCount > 300), // rawItemCount = 300; // client cap but uint8 max value is 255 @@ -582,10 +582,11 @@ void WorldSession::SendListInventory(uint64 vendorGuid) const float discountMod = _player->GetReputationPriceDiscount(vendor); uint8 count = 0; - for (uint8 slot = 0; slot < rawItemCount; ++slot) + for (uint32 slot = 0; slot < rawItemCount; ++slot) { VendorItem const* vendorItem = vendorItems->GetItem(slot); - if (!vendorItem) continue; + if (!vendorItem) + continue; if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM) { @@ -622,18 +623,18 @@ void WorldSession::SendListInventory(uint64 vendorGuid) if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES)) price -= CalculatePct(price, priceMod); - ++count; itemsData << uint32(slot + 1); // client expects counting to start at 1 itemsData << uint32(itemTemplate->MaxDurability); - if (vendorItem->ExtendedCost != 0) + if (vendorItem->ExtendedCost) { enablers.push_back(0); itemsData << uint32(vendorItem->ExtendedCost); } else enablers.push_back(1); - enablers.push_back(1); // unk bit + + enablers.push_back(1); // item is unlocked itemsData << uint32(vendorItem->item); itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency @@ -642,6 +643,9 @@ void WorldSession::SendListInventory(uint64 vendorGuid) // if (!unk "enabler") data << uint32(something); itemsData << int32(leftInStock); itemsData << uint32(itemTemplate->BuyCount); + + if (++count >= MAX_VENDOR_ITEMS) + break; } else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY) { @@ -649,22 +653,16 @@ void WorldSession::SendListInventory(uint64 vendorGuid) if (!currencyTemplate) continue; - if (vendorItem->ExtendedCost == 0) + if (!vendorItem->ExtendedCost) continue; // there's no price defined for currencies, only extendedcost is used - ++count; itemsData << uint32(slot + 1); // client expects counting to start at 1 itemsData << uint32(0); // max durability - if (vendorItem->ExtendedCost != 0) - { - enablers.push_back(0); - itemsData << uint32(vendorItem->ExtendedCost); - } - else - enablers.push_back(1); + enablers.push_back(0); + itemsData << uint32(vendorItem->ExtendedCost); - enablers.push_back(1); // unk bit + enablers.push_back(1); // item is unlocked itemsData << uint32(vendorItem->item); itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency @@ -673,6 +671,9 @@ void WorldSession::SendListInventory(uint64 vendorGuid) // if (!unk "enabler") data << uint32(something); itemsData << int32(-1); itemsData << uint32(vendorItem->maxcount); + + if (++count >= MAX_VENDOR_ITEMS) + break; } // else error } @@ -706,7 +707,13 @@ void WorldSession::SendListInventory(uint64 vendorGuid) data.WriteByteSeq(guid[0]); data.WriteByteSeq(guid[6]); - data << uint8(count == 0); // unk byte, item count 0: 1, item count != 0: 0 or some "random" value below 300 + // It doesn't matter what value is used here (PROBABLY its full vendor size) + // What matters is that if count of items we can see is 0 and this field is 1 + // then client will open the vendor list, otherwise it won't + if (rawItemCount) + data << uint8(rawItemCount); + else + data << uint8(vendor->IsArmorer()); data.WriteByteSeq(guid[2]); data.WriteByteSeq(guid[3]); |
