From 1e51d22d2990c69c4725133733c99599ddb0abd1 Mon Sep 17 00:00:00 2001 From: Intel Date: Fri, 14 Nov 2014 14:47:20 +0200 Subject: Core/DataStores: Updated Item DataStores Signed-off-by: Nayd --- .../game/AuctionHouseBot/AuctionHouseBotSeller.cpp | 2 +- src/server/game/DataStores/DB2Stores.cpp | 17 +++ src/server/game/DataStores/DB2Stores.h | 6 + src/server/game/DataStores/DB2Structure.h | 96 +++++++++++++++- src/server/game/DataStores/DB2Utility.cpp | 2 + src/server/game/DataStores/DB2fmt.h | 6 +- src/server/game/Entities/Creature/Creature.h | 2 +- src/server/game/Entities/Item/Item.cpp | 27 ++--- src/server/game/Entities/Item/Item.h | 4 +- src/server/game/Entities/Item/ItemPrototype.h | 32 +++--- src/server/game/Entities/Player/Player.cpp | 126 +++++++++------------ src/server/game/Globals/ObjectMgr.cpp | 82 ++++++++------ src/server/game/Groups/Group.cpp | 2 +- src/server/game/Handlers/AuctionHouseHandler.cpp | 2 +- src/server/game/Handlers/ItemHandler.cpp | 10 +- src/server/game/Handlers/LootHandler.cpp | 4 +- src/server/game/Handlers/MailHandler.cpp | 4 +- src/server/game/Handlers/SpellHandler.cpp | 10 +- src/server/game/Loot/LootMgr.cpp | 16 +-- src/server/game/Spells/Spell.cpp | 71 ++++++------ src/server/game/Spells/SpellEffects.cpp | 10 +- 21 files changed, 321 insertions(+), 210 deletions(-) (limited to 'src') diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp index 6d2cc74239c..f17e0efda17 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp @@ -320,7 +320,7 @@ bool AuctionBotSeller::Initialize() continue; } - if (prototype->Flags & ITEM_FLAG_UNLOCKED) + if (prototype->Flags[0] & ITEM_FLAG_UNLOCKED) { // skip any not locked lootable items (mostly quest specific or reward cases) if (!prototype->LockID) diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 413c55b9da6..c4d47e26468 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -25,8 +25,11 @@ DB2Storage sHolidaysStore(HolidaysEntryfmt); DB2Storage sItemStore(Itemfmt, &DB2Utilities::HasItemEntry, &DB2Utilities::WriteItemDbReply); +DB2Storage sItemAppearanceStore(ItemAppearanceEntryfmt); +ItemDisplayIDMap sItemDisplayIDMap; DB2Storage sItemCurrencyCostStore(ItemCurrencyCostfmt); DB2Storage sItemExtendedCostStore(ItemExtendedCostEntryfmt); +DB2Storage sItemEffectStore(ItemEffectEntryfmt); DB2Storage sItemSparseStore(ItemSparsefmt, &DB2Utilities::HasItemSparseEntry, &DB2Utilities::WriteItemSparseDbReply); DB2Storage sKeyChainStore(KeyChainfmt); DB2Storage sOverrideSpellDataStore(OverrideSpellDataEntryfmt); @@ -120,9 +123,11 @@ void LoadDB2Stores(std::string const& dataPath) LoadDB2(availableDb2Locales, bad_db2_files, sHolidaysStore, db2Path, "Holidays.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sItemStore, db2Path, "Item.db2"); + LoadDB2(availableDb2Locales, bad_db2_files, sItemAppearanceStore, db2Path, "ItemAppearance.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sItemCurrencyCostStore, db2Path, "ItemCurrencyCost.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sItemSparseStore, db2Path, "Item-sparse.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sItemExtendedCostStore, db2Path, "ItemExtendedCost.db2"); + LoadDB2(availableDb2Locales, bad_db2_files, sItemEffectStore, db2Path, "ItemEffect.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sKeyChainStore, db2Path, "KeyChain.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sOverrideSpellDataStore, db2Path, "OverrideSpellData.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sPhaseGroupStore, db2Path, "PhaseXPhaseGroup.db2"); @@ -138,6 +143,10 @@ void LoadDB2Stores(std::string const& dataPath) LoadDB2(availableDb2Locales, bad_db2_files, sTaxiPathStore, db2Path, "TaxiPath.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sTaxiPathNodeStore, db2Path, "TaxiPathNode.db2"); + for (uint32 i = 0; i < sItemAppearanceStore.GetNumRows(); ++i) + if (ItemAppearanceEntry const* entry = sItemAppearanceStore.LookupEntry(i)) + sItemDisplayIDMap[entry->AppearanceID] = entry->DisplayID; + for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) sTaxiPathSetBySource[entry->From][entry->To] = TaxiPathBySourceAndDestination(entry->ID, entry->Cost); @@ -260,3 +269,11 @@ DB2StorageBase const* GetDB2Storage(uint32 type) return NULL; } + +uint32 GetItemDisplayID(uint32 appearanceID) +{ + auto itr = sItemDisplayIDMap.find(appearanceID); + if (itr != sItemDisplayIDMap.end()) + return itr->second; + return 0; +} diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 40632a31d3c..29fe93ce2b1 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -21,11 +21,15 @@ #include "DB2Store.h" #include "DB2Structure.h" #include +#include extern DB2Storage sHolidaysStore; extern DB2Storage sItemStore; +extern DB2Storage sItemAppearanceStore; +extern ItemDisplayIDMap sItemDisplayIDMap; extern DB2Storage sItemCurrencyCostStore; extern DB2Storage sItemExtendedCostStore; +extern DB2Storage sItemEffectStore; extern DB2Storage sItemSparseStore; extern DB2Storage sKeyChainStore; extern DB2Storage sOverrideSpellDataStore; @@ -53,4 +57,6 @@ void LoadDB2Stores(std::string const& dataPath); DB2StorageBase const* GetDB2Storage(uint32 type); +uint32 GetItemDisplayID(uint32 appearanceID); + #endif diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index cfc4b97b10a..e74a4a5e26c 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -58,9 +58,17 @@ struct ItemEntry uint32 SubClass; // 2 int32 SoundOverrideSubclass; // 3 int32 Material; // 4 - uint32 DisplayId; // 5 - uint32 InventoryType; // 6 - uint32 Sheath; // 7 + uint32 InventoryType; // 5 + uint32 Sheath; // 6 + uint32 AppearanceID; // 7 (ItemAppearance.db2) + //uint32 Unk; // 8 +}; + +struct ItemAppearanceEntry +{ + uint32 ID; // 0 (reference to ItemModifiedAppearance.db2?) + uint32 DisplayID; // 1 + uint32 AppearanceID; // 2 }; struct ItemCurrencyCostEntry @@ -69,9 +77,85 @@ struct ItemCurrencyCostEntry uint32 ItemId; // 1 }; +struct ItemEffectEntry +{ + uint32 ID; // 0 + uint32 ItemID; // 1 + uint32 OrderIndex; // 2 + uint32 SpellID; // 3 + uint32 Trigger; // 4 + uint32 Charges; // 5 + int32 Cooldown; // 6 + uint32 Category; // 7 + int32 CategoryCooldown; // 8 +}; + struct ItemSparseEntry { - uint32 ID; // 0 + uint32 ID; // 0 + uint32 Quality; // 1 + uint32 Flags[3]; // 2-4 + float Unk1; // 5 + float Unk2; // 6 + uint32 BuyCount; // 7 + uint32 BuyPrice; // 8 + uint32 SellPrice; // 9 + uint32 InventoryType; // 10 + int32 AllowableClass; // 11 + int32 AllowableRace; // 12 + uint32 ItemLevel; // 13 + int32 RequiredLevel; // 14 + uint32 RequiredSkill; // 15 + uint32 RequiredSkillRank; // 16 + uint32 RequiredSpell; // 17 + uint32 RequiredHonorRank; // 18 + uint32 RequiredCityRank; // 19 + uint32 RequiredReputationFaction; // 20 + uint32 RequiredReputationRank; // 21 + uint32 MaxCount; // 22 + uint32 Stackable; // 23 + uint32 ContainerSlots; // 24 + int32 ItemStatType[MAX_ITEM_PROTO_STATS]; // 25 - 34 + uint32 ItemStatValue[MAX_ITEM_PROTO_STATS]; // 35 - 44 + int32 ItemStatUnk1[MAX_ITEM_PROTO_STATS]; // 45 - 54 + int32 ItemStatUnk2[MAX_ITEM_PROTO_STATS]; // 55 - 64 + uint32 ScalingStatDistribution; // 65 + uint32 DamageType; // 66 + uint32 Delay; // 67 + float RangedModRange; // 68 + uint32 Bonding; // 69 + LocalizedString* Name; // 70 + LocalizedString* Name2; // 71 + LocalizedString* Name3; // 72 + LocalizedString* Name4; // 73 + LocalizedString* Description; // 74 + uint32 PageText; // 75 + uint32 LanguageID; // 76 + uint32 PageMaterial; // 77 + uint32 StartQuest; // 78 + uint32 LockID; // 79 + int32 Material; // 80 + uint32 Sheath; // 81 + uint32 RandomProperty; // 82 + uint32 RandomSuffix; // 83 + uint32 ItemSet; // 84 + uint32 Area; // 85 + uint32 Map; // 86 + uint32 BagFamily; // 87 + uint32 TotemCategory; // 88 + uint32 SocketColor[MAX_ITEM_PROTO_SOCKETS]; // 89-91 + uint32 SocketBonus; // 92 + uint32 GemProperties; // 93 + float ArmorDamageModifier; // 94 + uint32 Duration; // 95 + uint32 ItemLimitCategory; // 96 + uint32 HolidayID; // 97 + float StatScalingFactor; // 98 + uint32 CurrencySubstitutionID; // 99 + uint32 CurrencySubstitutionCount; // 100 + //uint32 Unk3; // 101 + + /*uint32 ID; // 0 uint32 Quality; // 1 uint32 Flags; // 2 uint32 Flags2; // 3 @@ -139,7 +223,7 @@ struct ItemSparseEntry uint32 HolidayId; // 127 float StatScalingFactor; // 128 int32 CurrencySubstitutionId; // 129 - int32 CurrencySubstitutionCount; // 130 + int32 CurrencySubstitutionCount; // 130*/ }; #define MAX_ITEM_EXT_COST_ITEMS 5 @@ -337,6 +421,8 @@ struct TaxiPathNodeEntry #pragma pack(pop) #endif +typedef std::map ItemDisplayIDMap; + struct TaxiPathBySourceAndDestination { TaxiPathBySourceAndDestination() : ID(0), price(0) { } diff --git a/src/server/game/DataStores/DB2Utility.cpp b/src/server/game/DataStores/DB2Utility.cpp index 5a0174c3a74..37b7fb949db 100644 --- a/src/server/game/DataStores/DB2Utility.cpp +++ b/src/server/game/DataStores/DB2Utility.cpp @@ -50,6 +50,7 @@ void DB2Utilities::WriteItemDbReply(DB2Storage const& /*store*/, uint void DB2Utilities::WriteItemSparseDbReply(DB2Storage const& /*store*/, uint32 id, uint32 locale, ByteBuffer& buffer) { + /* TODO: 6.x update ItemTemplate const* proto = sObjectMgr->GetItemTemplate(id); ASSERT(proto); @@ -168,4 +169,5 @@ void DB2Utilities::WriteItemSparseDbReply(DB2Storage const& /*s buffer << float(proto->StatScalingFactor); // StatScalingFactor buffer << uint32(proto->CurrencySubstitutionId); buffer << uint32(proto->CurrencySubstitutionCount); + */ } diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h index c4d819a48d0..4c08496f91a 100644 --- a/src/server/game/DataStores/DB2fmt.h +++ b/src/server/game/DataStores/DB2fmt.h @@ -19,10 +19,12 @@ #define TRINITY_DB2SFRM_H char const HolidaysEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix"; -char const Itemfmt[]="niiiiiii"; +char const Itemfmt[]="niiiiiiix"; +char const ItemAppearanceEntryfmt[]="nii"; char const ItemCurrencyCostfmt[]="xn"; -char const ItemSparsefmt[]="niiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisssssiiiiiiiiiiiiiiiiiiiiiifiiifii"; +char const ItemSparsefmt[]="niiiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifisssssiiiiiiiiiiiiiiiiiiifiiifiix"; char const ItemExtendedCostEntryfmt[]="nxxiiiiiiiiiiiixiiiiiiiiiiiiii"; +char const ItemEffectEntryfmt[]="niiiiiiii"; char const KeyChainfmt[]="nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; char const OverrideSpellDataEntryfmt[] = "niiiiiiiiiixx"; char const PhaseGroupEntryfmt[] = "nii"; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index eb2dc5171cc..9acde98a7a8 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -349,7 +349,7 @@ struct VendorItem uint8 Type; //helpers - bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->Flags2 & ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD || !ExtendedCost; } + bool IsGoldRequired(ItemTemplate const* pProto) const { return pProto->Flags[1] & ITEM_FLAGS_EXTRA_EXT_COST_REQUIRES_GOLD || !ExtendedCost; } }; typedef std::vector VendorItemList; diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 74c6f7516db..f42b93f07eb 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -284,8 +284,8 @@ bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owne SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability); SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - SetSpellCharges(i, itemProto->Spells[i].SpellCharges); + for (uint8 i = 0; i < itemProto->Effects.size(); ++i) + SetSpellCharges(i, itemProto->Effects[i].Charges); SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Duration); SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, 0); @@ -340,8 +340,9 @@ void Item::SaveToDB(SQLTransaction& trans) stmt->setUInt32(++index, GetUInt32Value(ITEM_FIELD_DURATION)); std::ostringstream ssSpells; - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - ssSpells << GetSpellCharges(i) << ' '; + if (ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(GetEntry())) + for (uint8 i = 0; i < itemProto->Effects.size(); ++i) + ssSpells << GetSpellCharges(i) << ' '; stmt->setString(++index, ssSpells.str()); stmt->setUInt32(++index, GetUInt32Value(ITEM_FIELD_FLAGS)); @@ -440,9 +441,9 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fi need_save = true; } - Tokenizer tokens(fields[4].GetString(), ' ', MAX_ITEM_PROTO_SPELLS); - if (tokens.size() == MAX_ITEM_PROTO_SPELLS) - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + Tokenizer tokens(fields[4].GetString(), ' ', proto->Effects.size()); + if (tokens.size() == proto->Effects.size()) + for (uint8 i = 0; i < proto->Effects.size(); ++i) SetSpellCharges(i, atoi(tokens[i])); SetUInt32Value(ITEM_FIELD_FLAGS, fields[5].GetUInt32()); @@ -1236,7 +1237,7 @@ bool Item::CanBeTransmogrified() const if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE) return false; - if (proto->Flags2 & ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG) + if (proto->Flags[1] & ITEM_FLAGS_EXTRA_CANNOT_BE_TRANSMOG) return false; if (!HasStats()) @@ -1252,7 +1253,7 @@ bool Item::CanTransmogrify() const if (!proto) return false; - if (proto->Flags2 & ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG) + if (proto->Flags[1] & ITEM_FLAGS_EXTRA_CANNOT_TRANSMOG) return false; if (proto->Quality == ITEM_QUALITY_LEGENDARY) @@ -1265,7 +1266,7 @@ bool Item::CanTransmogrify() const if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE) return false; - if (proto->Flags2 & ITEM_FLAGS_EXTRA_CAN_TRANSMOG) + if (proto->Flags[1] & ITEM_FLAGS_EXTRA_CAN_TRANSMOG) return true; if (!HasStats()) @@ -1326,7 +1327,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) { normalSellPrice = true; - if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE) + if (proto->Flags[1] & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE) { return proto->BuyPrice; } @@ -1437,7 +1438,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) } normalSellPrice = false; - return uint32(qualityFactor * proto->Unk430_2 * proto->Unk430_1 * typeFactor * baseFactor); + return uint32(qualityFactor * proto->Unk1 * proto->Unk2 * typeFactor * baseFactor); } } @@ -1445,7 +1446,7 @@ uint32 Item::GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice /*= { uint32 cost = 0; - if (proto->Flags2 & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE) + if (proto->Flags[1] & ITEM_FLAGS_EXTRA_HAS_NORMAL_PRICE) cost = proto->SellPrice; else { diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 6d60eb2466a..c4fca9cc4ba 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -230,8 +230,8 @@ class Item : public Object void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND, val); } bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_SOULBOUND); } - bool IsBoundAccountWide() const { return (GetTemplate()->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT) != 0; } - bool IsBattlenetAccountBound() const { return (GetTemplate()->Flags2 & ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND) != 0; } + bool IsBoundAccountWide() const { return (GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT) != 0; } + bool IsBattlenetAccountBound() const { return (GetTemplate()->Flags[1] & ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND) != 0; } bool IsBindedNotWith(Player const* player) const; bool IsBoundByEnchant() const; virtual void SaveToDB(SQLTransaction& trans); diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h index 32781f68e34..e28e8a21678 100644 --- a/src/server/game/Entities/Item/ItemPrototype.h +++ b/src/server/game/Entities/Item/ItemPrototype.h @@ -588,22 +588,22 @@ struct _ItemStat int32 ItemStatUnk2; }; -struct _Spell -{ - int32 SpellId; // id from Spell.dbc - uint32 SpellTrigger; - int32 SpellCharges; - int32 SpellCooldown; - uint32 SpellCategory; // id from SpellCategory.dbc - int32 SpellCategoryCooldown; -}; - struct _Socket { uint32 Color; uint32 Content; }; +struct ItemEffect +{ + uint32 SpellID; + uint32 Trigger; + uint32 Charges; + int32 Cooldown; + uint32 Category; + int32 CategoryCooldown; +}; + // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform #if defined(__GNUC__) #pragma pack() @@ -613,7 +613,6 @@ struct _Socket #define MAX_ITEM_PROTO_DAMAGES 2 // changed in 3.1.0 #define MAX_ITEM_PROTO_SOCKETS 3 -#define MAX_ITEM_PROTO_SPELLS 5 #define MAX_ITEM_PROTO_STATS 10 struct ItemTemplate @@ -625,10 +624,9 @@ struct ItemTemplate std::string Name1; uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc uint32 Quality; - uint32 Flags; - uint32 Flags2; - float Unk430_1; - float Unk430_2; + uint32 Flags[3]; + float Unk1; + float Unk2; uint32 BuyCount; int32 BuyPrice; uint32 SellPrice; @@ -652,7 +650,7 @@ struct ItemTemplate uint32 DamageType; // id from Resistances.dbc uint32 Delay; float RangedModRange; - _Spell Spells[MAX_ITEM_PROTO_SPELLS]; + std::vector Effects; uint32 Bonding; std::string Description; uint32 PageText; @@ -748,7 +746,7 @@ struct ItemTemplate bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; } bool IsVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ENCHANTMENT; } - bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_PROTO_FLAG_CONJURED); } + bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags[0] & ITEM_PROTO_FLAG_CONJURED); } bool IsRangedWeapon() const { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b26099c8b72..1026681cd81 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1145,7 +1145,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac // special amount for food/drink if (iProto->Class == ITEM_CLASS_CONSUMABLE && iProto->SubClass == ITEM_SUBCLASS_FOOD_DRINK) { - switch (iProto->Spells[0].SpellCategory) + switch (iProto->Effects[0].Category) { case SPELL_CATEGORY_FOOD: // food count = getClass() == CLASS_DEATH_KNIGHT ? 10 : 4; @@ -7927,7 +7927,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply } // Apply Spell Power from ScalingStatValue if set - if (ssv && proto->Flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON) + if (ssv && proto->Flags[1] & ITEM_FLAGS_EXTRA_CASTER_WEAPON) if (int32 spellbonus = int32(ssv->SpellPower)) ApplySpellPowerBonus(spellbonus, apply); @@ -8002,7 +8002,7 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt if (ssv) { float damageMultiplier = 0.0f; - extraDPS = ssv->GetDPSAndDamageMultiplier(proto->SubClass, (proto->Flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON) != 0, &damageMultiplier); + extraDPS = ssv->GetDPSAndDamageMultiplier(proto->SubClass, (proto->Flags[1] & ITEM_FLAGS_EXTRA_CASTER_WEAPON) != 0, &damageMultiplier); if (extraDPS) { float average = extraDPS * proto->Delay / 1000.0f; @@ -8128,20 +8128,16 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change) if (!proto) return; - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (uint8 i = 0; i < proto->Effects.size(); ++i) { - _Spell const& spellData = proto->Spells[i]; - - // no spell - if (!spellData.SpellId) - continue; + ItemEffect const& effectData = proto->Effects[i]; // wrong triggering type - if (apply && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP) + if (apply && effectData.Trigger != ITEM_SPELLTRIGGER_ON_EQUIP) continue; // check if it is valid spell - SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(spellData.SpellId); + SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(effectData.SpellID); if (!spellproto) continue; @@ -8256,22 +8252,18 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 if (procVictim & PROC_FLAG_TAKEN_DAMAGE) //if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE) { - for (uint8 i = 0; i < MAX_ITEM_SPELLS; ++i) + for (uint8 i = 0; i < proto->Effects.size(); ++i) { - _Spell const& spellData = proto->Spells[i]; - - // no spell - if (!spellData.SpellId) - continue; + ItemEffect const& effectData = proto->Effects[i]; // wrong triggering type - if (spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) + if (effectData.Trigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) continue; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellData.SpellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effectData.SpellID); if (!spellInfo) { - TC_LOG_ERROR("entities.player.items", "WORLD: unknown Item spellid %i", spellData.SpellId); + TC_LOG_ERROR("entities.player.items", "WORLD: unknown Item spellid %i", effectData.SpellID); continue; } @@ -8366,10 +8358,10 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 { ItemTemplate const* proto = item->GetTemplate(); // special learning case - if (proto->Spells[0].SpellId == 483 || proto->Spells[0].SpellId == 55884) + if (proto->Effects[0].SpellID == 483 || proto->Effects[0].SpellID == 55884) { - uint32 learn_spell_id = proto->Spells[0].SpellId; - uint32 learning_spell_id = proto->Spells[1].SpellId; + uint32 learn_spell_id = proto->Effects[0].SpellID; + uint32 learning_spell_id = proto->Effects[1].SpellID; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(learn_spell_id); if (!spellInfo) @@ -8391,22 +8383,18 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 uint8 count = 0; // item spells cast at use - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (uint8 i = 0; i < proto->Effects.size(); ++i) { - _Spell const& spellData = proto->Spells[i]; - - // no spell - if (!spellData.SpellId) - continue; + ItemEffect const& effectData = proto->Effects[i]; // wrong triggering type - if (spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + if (effectData.Trigger != ITEM_SPELLTRIGGER_ON_USE) continue; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellData.SpellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effectData.SpellID); if (!spellInfo) { - TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring", proto->ItemId, spellData.SpellId); + TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring", proto->ItemId, effectData.SpellID); continue; } @@ -11521,10 +11509,10 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const if (!proto) return EQUIP_ERR_ITEM_NOT_FOUND; - if ((proto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetTeam() != HORDE) + if ((proto->Flags[1] & ITEM_FLAGS_EXTRA_HORDE_ONLY) && GetTeam() != HORDE) return EQUIP_ERR_CANT_EQUIP_EVER; - if ((proto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetTeam() != ALLIANCE) + if ((proto->Flags[1] & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && GetTeam() != ALLIANCE) return EQUIP_ERR_CANT_EQUIP_EVER; if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0) @@ -11549,8 +11537,8 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const return EQUIP_ERR_CLIENT_LOCKED_OUT; // learning (recipes, mounts, pets, etc.) - if (proto->Spells[0].SpellId == 483 || proto->Spells[0].SpellId == 55884) - if (HasSpell(proto->Spells[1].SpellId)) + if (proto->Effects[0].SpellID == 483 || proto->Effects[0].SpellID == 55884) + if (HasSpell(proto->Effects[1].SpellID)) return EQUIP_ERR_INTERNAL_BAG_ERROR; return EQUIP_ERR_OK; @@ -11752,11 +11740,11 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool AddItemDurations(pItem); const ItemTemplate* proto = pItem->GetTemplate(); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger + for (uint8 i = 0; i < proto->Effects.size(); ++i) + if (proto->Effects[i].Trigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) // On obtain trigger if (bag == INVENTORY_SLOT_BAG_0 || (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)) - if (!HasAura(proto->Spells[i].SpellId)) - CastSpell(this, proto->Spells[i].SpellId, true, pItem); + if (!HasAura(proto->Effects[i].SpellID)) + CastSpell(this, proto->Effects[i].SpellID, true, pItem); return pItem; } @@ -11795,11 +11783,11 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool pItem2->SetState(ITEM_CHANGED, this); const ItemTemplate* proto = pItem2->GetTemplate(); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger + for (uint8 i = 0; i < proto->Effects.size(); ++i) + if (proto->Effects[i].Trigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) // On obtain trigger if (bag == INVENTORY_SLOT_BAG_0 || (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)) - if (!HasAura(proto->Spells[i].SpellId)) - CastSpell(this, proto->Spells[i].SpellId, true, pItem2); + if (!HasAura(proto->Effects[i].SpellID)) + CastSpell(this, proto->Effects[i].SpellID, true, pItem2); return pItem2; } @@ -12141,9 +12129,9 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) RemoveTradeableItem(pItem); const ItemTemplate* proto = pItem->GetTemplate(); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger - RemoveAurasDueToSpell(proto->Spells[i].SpellId); + for (uint8 i = 0; i < proto->Effects.size(); ++i) + if (proto->Effects[i].Trigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) // On obtain trigger + RemoveAurasDueToSpell(proto->Effects[i].SpellID); ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); sScriptMgr->OnItemRemove(this, pItem); @@ -12197,7 +12185,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) // Delete rolled money / loot from db. // MUST be done before RemoveFromWorld() or GetTemplate() fails if (ItemTemplate const* pTmp = pItem->GetTemplate()) - if (pTmp->Flags & ITEM_PROTO_FLAG_OPENABLE) + if (pTmp->Flags[0] & ITEM_PROTO_FLAG_OPENABLE) pItem->ItemContainerDeleteLootMoneyAndLootItemsFromDB(); if (IsInWorld() && update) @@ -17998,7 +17986,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F remove = true; } // "Conjured items disappear if you are logged out for more than 15 minutes" - else if (timeDiff > 15 * MINUTE && proto->Flags & ITEM_PROTO_FLAG_CONJURED) + else if (timeDiff > 15 * MINUTE && proto->Flags[0] & ITEM_PROTO_FLAG_CONJURED) { TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (%s, name: '%s', diff: %u) has conjured item (%s, entry: %u) with expired lifetime (15 minutes). Deleting item.", GetGUID().ToString().c_str(), GetName().c_str(), timeDiff, item->GetGUID().ToString().c_str(), item->GetEntry()); @@ -21538,7 +21526,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c if (!bStore) AutoUnequipOffhandIfNeed(); - if (pProto->Flags & ITEM_PROTO_FLAG_REFUNDABLE && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1) + if (pProto->Flags[0] & ITEM_PROTO_FLAG_REFUNDABLE && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1) { it->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE); it->SetRefundRecipient(GetGUID()); @@ -21730,7 +21718,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin return false; } - if (!IsGameMaster() && ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeam() == ALLIANCE) || (pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeam() == HORDE))) + if (!IsGameMaster() && ((pProto->Flags[1] & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeam() == ALLIANCE) || (pProto->Flags[1] == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeam() == HORDE))) return false; Creature* creature = GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); @@ -22063,13 +22051,13 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite { if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId)) { - for (uint8 idx = 0; idx < MAX_ITEM_SPELLS; ++idx) + for (uint8 idx = 0; idx < proto->Effects.size(); ++idx) { - if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id) + if (uint32(proto->Effects[idx].SpellID) == spellInfo->Id) { - cat = proto->Spells[idx].SpellCategory; - rec = proto->Spells[idx].SpellCooldown; - catrec = proto->Spells[idx].SpellCategoryCooldown; + cat = proto->Effects[idx].Category; + rec = proto->Effects[idx].Cooldown; + catrec = proto->Effects[idx].CategoryCooldown; break; } } @@ -22244,9 +22232,9 @@ void Player::UpdatePotionCooldown(Spell* spell) { // spell/item pair let set proper cooldown (except not existed charged spell cooldown spellmods for potions) if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(m_lastPotionId)) - for (uint8 idx = 0; idx < MAX_ITEM_SPELLS; ++idx) - if (proto->Spells[idx].SpellId && proto->Spells[idx].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE) - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[idx].SpellId)) + for (uint8 idx = 0; idx < proto->Effects.size(); ++idx) + if (proto->Effects[idx].Trigger == ITEM_SPELLTRIGGER_ON_USE) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Effects[idx].SpellID)) SendCooldownEvent(spellInfo, m_lastPotionId); } // from spell cases (m_lastPotionId set in Spell::SendSpellCooldown) @@ -23157,28 +23145,26 @@ void Player::ApplyEquipCooldown(Item* pItem) if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_PROTO_FLAG_NO_EQUIP_COOLDOWN)) return; - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - _Spell const& spellData = pItem->GetTemplate()->Spells[i]; + ItemTemplate const* proto = pItem->GetTemplate(); - // no spell - if (!spellData.SpellId) - continue; + for (uint8 i = 0; i < proto->Effects.size(); ++i) + { + ItemEffect const& effectData = proto->Effects[i]; // wrong triggering type (note: ITEM_SPELLTRIGGER_ON_NO_DELAY_USE not have cooldown) - if (spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + if (effectData.Trigger != ITEM_SPELLTRIGGER_ON_USE) continue; // Don't replace longer cooldowns by equip cooldown if we have any. - SpellCooldowns::iterator itr = m_spellCooldowns.find(spellData.SpellId); + SpellCooldowns::iterator itr = m_spellCooldowns.find(effectData.SpellID); if (itr != m_spellCooldowns.end() && itr->second.itemid == pItem->GetEntry() && itr->second.end > time(NULL) + 30) continue; - AddSpellCooldown(spellData.SpellId, pItem->GetEntry(), time(NULL) + 30); + AddSpellCooldown(effectData.SpellID, pItem->GetEntry(), time(NULL) + 30); WorldPacket data(SMSG_ITEM_COOLDOWN, 12); data << pItem->GetGUID(); - data << uint32(spellData.SpellId); + data << uint32(effectData.SpellID); GetSession()->SendPacket(&data); } } @@ -25290,7 +25276,7 @@ InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limi InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8 except_slot, uint32 limit_count) const { // check unique-equipped on item - if (itemProto->Flags & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED) + if (itemProto->Flags[0] & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED) { // there is an equip limit on this item if (HasItemOrGemWithIdEquipped(itemProto->ItemId, 1, except_slot)) diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 51088e0000f..755b6a2ac59 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2435,7 +2435,7 @@ void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, { *disenchantID = 0; *(int32*)requiredDisenchantSkill = -1; - if ((itemTemplate.Flags & (ITEM_PROTO_FLAG_CONJURED | ITEM_PROTO_FLAG_UNK6)) || + if ((itemTemplate.Flags[0] & (ITEM_PROTO_FLAG_CONJURED | ITEM_PROTO_FLAG_UNK6)) || itemTemplate.Bonding == BIND_QUEST_ITEM || itemTemplate.Area || itemTemplate.Map || itemTemplate.Stackable > 1 || itemTemplate.Quality < ITEM_QUALITY_UNCOMMON || itemTemplate.Quality > ITEM_QUALITY_EPIC || @@ -2492,12 +2492,11 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.SubClass = db2Data->SubClass; itemTemplate.SoundOverrideSubclass = db2Data->SoundOverrideSubclass; itemTemplate.Name1 = sparse->Name->Str[sWorld->GetDefaultDbcLocale()]; - itemTemplate.DisplayInfoID = db2Data->DisplayId; + itemTemplate.DisplayInfoID = GetItemDisplayID(db2Data->AppearanceID); itemTemplate.Quality = sparse->Quality; - itemTemplate.Flags = sparse->Flags; - itemTemplate.Flags2 = sparse->Flags2; - itemTemplate.Unk430_1 = sparse->Unk430_1; - itemTemplate.Unk430_2 = sparse->Unk430_2; + memcpy(itemTemplate.Flags, sparse->Flags, sizeof(itemTemplate.Flags)); + itemTemplate.Unk1 = sparse->Unk1; + itemTemplate.Unk2 = sparse->Unk2; itemTemplate.BuyCount = std::max(sparse->BuyCount, 1u); itemTemplate.BuyPrice = sparse->BuyPrice; itemTemplate.SellPrice = sparse->SellPrice; @@ -2529,21 +2528,12 @@ void ObjectMgr::LoadItemTemplates() // cache item damage FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, sparse->ItemLevel, db2Data->Class, db2Data->SubClass, sparse->Quality, sparse->Delay, sparse->StatScalingFactor, - sparse->InventoryType, sparse->Flags2); + sparse->InventoryType, sparse->Flags[1]); itemTemplate.DamageType = sparse->DamageType; itemTemplate.Armor = FillItemArmor(sparse->ItemLevel, db2Data->Class, db2Data->SubClass, sparse->Quality, sparse->InventoryType); itemTemplate.Delay = sparse->Delay; itemTemplate.RangedModRange = sparse->RangedModRange; - for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - itemTemplate.Spells[i].SpellId = sparse->SpellId[i]; - itemTemplate.Spells[i].SpellTrigger = sparse->SpellTrigger[i]; - itemTemplate.Spells[i].SpellCharges = sparse->SpellCharges[i]; - itemTemplate.Spells[i].SpellCooldown = sparse->SpellCooldown[i]; - itemTemplate.Spells[i].SpellCategory = sparse->SpellCategory[i]; - itemTemplate.Spells[i].SpellCategoryCooldown = sparse->SpellCategoryCooldown[i]; - } itemTemplate.SpellPPMRate = 0.0f; itemTemplate.Bonding = sparse->Bonding; @@ -2565,8 +2555,9 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.TotemCategory = sparse->TotemCategory; for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i) { - itemTemplate.Socket[i].Color = sparse->Color[i]; - itemTemplate.Socket[i].Content = sparse->Content[i]; + itemTemplate.Socket[i].Color = sparse->SocketColor[i]; + // TODO: 6.x update/remove this + itemTemplate.Socket[i].Content = 0; } itemTemplate.socketBonus = sparse->SocketBonus; @@ -2576,9 +2567,9 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.ArmorDamageModifier = sparse->ArmorDamageModifier; itemTemplate.Duration = sparse->Duration; itemTemplate.ItemLimitCategory = sparse->ItemLimitCategory; - itemTemplate.HolidayId = sparse->HolidayId; + itemTemplate.HolidayId = sparse->HolidayID; itemTemplate.StatScalingFactor = sparse->StatScalingFactor; - itemTemplate.CurrencySubstitutionId = sparse->CurrencySubstitutionId; + itemTemplate.CurrencySubstitutionId = sparse->CurrencySubstitutionID; itemTemplate.CurrencySubstitutionCount = sparse->CurrencySubstitutionCount; itemTemplate.ScriptId = 0; itemTemplate.FoodType = 0; @@ -2587,6 +2578,29 @@ void ObjectMgr::LoadItemTemplates() ++sparseCount; } + // Load item effects (spells) + for (uint32 effectId = 0; effectId < sItemEffectStore.GetNumRows(); ++effectId) + { + ItemEffectEntry const* effectEntry = sItemEffectStore.LookupEntry(effectId); + if (!effectEntry) + continue; + + auto itemItr = _itemTemplateStore.find(effectEntry->ItemID); + if (itemItr == _itemTemplateStore.end()) + continue; + + ItemTemplate& itemTemplate = itemItr->second; + + ItemEffect effect; + effect.SpellID = effectEntry->SpellID; + effect.Trigger = effectEntry->Trigger; + effect.Charges = effectEntry->Charges; + effect.Cooldown = effectEntry->Cooldown; + effect.Category = effectEntry->Category; + effect.CategoryCooldown = effectEntry->CategoryCooldown; + itemTemplate.Effects.push_back(effect); + } + // Load missing items from item_template AND overwrite data from Item-sparse.db2 (item_template is supposed to contain Item-sparse.adb data) // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 QueryResult result = WorldDatabase.Query("SELECT entry, Class, SubClass, SoundOverrideSubclass, Name, DisplayId, Quality, Flags, FlagsExtra, Unk430_1, Unk430_2, BuyCount, BuyPrice, SellPrice, " @@ -2646,10 +2660,10 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.Name1 = fields[4].GetString(); itemTemplate.DisplayInfoID = fields[5].GetUInt32(); itemTemplate.Quality = uint32(fields[6].GetUInt8()); - itemTemplate.Flags = fields[7].GetUInt32(); - itemTemplate.Flags2 = fields[8].GetUInt32(); - itemTemplate.Unk430_1 = fields[9].GetFloat(); - itemTemplate.Unk430_2 = fields[10].GetFloat(); + itemTemplate.Flags[0] = fields[7].GetUInt32(); + itemTemplate.Flags[1] = fields[8].GetUInt32(); + itemTemplate.Unk1 = fields[9].GetFloat(); + itemTemplate.Unk2 = fields[10].GetFloat(); itemTemplate.BuyCount = uint32(fields[11].GetUInt8()); itemTemplate.BuyPrice = int32(fields[12].GetInt64()); itemTemplate.SellPrice = fields[13].GetUInt32(); @@ -2682,7 +2696,7 @@ void ObjectMgr::LoadItemTemplates() // cache item damage FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, itemTemplate.ItemLevel, itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, fields[71].GetUInt16(), - fields[131].GetFloat(), itemTemplate.InventoryType, itemTemplate.Flags2); + fields[131].GetFloat(), itemTemplate.InventoryType, itemTemplate.Flags[1]); itemTemplate.DamageType = fields[70].GetUInt8(); itemTemplate.Armor = FillItemArmor(itemTemplate.ItemLevel, itemTemplate.Class, @@ -2691,14 +2705,16 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.Delay = fields[71].GetUInt16(); itemTemplate.RangedModRange = fields[72].GetFloat(); - for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - itemTemplate.Spells[i].SpellId = fields[73 + 6 * i + 0].GetInt32(); - itemTemplate.Spells[i].SpellTrigger = uint32(fields[73 + 6 * i + 1].GetUInt8()); - itemTemplate.Spells[i].SpellCharges = int32(fields[73 + 6 * i + 2].GetInt16()); - itemTemplate.Spells[i].SpellCooldown = fields[73 + 6 * i + 3].GetInt32(); - itemTemplate.Spells[i].SpellCategory = uint32(fields[73 + 6 * i + 4].GetUInt16()); - itemTemplate.Spells[i].SpellCategoryCooldown = fields[73 + 6 * i + 5].GetInt32(); + // TODO: 6.x move this to new itemeffect table (probably itemeffect_dbc?) + itemTemplate.Effects.resize(3); + for (uint32 i = 0; i < 3; ++i) + { + itemTemplate.Effects[i].SpellID = fields[73 + 6 * i + 0].GetInt32(); + itemTemplate.Effects[i].Trigger = uint32(fields[73 + 6 * i + 1].GetUInt8()); + itemTemplate.Effects[i].Charges = int32(fields[73 + 6 * i + 2].GetInt16()); + itemTemplate.Effects[i].Cooldown = fields[73 + 6 * i + 3].GetInt32(); + itemTemplate.Effects[i].Category = uint32(fields[73 + 6 * i + 4].GetUInt16()); + itemTemplate.Effects[i].CategoryCooldown = fields[73 + 6 * i + 5].GetInt32(); } itemTemplate.SpellPPMRate = 0.0f; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index e0f443b7da6..c4e4b6f21ae 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1134,7 +1134,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) if (item->DisenchantID && m_maxEnchantingLevel >= item->RequiredDisenchantSkill) r->rollVoteMask |= ROLL_FLAG_TYPE_DISENCHANT; - if (item->Flags2 & ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED) + if (item->Flags[1] & ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED) r->rollVoteMask &= ~ROLL_FLAG_TYPE_NEED; loot->items[itemSlot].is_blocked = true; diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index e7e45e0bf19..d52e218e66d 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -213,7 +213,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) itemEntry = item->GetTemplate()->ItemId; if (sAuctionMgr->GetAItem(item->GetGUID().GetCounter()) || !item->CanBeTraded() || item->IsNotEmptyBag() || - item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || + item->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || item->GetCount() < count[i] || itemEntry != item->GetTemplate()->ItemId) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index f6566044278..95bcecbfdeb 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -288,7 +288,7 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData) return; } - if (pItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_INDESTRUCTIBLE) + if (pItem->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_INDESTRUCTIBLE) { _player->SendEquipError(EQUIP_ERR_DROP_BOUND_ITEM, NULL, NULL); return; @@ -626,8 +626,8 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid) continue; // Only display items in vendor lists for the team the player is on - if ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || - (itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE)) + if ((itemTemplate->Flags[1] & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || + (itemTemplate->Flags[1] & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE)) continue; // Items sold out are not displayed in list @@ -970,7 +970,7 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) return; } - if (!(gift->GetTemplate()->Flags & ITEM_PROTO_FLAG_WRAPPER)) // cheating: non-wrapper wrapper + if (!(gift->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_WRAPPER)) // cheating: non-wrapper wrapper { _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, NULL); return; @@ -1157,7 +1157,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) ItemTemplate const* iGemProto = Gems[i]->GetTemplate(); // unique item (for new and already placed bit removed enchantments - if (iGemProto->Flags & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED) + if (iGemProto->Flags[0] & ITEM_PROTO_FLAG_UNIQUE_EQUIPPED) { for (int j = 0; j < MAX_GEM_SOCKETS; ++j) { diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index a4376c4534e..56c4feebf77 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -334,7 +334,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid) ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling - if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) + if (proto->Flags[0] & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); @@ -350,7 +350,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid) else { // Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item - if (pItem->loot.isLooted() || !(proto->Flags & ITEM_PROTO_FLAG_OPENABLE)) + if (pItem->loot.isLooted() || !(proto->Flags[0] & ITEM_PROTO_FLAG_OPENABLE)) player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } return; // item can be looted only single player diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 69ffef3cdb1..60cde45e8c4 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -252,7 +252,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) if (Item* item = player->GetItemByGuid(itemGUIDs[i])) { ItemTemplate const* itemProto = item->GetTemplate(); - if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) + if (!itemProto || !(itemProto->Flags[0] & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; @@ -306,7 +306,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) } } - if (item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) + if (item->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 3ecba691bbb..05f600e1207 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -138,14 +138,14 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) } // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) - if (proto->Class == ITEM_CLASS_CONSUMABLE && !(proto->Flags & ITEM_PROTO_FLAG_USEABLE_IN_ARENA) && pUser->InArena()) + if (proto->Class == ITEM_CLASS_CONSUMABLE && !(proto->Flags[0] & ITEM_PROTO_FLAG_USEABLE_IN_ARENA) && pUser->InArena()) { pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, NULL); return; } // don't allow items banned in arena - if (proto->Flags & ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA && pUser->InArena()) + if (proto->Flags[0] & ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA && pUser->InArena()) { pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, NULL); return; @@ -153,9 +153,9 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) if (pUser->IsInCombat()) { - for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (int i = 0; i < proto->Effects.size(); ++i) { - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId)) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Effects[i].SpellID)) { if (!spellInfo->CanBeUsedInCombat()) { @@ -219,7 +219,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) } // Verify that the bag is an actual bag or wrapped item that can be used "normally" - if (!(proto->Flags & ITEM_PROTO_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) + if (!(proto->Flags[0] & ITEM_PROTO_FLAG_OPENABLE) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) { pUser->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, NULL); TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [%s] tried to open item [%s, entry: %u] which is not openable!", diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index bde2f17b132..5ec917c4381 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -364,7 +364,7 @@ LootItem::LootItem(LootStoreItem const& li) conditions = li.conditions; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemid); - freeforall = proto && (proto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT); + freeforall = proto && (proto->Flags[0] & ITEM_PROTO_FLAG_PARTY_LOOT); follow_loot_rules = proto && (proto->FlagsCu & ITEM_FLAGS_CU_FOLLOW_LOOT_RULES); needs_quest = li.needs_quest; @@ -391,14 +391,14 @@ bool LootItem::AllowedForPlayer(Player const* player) const return false; // not show loot for players without profession or those who already know the recipe - if ((pProto->Flags & ITEM_PROTO_FLAG_SMART_LOOT) && (!player->HasSkill(pProto->RequiredSkill) || player->HasSpell(pProto->Spells[1].SpellId))) + if ((pProto->Flags[0] & ITEM_PROTO_FLAG_SMART_LOOT) && (!player->HasSkill(pProto->RequiredSkill) || player->HasSpell(pProto->Effects[1].SpellID))) return false; // not show loot for not own team - if ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY) && player->GetTeam() != HORDE) + if ((pProto->Flags[1] & ITEM_FLAGS_EXTRA_HORDE_ONLY) && player->GetTeam() != HORDE) return false; - if ((pProto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE) + if ((pProto->Flags[1] & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE) return false; // check quest requirements @@ -440,7 +440,7 @@ void Loot::AddItem(LootStoreItem const& item) // non-conditional one-player only items are counted here, // free for all items are counted in FillFFALoot(), // non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot() - if (!item.needs_quest && item.conditions.empty() && !(proto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT)) + if (!item.needs_quest && item.conditions.empty() && !(proto->Flags[0] & ITEM_PROTO_FLAG_PARTY_LOOT)) ++unlootedCount; } } @@ -1657,7 +1657,7 @@ void LoadLootTemplates_Item() // remove real entries and check existence loot ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) - if (lootIdSet.find(itr->second.ItemId) != lootIdSet.end() && itr->second.Flags & ITEM_PROTO_FLAG_OPENABLE) + if (lootIdSet.find(itr->second.ItemId) != lootIdSet.end() && itr->second.Flags[0] & ITEM_PROTO_FLAG_OPENABLE) lootIdSet.erase(itr->second.ItemId); // output error for any still listed (not referenced from appropriate table) ids @@ -1682,7 +1682,7 @@ void LoadLootTemplates_Milling() ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - if (!(itr->second.Flags & ITEM_PROTO_FLAG_MILLABLE)) + if (!(itr->second.Flags[0] & ITEM_PROTO_FLAG_MILLABLE)) continue; if (lootIdSet.find(itr->second.ItemId) != lootIdSet.end()) @@ -1745,7 +1745,7 @@ void LoadLootTemplates_Prospecting() ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - if (!(itr->second.Flags & ITEM_PROTO_FLAG_PROSPECTABLE)) + if (!(itr->second.Flags[0] & ITEM_PROTO_FLAG_PROSPECTABLE)) continue; if (lootIdSet.find(itr->second.ItemId) != lootIdSet.end()) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 0f412a8cc3e..8583d055123 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4301,30 +4301,27 @@ void Spell::TakeCastItem() bool expendable = false; bool withoutCharges = false; - for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (int i = 0; i < proto->Effects.size(); ++i) { - if (proto->Spells[i].SpellId) + // item has limited charges + if (proto->Effects[i].Charges) { - // item has limited charges - if (proto->Spells[i].SpellCharges) - { - if (proto->Spells[i].SpellCharges < 0) - expendable = true; - - int32 charges = m_CastItem->GetSpellCharges(i); + if (proto->Effects[i].Charges < 0) + expendable = true; - // item has charges left - if (charges) - { - (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use - if (proto->Stackable == 1) - m_CastItem->SetSpellCharges(i, charges); - m_CastItem->SetState(ITEM_CHANGED, player); - } + int32 charges = m_CastItem->GetSpellCharges(i); - // all charges used - withoutCharges = (charges == 0); + // item has charges left + if (charges) + { + (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use + if (proto->Stackable == 1) + m_CastItem->SetSpellCharges(i, charges); + m_CastItem->SetState(ITEM_CHANGED, player); } + + // all charges used + withoutCharges = (charges == 0); } } @@ -4558,7 +4555,7 @@ void Spell::TakeReagents() ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : NULL; // do not take reagents for these item casts - if (castItemTemplate && castItemTemplate->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST) + if (castItemTemplate && castItemTemplate->Flags[0] & ITEM_PROTO_FLAG_TRIGGERED_CAST) return; Player* p_caster = m_caster->ToPlayer(); @@ -4576,11 +4573,11 @@ void Spell::TakeReagents() // if CastItem is also spell reagent if (castItemTemplate && castItemTemplate->ItemId == itemid) { - for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) + for (int s = 0; s < castItemTemplate->Effects.size(); ++s) { // CastItem will be used up and does not count as reagent int32 charges = m_CastItem->GetSpellCharges(s); - if (castItemTemplate->Spells[s].SpellCharges < 0 && abs(charges) < 2) + if (castItemTemplate->Effects[s].Charges < 0 && abs(charges) < 2) { ++itemcount; break; @@ -5914,8 +5911,8 @@ SpellCastResult Spell::CheckItems() if (!proto) return SPELL_FAILED_ITEM_NOT_READY; - for (uint8 i = 0; i < MAX_ITEM_SPELLS; ++i) - if (proto->Spells[i].SpellCharges) + for (uint8 i = 0; i < proto->Effects.size(); ++i) + if (proto->Effects[i].Charges) if (m_CastItem->GetSpellCharges(i) == 0) return SPELL_FAILED_NO_CHARGES_REMAIN; @@ -5989,7 +5986,7 @@ SpellCastResult Spell::CheckItems() } // do not take reagents for these item casts - if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST)) + if (!(m_CastItem && m_CastItem->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_TRIGGERED_CAST)) { bool checkReagents = !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST) && !player->CanNoReagentCast(m_spellInfo); // Not own traded item (in trader trade slot) requires reagents even if triggered spell @@ -6015,11 +6012,11 @@ SpellCastResult Spell::CheckItems() ItemTemplate const* proto = m_CastItem->GetTemplate(); if (!proto) return SPELL_FAILED_ITEM_NOT_READY; - for (uint8 s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) + for (uint8 s = 0; s < proto->Effects.size(); ++s) { // CastItem will be used up and does not count as reagent int32 charges = m_CastItem->GetSpellCharges(s); - if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2) + if (proto->Effects[s].Charges < 0 && abs(charges) < 2) { ++itemcount; break; @@ -6093,7 +6090,7 @@ SpellCastResult Spell::CheckItems() if (m_targets.GetItemTarget()->GetOwner() != m_caster) return SPELL_FAILED_NOT_TRADEABLE; // do not allow to enchant vellum from scroll made by vellum-prevent exploit - if (m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST) + if (m_CastItem && m_CastItem->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_TRIGGERED_CAST) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1); @@ -6114,12 +6111,12 @@ SpellCastResult Spell::CheckItems() return SPELL_FAILED_LOWLEVEL; bool isItemUsable = false; - for (uint8 e = 0; e < MAX_ITEM_PROTO_SPELLS; ++e) + ItemTemplate const* proto = targetItem->GetTemplate(); + for (uint8 e = 0; e < proto->Effects.size(); ++e) { - ItemTemplate const* proto = targetItem->GetTemplate(); - if (proto->Spells[e].SpellId && ( - proto->Spells[e].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE || - proto->Spells[e].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)) + if (proto->Effects[e].SpellID && ( + proto->Effects[e].Trigger == ITEM_SPELLTRIGGER_ON_USE || + proto->Effects[e].Trigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)) { isItemUsable = true; break; @@ -6216,7 +6213,7 @@ SpellCastResult Spell::CheckItems() if (!m_targets.GetItemTarget()) return SPELL_FAILED_CANT_BE_PROSPECTED; //ensure item is a prospectable ore - if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_PROTO_FLAG_PROSPECTABLE)) + if (!(m_targets.GetItemTarget()->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_PROSPECTABLE)) return SPELL_FAILED_CANT_BE_PROSPECTED; //prevent prospecting in trade slot if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID()) @@ -6239,7 +6236,7 @@ SpellCastResult Spell::CheckItems() if (!m_targets.GetItemTarget()) return SPELL_FAILED_CANT_BE_MILLED; //ensure item is a millable herb - if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_PROTO_FLAG_MILLABLE)) + if (!(m_targets.GetItemTarget()->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_MILLABLE)) return SPELL_FAILED_CANT_BE_MILLED; //prevent milling in trade slot if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID()) @@ -6296,8 +6293,8 @@ SpellCastResult Spell::CheckItems() if (Item* pitem = player->GetItemByEntry(item_id)) { - for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - if (pProto->Spells[x].SpellCharges != 0 && pitem->GetSpellCharges(x) == pProto->Spells[x].SpellCharges) + for (int x = 0; x < pProto->Effects.size(); ++x) + if (pProto->Effects[x].Charges != 0 && pitem->GetSpellCharges(x) == pProto->Effects[x].Charges) return SPELL_FAILED_ITEM_AT_MAX_CHARGES; } break; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index de1107bd428..9c12abbe6e2 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2509,7 +2509,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) else { // do not increase skill if vellum used - if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST)) + if (!(m_CastItem && m_CastItem->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_TRIGGERED_CAST)) player->UpdateCraftSkill(m_spellInfo->Id); uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; @@ -4957,7 +4957,7 @@ void Spell::EffectProspecting(SpellEffIndex /*effIndex*/) if (!player) return; - if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_PROTO_FLAG_PROSPECTABLE)) + if (!itemTarget || !(itemTarget->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_PROSPECTABLE)) return; if (itemTarget->GetCount() < 5) @@ -4982,7 +4982,7 @@ void Spell::EffectMilling(SpellEffIndex /*effIndex*/) if (!player) return; - if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_PROTO_FLAG_MILLABLE)) + if (!itemTarget || !(itemTarget->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_MILLABLE)) return; if (itemTarget->GetCount() < 5) @@ -5640,8 +5640,8 @@ void Spell::EffectRechargeManaGem(SpellEffIndex /*effIndex*/) if (Item* pItem = player->GetItemByEntry(item_id)) { - for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - pItem->SetSpellCharges(x, pProto->Spells[x].SpellCharges); + for (int x = 0; x < pProto->Effects.size(); ++x) + pItem->SetSpellCharges(x, pProto->Effects[x].Charges); pItem->SetState(ITEM_CHANGED, player); } } -- cgit v1.2.3