aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIntel <chemicstry@gmail.com>2014-11-14 14:47:20 +0200
committerNayd <dnpd.dd@gmail.com>2014-11-15 04:27:37 +0000
commit1e51d22d2990c69c4725133733c99599ddb0abd1 (patch)
tree93a35434839f0c350084e514ede50a1af4c8371a
parentb5236a6cdc0161e4240435280b388868f443c9b2 (diff)
Core/DataStores: Updated Item DataStores
Signed-off-by: Nayd <dnpd.dd@gmail.com>
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp2
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp17
-rw-r--r--src/server/game/DataStores/DB2Stores.h6
-rw-r--r--src/server/game/DataStores/DB2Structure.h96
-rw-r--r--src/server/game/DataStores/DB2Utility.cpp2
-rw-r--r--src/server/game/DataStores/DB2fmt.h6
-rw-r--r--src/server/game/Entities/Creature/Creature.h2
-rw-r--r--src/server/game/Entities/Item/Item.cpp27
-rw-r--r--src/server/game/Entities/Item/Item.h4
-rw-r--r--src/server/game/Entities/Item/ItemPrototype.h32
-rw-r--r--src/server/game/Entities/Player/Player.cpp126
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp82
-rw-r--r--src/server/game/Groups/Group.cpp2
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp2
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp10
-rw-r--r--src/server/game/Handlers/LootHandler.cpp4
-rw-r--r--src/server/game/Handlers/MailHandler.cpp4
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp10
-rw-r--r--src/server/game/Loot/LootMgr.cpp16
-rw-r--r--src/server/game/Spells/Spell.cpp71
-rw-r--r--src/server/game/Spells/SpellEffects.cpp10
21 files changed, 321 insertions, 210 deletions
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<HolidaysEntry> sHolidaysStore(HolidaysEntryfmt);
DB2Storage<ItemEntry> sItemStore(Itemfmt, &DB2Utilities::HasItemEntry, &DB2Utilities::WriteItemDbReply);
+DB2Storage<ItemAppearanceEntry> sItemAppearanceStore(ItemAppearanceEntryfmt);
+ItemDisplayIDMap sItemDisplayIDMap;
DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore(ItemCurrencyCostfmt);
DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
+DB2Storage<ItemEffectEntry> sItemEffectStore(ItemEffectEntryfmt);
DB2Storage<ItemSparseEntry> sItemSparseStore(ItemSparsefmt, &DB2Utilities::HasItemSparseEntry, &DB2Utilities::WriteItemSparseDbReply);
DB2Storage<KeyChainEntry> sKeyChainStore(KeyChainfmt);
DB2Storage<OverrideSpellDataEntry> 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 <string>
+#include <map>
extern DB2Storage<HolidaysEntry> sHolidaysStore;
extern DB2Storage<ItemEntry> sItemStore;
+extern DB2Storage<ItemAppearanceEntry> sItemAppearanceStore;
+extern ItemDisplayIDMap sItemDisplayIDMap;
extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore;
extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore;
+extern DB2Storage<ItemEffectEntry> sItemEffectStore;
extern DB2Storage<ItemSparseEntry> sItemSparseStore;
extern DB2Storage<KeyChainEntry> sKeyChainStore;
extern DB2Storage<OverrideSpellDataEntry> 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<uint32, uint32> 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<ItemEntry> const& /*store*/, uint
void DB2Utilities::WriteItemSparseDbReply(DB2Storage<ItemSparseEntry> 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<ItemSparseEntry> 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<VendorItem*> 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<ItemEffect> 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);
}
}