mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-24 19:06:49 +01:00
Core/Transmog: Charge money for transmogrification
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user