aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/DataStores/DBCStores.cpp6
-rwxr-xr-xsrc/server/game/DataStores/DBCStores.h6
-rwxr-xr-xsrc/server/game/DataStores/DBCStructure.h49
-rwxr-xr-xsrc/server/game/DataStores/DBCfmt.h10
-rwxr-xr-xsrc/server/game/Entities/Item/Item.cpp167
-rwxr-xr-xsrc/server/game/Entities/Item/Item.h5
-rwxr-xr-xsrc/server/game/Entities/Item/ItemPrototype.h9
-rwxr-xr-xsrc/server/game/Handlers/ItemHandler.cpp8
8 files changed, 250 insertions, 10 deletions
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index f7f38021daf..fb2e0806d99 100755
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -110,9 +110,15 @@ DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptf
DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
+DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore(ImportPriceArmorfmt);
+DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore(ImportPriceQualityfmt);
+DBCStorage <ImportPriceShieldEntry> sImportPriceShieldStore(ImportPriceShieldfmt);
+DBCStorage <ImportPriceWeaponEntry> sImportPriceWeaponStore(ImportPriceWeaponfmt);
+DBCStorage <ItemPriceBaseEntry> sItemPriceBaseStore(ItemPriceBasefmt);
DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore(ItemArmorQualityfmt);
DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore(ItemArmorShieldfmt);
DBCStorage <ItemArmorTotalEntry> sItemArmorTotalStore(ItemArmorTotalfmt);
+DBCStorage <ItemClassEntry> sItemClassStore(ItemClassfmt);
DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt);
DBCStorage <ItemDamageEntry> sItemDamageAmmoStore(ItemDamagefmt);
DBCStorage <ItemDamageEntry> sItemDamageOneHandStore(ItemDamagefmt);
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index d94b60c1384..252d8c53d92 100755
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -121,9 +121,15 @@ extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
extern DBCStorage <gtOCTHpPerStaminaEntry> sGtOCTHpPerStaminaStore;
extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
extern DBCStorage <HolidaysEntry> sHolidaysStore;
+extern DBCStorage <ImportPriceArmorEntry> sImportPriceArmorStore;
+extern DBCStorage <ImportPriceQualityEntry> sImportPriceQualityStore;
+extern DBCStorage <ImportPriceShieldEntry> sImportPriceShieldStore;
+extern DBCStorage <ImportPriceWeaponEntry> sImportPriceWeaponStore;
+extern DBCStorage <ItemPriceBaseEntry> sItemPriceBaseStore;
extern DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore;
extern DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore;
extern DBCStorage <ItemArmorTotalEntry> sItemArmorTotalStore;
+extern DBCStorage <ItemClassEntry> sItemClassStore;
extern DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore;
extern DBCStorage <ItemDamageEntry> sItemDamageAmmoStore;
extern DBCStorage <ItemDamageEntry> sItemDamageOneHandStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index cde1aa51e0d..1a9c7b16398 100755
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1153,6 +1153,45 @@ struct HolidaysEntry
//uint32 flags; // 54 m_flags (0 = Darkmoon Faire, Fishing Contest and Wotlk Launch, rest is 1)
};
+// ImportPriceArmor.dbc
+struct ImportPriceArmorEntry
+{
+ uint32 InventoryType; // 1 Id/InventoryType
+ float ClothFactor; // 2 Price factor cloth
+ float LeatherFactor; // 3 Price factor leather
+ float MailFactor; // 4 Price factor mail
+ float PlateFactor; // 5 Price factor plate
+};
+
+// ImportPriceQuality.dbc
+struct ImportPriceQualityEntry
+{
+ uint32 QualityId; // 1 Quality Id (+1?)
+ float Factor; // 2 Price factor
+};
+
+// ImportPriceShield.dbc
+struct ImportPriceShieldEntry
+{
+ uint32 Id; // 1 Unk id (only 1 and 2)
+ float Factor; // 2 Price factor
+};
+
+// ImportPriceWeapon.dbc
+struct ImportPriceWeaponEntry
+{
+ uint32 Id; // 1 Unk id (mainhand - 0, offhand - 1, weapon - 2, 2hweapon - 3, ranged/rangedright/relic - 4)
+ float Factor; // 2 Price factor
+};
+
+// ItemPriceBase.dbc
+struct ItemPriceBaseEntry
+{
+ uint32 ItemLevel; // 2 Item level (1 - 1000)
+ float ArmorFactor; // 3 Price factor for armor
+ float WeaponFactor; // 4 Price factor for weapons
+};
+
// common struct for:
// ItemDamageAmmo.dbc
// ItemDamageOneHand.dbc
@@ -1190,6 +1229,16 @@ struct ItemArmorTotalEntry
float Value[4]; // 2-5 multiplier for armor types (cloth...plate)
};
+// ItemClass.dbc
+struct ItemClassEntry
+{
+ uint32 Class; // 1 item class id
+ //uint32 Unk; // 2 unk
+ //uint32 IsWeapon; // 3 1 for weapon, 0 for everything else
+ float PriceFactor; // 4 used to calculate certain prices
+ //char* Name; // class name
+};
+
struct ItemBagFamilyEntry
{
uint32 ID; // 0
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 780a33685d6..3c2900f60e9 100755
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -19,6 +19,9 @@
#ifndef TRINITY_DBCSFRM_H
#define TRINITY_DBCSFRM_H
+// x - skip<uint32>, X - skip<uint8>, s - char*, f - float, i - uint32, b - uint8, d - index (not included)
+// n - index (included), l - bool, p - field present in sql dbc, a - field absent in sql dbc
+
const char Achievementfmt[]="niixsxiixixxii";
//const std::string CustomAchievementfmt="pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp";
//const std::string CustomAchievementIndex = "ID";
@@ -74,12 +77,17 @@ const char GtOCTRegenHPfmt[]="f";
//const char GtOCTRegenMPfmt[]="f";
const char GtRegenHPPerSptfmt[]="f";
const char GtRegenMPPerSptfmt[]="xf";
-
const char Holidaysfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix";
+const char ImportPriceArmorfmt[]="nffff";
+const char ImportPriceQualityfmt[]="nf";
+const char ImportPriceShieldfmt[]="nf";
+const char ImportPriceWeaponfmt[]="nf";
+const char ItemPriceBasefmt[]="diff";
const char ItemBagFamilyfmt[]="nx";
const char ItemArmorQualityfmt[]="nfffffffi";
const char ItemArmorShieldfmt[]="nifffffff";
const char ItemArmorTotalfmt[]="niffff";
+const char ItemClassfmt[]="dixxfs";
const char ItemDamagefmt[]="nfffffffi";
const char ItemDisenchantLootfmt[]="niiiiii";
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 130aac50935..59c23ec5176 100755
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -1275,7 +1275,7 @@ bool Item::CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* t
proto1->InventoryType == INVTYPE_QUIVER)
return false;
- if (proto1->SubClass != proto2->SubClass && (proto1->Class != ITEM_CLASS_WEAPON || !transmogrified->IsRangedWeapon() || !transmogrifier->IsRangedWeapon()))
+ if (proto1->SubClass != proto2->SubClass && (proto1->Class != ITEM_CLASS_WEAPON || !proto2->IsRangedWeapon() || !proto1->IsRangedWeapon()))
return false;
if (proto1->InventoryType != proto2->InventoryType &&
@@ -1290,20 +1290,171 @@ bool Item::HasStats() const
if (GetItemRandomPropertyId() != 0)
return true;
+ ItemTemplate const* proto = GetTemplate();
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
- if (GetTemplate()->ItemStat[i].ItemStatValue != 0)
+ if (proto->ItemStat[i].ItemStatValue != 0)
return true;
return false;
}
-bool Item::IsRangedWeapon() const
+// used by mail items, transmog cost, stationeryinfo and others
+uint32 Item::GetSellPrice(bool& normalSellPrice) const
{
ItemTemplate const* proto = GetTemplate();
- if (proto && proto->Class == ITEM_CLASS_WEAPON)
- return proto->SubClass == ITEM_SUBCLASS_WEAPON_BOW ||
- proto->SubClass == ITEM_SUBCLASS_WEAPON_GUN ||
- proto->SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW;
+ normalSellPrice = true;
- return false;
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ {
+ return proto->BuyPrice;
+ }
+ else
+ {
+ ImportPriceQualityEntry const* qualityPrice = sImportPriceQualityStore.LookupEntry(proto->Quality + 1);
+ ItemPriceBaseEntry const* basePrice = sItemPriceBaseStore.LookupEntry(proto->ItemLevel);
+
+ if (!qualityPrice || !basePrice)
+ return 0;
+
+ float qualityFactor = qualityPrice->Factor;
+ float baseFactor = 0.0f;
+
+ uint32 inventoryType = proto->InventoryType;
+
+ if (inventoryType == INVTYPE_WEAPON ||
+ inventoryType == INVTYPE_2HWEAPON ||
+ inventoryType == INVTYPE_WEAPONMAINHAND ||
+ inventoryType == INVTYPE_WEAPONOFFHAND ||
+ inventoryType == INVTYPE_RANGED ||
+ inventoryType == INVTYPE_THROWN ||
+ inventoryType == INVTYPE_RANGEDRIGHT)
+ baseFactor = basePrice->WeaponFactor;
+ else
+ baseFactor = basePrice->ArmorFactor;
+
+ if (inventoryType == INVTYPE_ROBE)
+ inventoryType = INVTYPE_CHEST;
+
+ float typeFactor = 0.0f;
+ uint8 wepType = -1;
+
+ switch (inventoryType)
+ {
+ case INVTYPE_HEAD:
+ case INVTYPE_SHOULDERS:
+ case INVTYPE_CHEST:
+ case INVTYPE_WAIST:
+ case INVTYPE_LEGS:
+ case INVTYPE_FEET:
+ case INVTYPE_WRISTS:
+ case INVTYPE_HANDS:
+ case INVTYPE_CLOAK:
+ {
+ ImportPriceArmorEntry const* armorPrice = sImportPriceArmorStore.LookupEntry(inventoryType);
+ if (!armorPrice)
+ return 0;
+
+ switch (proto->SubClass)
+ {
+ case ITEM_SUBCLASS_ARMOR_MISCELLANEOUS:
+ case ITEM_SUBCLASS_ARMOR_CLOTH:
+ {
+ typeFactor = armorPrice->ClothFactor;
+ break;
+ }
+ case ITEM_SUBCLASS_ARMOR_LEATHER:
+ {
+ typeFactor = armorPrice->ClothFactor;
+ break;
+ }
+ case ITEM_SUBCLASS_ARMOR_MAIL:
+ {
+ typeFactor = armorPrice->ClothFactor;
+ break;
+ }
+ case ITEM_SUBCLASS_ARMOR_PLATE:
+ {
+ typeFactor = armorPrice->ClothFactor;
+ break;
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+
+ break;
+ }
+ case INVTYPE_SHIELD:
+ {
+ ImportPriceShieldEntry const* shieldPrice = sImportPriceShieldStore.LookupEntry(1); // it only has two rows, it's unclear which is the one used
+ if (!shieldPrice)
+ return 0;
+
+ typeFactor = shieldPrice->Factor;
+ break;
+ }
+ case INVTYPE_WEAPONMAINHAND:
+ wepType = 0; // unk enum, fall back
+ case INVTYPE_WEAPONOFFHAND:
+ wepType = 1; // unk enum, fall back
+ case INVTYPE_WEAPON:
+ wepType = 2; // unk enum, fall back
+ case INVTYPE_2HWEAPON:
+ wepType = 3; // unk enum, fall back
+ case INVTYPE_RANGED:
+ case INVTYPE_RANGEDRIGHT:
+ case INVTYPE_RELIC:
+ {
+ wepType = 4; // unk enum
+
+ ImportPriceWeaponEntry const* weaponPrice = sImportPriceWeaponStore.LookupEntry(wepType + 1); // it only has two rows, it's unclear which is the one used
+ if (!weaponPrice)
+ return 0;
+
+ typeFactor = weaponPrice->Factor;
+ break;
+ }
+ default:
+ return proto->BuyPrice;
+ }
+
+ normalSellPrice = false;
+ return (uint32)(qualityFactor * proto->Unk430_2 * proto->Unk430_1 * typeFactor * baseFactor);
+ }
+}
+
+uint32 Item::GetTransmogrifyCost() const
+{
+ ItemTemplate const* proto = GetTemplate();
+ uint32 cost = 0;
+
+ if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE)
+ cost = proto->SellPrice;
+ else
+ {
+ bool normalPrice;
+ cost = GetSellPrice(normalPrice);
+
+ if (!normalPrice)
+ {
+ if (proto->BuyCount <= 1)
+ {
+ ItemClassEntry const* classEntry = sItemClassStore.LookupEntry(proto->Class);
+ if (classEntry)
+ cost *= classEntry->PriceFactor;
+ else
+ cost = 0;
+ }
+ else
+ cost /= 4 * proto->BuyCount;
+ }
+ else
+ cost = proto->SellPrice;
+ }
+
+ if (cost < 10000)
+ cost = 10000;
+
+ return cost;
}
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 64b74539727..2d5ebaa555f 100755
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -323,7 +323,7 @@ class Item : public Object
bool IsWeaponVellum() const { return GetTemplate()->IsWeaponVellum(); }
bool IsArmorVellum() const { return GetTemplate()->IsArmorVellum(); }
bool IsConjuredConsumable() const { return GetTemplate()->IsConjuredConsumable(); }
- bool IsRangedWeapon() const;
+ bool IsRangedWeapon() const { return GetTemplate()->IsRangedWeapon(); }
// Item Refund system
void SetNotRefundable(Player* owner, bool changestate = true, SQLTransaction* trans = NULL);
@@ -350,6 +350,7 @@ class Item : public Object
bool CanBeTransmogrified() const;
bool CanTransmogrify() const;
static bool CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* transmogrifier);
+ uint32 GetTransmogrifyCost() const;
uint32 GetVisibleEntry() const
{
@@ -358,6 +359,8 @@ class Item : public Object
return GetEntry();
}
+ uint32 GetSellPrice(bool& success) const;
+
private:
std::string m_text;
uint8 m_slot;
diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
index 7bfe43e0691..cfc65292507 100755
--- a/src/server/game/Entities/Item/ItemPrototype.h
+++ b/src/server/game/Entities/Item/ItemPrototype.h
@@ -196,6 +196,7 @@ enum ItemFlagsExtra
ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD = 0x00000004, // when item uses extended cost, gold is also required
ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100,
ITEM_FLAGS_EXTRA_CASTER_WEAPON = 0x00000200,
+ ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE = 0x00004000,
ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND = 0x00020000,
ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG = 0x00200000,
ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG = 0x00400000,
@@ -740,6 +741,14 @@ struct ItemTemplate
bool IsWeaponVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT; }
bool IsArmorVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ITEM_ENCHANTMENT; }
bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_PROTO_FLAG_CONJURED); }
+
+ bool IsRangedWeapon() const
+ {
+ return Class == ITEM_CLASS_WEAPON ||
+ SubClass == ITEM_SUBCLASS_WEAPON_BOW ||
+ SubClass == ITEM_SUBCLASS_WEAPON_GUN ||
+ SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW;
+ }
};
// Benchmarked: Faster than std::map (insert/find)
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index b36ca5853cf..18859e766d1 100755
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -1534,6 +1534,7 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
return;
}
+ int32 cost = 0;
for (uint8 i = 0; i < count; ++i)
{
// slot of the transmogrified item
@@ -1615,7 +1616,14 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
itemTransmogrifier->SetOwnerGUID(player->GetGUID());
itemTransmogrifier->SetNotRefundable(player);
itemTransmogrifier->ClearSoulboundTradeable(player);
+
+ cost += itemTransmogrified->GetTransmogrifyCost();
}
+
+ // trusting the client, if it got here it has to have enough money
+ // ... unless client was modified
+ if (cost) // 0 cost if reverting look
+ player->ModifyMoney(-cost);
}
delete[] itemGuids;