aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2013-07-22 19:52:18 +0200
committerShauren <shauren.trinity@gmail.com>2013-07-22 19:52:18 +0200
commit21c42bf5a7e916bbb705b3195acaa890dc0126f8 (patch)
tree3ac7dd795a2ec553601d984dbf29ebe5a50cf5c3
parent35799424389f578854149297b68b51f84a79dab1 (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.h6
-rw-r--r--src/server/game/DataStores/DB2fmt.h2
-rw-r--r--src/server/game/DataStores/DBCEnums.h10
-rw-r--r--src/server/game/Entities/Creature/Creature.h4
-rw-r--r--src/server/game/Entities/Player/Player.cpp86
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp41
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]);