diff options
21 files changed, 369 insertions, 92 deletions
diff --git a/sql/updates/characters/2012_08_01_00_characters_item_instance_434.sql b/sql/updates/characters/2012_08_01_00_characters_item_instance_434.sql new file mode 100644 index 00000000000..b87b781e293 --- /dev/null +++ b/sql/updates/characters/2012_08_01_00_characters_item_instance_434.sql @@ -0,0 +1,11 @@ +UPDATE `item_instance` SET `enchantments` = REPLACE(`enchantments`,' ',' '); +UPDATE `item_instance` SET `enchantments` = CONCAT(TRIM(`enchantments`),' '); + +UPDATE `item_instance` SET `enchantments` = CONCAT( + SUBSTRING_INDEX(`enchantments`, ' ', 7*3), + ' 0 0 0 0 0 0 0 0 0 ', + SUBSTRING_INDEX(`enchantments`, ' ', -(12-7)*3 - 1)) +WHERE (LENGTH(`enchantments`) - LENGTH(REPLACE(`enchantments`, ' ', ''))) = 12*3; + +UPDATE `item_instance` SET `enchantments` = REPLACE(`enchantments`,' ',' '); +UPDATE `item_instance` SET `enchantments` = CONCAT(TRIM(`enchantments`),' '); diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index a7b4fe4c07f..386e8546236 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -25,6 +25,7 @@ #include "Util.h" #include "Vehicle.h" #include "SharedDefines.h" +#include "ItemPrototype.h" #include <map> #include <set> diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 80f62d9cedb..a9de83d3f80 100755 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -21,6 +21,7 @@ #include "SharedDefines.h" #include "SpellMgr.h" #include "DBCfmt.h" +#include "ItemPrototype.h" #include <map> @@ -109,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); @@ -390,7 +397,13 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc");//14545 LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceArmorStore, dbcPath, "ImportPriceArmor.dbc"); // 15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceQualityStore, dbcPath, "ImportPriceQuality.dbc"); // 15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceShieldStore, dbcPath, "ImportPriceShield.dbc"); // 15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sImportPriceWeaponStore, dbcPath, "ImportPriceWeapon.dbc"); // 15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemPriceBaseStore, dbcPath, "ItemPriceBase.dbc"); // 15595 LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc");//14545 + LoadDBC(availableDbcLocales, bad_dbc_files, sItemClassStore, dbcPath, "ItemClass.dbc"); // 15595 //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemDisplayInfoStore, dbcPath, "ItemDisplayInfo.dbc"); -- not used currently LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc");//14545 LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc");//14545 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..03521512c99 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[]="dixxfx"; 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..9c5d03f5440 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); + 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 2f9d10bb9d5..2d5ebaa555f 100755 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -164,14 +164,15 @@ enum EnchantmentSlot PRISMATIC_ENCHANTMENT_SLOT = 6, // added at apply special permanent enchantment //TODO: 7, //TODO: 8, - MAX_INSPECTED_ENCHANTMENT_SLOT = 9, - - PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix - PROP_ENCHANTMENT_SLOT_1 = 8, // used with RandomSuffix - PROP_ENCHANTMENT_SLOT_2 = 9, // used with RandomSuffix and RandomProperty - PROP_ENCHANTMENT_SLOT_3 = 10, // used with RandomProperty - PROP_ENCHANTMENT_SLOT_4 = 11, // used with RandomProperty - MAX_ENCHANTMENT_SLOT = 12 + TRANSMOGRIFY_ENCHANTMENT_SLOT = 9, + MAX_INSPECTED_ENCHANTMENT_SLOT = 10, + + PROP_ENCHANTMENT_SLOT_0 = 10, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_1 = 11, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_2 = 12, // used with RandomSuffix and RandomProperty + PROP_ENCHANTMENT_SLOT_3 = 13, // used with RandomProperty + PROP_ENCHANTMENT_SLOT_4 = 14, // used with RandomProperty + MAX_ENCHANTMENT_SLOT = 15 }; #define MAX_VISIBLE_ITEM_OFFSET 2 // 2 fields per visible item (entry+enchantment) @@ -322,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); @@ -349,6 +350,16 @@ 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 + { + if (uint32 transmogrification = GetEnchantmentId(TRANSMOGRIFY_ENCHANTMENT_SLOT)) + return transmogrification; + return GetEntry(); + } + + uint32 GetSellPrice(bool& success) const; private: std::string m_text; 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/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index f3375fb115e..f729fe1502f 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -12357,7 +12357,7 @@ void Player::SetVisibleItemSlot(uint8 slot, Item* pItem) { if (pItem) { - SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetEntry()); + SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slot * 2), pItem->GetVisibleEntry()); SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 0, pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)); SetUInt16Value(PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + (slot * 2), 1, pItem->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT)); } @@ -25717,7 +25717,7 @@ uint8 Player::AddVoidStorageItem(const VoidStorageItem& item) GetSession()->SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); return -1; } - + _voidStorageItems[slot] = new VoidStorageItem(item.ItemId, item.ItemEntry, item.CreatorGuid, item.ItemRandomPropertyId, item.ItemSuffixFactor); return slot; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 258e5d3ec25..1c56c64c985 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2448,25 +2448,25 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.ContainerSlots = uint32(fields[28].GetUInt8()); for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) { - itemTemplate.ItemStat[i].ItemStatType = uint32(fields[28 + i * 4 + 0].GetUInt8()); - itemTemplate.ItemStat[i].ItemStatValue = int32(fields[28 + i * 4 + 1].GetInt16()); - itemTemplate.ItemStat[i].ItemStatUnk1 = fields[28 + i * 4 + 2].GetInt32(); - itemTemplate.ItemStat[i].ItemStatUnk2 = fields[28 + i * 4 + 3].GetInt32(); + itemTemplate.ItemStat[i].ItemStatType = uint32(fields[29 + i * 4 + 0].GetUInt8()); + itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i * 4 + 1].GetInt16()); + itemTemplate.ItemStat[i].ItemStatUnk1 = fields[29 + i * 4 + 2].GetInt32(); + itemTemplate.ItemStat[i].ItemStatUnk2 = fields[29 + i * 4 + 3].GetInt32(); } itemTemplate.ScalingStatDistribution = uint32(fields[69].GetUInt16()); // cache item damage FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, itemTemplate.ItemLevel, - itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, fields[71].GetUInt32(), + itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, fields[71].GetUInt16(), fields[131].GetFloat(), itemTemplate.InventoryType, itemTemplate.Flags2); - itemTemplate.DamageType = fields[70].GetUInt32(); + itemTemplate.DamageType = fields[70].GetUInt8(); itemTemplate.Armor = FillItemArmor(itemTemplate.ItemLevel, itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, itemTemplate.InventoryType); - itemTemplate.Delay = fields[71].GetUInt32(); + itemTemplate.Delay = fields[71].GetUInt16(); itemTemplate.RangedModRange = fields[72].GetFloat(); for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { @@ -8906,7 +8906,7 @@ void ObjectMgr::LoadHotfixData() HotfixInfo info; info.Entry = fields[0].GetUInt32(); info.Type = fields[1].GetUInt32(); - info.Timestamp = fields[2].GetUInt32(); + info.Timestamp = fields[2].GetUInt64(); _hotfixData.push_back(info); ++count; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index d75d25b00e2..996e0e97ea6 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -850,26 +850,27 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) LoadAccountData(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA), PER_CHARACTER_CACHE_MASK); SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); + bool featureBit4 = true; data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 7); // checked in 4.2.2 data << uint8(2); // unknown value + data << uint32(1); + data << uint32(1); + data << uint32(2); data << uint32(0); - data << uint32(0); - data << uint32(0); - data << uint32(0); - data.WriteBit(0); - data.WriteBit(0); - data.WriteBit(0); + data.WriteBit(1); + data.WriteBit(1); data.WriteBit(0); + data.WriteBit(featureBit4); data.WriteBit(0); data.WriteBit(0); data.FlushBits(); - //if (featureBit4) - //{ - // data << uint32(0); - // data << uint32(0); - // data << uint32(0); - // data << uint32(0); - //} + if (featureBit4) + { + data << uint32(1); + data << uint32(0); + data << uint32(10); + data << uint32(60); + } //if (featureBit5) //{ diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index 60b698d79b8..8ffb41ddc87 100755 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -59,86 +59,90 @@ void WorldSession::SendPartyResult(PartyOperation operation, const std::string& SendPacket(&data); } -void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) +void WorldSession::HandleGroupInviteOpcode(WorldPacket & recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GROUP_INVITE"); - //BytesGuid guid; - //guid.guid = 0; + ObjectGuid crossRealmGuid; // unused - //recv_data.ReadByteMask(guid.bytes[6]); - //recv_data.ReadByteMask(guid.bytes[5]); - //recv_data.ReadByteMask(guid.bytes[0]); - //recv_data.ReadByteMask(guid.bytes[3]); - //recv_data.ReadByteMask(guid.bytes[4]); - //recv_data.ReadByteMask(guid.bytes[7]); - //recv_data.ReadByteMask(guid.bytes[1]); - //recv_data.ReadByteMask(guid.bytes[2]); + recvData.read_skip<uint32>(); // Non-zero in cross realm invites + recvData.read_skip<uint32>(); // Always 0 - recv_data.read_skip<uint32>(); - recv_data.read_skip<uint32>(); + crossRealmGuid[2] = recvData.ReadBit(); + crossRealmGuid[7] = recvData.ReadBit(); - std::string membername; - recv_data >> membername; - recv_data.read_skip<uint32>(); + uint8 realmLen = recvData.ReadBits(9); + + crossRealmGuid[3] = recvData.ReadBit(); - //recv_data.ReadByteSeq(guid.bytes[0]); - //recv_data.ReadByteSeq(guid.bytes[7]); - //recv_data.ReadByteSeq(guid.bytes[4]); - //recv_data.ReadByteSeq(guid.bytes[1]); - //recv_data.ReadByteSeq(guid.bytes[2]); - //recv_data.ReadByteSeq(guid.bytes[6]); - //recv_data.ReadByteSeq(guid.bytes[5]); - std::string string0; - recv_data >> string0; - //recv_data.ReadByteSeq(guid.bytes[3]); + uint8 nameLen = recvData.ReadBits(10); + + crossRealmGuid[5] = recvData.ReadBit(); + crossRealmGuid[4] = recvData.ReadBit(); + crossRealmGuid[6] = recvData.ReadBit(); + crossRealmGuid[0] = recvData.ReadBit(); + crossRealmGuid[1] = recvData.ReadBit(); + + recvData.ReadByteSeq(crossRealmGuid[4]); + recvData.ReadByteSeq(crossRealmGuid[7]); + recvData.ReadByteSeq(crossRealmGuid[6]); + + std::string memberName, realmName; + memberName = recvData.ReadString(nameLen); + realmName = recvData.ReadString(realmLen); // unused + + recvData.ReadByteSeq(crossRealmGuid[1]); + recvData.ReadByteSeq(crossRealmGuid[0]); + recvData.ReadByteSeq(crossRealmGuid[5]); + recvData.ReadByteSeq(crossRealmGuid[3]); + recvData.ReadByteSeq(crossRealmGuid[2]); // attempt add selected player // cheating - if (!normalizePlayerName(membername)) + if (!normalizePlayerName(memberName)) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S); return; } - Player* player = sObjectAccessor->FindPlayerByName(membername.c_str()); + Player* player = sObjectAccessor->FindPlayerByName(memberName.c_str()); // no player if (!player) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S); return; } // restrict invite to GMs if (!sWorld->getBoolConfig(CONFIG_ALLOW_GM_GROUP) && !GetPlayer()->isGameMaster() && player->isGameMaster()) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_BAD_PLAYER_NAME_S); return; } // can't group with if (!GetPlayer()->isGameMaster() && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && GetPlayer()->GetTeam() != player->GetTeam()) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_PLAYER_WRONG_FACTION); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PLAYER_WRONG_FACTION); return; } if (GetPlayer()->GetInstanceId() != 0 && player->GetInstanceId() != 0 && GetPlayer()->GetInstanceId() != player->GetInstanceId() && GetPlayer()->GetMapId() == player->GetMapId()) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_TARGET_NOT_IN_INSTANCE_S); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_TARGET_NOT_IN_INSTANCE_S); return; } // just ignore us if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty()) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S); return; } if (player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_IGNORING_YOU_S); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S); return; } @@ -152,7 +156,7 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) // player already in another group or invited if (group2 || player->GetGroupInvite()) { - SendPartyResult(PARTY_OP_INVITE, membername, ERR_ALREADY_IN_GROUP_S); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_ALREADY_IN_GROUP_S); if (group2) { @@ -221,7 +225,7 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket & recv_data) data << uint32(0); // unk player->GetSession()->SendPacket(&data); - SendPartyResult(PARTY_OP_INVITE, membername, ERR_PARTY_RESULT_OK); + SendPartyResult(PARTY_OP_INVITE, memberName, ERR_PARTY_RESULT_OK); } void WorldSession::HandleGroupAcceptOpcode(WorldPacket& recv_data) diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 0b21363a783..18859e766d1 100755 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -746,7 +746,7 @@ void WorldSession::SendListInventory(uint64 vendorGuid) VendorItemData const* vendorItems = vendor->GetVendorItems(); uint8 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0; - //if (rawItemCount > 300), + //if (rawItemCount > 300), // rawItemCount = 300; // client cap but uint8 max value is 255 ByteBuffer itemsData(32 * rawItemCount); @@ -783,7 +783,7 @@ void WorldSession::SendListInventory(uint64 vendorGuid) if (leftInStock == 0) continue; } - + int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0; uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem); @@ -1464,7 +1464,6 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) Player* player = GetPlayer(); // Read data - uint32 count = recvData.ReadBits(22); if (count < EQUIPMENT_SLOT_START || count >= EQUIPMENT_SLOT_END) @@ -1477,7 +1476,7 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) ObjectGuid* itemGuids = new ObjectGuid[count]; uint32* newEntries = new uint32[count]; uint32* slots = new uint32[count]; - + for (uint8 i = 0; i < count; ++i) { itemGuids[i][0] = recvData.ReadBit(); @@ -1535,6 +1534,7 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) return; } + int32 cost = 0; for (uint8 i = 0; i < count; ++i) { // slot of the transmogrified item @@ -1592,8 +1592,8 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) if (!newEntries[i]) // reset look { - player->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slots[i] * 2), itemTransmogrified->GetEntry()); - itemTransmogrified->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_10_1, 0); + itemTransmogrified->ClearEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT); + player->SetVisibleItemSlot(slots[i], itemTransmogrified); } else { @@ -1604,9 +1604,8 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) } // All okay, proceed - - player->SetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + (slots[i] * 2), newEntries[i]); - itemTransmogrified->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_10_1, newEntries[i]); + itemTransmogrified->SetEnchantment(TRANSMOGRIFY_ENCHANTMENT_SLOT, newEntries[i], 0, 0); + player->SetVisibleItemSlot(slots[i], itemTransmogrified); itemTransmogrified->UpdatePlayedTime(player); @@ -1617,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; diff --git a/src/server/game/Handlers/VoidStorageHandler.cpp b/src/server/game/Handlers/VoidStorageHandler.cpp index 3938def0cc7..5e3ecc89e21 100644 --- a/src/server/game/Handlers/VoidStorageHandler.cpp +++ b/src/server/game/Handlers/VoidStorageHandler.cpp @@ -20,6 +20,7 @@ #include "WorldSession.h" #include "World.h" #include "ObjectAccessor.h" +#include "ObjectMgr.h" #include "Log.h" #include "Opcodes.h" #include "Player.h" diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp index 69f087a6b2a..6a3c2ba8eea 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp @@ -19,6 +19,7 @@ #include "MovementPacketBuilder.h" #include "MoveSpline.h" #include "WorldPacket.h" +#include "Object.h" namespace Movement { diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index ff351f90f74..32dc58e582b 100755 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -19,6 +19,7 @@ #include "QuestDef.h" #include "Player.h" #include "World.h" +#include "ObjectMgr.h" Quest::Quest(Field* questRecord) { diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 1c8afd2a90b..b72956ce313 100755 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -22,6 +22,7 @@ #include "Define.h" #include "DatabaseEnv.h" #include "SharedDefines.h" +#include "WorldPacket.h" #include <string> #include <vector> diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 166a9ad5601..47ca9d86e31 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -21,6 +21,7 @@ */ #include "Opcodes.h" +#include "WorldSession.h" OpcodeHandler* opcodeTable[NUM_OPCODE_HANDLERS] = { }; @@ -313,7 +314,7 @@ void InitOpcodes() //DEFINE_OPCODE_HANDLER(CMSG_GROUP_CHANGE_SUB_GROUP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupChangeSubGroupOpcode ); //DEFINE_OPCODE_HANDLER(CMSG_GROUP_DECLINE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDeclineOpcode ); //DEFINE_OPCODE_HANDLER(CMSG_GROUP_DISBAND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupDisbandOpcode ); - //DEFINE_OPCODE_HANDLER(CMSG_GROUP_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_GROUP_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupInviteOpcode ); //DEFINE_OPCODE_HANDLER(CMSG_GROUP_RAID_CONVERT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupRaidConvertOpcode ); //DEFINE_OPCODE_HANDLER(CMSG_GROUP_SET_LEADER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSetLeaderOpcode ); //DEFINE_OPCODE_HANDLER(CMSG_GROUP_SWAP_SUB_GROUP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGroupSwapSubGroupOpcode ); @@ -683,8 +684,8 @@ void InitOpcodes() DEFINE_OPCODE_HANDLER(CMSG_VOID_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleVoidSwapItem ); //DEFINE_OPCODE_HANDLER(CMSG_WARDEN_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleWardenDataOpcode ); //DEFINE_OPCODE_HANDLER(CMSG_WEATHER_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode ); - //DEFINE_OPCODE_HANDLER(CMSG_WHOIS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_WHO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoOpcode ); + DEFINE_OPCODE_HANDLER(CMSG_WHOIS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWhoisOpcode ); DEFINE_OPCODE_HANDLER(CMSG_WORLD_STATE_UI_TIMER_UPDATE, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleWorldStateUITimerUpdate ); //DEFINE_OPCODE_HANDLER(CMSG_WORLD_TELEPORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode ); //DEFINE_OPCODE_HANDLER(CMSG_WRAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode ); @@ -1392,8 +1393,8 @@ void InitOpcodes() DEFINE_OPCODE_HANDLER(SMSG_VOID_STORAGE_FAILED, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_WARDEN_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_WEATHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_WHO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_WHOIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_WHO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_WHOIS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_WORLD_STATE_UI_TIMER_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_ZONE_MAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_ZONE_UNDER_ATTACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index b1790d096b8..6ee5ade502a 100755 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -1438,6 +1438,7 @@ enum PacketProcessing }; class WorldPacket; +class WorldSession; typedef void(WorldSession::*pOpcodeHandler)(WorldPacket& recvPacket); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 38351e8340b..fb9c90e94b8 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -30,6 +30,7 @@ #include "World.h" #include "WorldPacket.h" #include "Cryptography/BigNumber.h" +#include "Opcodes.h" class CalendarEvent; class CalendarInvite; |