aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2011-11-25 23:24:40 +0100
committerShauren <shauren.trinity@gmail.com>2011-11-25 23:24:40 +0100
commite8c3a3ac9c032cf56ec11620ba7dd33efed487c5 (patch)
tree03cb750cfc0028b053b07dd5f2b50bc1b4d0c247 /src/server/game
parent8d3bc5e8b9515499f366ec7173d70978bb0009e7 (diff)
Core/Items
* Updated ItemTemplate structure to 4.x * Calculate armor, damage and disenchant loot from dbc files TODO: Use dbc disenchant ids in disenchant_loot_template
Diffstat (limited to 'src/server/game')
-rwxr-xr-xsrc/server/game/DataStores/DBCStores.cpp22
-rwxr-xr-xsrc/server/game/DataStores/DBCStores.h1
-rwxr-xr-xsrc/server/game/DataStores/DBCStructure.h14
-rwxr-xr-xsrc/server/game/DataStores/DBCfmt.h1
-rwxr-xr-xsrc/server/game/Entities/Item/ItemPrototype.h54
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp55
-rwxr-xr-xsrc/server/game/Entities/Player/Player.h4
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp4
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp971
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h3
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp2
-rwxr-xr-xsrc/server/game/Loot/LootMgr.cpp21
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/ItemHandler.cpp294
-rwxr-xr-xsrc/server/game/Server/Protocol/Opcodes.cpp8
-rwxr-xr-xsrc/server/game/Server/WorldSession.h4
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp2
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp2
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp4
-rwxr-xr-xsrc/server/game/World/World.cpp14
19 files changed, 679 insertions, 801 deletions
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index ceba8d178cf..9bdbce70acc 100755
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -111,20 +111,12 @@ DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptf
DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
-DBCStorage <ItemClassEntry> sItemClassStore(ItemClassfmt);
-//DBCStorage <ItemEntry> sItemStore(Itemfmt);
-DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt);
-//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
-//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
-//DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
-DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
-DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
-DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
-DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
-
DBCStorage <ItemArmorQualityEntry> sItemArmorQualityStore(ItemArmorQualityfmt);
DBCStorage <ItemArmorShieldEntry> sItemArmorShieldStore(ItemArmorShieldfmt);
DBCStorage <ItemArmorTotalEntry> sItemArmorTotalStore(ItemArmorTotalfmt);
+DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt);
+DBCStorage <ItemClassEntry> sItemClassStore(ItemClassfmt);
+//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
DBCStorage <ItemDamageEntry> sItemDamageAmmoStore(ItemDamagefmt);
DBCStorage <ItemDamageEntry> sItemDamageOneHandStore(ItemDamagefmt);
DBCStorage <ItemDamageEntry> sItemDamageOneHandCasterStore(ItemDamagefmt);
@@ -133,6 +125,13 @@ DBCStorage <ItemDamageEntry> sItemDamageThrownStore(ItemDamagefmt);
DBCStorage <ItemDamageEntry> sItemDamageTwoHandStore(ItemDamagefmt);
DBCStorage <ItemDamageEntry> sItemDamageTwoHandCasterStore(ItemDamagefmt);
DBCStorage <ItemDamageEntry> sItemDamageWandStore(ItemDamagefmt);
+DBCStorage <ItemDisenchantLootEntry> sItemDisenchantLootStore(ItemDisenchantLootfmt);
+//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
+//DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
+DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
+DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
+DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
+DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
DBCStorage <LFGDungeonEntry> sLFGDungeonStore(LFGDungeonEntryfmt);
//DBCStorage <LiquidTypeEntry> sLiquidTypeStore(LiquidTypeEntryfmt);
@@ -409,6 +408,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandStore, dbcPath, "ItemDamageTwoHand.dbc");//14545
LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageTwoHandCasterStore,dbcPath, "ItemDamageTwoHandCaster.dbc");//14545
LoadDBC(availableDbcLocales, bad_dbc_files, sItemDamageWandStore, dbcPath, "ItemDamageWand.dbc");//14545
+ LoadDBC(availableDbcLocales, bad_dbc_files, sItemDisenchantLootStore, dbcPath, "ItemDisenchantLoot.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sItemClassStore, dbcPath,"ItemClass.dbc");//14545
LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc");//14545
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index fc20d61982f..aee179af3b2 100755
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -128,6 +128,7 @@ extern DBCStorage <ItemDamageEntry> sItemDamageTwoHandStore;
extern DBCStorage <ItemDamageEntry> sItemDamageTwoHandCasterStore;
extern DBCStorage <ItemDamageEntry> sItemDamageWandStore;
//extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
+extern DBCStorage <ItemDisenchantLootEntry> sItemDisenchantLootStore;
extern DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore;
extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 7dbb8a200aa..ae71b24bdcb 100755
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1169,7 +1169,7 @@ struct ItemClassEntry
struct ItemDamageEntry
{
uint32 Id; // 0 item level
- float Value[7]; // 1-7 multiplier for item quality
+ float DPS[7]; // 1-7 multiplier for item quality
uint32 Id2; // 8 item level
};
@@ -1216,6 +1216,17 @@ struct ItemDisplayInfoEntry
// 11 m_particleColorID
};
+struct ItemDisenchantLootEntry
+{
+ uint32 Id;
+ uint32 ItemClass;
+ int32 Unk;
+ uint32 ItemQuality;
+ uint32 MinItemLevel;
+ uint32 MaxItemLevel;
+ uint32 RequiredDisenchantSkill;
+};
+
//struct ItemCondExtCostsEntry
//{
// uint32 ID;
@@ -2317,4 +2328,3 @@ typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath;
#define TaxiMaskSize 14
typedef uint32 TaxiMask[TaxiMaskSize];
#endif
-
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index be2fe6916e4..28df75f185b 100755
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -82,6 +82,7 @@ const char ItemArmorQualityfmt[]="nfffffffi";
const char ItemArmorShieldfmt[]="nifffffff";
const char ItemArmorTotalfmt[]="niffff";
const char ItemDamagefmt[]="nfffffffi";
+const char ItemDisenchantLootfmt[]="niiiiii";
const char ItemClassfmt[]="dixxx";
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
//const char ItemCondExtCostsEntryfmt[]="xiii";
diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
index c15189dfb5f..0234b90e7f5 100755
--- a/src/server/game/Entities/Item/ItemPrototype.h
+++ b/src/server/game/Entities/Item/ItemPrototype.h
@@ -67,7 +67,15 @@ enum ItemModType
ITEM_MOD_SPELL_POWER = 45,
ITEM_MOD_HEALTH_REGEN = 46,
ITEM_MOD_SPELL_PENETRATION = 47,
- ITEM_MOD_BLOCK_VALUE = 48
+ ITEM_MOD_BLOCK_VALUE = 48,
+ ITEM_MOD_MASTERY_RATING = 49,
+ ITEM_MOD_EXTRA_ARMOR = 50,
+ ITEM_MOD_FIRE_RESISTANCE = 51,
+ ITEM_MOD_FROST_RESISTANCE = 52,
+ ITEM_MOD_HOLY_RESISTANCE = 53,
+ ITEM_MOD_SHADOW_RESISTANCE = 54,
+ ITEM_MOD_NATURE_RESISTANCE = 55,
+ ITEM_MOD_ARCANE_RESISTANCE = 56,
};
#define MAX_ITEM_MOD 49
@@ -543,24 +551,19 @@ inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemS
#pragma pack(push, 1)
#endif
-struct _Damage
-{
- float DamageMin;
- float DamageMax;
- uint32 DamageType; // id from Resistances.dbc
-};
-
struct _ItemStat
{
uint32 ItemStatType;
int32 ItemStatValue;
+ int32 ItemStatUnk1;
+ int32 ItemStatUnk2;
};
+
struct _Spell
{
int32 SpellId; // id from Spell.dbc
uint32 SpellTrigger;
int32 SpellCharges;
- float SpellPPMRate;
int32 SpellCooldown;
uint32 SpellCategory; // id from SpellCategory.dbc
int32 SpellCategoryCooldown;
@@ -583,7 +586,7 @@ struct ItemTemplate
uint32 Class; // id from ItemClass.dbc
uint32 SubClass; // id from ItemSubClass.dbc
int32 Unk0;
- std::string Name1;
+ std::string Name1;
uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc
uint32 Quality;
uint32 Flags;
@@ -609,18 +612,15 @@ struct ItemTemplate
uint32 StatsCount;
_ItemStat ItemStat[MAX_ITEM_PROTO_STATS];
uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc
- _Damage Damage[MAX_ITEM_PROTO_DAMAGES];
+ float DamageMin;
+ float DamageMax;
+ uint32 DamageType; // id from Resistances.dbc
+ float DPS;
uint32 Armor;
- uint32 HolyRes;
- uint32 FireRes;
- uint32 NatureRes;
- uint32 FrostRes;
- uint32 ShadowRes;
- uint32 ArcaneRes;
uint32 Delay;
- uint32 AmmoType;
float RangedModRange;
_Spell Spells[MAX_ITEM_PROTO_SPELLS];
+ float SpellPPMRate;
uint32 Bonding;
std::string Description;
uint32 PageText;
@@ -632,7 +632,6 @@ struct ItemTemplate
uint32 Sheath;
int32 RandomProperty; // id from ItemRandomProperties.dbc
int32 RandomSuffix; // id from ItemRandomSuffix.dbc
- uint32 Block;
uint32 ItemSet; // id from ItemSet.dbc
uint32 MaxDurability;
uint32 Area; // id from AreaTable.dbc
@@ -647,6 +646,9 @@ struct ItemTemplate
int32 Duration; // negative = realtime, positive = ingame time
uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc
uint32 HolidayId; // id from Holidays.dbc
+ float StatScalingFactor;
+ int32 Field130;
+ int32 Field131;
uint32 ScriptId;
uint32 DisenchantID;
uint32 FoodType;
@@ -679,22 +681,12 @@ struct ItemTemplate
return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF-1) : uint32(Stackable);
}
- float getDPS() const
- {
- if (Delay == 0)
- return 0;
- float temp = 0;
- for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- temp+=Damage[i].DamageMin + Damage[i].DamageMax;
- return temp*500/Delay;
- }
-
int32 getFeralBonus(int32 extraDPS = 0) const
{
// 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
- if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3)
+ if (Class == ITEM_CLASS_WEAPON && (1 << SubClass) & 0x02A5F3)
{
- int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767;
+ int32 bonus = int32((extraDPS + DPS) * 14.0f) - 767;
if (bonus < 0)
return 0;
return bonus;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index b75f3f07d55..3017a618a20 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -8032,6 +8032,24 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
case ITEM_MOD_SPELL_HEALING_DONE:
case ITEM_MOD_SPELL_DAMAGE_DONE:
break;
+ case ITEM_MOD_FIRE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_FROST_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_HOLY_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_SHADOW_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_NATURE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(val), apply);
+ break;
+ case ITEM_MOD_ARCANE_RESISTANCE:
+ HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(val), apply);
+ break;
}
}
@@ -8068,27 +8086,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
if (proto->ArmorDamageModifier > 0)
HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
- if (proto->Block)
- HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
-
- if (proto->HolyRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply);
-
- if (proto->FireRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply);
-
- if (proto->NatureRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply);
-
- if (proto->FrostRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply);
-
- if (proto->ShadowRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply);
-
- if (proto->ArcaneRes)
- HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
-
WeaponAttackType attType = BASE_ATTACK;
if (slot == EQUIPMENT_SLOT_RANGED && (
@@ -8123,8 +8120,8 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt
attType = OFF_ATTACK;
}
- float minDamage = proto->Damage[0].DamageMin;
- float maxDamage = proto->Damage[0].DamageMax;
+ float minDamage = proto->DamageMin;
+ float maxDamage = proto->DamageMax;
// If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage
int32 extraDPS = 0;
@@ -8410,7 +8407,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
float chance = (float)spellInfo->ProcChance;
- if (spellData.SpellPPMRate)
+ if (proto->SpellPPMRate)
{
if (spellData.SpellId == 52781) // Persuasive Strike
{
@@ -8425,7 +8422,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
}
}
uint32 WeaponSpeed = GetAttackTime(attType);
- chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate, spellInfo);
+ chance = GetPPMProcChance(WeaponSpeed, proto->SpellPPMRate, spellInfo);
}
else if (chance > 100.0f)
{
@@ -18334,7 +18331,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setFloat(index++, finiteAlways(GetPositionY()));
stmt->setFloat(index++, finiteAlways(GetPositionZ()));
stmt->setFloat(index++, finiteAlways(GetOrientation()));
-
+
std::ostringstream ss;
ss << m_taxi;
stmt->setString(index++, ss.str());
@@ -18356,7 +18353,7 @@ void Player::SaveToDB(bool create /*=false*/)
ss.str().clear();
ss << m_taxi.SaveTaxiDestinationsToString();
-
+
stmt->setString(index++, ss.str());
stmt->setUInt32(index++, GetArenaPoints());
stmt->setUInt32(index++, GetHonorPoints());
@@ -18389,7 +18386,7 @@ void Player::SaveToDB(bool create /*=false*/)
for (uint32 i = 0; i < EQUIPMENT_SLOT_END * 2; ++i)
ss << GetUInt32Value(PLAYER_VISIBLE_ITEM_1_ENTRYID + i) << ' ';
stmt->setString(index++, ss.str());
-
+
ss.str().clear();
// ...and bags for enum opcode
for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
@@ -24825,4 +24822,4 @@ bool Player::IsInWhisperWhiteList(uint64 guid)
return true;
}
return false;
-}
+} \ No newline at end of file
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index b2457a87e82..efe9dd487d5 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1844,7 +1844,7 @@ class Player : public Unit, public GridObject<Player>
void RemoveFromGroup(RemoveMethod method = GROUP_REMOVEMETHOD_DEFAULT) { RemoveFromGroup(GetGroup(), GetGUID(), method); }
void SendUpdateToOutOfRangeGroupMembers();
- void SetInGuild(uint32 GuildId)
+ void SetInGuild(uint32 GuildId)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_GUILD_ID);
stmt->setUInt32(0, GuildId);
@@ -2538,7 +2538,7 @@ class Player : public Unit, public GridObject<Player>
CreatureDisplayInfoEntry const* mountDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID));
if (!mountDisplayInfo)
return GetCollisionHeight(false);
-
+
CreatureModelDataEntry const* mountModelData = sCreatureModelDataStore.LookupEntry(mountDisplayInfo->ModelId);
if (!mountModelData)
return GetCollisionHeight(false);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 545ba676091..87834d27f34 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -2715,7 +2715,7 @@ float Unit::GetUnitBlockChance() const
if (player->CanBlock())
{
Item* tmpitem = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
- if (tmpitem && !tmpitem->IsBroken() && tmpitem->GetTemplate()->Block)
+ if (tmpitem && !tmpitem->IsBroken())
return GetFloatValue(PLAYER_BLOCK_PERCENTAGE);
}
// is player but has no block ability or no not broken shield equipped
@@ -8674,7 +8674,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
ItemTemplate const* weapon = item->GetTemplate();
- float weaponDPS = weapon->getDPS();
+ float weaponDPS = weapon->DPS;
float attackPower = GetTotalAttackPowerValue(BASE_ATTACK) / 14.0f;
float weaponSpeed = float(weapon->Delay) / 1000.0f;
basepoints0 = int32((weaponDPS + attackPower) * weaponSpeed);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index f2553b3ace5..3218f954078 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -2093,600 +2093,493 @@ void ObjectMgr::LoadItemLocales()
sLog->outString();
}
-void ObjectMgr::LoadItemTemplates()
+void FillItemDamageFields(float* minDamage, float* maxDamage, float* dps, uint32 itemLevel, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32 delay, float statScalingFactor, uint32 inventoryType, uint32 flags2)
{
- uint32 oldMSTime = getMSTime();
-
- // 0 1 2 3 4 5 6 7 8 9 10 11 12
- QueryResult result = WorldDatabase.Query("SELECT entry, class, subclass, unk0, name, displayid, Quality, Flags, FlagsExtra, BuyCount, BuyPrice, SellPrice, InventoryType, "
- // 13 14 15 16 17 18 19 20
- "AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, requiredspell, requiredhonorrank, "
- // 21 22 23 24 25 26 27 28
- "RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, maxcount, stackable, ContainerSlots, StatsCount, stat_type1, "
- // 29 30 31 32 33 34 35 36 37 38
- "stat_value1, stat_type2, stat_value2, stat_type3, stat_value3, stat_type4, stat_value4, stat_type5, stat_value5, stat_type6, "
- // 39 40 41 42 43 44 45 46 47
- "stat_value6, stat_type7, stat_value7, stat_type8, stat_value8, stat_type9, stat_value9, stat_type10, stat_value10, "
- // 48 49 50 51 52 53 54 55 56 57 58
- "ScalingStatDistribution, ScalingStatValue, dmg_min1, dmg_max1, dmg_type1, dmg_min2, dmg_max2, dmg_type2, armor, holy_res, fire_res, "
- // 59 60 61 62 63 64 65 66 67 68
- "nature_res, frost_res, shadow_res, arcane_res, delay, ammo_type, RangedModRange, spellid_1, spelltrigger_1, spellcharges_1, "
- // 69 70 71 72 73 74 75
- "spellppmRate_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, spellid_2, spelltrigger_2, spellcharges_2, "
- // 76 77 78 79 80 81 82
- "spellppmRate_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, spellid_3, spelltrigger_3, spellcharges_3, "
- // 83 84 85 86 87 88 89
- "spellppmRate_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, spellid_4, spelltrigger_4, spellcharges_4, "
- // 90 91 92 93 94 95 96
- "spellppmRate_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, spellid_5, spelltrigger_5, spellcharges_5, "
- // 97 98 99 100 101 102 103 104 105
- "spellppmRate_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, bonding, description, PageText, LanguageID, PageMaterial, "
- // 106 107 108 109 110 111 112 113 114 115 116 117
- "startquest, lockid, Material, sheath, RandomProperty, RandomSuffix, block, itemset, MaxDurability, area, Map, BagFamily, "
- // 118 119 120 121 122 123 124 125
- "TotemCategory, socketColor_1, socketContent_1, socketColor_2, socketContent_2, socketColor_3, socketContent_3, socketBonus, "
- // 126 127 128 129 130 131 132 133
- "GemProperties, RequiredDisenchantSkill, ArmorDamageModifier, Duration, ItemLimitCategory, HolidayId, ScriptName, DisenchantID, "
- // 134 135 136
- "FoodType, minMoneyLoot, maxMoneyLoot FROM item_template");
-
- if (!result)
- {
- sLog->outString(">> Loaded 0 item templates. DB table `item_template` is empty.");
- sLog->outString();
+ *minDamage = *maxDamage = *dps = 0.0f;
+ if (itemClass != ITEM_CLASS_WEAPON || quality > ITEM_QUALITY_ARTIFACT)
return;
- }
- uint32 count = 0;
- bool enforceDBCAttributes = sWorld->getBoolConfig(CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES);
+ DBCStorage<ItemDamageEntry>* store = NULL;
+ // get the right store here
+ if (inventoryType > 0xD + 13)
+ return;
- do
+ switch (inventoryType)
{
- Field* fields = result->Fetch();
-
- uint32 entry = fields[0].GetUInt32();
-
- ItemTemplate& itemTemplate = ItemTemplateStore[entry];
-
- itemTemplate.ItemId = entry;
- itemTemplate.Class = uint32(fields[1].GetUInt8());
- itemTemplate.SubClass = uint32(fields[2].GetUInt8());
- itemTemplate.Unk0 = fields[3].GetInt32();
- itemTemplate.Name1 = fields[4].GetString();
- itemTemplate.DisplayInfoID = fields[5].GetUInt32();
- itemTemplate.Quality = uint32(fields[6].GetUInt8());
- itemTemplate.Flags = uint32(fields[7].GetInt64());
- itemTemplate.Flags2 = fields[8].GetUInt32();
- itemTemplate.BuyCount = uint32(fields[9].GetUInt8());
- itemTemplate.BuyPrice = int32(fields[10].GetInt64());
- itemTemplate.SellPrice = fields[11].GetUInt32();
- itemTemplate.InventoryType = uint32(fields[12].GetUInt8());
- itemTemplate.AllowableClass = fields[13].GetInt32();
- itemTemplate.AllowableRace = fields[14].GetInt32();
- itemTemplate.ItemLevel = uint32(fields[15].GetUInt16());
- itemTemplate.RequiredLevel = uint32(fields[16].GetUInt8());
- itemTemplate.RequiredSkill = uint32(fields[17].GetUInt16());
- itemTemplate.RequiredSkillRank = uint32(fields[18].GetUInt16());
- itemTemplate.RequiredSpell = fields[19].GetUInt32();
- itemTemplate.RequiredHonorRank = fields[20].GetUInt32();
- itemTemplate.RequiredCityRank = fields[21].GetUInt32();
- itemTemplate.RequiredReputationFaction = uint32(fields[22].GetUInt16());
- itemTemplate.RequiredReputationRank = uint32(fields[23].GetUInt16());
- itemTemplate.MaxCount = fields[24].GetInt32();
- itemTemplate.Stackable = fields[25].GetInt32();
- itemTemplate.ContainerSlots = uint32(fields[26].GetUInt8());
- itemTemplate.StatsCount = uint32(fields[27].GetUInt8());
-
- for (uint8 i = 0; i < itemTemplate.StatsCount; ++i)
- {
- itemTemplate.ItemStat[i].ItemStatType = uint32(fields[28 + i*2].GetUInt8());
- itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i*2].GetInt16());
- }
-
- itemTemplate.ScalingStatDistribution = uint32(fields[48].GetUInt16());
- //itemTemplate.ScalingStatValue = fields[49].GetInt32();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- {
- itemTemplate.Damage[i].DamageMin = fields[50 + i*3].GetFloat();
- itemTemplate.Damage[i].DamageMax = fields[51 + i*3].GetFloat();
- itemTemplate.Damage[i].DamageType = uint32(fields[52 + i*3].GetUInt8());
- }
-
- itemTemplate.Armor = uint32(fields[56].GetUInt16());
- itemTemplate.HolyRes = uint32(fields[57].GetUInt8());
- itemTemplate.FireRes = uint32(fields[58].GetUInt8());
- itemTemplate.NatureRes = uint32(fields[59].GetUInt8());
- itemTemplate.FrostRes = uint32(fields[60].GetUInt8());
- itemTemplate.ShadowRes = uint32(fields[61].GetUInt8());
- itemTemplate.ArcaneRes = uint32(fields[62].GetUInt8());
- itemTemplate.Delay = uint32(fields[63].GetUInt16());
- itemTemplate.AmmoType = uint32(fields[64].GetUInt8());
- itemTemplate.RangedModRange = fields[65].GetFloat();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
- {
- itemTemplate.Spells[i].SpellId = fields[66 + i*7 ].GetInt32();
- itemTemplate.Spells[i].SpellTrigger = uint32(fields[67 + i*7].GetUInt8());
- itemTemplate.Spells[i].SpellCharges = int32(fields[68 + i*7].GetInt16());
- itemTemplate.Spells[i].SpellPPMRate = fields[69 + i*7].GetFloat();
- itemTemplate.Spells[i].SpellCooldown = fields[70 + i*7].GetInt32();
- itemTemplate.Spells[i].SpellCategory = uint32(fields[71 + i*7].GetUInt16());
- itemTemplate.Spells[i].SpellCategoryCooldown = fields[72 + i*7].GetInt32();
- }
-
- itemTemplate.Bonding = uint32(fields[101].GetUInt8());
- itemTemplate.Description = fields[102].GetString();
- itemTemplate.PageText = fields[103].GetUInt32();
- itemTemplate.LanguageID = uint32(fields[104].GetUInt8());
- itemTemplate.PageMaterial = uint32(fields[105].GetUInt8());
- itemTemplate.StartQuest = fields[106].GetUInt32();
- itemTemplate.LockID = fields[107].GetUInt32();
- itemTemplate.Material = int32(fields[108].GetInt8());
- itemTemplate.Sheath = uint32(fields[109].GetUInt8());
- itemTemplate.RandomProperty = fields[110].GetUInt32();
- itemTemplate.RandomSuffix = fields[111].GetInt32();
- itemTemplate.Block = fields[112].GetUInt32();
- itemTemplate.ItemSet = fields[113].GetUInt32();
- itemTemplate.MaxDurability = uint32(fields[114].GetUInt16());
- itemTemplate.Area = fields[115].GetUInt32();
- itemTemplate.Map = uint32(fields[116].GetUInt16());
- itemTemplate.BagFamily = fields[117].GetUInt32();
- itemTemplate.TotemCategory = fields[118].GetUInt32();
-
- for (uint8 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
- {
- itemTemplate.Socket[i].Color = uint32(fields[119 + i*2].GetUInt8());
- itemTemplate.Socket[i].Content = fields[120 + i*2].GetUInt32();
- }
-
- itemTemplate.socketBonus = fields[125].GetUInt32();
- itemTemplate.GemProperties = fields[126].GetUInt32();
- itemTemplate.RequiredDisenchantSkill = uint32(fields[127].GetInt16());
- itemTemplate.ArmorDamageModifier = fields[128].GetFloat();
- itemTemplate.Duration = fields[129].GetInt32();
- itemTemplate.ItemLimitCategory = uint32(fields[130].GetInt16());
- itemTemplate.HolidayId = fields[131].GetUInt32();
- itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetCString());
- itemTemplate.DisenchantID = fields[133].GetUInt32();
- itemTemplate.FoodType = uint32(fields[134].GetUInt8());
- itemTemplate.MinMoneyLoot = fields[135].GetUInt32();
- itemTemplate.MaxMoneyLoot = fields[136].GetUInt32();
-
- // Checks
-
- /*ItemEntry const* dbcitem = sItemStore.LookupEntry(entry);
-
- if (dbcitem)
- {
- if (itemTemplate.Class != dbcitem->Class)
- {
- sLog->outErrorDb("Item (Entry: %u) does not have a correct class %u, must be %u .", entry, itemTemplate.Class, dbcitem->Class);
- if (enforceDBCAttributes)
- itemTemplate.Class = dbcitem->Class;
- }
-
- if (itemTemplate.Unk0 != dbcitem->Unk0)
- {
- sLog->outErrorDb("Item (Entry: %u) does not have a correct Unk0 (%i), must be %i .", entry, itemTemplate.Unk0, dbcitem->Unk0);
- if (enforceDBCAttributes)
- itemTemplate.Unk0 = dbcitem->Unk0;
- }
- if (itemTemplate.Material != dbcitem->Material)
- {
- sLog->outErrorDb("Item (Entry: %u) does not have a correct material (%i), must be %i .", entry, itemTemplate.Material, dbcitem->Material);
- if (enforceDBCAttributes)
- itemTemplate.Material = dbcitem->Material;
- }
- if (itemTemplate.InventoryType != dbcitem->InventoryType)
- {
- sLog->outErrorDb("Item (Entry: %u) does not have a correct inventory type (%u), must be %u .", entry, itemTemplate.InventoryType, dbcitem->InventoryType);
- if (enforceDBCAttributes)
- itemTemplate.InventoryType = dbcitem->InventoryType;
- }
- if (itemTemplate.DisplayInfoID != dbcitem->DisplayId)
- {
- sLog->outErrorDb("Item (Entry: %u) does not have a correct display id (%u), must be %u .", entry, itemTemplate.DisplayInfoID, dbcitem->DisplayId);
- if (enforceDBCAttributes)
- itemTemplate.DisplayInfoID = dbcitem->DisplayId;
- }
- if (itemTemplate.Sheath != dbcitem->Sheath)
+ case INVTYPE_AMMO:
+ store = &sItemDamageAmmoStore;
+ break;
+ case INVTYPE_2HWEAPON:
+ if (flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ store = &sItemDamageTwoHandCasterStore;
+ else
+ store = &sItemDamageTwoHandStore;
+ break;
+ case INVTYPE_RANGED:
+ case INVTYPE_THROWN:
+ case INVTYPE_RANGEDRIGHT:
+ switch (itemSubClass)
{
- sLog->outErrorDb("Item (Entry: %u) does not have a correct sheathid (%u), must be %u .", entry, itemTemplate.Sheath, dbcitem->Sheath);
- if (enforceDBCAttributes)
- itemTemplate.Sheath = dbcitem->Sheath;
+ case ITEM_SUBCLASS_WEAPON_WAND:
+ store = &sItemDamageWandStore;
+ break;
+ case ITEM_SUBCLASS_WEAPON_THROWN:
+ store = &sItemDamageThrownStore;
+ break;
+ case ITEM_SUBCLASS_WEAPON_BOW:
+ case ITEM_SUBCLASS_WEAPON_GUN:
+ case ITEM_SUBCLASS_WEAPON_CROSSBOW:
+ store = &sItemDamageRangedStore;
+ break;
+ default:
+ return;
}
+ break;
+ case INVTYPE_WEAPON:
+ case INVTYPE_WEAPONMAINHAND:
+ case INVTYPE_WEAPONOFFHAND:
+ if (flags2 & ITEM_FLAGS_EXTRA_CASTER_WEAPON)
+ store = &sItemDamageOneHandCasterStore;
+ else
+ store = &sItemDamageOneHandStore;
+ break;
+ default:
+ return;
+ }
- }
- else
- sLog->outErrorDb("Item (Entry: %u) does not exist in item.dbc! (not correct id?).", entry);*/
-
- if (itemTemplate.Class >= MAX_ITEM_CLASS)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong Class value (%u)", entry, itemTemplate.Class);
- itemTemplate.Class = ITEM_CLASS_MISC;
- }
-
- if (itemTemplate.SubClass >= MaxItemSubclassValues[itemTemplate.Class])
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong Subclass value (%u) for class %u", entry, itemTemplate.SubClass, itemTemplate.Class);
- itemTemplate.SubClass = 0;// exist for all item classes
- }
+ if (!store)
+ return;
- if (itemTemplate.Quality >= MAX_ITEM_QUALITY)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong Quality value (%u)", entry, itemTemplate.Quality);
- itemTemplate.Quality = ITEM_QUALITY_NORMAL;
- }
+ ItemDamageEntry const* damageInfo = store->LookupEntry(itemLevel);
+ if (!damageInfo)
+ return;
- if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY)
- {
- if (FactionEntry const* faction = sFactionStore.LookupEntry(HORDE))
- if ((itemTemplate.AllowableRace & faction->BaseRepRaceMask[0]) == 0)
- sLog->outErrorDb("Item (Entry: %u) has value (%u) in `AllowableRace` races, not compatible with ITEM_FLAGS_EXTRA_HORDE_ONLY (%u) in Flags field, item cannot be equipped or used by these races.",
- entry, itemTemplate.AllowableRace, ITEM_FLAGS_EXTRA_HORDE_ONLY);
+ *dps = damageInfo->DPS[quality];
+ float avgDamage = *dps * delay * 0.001f;
+ *minDamage = (statScalingFactor * -0.5f + 1.0f) * avgDamage;
+ *maxDamage = floor(float(avgDamage * (statScalingFactor * 0.5f + 1.0f) + 0.5f));
+}
- if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY)
- sLog->outErrorDb("Item (Entry: %u) has value (%u) in `Flags2` flags (ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) and ITEM_FLAGS_EXTRA_HORDE_ONLY (%u) in Flags field, this is a wrong combination.",
- entry, ITEM_FLAGS_EXTRA_ALLIANCE_ONLY, ITEM_FLAGS_EXTRA_HORDE_ONLY);
- }
- else if (itemTemplate.Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY)
- {
- if (FactionEntry const* faction = sFactionStore.LookupEntry(ALLIANCE))
- if ((itemTemplate.AllowableRace & faction->BaseRepRaceMask[0]) == 0)
- sLog->outErrorDb("Item (Entry: %u) has value (%u) in `AllowableRace` races, not compatible with ITEM_FLAGS_EXTRA_ALLIANCE_ONLY (%u) in Flags field, item cannot be equipped or used by these races.",
- entry, itemTemplate.AllowableRace, ITEM_FLAGS_EXTRA_ALLIANCE_ONLY);
- }
+uint32 FillItemArmor(uint32 itemlevel, uint32 itemClass, uint32 itemSubclass, uint32 quality, uint32 inventoryType)
+{
+ if (quality > ITEM_QUALITY_ARTIFACT)
+ return 0;
- if (itemTemplate.BuyCount <= 0)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong BuyCount value (%u), set to default(1).", entry, itemTemplate.BuyCount);
- itemTemplate.BuyCount = 1;
- }
+ // all items but shields
+ if (itemClass != ITEM_CLASS_ARMOR || itemSubclass != ITEM_SUBCLASS_ARMOR_SHIELD)
+ {
+ ItemArmorQualityEntry const* armorQuality = sItemArmorQualityStore.LookupEntry(itemlevel);
+ ItemArmorTotalEntry const* armorToral = sItemArmorTotalStore.LookupEntry(itemlevel);
+ if (!armorQuality || !armorToral)
+ return 0;
- if (itemTemplate.InventoryType >= MAX_INVTYPE)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong InventoryType value (%u)", entry, itemTemplate.InventoryType);
- itemTemplate.InventoryType = INVTYPE_NON_EQUIP;
- }
+ if (inventoryType == INVTYPE_ROBE)
+ inventoryType = INVTYPE_CHEST;
- if (itemTemplate.RequiredSkill >= MAX_SKILL_TYPE)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong RequiredSkill value (%u)", entry, itemTemplate.RequiredSkill);
- itemTemplate.RequiredSkill = 0;
- }
+ ArmorLocationEntry const* location = sArmorLocationStore.LookupEntry(inventoryType);
+ if (!location)
+ return 0;
- {
- // can be used in equip slot, as page read use in inventory, or spell casting at use
- bool req = itemTemplate.InventoryType != INVTYPE_NON_EQUIP || itemTemplate.PageText;
- if (!req)
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellId)
- {
- req = true;
- break;
- }
- }
+ if (itemSubclass < ITEM_SUBCLASS_ARMOR_CLOTH)
+ return 0;
- if (req)
- {
- if (!(itemTemplate.AllowableClass & CLASSMASK_ALL_PLAYABLE))
- sLog->outErrorDb("Item (Entry: %u) does not have any playable classes (%u) in `AllowableClass` and can't be equipped or used.", entry, itemTemplate.AllowableClass);
+ return uint32(armorQuality->Value[quality] * armorToral->Value[quality] * location->Value[itemSubclass - 1] + 0.5f);
+ }
- if (!(itemTemplate.AllowableRace & RACEMASK_ALL_PLAYABLE))
- sLog->outErrorDb("Item (Entry: %u) does not have any playable races (%u) in `AllowableRace` and can't be equipped or used.", entry, itemTemplate.AllowableRace);
- }
- }
+ // shields
+ ItemArmorShieldEntry const* shield = sItemArmorShieldStore.LookupEntry(itemlevel);
+ if (!shield)
+ return 0;
- if (itemTemplate.RequiredSpell && !sSpellMgr->GetSpellInfo(itemTemplate.RequiredSpell))
- {
- sLog->outErrorDb("Item (Entry: %u) has a wrong (non-existing) spell in RequiredSpell (%u)", entry, itemTemplate.RequiredSpell);
- itemTemplate.RequiredSpell = 0;
- }
+ return uint32(shield->Value[quality] + 0.5f);
+}
- if (itemTemplate.RequiredReputationRank >= MAX_REPUTATION_RANK)
- sLog->outErrorDb("Item (Entry: %u) has wrong reputation rank in RequiredReputationRank (%u), item can't be used.", entry, itemTemplate.RequiredReputationRank);
+void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, uint32 itemClass, uint32 quality, uint32 itemLevel)
+{
+ for (uint32 i = 0; i < sItemDisenchantLootStore.GetNumRows(); ++i)
+ {
+ ItemDisenchantLootEntry const* disenchant = sItemDisenchantLootStore.LookupEntry(i);
+ if (!disenchant)
+ continue;
- if (itemTemplate.RequiredReputationFaction)
+ if (disenchant->ItemClass == itemClass &&
+ disenchant->ItemQuality == quality &&
+ disenchant->MinItemLevel <= itemLevel &&
+ disenchant->MaxItemLevel >= itemLevel)
{
- if (!sFactionStore.LookupEntry(itemTemplate.RequiredReputationFaction))
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong (not existing) faction in RequiredReputationFaction (%u)", entry, itemTemplate.RequiredReputationFaction);
- itemTemplate.RequiredReputationFaction = 0;
- }
-
- if (itemTemplate.RequiredReputationRank == MIN_REPUTATION_RANK)
- sLog->outErrorDb("Item (Entry: %u) has min. reputation rank in RequiredReputationRank (0) but RequiredReputationFaction > 0, faction setting is useless.", entry);
+ *disenchantID = disenchant->Id;
+ *requiredDisenchantSkill = disenchant->RequiredDisenchantSkill;
+ return;
}
+ }
- if (itemTemplate.MaxCount < -1)
- {
- sLog->outErrorDb("Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.", entry, itemTemplate.MaxCount);
- itemTemplate.MaxCount = -1;
- }
+ *disenchantID = 0;
+ *(int32*)requiredDisenchantSkill = -1;
+}
- if (itemTemplate.Stackable == 0)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.", entry, itemTemplate.Stackable);
- itemTemplate.Stackable = 1;
- }
- else if (itemTemplate.Stackable < -1)
- {
- sLog->outErrorDb("Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.", entry, itemTemplate.Stackable);
- itemTemplate.Stackable = -1;
- }
+void ObjectMgr::LoadItemTemplates()
+{
+ uint32 oldMSTime = getMSTime();
+ uint32 sparseCount = 0;
+ uint32 dbCount = 0;
- if (itemTemplate.ContainerSlots > MAX_BAG_SIZE)
- {
- sLog->outErrorDb("Item (Entry: %u) has too large value in ContainerSlots (%u), replace by hardcoded limit (%u).", entry, itemTemplate.ContainerSlots, MAX_BAG_SIZE);
- itemTemplate.ContainerSlots = MAX_BAG_SIZE;
- }
+ for (uint32 itemId = 0; itemId < sItemSparseStore.GetNumRows(); ++itemId)
+ {
+ ItemSparseEntry const* sparse = sItemSparseStore.LookupEntry(itemId);
+ ItemEntry const* db2Data = sItemStore.LookupEntry(itemId);
+ if (!sparse || !db2Data)
+ continue;
- if (itemTemplate.StatsCount > MAX_ITEM_PROTO_STATS)
- {
- sLog->outErrorDb("Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u).", entry, itemTemplate.StatsCount, MAX_ITEM_PROTO_STATS);
- itemTemplate.StatsCount = MAX_ITEM_PROTO_STATS;
- }
+ ItemTemplate& itemTemplate = ItemTemplateStore[itemId];
+
+ itemTemplate.ItemId = itemId;
+ itemTemplate.Class = db2Data->Class;
+ itemTemplate.SubClass = db2Data->SubClass;
+ itemTemplate.Unk0 = db2Data->Unk0;
+ itemTemplate.Name1 = sparse->Name;
+ itemTemplate.DisplayInfoID = db2Data->DisplayId;
+ itemTemplate.Quality = sparse->Quality;
+ itemTemplate.Flags = sparse->Flags;
+ itemTemplate.Flags2 = sparse->Flags2;
+ itemTemplate.BuyCount = 1;
+ itemTemplate.BuyPrice = sparse->BuyPrice;
+ itemTemplate.SellPrice = sparse->SellPrice;
+ itemTemplate.InventoryType = db2Data->InventoryType;
+ itemTemplate.AllowableClass = sparse->AllowableClass;
+ itemTemplate.AllowableRace = sparse->AllowableRace;
+ itemTemplate.ItemLevel = sparse->ItemLevel;
+ itemTemplate.RequiredLevel = sparse->RequiredLevel;
+ itemTemplate.RequiredSkill = sparse->RequiredSkill;
+ itemTemplate.RequiredSkillRank = sparse->RequiredSkillRank;
+ itemTemplate.RequiredSpell = sparse->RequiredSpell;
+ itemTemplate.RequiredHonorRank = sparse->RequiredHonorRank;
+ itemTemplate.RequiredCityRank = sparse->RequiredCityRank;
+ itemTemplate.RequiredReputationFaction = sparse->RequiredReputationFaction;
+ itemTemplate.RequiredReputationRank = sparse->RequiredReputationRank;
+ itemTemplate.MaxCount = sparse->MaxCount;
+ itemTemplate.Stackable = sparse->Stackable;
+ itemTemplate.ContainerSlots = sparse->ContainerSlots;
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ {
+ itemTemplate.ItemStat[i].ItemStatType = sparse->ItemStatType[i];
+ itemTemplate.ItemStat[i].ItemStatValue = sparse->ItemStatValue[i];
+ itemTemplate.ItemStat[i].ItemStatUnk1 = sparse->ItemStatUnk1[i];
+ itemTemplate.ItemStat[i].ItemStatUnk2 = sparse->ItemStatUnk2[i];
+ }
+
+ itemTemplate.ScalingStatDistribution = sparse->ScalingStatDistribution;
+
+ // 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);
+
+ 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;
+ itemTemplate.Description = sparse->Description;
+ itemTemplate.PageText = sparse->PageText;
+ itemTemplate.LanguageID = sparse->LanguageID;
+ itemTemplate.PageMaterial = sparse->PageMaterial;
+ itemTemplate.StartQuest = sparse->StartQuest;
+ itemTemplate.LockID = sparse->LockID;
+ itemTemplate.Material = sparse->Material;
+ itemTemplate.Sheath = sparse->Sheath;
+ itemTemplate.RandomProperty = sparse->RandomProperty;
+ itemTemplate.RandomSuffix = sparse->RandomSuffix;
+ itemTemplate.ItemSet = sparse->ItemSet;
+ itemTemplate.MaxDurability = sparse->MaxDurability;
+ itemTemplate.Area = sparse->Area;
+ itemTemplate.Map = sparse->Map;
+ itemTemplate.BagFamily = sparse->BagFamily;
+ 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.socketBonus = sparse->SocketBonus;
+ itemTemplate.GemProperties = sparse->GemProperties;
+ FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill,
+ db2Data->Class, sparse->Quality, sparse->ItemLevel);
+
+ itemTemplate.ArmorDamageModifier = sparse->ArmorDamageModifier;
+ itemTemplate.Duration = sparse->Duration;
+ itemTemplate.ItemLimitCategory = sparse->ItemLimitCategory;
+ itemTemplate.HolidayId = sparse->HolidayId;
+ itemTemplate.StatScalingFactor = sparse->StatScalingFactor;
+ itemTemplate.Field130 = sparse->Field130;
+ itemTemplate.Field131 = sparse->Field131;
+ itemTemplate.ScriptId = 0;
+ itemTemplate.FoodType = 0;
+ itemTemplate.MinMoneyLoot = 0;
+ itemTemplate.MaxMoneyLoot = 0;
+ ++sparseCount;
+ }
+
+ // 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
+ QueryResult result = WorldDatabase.Query("SELECT entry, Class, SubClass, Unk0, Name, DisplayId, Quality, Flags, FlagsExtra, BuyPrice, SellPrice, InventoryType, "
+ // 12 13 14 15 16 17 18 19
+ "AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, RequiredSpell, RequiredHonorRank, "
+ // 20 21 22 23 24 25
+ "RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, MaxCount, Stackable, ContainerSlots, "
+ // 26 27 28 29 30 31 32 33
+ "stat_type1, stat_value1, stat_unk1_1, stat_unk2_1, stat_type2, stat_value2, stat_unk1_2, stat_unk2_2, "
+ // 34 35 36 37 38 39 40 41
+ "stat_type3, stat_value3, stat_unk1_3, stat_unk2_3, stat_type4, stat_value4, stat_unk1_4, stat_unk2_4, "
+ // 42 43 44 45 46 47 48 49
+ "stat_type5, stat_value5, stat_unk1_5, stat_unk2_5, stat_type6, stat_value6, stat_unk1_6, stat_unk2_6, "
+ // 50 51 52 53 54 55 56 57
+ "stat_type7, stat_value7, stat_unk1_7, stat_unk2_7, stat_type8, stat_value8, stat_unk1_8, stat_unk2_8, "
+ // 58 59 60 61 62 63 64 65
+ "stat_type9, stat_value9, stat_unk1_9, stat_unk2_9, stat_type10, stat_value10, stat_unk1_10, stat_unk2_10, "
+ // 66 67 68 69
+ "ScalingStatDistribution, DamageType, Delay, RangedModRange, "
+ // 70 71 72 73 74 75
+ "spellid_1, spelltrigger_1, spellcharges_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, "
+ // 76 77 78 79 80 81
+ "spellid_2, spelltrigger_2, spellcharges_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, "
+ // 82 83 84 85 86 87
+ "spellid_3, spelltrigger_3, spellcharges_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, "
+ // 88 89 90 91 92 93
+ "spellid_4, spelltrigger_4, spellcharges_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, "
+ // 94 95 96 97 98 99
+ "spellid_5, spelltrigger_5, spellcharges_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, "
+ // 100 101 102 103 104 105 106 107
+ "Bonding, Description, PageText, LanguageID, PageMaterial, StartQuest, LockID, Material, "
+ // 108 109 110 111 112 113 114 115 116
+ "Sheath, RandomProperty, RandomSuffix, ItemSet, MaxDurability, Area, Map, BagFamily, TotemCategory, "
+ // 117 118 119 120 121 122 123
+ "SocketColor_1, SocketContent_1, SocketColor_2, SocketContent_2, SocketColor_3, SocketContent_3, SocketBonus, "
+ // 124 125 126 127 128 129 130 131
+ "GemProperties, ArmorDamageModifier, Duration, ItemLimitCategory, HolidayId, StatScalingFactor, Field130, Field131 "
+ "FROM item_template");
- for (uint8 j = 0; j < itemTemplate.StatsCount; ++j)
+ if (result)
+ {
+ do
{
- // for ItemStatValue != 0
- if (itemTemplate.ItemStat[j].ItemStatValue && itemTemplate.ItemStat[j].ItemStatType >= MAX_ITEM_MOD)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong (non-existing?) stat_type%d (%u)", entry, j+1, itemTemplate.ItemStat[j].ItemStatType);
- itemTemplate.ItemStat[j].ItemStatType = 0;
- }
-
- switch (itemTemplate.ItemStat[j].ItemStatType)
- {
- case ITEM_MOD_SPELL_HEALING_DONE:
- case ITEM_MOD_SPELL_DAMAGE_DONE:
- sLog->outErrorDb("Item (Entry: %u) has deprecated stat_type%d (%u)", entry, j+1, itemTemplate.ItemStat[j].ItemStatType);
- break;
- default:
- break;
- }
- }
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (ItemTemplateStore.find(itemId) != ItemTemplateStore.end())
+ --sparseCount;
+
+ ItemTemplate& itemTemplate = ItemTemplateStore[itemId];
+
+ itemTemplate.ItemId = itemId;
+ itemTemplate.Class = fields[1].GetUInt32();
+ itemTemplate.SubClass = fields[2].GetUInt32();
+ itemTemplate.Unk0 = fields[3].GetInt32();
+ itemTemplate.Name1 = fields[4].GetString();
+ itemTemplate.DisplayInfoID = fields[5].GetUInt32();
+ itemTemplate.Quality = fields[6].GetUInt32();
+ itemTemplate.Flags = fields[7].GetUInt32();
+ itemTemplate.Flags2 = fields[8].GetUInt32();
+ itemTemplate.BuyCount = 1;
+ itemTemplate.BuyPrice = fields[9].GetInt32();
+ itemTemplate.SellPrice = fields[10].GetUInt32();
+ itemTemplate.InventoryType = fields[11].GetUInt32();
+ itemTemplate.AllowableClass = fields[12].GetUInt32();
+ itemTemplate.AllowableRace = fields[13].GetUInt32();
+ itemTemplate.ItemLevel = fields[14].GetUInt32();
+ itemTemplate.RequiredLevel = fields[15].GetUInt32();
+ itemTemplate.RequiredSkill = fields[16].GetUInt32();
+ itemTemplate.RequiredSkillRank = fields[17].GetUInt32();
+ itemTemplate.RequiredSpell = fields[18].GetUInt32();
+ itemTemplate.RequiredHonorRank = fields[19].GetUInt32();
+ itemTemplate.RequiredCityRank = fields[20].GetUInt32();
+ itemTemplate.RequiredReputationFaction = fields[21].GetUInt32();
+ itemTemplate.RequiredReputationRank = fields[22].GetUInt32();
+ itemTemplate.MaxCount = fields[23].GetInt32();
+ itemTemplate.Stackable = fields[24].GetInt32();
+ itemTemplate.ContainerSlots = fields[25].GetUInt32();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
+ {
+ itemTemplate.ItemStat[i].ItemStatType = fields[26 + i * 4].GetUInt32();
+ itemTemplate.ItemStat[i].ItemStatValue = fields[26 + i * 4 + 1].GetInt32();
+ itemTemplate.ItemStat[i].ItemStatUnk1 = fields[26 + i * 4 + 2].GetInt32();
+ itemTemplate.ItemStat[i].ItemStatUnk2 = fields[26 + i * 4 + 3].GetInt32();
+ }
+
+ itemTemplate.ScalingStatDistribution = fields[66].GetUInt32();
+
+ // cache item damage
+ FillItemDamageFields(&itemTemplate.DamageMin, &itemTemplate.DamageMax, &itemTemplate.DPS, itemTemplate.ItemLevel,
+ itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, fields[68].GetUInt32(),
+ fields[129].GetFloat(), itemTemplate.InventoryType, itemTemplate.Flags2);
+
+ itemTemplate.DamageType = fields[67].GetUInt32();
+ itemTemplate.Armor = FillItemArmor(itemTemplate.ItemLevel, itemTemplate.Class, itemTemplate.SubClass, itemTemplate.Quality, itemTemplate.InventoryType);
+ itemTemplate.Delay = fields[68].GetUInt32();
+ itemTemplate.RangedModRange = fields[69].GetFloat();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
+ {
+ itemTemplate.Spells[i].SpellId = fields[70 + 6 * i].GetInt32();
+ itemTemplate.Spells[i].SpellTrigger = fields[70 + 6 * i + 1].GetUInt32();
+ itemTemplate.Spells[i].SpellCharges = fields[70 + 6 * i + 2].GetInt32();
+ itemTemplate.Spells[i].SpellCooldown = fields[70 + 6 * i + 3].GetInt32();
+ itemTemplate.Spells[i].SpellCategory = fields[70 + 6 * i + 4].GetUInt32();
+ itemTemplate.Spells[i].SpellCategoryCooldown = fields[70 + 6 * i + 5].GetInt32();
+ }
+
+ itemTemplate.SpellPPMRate = 0.0f;
+ itemTemplate.Bonding = fields[100].GetUInt32();
+ itemTemplate.Description = fields[101].GetString();
+ itemTemplate.PageText = fields[102].GetUInt32();
+ itemTemplate.LanguageID = fields[103].GetUInt32();
+ itemTemplate.PageMaterial = fields[104].GetUInt32();
+ itemTemplate.StartQuest = fields[105].GetUInt32();
+ itemTemplate.LockID = fields[106].GetUInt32();
+ itemTemplate.Material = fields[107].GetInt32();
+ itemTemplate.Sheath = fields[108].GetUInt32();
+ itemTemplate.RandomProperty = fields[109].GetInt32();
+ itemTemplate.RandomSuffix = fields[110].GetInt32();
+ itemTemplate.ItemSet = fields[111].GetUInt32();
+ itemTemplate.MaxDurability = fields[112].GetUInt32();
+ itemTemplate.Area = fields[113].GetUInt32();
+ itemTemplate.Map = fields[114].GetUInt32();
+ itemTemplate.BagFamily = fields[115].GetUInt32();
+ itemTemplate.TotemCategory = fields[116].GetUInt32();
+ for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i)
+ {
+ itemTemplate.Socket[i].Color = fields[117 + i * 2].GetUInt32();
+ itemTemplate.Socket[i].Content = fields[117 + i * 2 + 1].GetUInt32();
+ }
+
+ itemTemplate.socketBonus = fields[123].GetUInt32();
+ itemTemplate.GemProperties = fields[124].GetUInt32();
+ FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill,
+ itemTemplate.Class, itemTemplate.Quality, itemTemplate.ItemLevel);
+
+ itemTemplate.ArmorDamageModifier = fields[125].GetFloat();
+ itemTemplate.Duration = fields[126].GetUInt32();
+ itemTemplate.ItemLimitCategory = fields[127].GetUInt32();
+ itemTemplate.HolidayId = fields[128].GetUInt32();
+ itemTemplate.StatScalingFactor = fields[129].GetFloat();
+ itemTemplate.Field130 = fields[130].GetInt32();
+ itemTemplate.Field131 = fields[131].GetInt32();
+ itemTemplate.ScriptId = 0;
+ itemTemplate.FoodType = 0;
+ itemTemplate.MinMoneyLoot = 0;
+ itemTemplate.MaxMoneyLoot = 0;
+ ++dbCount;
+ } while (result->NextRow());
+ }
- for (uint8 j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j)
- {
- if (itemTemplate.Damage[j].DamageType >= MAX_SPELL_SCHOOL)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong dmg_type%d (%u)", entry, j+1, itemTemplate.Damage[j].DamageType);
- itemTemplate.Damage[j].DamageType = 0;
- }
- }
+ // Check if item templates for DBC referenced character start outfit are present
+ std::set<uint32> notFoundOutfit;
+ for (uint32 i = 1; i < sCharStartOutfitStore.GetNumRows(); ++i)
+ {
+ CharStartOutfitEntry const* entry = sCharStartOutfitStore.LookupEntry(i);
+ if (!entry)
+ continue;
- // special format
- if ((itemTemplate.Spells[0].SpellId == 483) || (itemTemplate.Spells[0].SpellId == 55884))
+ for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j)
{
- // spell_1
- if (itemTemplate.Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format", entry, 0+1, itemTemplate.Spells[0].SpellTrigger);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[0].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
-
- // spell_2 have learning spell
- if (itemTemplate.Spells[1].SpellTrigger != ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format.", entry, 1+1, itemTemplate.Spells[1].SpellTrigger);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (!itemTemplate.Spells[1].SpellId)
- {
- sLog->outErrorDb("Item (Entry: %u) does not have an expected spell in spellid_%d in special learning format.", entry, 1+1);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (itemTemplate.Spells[1].SpellId != -1)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[1].SpellId);
- if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[1].SpellId, NULL))
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)", entry, 1+1, itemTemplate.Spells[1].SpellId);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- // allowed only in special format
- else if ((itemTemplate.Spells[1].SpellId == 483) || (itemTemplate.Spells[1].SpellId == 55884))
- {
- sLog->outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%d)", entry, 1+1, itemTemplate.Spells[1].SpellId);
- itemTemplate.Spells[0].SpellId = 0;
- itemTemplate.Spells[1].SpellId = 0;
- itemTemplate.Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- }
+ if (entry->ItemId[j] <= 0)
+ continue;
- // spell_3*, spell_4*, spell_5* is empty
- for (uint8 j = 2; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)", entry, j+1, itemTemplate.Spells[j].SpellTrigger);
- itemTemplate.Spells[j].SpellId = 0;
- itemTemplate.Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
- else if (itemTemplate.Spells[j].SpellId != 0)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong spell in spellid_%d (%d) for learning special format", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- }
- }
- // normal spell list
- else
- {
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SPELLS; ++j)
- {
- if (itemTemplate.Spells[j].SpellTrigger >= MAX_ITEM_SPELLTRIGGER || itemTemplate.Spells[j].SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)", entry, j+1, itemTemplate.Spells[j].SpellTrigger);
- itemTemplate.Spells[j].SpellId = 0;
- itemTemplate.Spells[j].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
- }
+ uint32 item_id = entry->ItemId[j];
- if (itemTemplate.Spells[j].SpellId && itemTemplate.Spells[j].SpellId != -1)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itemTemplate.Spells[j].SpellId);
- if (!spellInfo && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, itemTemplate.Spells[j].SpellId, NULL))
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%d)", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- // allowed only in special format
- else if ((itemTemplate.Spells[j].SpellId == 483) || (itemTemplate.Spells[j].SpellId == 55884))
- {
- sLog->outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%d)", entry, j+1, itemTemplate.Spells[j].SpellId);
- itemTemplate.Spells[j].SpellId = 0;
- }
- }
- }
+ if (!GetItemTemplate(item_id))
+ notFoundOutfit.insert(item_id);
}
+ }
- if (itemTemplate.Bonding >= MAX_BIND_TYPE)
- sLog->outErrorDb("Item (Entry: %u) has wrong Bonding value (%u)", entry, itemTemplate.Bonding);
-
- if (itemTemplate.PageText && !GetPageText(itemTemplate.PageText))
- sLog->outErrorDb("Item (Entry: %u) has non existing first page (Id:%u)", entry, itemTemplate.PageText);
+ for (std::set<uint32>::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr)
+ sLog->outErrorDb("Item (Entry: %u) does not exist in `item_template` but is referenced in `CharStartOutfit.dbc`", *itr);
- if (itemTemplate.LockID && !sLockStore.LookupEntry(itemTemplate.LockID))
- sLog->outErrorDb("Item (Entry: %u) has wrong LockID (%u)", entry, itemTemplate.LockID);
+ sLog->outString(">> Loaded %u item templates from Item-sparse.db2 and %u from database in %u ms", sparseCount, dbCount, GetMSTimeDiffToNow(oldMSTime));
+ sLog->outString();
+}
- if (itemTemplate.Sheath >= MAX_SHEATHETYPE)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong Sheath (%u)", entry, itemTemplate.Sheath);
- itemTemplate.Sheath = SHEATHETYPE_NONE;
- }
+void ObjectMgr::LoadItemTemplateAddon()
+{
+ uint32 oldMSTime = getMSTime();
+ uint32 count = 0;
- if (itemTemplate.RandomProperty)
+ QueryResult result = WorldDatabase.Query("SELECT Id, BuyCount, FoodType, MinMoneyLoot, MaxMoneyLoot, SpellPPMChance FROM item_template_addon");
+ if (result)
+ {
+ do
{
- // To be implemented later
- if (itemTemplate.RandomProperty == -1)
- itemTemplate.RandomProperty = 0;
-
- else if (!sItemRandomPropertiesStore.LookupEntry(GetItemEnchantMod(itemTemplate.RandomProperty)))
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (!GetItemTemplate(itemId))
{
- sLog->outErrorDb("Item (Entry: %u) has unknown (wrong or not listed in `item_enchantment_template`) RandomProperty (%u)", entry, itemTemplate.RandomProperty);
- itemTemplate.RandomProperty = 0;
+ sLog->outErrorDb("Item %u specified in `item_template_addon` does not exist, skipped.", itemId);
+ continue;
}
- }
-
- if (itemTemplate.RandomSuffix && !sItemRandomSuffixStore.LookupEntry(GetItemEnchantMod(itemTemplate.RandomSuffix)))
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong RandomSuffix (%u)", entry, itemTemplate.RandomSuffix);
- itemTemplate.RandomSuffix = 0;
- }
-
- if (itemTemplate.ItemSet && !sItemSetStore.LookupEntry(itemTemplate.ItemSet))
- {
- sLog->outErrorDb("Item (Entry: %u) have wrong ItemSet (%u)", entry, itemTemplate.ItemSet);
- itemTemplate.ItemSet = 0;
- }
-
- if (itemTemplate.Area && !GetAreaEntryByAreaID(itemTemplate.Area))
- sLog->outErrorDb("Item (Entry: %u) has wrong Area (%u)", entry, itemTemplate.Area);
- if (itemTemplate.Map && !sMapStore.LookupEntry(itemTemplate.Map))
- sLog->outErrorDb("Item (Entry: %u) has wrong Map (%u)", entry, itemTemplate.Map);
-
- if (itemTemplate.BagFamily)
- {
- // check bits
- for (uint32 j = 0; j < sizeof(itemTemplate.BagFamily)*8; ++j)
+ uint8 buyCount = fields[1].GetUInt8();
+ if (!buyCount)
{
- uint32 mask = 1 << j;
- if ((itemTemplate.BagFamily & mask) == 0)
- continue;
-
- ItemBagFamilyEntry const* bf = sItemBagFamilyStore.LookupEntry(j+1);
- if (!bf)
- {
- sLog->outErrorDb("Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit", entry);
- itemTemplate.BagFamily &= ~mask;
- continue;
- }
-
- if (BAG_FAMILY_MASK_CURRENCY_TOKENS & mask)
- {
- CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemTemplate.ItemId);
- if (!ctEntry)
- {
- sLog->outErrorDb("Item (Entry: %u) has currency bag family bit set in BagFamily but not listed in CurrencyTypes.dbc, remove bit", entry);
- itemTemplate.BagFamily &= ~mask;
- }
- }
+ sLog->outErrorDb("Item %u has BuyCount set to 0, corrected to 1.", itemId);
+ buyCount = 1;
}
- }
-
- if (itemTemplate.TotemCategory && !sTotemCategoryStore.LookupEntry(itemTemplate.TotemCategory))
- sLog->outErrorDb("Item (Entry: %u) has wrong TotemCategory (%u)", entry, itemTemplate.TotemCategory);
- for (uint8 j = 0; j < MAX_ITEM_PROTO_SOCKETS; ++j)
- {
- if (itemTemplate.Socket[j].Color && (itemTemplate.Socket[j].Color & SOCKET_COLOR_ALL) != itemTemplate.Socket[j].Color)
+ uint8 foodType = fields[2].GetUInt8();
+ uint32 minMoneyLoot = fields[3].GetUInt32();
+ uint32 maxMoneyLoot = fields[4].GetUInt32();
+ if (minMoneyLoot > maxMoneyLoot)
{
- sLog->outErrorDb("Item (Entry: %u) has wrong socketColor_%d (%u)", entry, j+1, itemTemplate.Socket[j].Color);
- itemTemplate.Socket[j].Color = 0;
+ sLog->outErrorDb("Minimum money loot specified in `item_template_addon` for item %u was greater than maximum amount, swapping.", itemId);
+ std::swap(minMoneyLoot, maxMoneyLoot);
}
- }
-
- if (itemTemplate.GemProperties && !sGemPropertiesStore.LookupEntry(itemTemplate.GemProperties))
- sLog->outErrorDb("Item (Entry: %u) has wrong GemProperties (%u)", entry, itemTemplate.GemProperties);
-
- if (itemTemplate.FoodType >= MAX_PET_DIET)
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong FoodType value (%u)", entry, itemTemplate.FoodType);
- itemTemplate.FoodType = 0;
- }
- if (itemTemplate.ItemLimitCategory && !sItemLimitCategoryStore.LookupEntry(itemTemplate.ItemLimitCategory))
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong LimitCategory value (%u)", entry, itemTemplate.ItemLimitCategory);
- itemTemplate.ItemLimitCategory = 0;
- }
+ ItemTemplate& itemTemplate = ItemTemplateStore[itemId];
+ itemTemplate.BuyCount = buyCount;
+ itemTemplate.FoodType = foodType;
+ itemTemplate.MinMoneyLoot = minMoneyLoot;
+ itemTemplate.MaxMoneyLoot = maxMoneyLoot;
+ itemTemplate.SpellPPMRate = fields[5].GetFloat();
+ ++count;
+ } while (result->NextRow());
+ }
- if (itemTemplate.HolidayId && !sHolidaysStore.LookupEntry(itemTemplate.HolidayId))
- {
- sLog->outErrorDb("Item (Entry: %u) has wrong HolidayId value (%u)", entry, itemTemplate.HolidayId);
- itemTemplate.HolidayId = 0;
- }
+ sLog->outString(">> Loaded %u item addon templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ sLog->outString();
+}
- ++count;
- }
- while (result->NextRow());
+void ObjectMgr::LoadItemScriptNames()
+{
+ uint32 oldMSTime = getMSTime();
+ uint32 count = 0;
- // Check if item templates for DBC referenced character start outfit are present
- std::set<uint32> notFoundOutfit;
- for (uint32 i = 1; i < sCharStartOutfitStore.GetNumRows(); ++i)
+ QueryResult result = WorldDatabase.Query("SELECT Id, ScriptName FROM item_script_names");
+ if (result)
{
- CharStartOutfitEntry const* entry = sCharStartOutfitStore.LookupEntry(i);
- if (!entry)
- continue;
-
- for (int j = 0; j < MAX_OUTFIT_ITEMS; ++j)
+ do
{
- if (entry->ItemId[j] <= 0)
+ Field* fields = result->Fetch();
+ uint32 itemId = fields[0].GetUInt32();
+ if (!GetItemTemplate(itemId))
+ {
+ sLog->outErrorDb("Item %u specified in `item_script_names` does not exist, skipped.", itemId);
continue;
+ }
- uint32 item_id = entry->ItemId[j];
-
- if (!sObjectMgr->GetItemTemplate(item_id))
- notFoundOutfit.insert(item_id);
- }
+ ItemTemplateStore[itemId].ScriptId = GetScriptId(fields[1].GetCString());
+ ++count;
+ } while (result->NextRow());
}
- for (std::set<uint32>::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr)
- sLog->outErrorDb("Item (Entry: %u) does not exist in `item_template` but is referenced in `CharStartOutfit.dbc`", *itr);
-
- sLog->outString(">> Loaded %u item templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ sLog->outString(">> Loaded %u item script names in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
@@ -8584,7 +8477,7 @@ void ObjectMgr::LoadScriptNames()
"UNION "
"SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' "
"UNION "
- "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' "
+ "SELECT DISTINCT(ScriptName) FROM item_script_names WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
@@ -8951,4 +8844,4 @@ VehicleAccessoryList const* ObjectMgr::GetVehicleAccessoryList(Vehicle* veh) con
if (itr != m_VehicleTemplateAccessoryMap.end())
return &itr->second;
return NULL;
-}
+} \ No newline at end of file
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 88c593a009d..e6ac7036d48 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -865,6 +865,8 @@ class ObjectMgr
void LoadGameobjects();
void LoadGameobjectRespawnTimes();
void LoadItemTemplates();
+ void LoadItemTemplateAddon();
+ void LoadItemScriptNames();
void LoadItemLocales();
void LoadItemSetNames();
void LoadItemSetNameLocales();
@@ -1285,7 +1287,6 @@ class ObjectMgr
PlayerClassInfo playerClassInfo[MAX_CLASSES];
void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const;
-
PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES];
typedef std::vector<uint32> PlayerXPperLevel; // [level]
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index 8eac07918de..dd1ae020a51 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -178,7 +178,7 @@ void GuildMgr::LoadGuilds()
CharacterDatabase.DirectExecute("DELETE gm FROM guild_member gm LEFT JOIN guild g ON gm.guildId = g.guildId WHERE g.guildId IS NULL");
// 0 1 2 3 4 5 6
- QueryResult result = CharacterDatabase.Query("SELECT guildid, gm.guid, rank, pnote, offnote, BankResetTimeMoney, BankRemMoney, "
+ QueryResult result = CharacterDatabase.Query("SELECT gm.guildid, gm.guid, rank, pnote, offnote, BankResetTimeMoney, BankRemMoney, "
// 7 8 9 10 11 12
"BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2, "
// 13 14 15 16 17 18
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index dd17e8277d6..acfb01ecc44 100755
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -232,7 +232,7 @@ void LootStore::ReportUnusedIds(LootIdSet const& ids_set) const
void LootStore::ReportNotExistedId(uint32 id) const
{
- sLog->outErrorDb("Table '%s' entry %d (%s) not exist but used as loot id in DB.", GetName(), id, GetEntryName());
+ sLog->outErrorDb("Table '%s' entry %d (%s) does not exist but used as loot id in DB.", GetName(), id, GetEntryName());
}
//
@@ -1461,16 +1461,17 @@ void LoadLootTemplates_Disenchant()
LootIdSet lootIdSet, loodIdSetUsed;
uint32 count = LootTemplates_Disenchant.LoadAndCollectLootIds(lootIdSet);
- ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore();
- for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr)
+ for (uint32 i = 0; i < sItemDisenchantLootStore.GetNumRows(); ++i)
{
- if (uint32 lootid = itr->second.DisenchantID)
- {
- if (lootIdSet.find(lootid) == lootIdSet.end())
- LootTemplates_Disenchant.ReportNotExistedId(lootid);
- else
- loodIdSetUsed.insert(lootid);
- }
+ ItemDisenchantLootEntry const* disenchant = sItemDisenchantLootStore.LookupEntry(i);
+ if (!disenchant)
+ continue;
+
+ uint32 lootid = disenchant->Id;
+ if (lootIdSet.find(lootid) == lootIdSet.end())
+ LootTemplates_Disenchant.ReportNotExistedId(lootid);
+ else
+ loodIdSetUsed.insert(lootid);
}
for (LootIdSet::const_iterator itr = loodIdSetUsed.begin(); itr != loodIdSetUsed.end(); ++itr)
diff --git a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp
index 53b864b4d90..3f301a7aba8 100755
--- a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp
@@ -280,160 +280,153 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket & recv_data)
// Only _static_ data send in this packet !!!
void WorldSession::HandleItemQuerySingleOpcode(WorldPacket & recv_data)
{
- //sLog->outDebug(LOG_FILTER_PACKETIO, "WORLD: CMSG_ITEM_QUERY_SINGLE");
- uint32 item;
- recv_data >> item;
+ uint32 count, type;
+ recv_data >> count >> type;
- sLog->outDetail("STORAGE: Item Query = %u", item);
+ if (type != DB2_REPLY_SPARSE && type != DB2_REPLY_ITEM)
+ return;
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item);
- if (pProto)
+ for (uint32 i = 0; i < count; ++i)
{
- std::string Name = pProto->Name1;
- std::string Description = pProto->Description;
-
- int loc_idx = GetSessionDbLocaleIndex();
- if (loc_idx >= 0)
+ uint32 item;
+ recv_data >> item;
+ recv_data.read_skip<uint64>();
+ WorldPacket data2(SMSG_DB_REPLY, 700);
+ ByteBuffer data;
+ data2 << uint32(type);
+ data2 << uint32(item);
+
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item);
+ if (proto)
{
- if (ItemLocale const* il = sObjectMgr->GetItemLocale(pProto->ItemId))
+ data << uint32(item);
+ if (type == DB2_REPLY_ITEM)
{
- ObjectMgr::GetLocaleString(il->Name, loc_idx, Name);
- ObjectMgr::GetLocaleString(il->Description, loc_idx, Description);
+ data << uint32(proto->Class);
+ data << uint32(proto->SubClass);
+ data << int32(proto->Unk0);
+ data << uint32(proto->Material);
+ data << uint32(proto->DisplayInfoID);
+ data << uint32(proto->InventoryType);
+ data << uint32(proto->Sheath);
}
- }
- // guess size
- WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 600);
- data << pProto->ItemId;
- data << pProto->Class;
- data << pProto->SubClass;
- data << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache?
- data << Name;
- data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
- data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
- data << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00);
- data << pProto->DisplayInfoID;
- data << pProto->Quality;
- data << pProto->Flags;
- data << pProto->Flags2;
- data << pProto->BuyPrice;
- data << pProto->SellPrice;
- data << pProto->InventoryType;
- data << pProto->AllowableClass;
- data << pProto->AllowableRace;
- data << pProto->ItemLevel;
- data << pProto->RequiredLevel;
- data << pProto->RequiredSkill;
- data << pProto->RequiredSkillRank;
- data << pProto->RequiredSpell;
- data << pProto->RequiredHonorRank;
- data << pProto->RequiredCityRank;
- data << pProto->RequiredReputationFaction;
- data << pProto->RequiredReputationRank;
- data << int32(pProto->MaxCount);
- data << int32(pProto->Stackable);
- data << pProto->ContainerSlots;
- data << pProto->StatsCount; // item stats count
- for (uint32 i = 0; i < pProto->StatsCount; ++i)
- {
- data << pProto->ItemStat[i].ItemStatType;
- data << pProto->ItemStat[i].ItemStatValue;
- }
- data << pProto->ScalingStatDistribution; // scaling stats distribution
- data << uint32(0);
- for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- {
- data << pProto->Damage[i].DamageMin;
- data << pProto->Damage[i].DamageMax;
- data << pProto->Damage[i].DamageType;
- }
-
- // resistances (7)
- data << pProto->Armor;
- data << pProto->HolyRes;
- data << pProto->FireRes;
- data << pProto->NatureRes;
- data << pProto->FrostRes;
- data << pProto->ShadowRes;
- data << pProto->ArcaneRes;
-
- data << pProto->Delay;
- data << pProto->AmmoType;
- data << pProto->RangedModRange;
-
- for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
- {
- // send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
- // use `item_template` or if not set then only use spell cooldowns
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(pProto->Spells[s].SpellId);
- if (spell)
+ else if (type == DB2_REPLY_SPARSE)
{
- bool db_data = pProto->Spells[s].SpellCooldown >= 0 || pProto->Spells[s].SpellCategoryCooldown >= 0;
-
- data << pProto->Spells[s].SpellId;
- data << pProto->Spells[s].SpellTrigger;
- data << uint32(-abs(pProto->Spells[s].SpellCharges));
-
- if (db_data)
- {
- data << uint32(pProto->Spells[s].SpellCooldown);
- data << uint32(pProto->Spells[s].SpellCategory);
- data << uint32(pProto->Spells[s].SpellCategoryCooldown);
- }
- else
- {
- data << uint32(spell->RecoveryTime);
- data << uint32(spell->Category);
- data << uint32(spell->CategoryRecoveryTime);
- }
+ data << uint32(proto->Quality);
+ data << uint32(proto->Flags);
+ data << uint32(proto->Flags2);
+ data << int32(proto->BuyPrice);
+ data << uint32(proto->SellPrice);
+ data << uint32(proto->InventoryType);
+ data << int32(proto->AllowableClass);
+ data << int32(proto->AllowableRace);
+ data << uint32(proto->ItemLevel);
+ data << uint32(proto->RequiredLevel);
+ data << uint32(proto->RequiredSkill);
+ data << uint32(proto->RequiredSkillRank);
+ data << uint32(proto->RequiredSpell);
+ data << uint32(proto->RequiredHonorRank);
+ data << uint32(proto->RequiredCityRank);
+ data << uint32(proto->RequiredReputationFaction);
+ data << uint32(proto->RequiredReputationRank);
+ data << int32(proto->MaxCount);
+ data << int32(proto->Stackable);
+ data << uint32(proto->ContainerSlots);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ data << uint32(proto->ItemStat[x].ItemStatType);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ data << int32(proto->ItemStat[x].ItemStatValue);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ data << int32(proto->ItemStat[x].ItemStatUnk1);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x)
+ data << int32(proto->ItemStat[x].ItemStatUnk2);
+
+ data << uint32(proto->ScalingStatDistribution);
+ data << uint32(proto->DamageType);
+ data << uint32(proto->Delay);
+ data << float(proto->RangedModRange);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ data << int32(proto->Spells[x].SpellId);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ data << uint32(proto->Spells[x].SpellTrigger);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ data << int32(proto->Spells[x].SpellCharges);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ data << int32(proto->Spells[x].SpellCooldown);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ data << uint32(proto->Spells[x].SpellCategory);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
+ data << int32(proto->Spells[x].SpellCategoryCooldown);
+
+ data << uint32(proto->Bonding);
+
+ // item name
+ std::string name = proto->Name1;
+ data << uint16(name.length() + 1);
+ data << name;
+
+ for (uint32 i = 0; i < 3; ++i) // other 3 names
+ data << uint16(0);
+
+ std::string desc = proto->Description;
+ data << uint16(desc.length() + 1);
+ data << desc;
+
+ data << uint32(proto->PageText);
+ data << uint32(proto->LanguageID);
+ data << uint32(proto->PageMaterial);
+ data << uint32(proto->StartQuest);
+ data << uint32(proto->LockID);
+ data << int32(proto->Material);
+ data << uint32(proto->Sheath);
+ data << int32(proto->RandomProperty);
+ data << int32(proto->RandomSuffix);
+ data << uint32(proto->ItemSet);
+ data << uint32(proto->MaxDurability);
+
+ data << uint32(proto->Area);
+ data << uint32(proto->Map);
+ data << uint32(proto->BagFamily);
+ data << uint32(proto->TotemCategory);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
+ data << uint32(proto->Socket[x].Color);
+
+ for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x)
+ data << uint32(proto->Socket[x].Content);
+
+ data << uint32(proto->socketBonus);
+ data << uint32(proto->GemProperties);
+ data << float(proto->ArmorDamageModifier);
+ data << int32(proto->Duration);
+ data << uint32(proto->ItemLimitCategory);
+ data << uint32(proto->HolidayId);
+ data << float(proto->StatScalingFactor); // StatScalingFactor
+ data << uint32(proto->Field130); // archaeology unk
+ data << uint32(proto->Field131); // archaeology findinds count
}
else
{
+ data << uint32(item | 0x80000000); // sometimes with | 0x80000000
data << uint32(0);
- data << uint32(0);
- data << uint32(0);
- data << uint32(-1);
- data << uint32(0);
- data << uint32(-1);
}
+
+ data2 << uint32(data.size());
+ data2.append(data);
}
- data << pProto->Bonding;
- data << Description;
- data << pProto->PageText;
- data << pProto->LanguageID;
- data << pProto->PageMaterial;
- data << pProto->StartQuest;
- data << pProto->LockID;
- data << int32(pProto->Material);
- data << pProto->Sheath;
- data << pProto->RandomProperty;
- data << pProto->RandomSuffix;
- data << pProto->Block;
- data << pProto->ItemSet;
- data << pProto->MaxDurability;
- data << pProto->Area;
- data << pProto->Map; // Added in 1.12.x & 2.0.1 client branch
- data << pProto->BagFamily;
- data << pProto->TotemCategory;
- for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
- {
- data << pProto->Socket[s].Color;
- data << pProto->Socket[s].Content;
- }
- data << pProto->socketBonus;
- data << pProto->GemProperties;
- data << pProto->RequiredDisenchantSkill;
- data << pProto->ArmorDamageModifier;
- data << uint32(abs(pProto->Duration)); // added in 2.4.2.8209, duration (seconds)
- data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
- data << pProto->HolidayId; // Holiday.dbc?
- SendPacket(&data);
- }
- else
- {
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item);
- WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4);
- data << uint32(item | 0x80000000);
- SendPacket(&data);
+
+ data2 << uint32(type);
+ _player->GetSession()->SendPacket(&data2);
}
}
@@ -981,25 +974,6 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
}
}
-void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data)
-{
- if (!GetPlayer()->isAlive())
- {
- GetPlayer()->SendEquipError(EQUIP_ERR_YOU_ARE_DEAD, NULL, NULL);
- return;
- }
-
- sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SET_AMMO");
- uint32 item;
-
- recv_data >> item;
-
- if (!item)
- GetPlayer()->RemoveAmmo();
- else
- GetPlayer()->SetAmmo(item);
-}
-
void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster, uint32 ItemID, uint32 SpellID)
{
WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 8f0487d563f..ad182b4120a 100755
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -40,7 +40,7 @@ void InitOpcodes()
}
memset(opcodeTable, 0, sizeof(opcodeTable));
-
+
//DEFINE_OPCODE_HANDLER(MSG_NULL_ACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
//DEFINE_OPCODE_HANDLER(CMSG_BOOTME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
//DEFINE_OPCODE_HANDLER(CMSG_DBLOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
@@ -658,7 +658,7 @@ void InitOpcodes()
//DEFINE_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_LIST_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(SMSG_SET_FLAT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(SMSG_SET_PCT_SPELL_MODIFIER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- //DEFINE_OPCODE_HANDLER(CMSG_SET_AMMO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetAmmoOpcode );
+ //DEFINE_OPCODE_HANDLER(CMSG_SET_AMMO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
//DEFINE_OPCODE_HANDLER(SMSG_CORPSE_RECLAIM_DELAY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(CMSG_SET_ACTIVE_MOVER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveMoverOpcode );
//DEFINE_OPCODE_HANDLER(CMSG_PET_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCancelAuraOpcode );
@@ -707,7 +707,7 @@ void InitOpcodes()
//DEFINE_OPCODE_HANDLER(CMSG_LFG_GET_STATUS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
//DEFINE_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(SMSG_RESET_RANGED_COMBAT_TIMER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- ////DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_MEMBER_ADDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_MEMBER_ADDED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(SMSG_CHAT_NOT_IN_PARTY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(CMSG_CANCEL_GROWTH_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelGrowthAuraOpcode );
//DEFINE_OPCODE_HANDLER(SMSG_CANCEL_AUTO_REPEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
@@ -919,7 +919,7 @@ void InitOpcodes()
//DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_ROLES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetRolesOpcode );
//DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_NEEDS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
//DEFINE_OPCODE_HANDLER(CMSG_LFG_SET_BOOT_VOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgSetBootVoteOpcode );
- ////DEFINE_OPCODE_HANDLER(SMSG_LFG_BOOT_PROPOSAL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
+ //DEFINE_OPCODE_HANDLER(SMSG_LFG_BOOT_PROPOSAL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(CMSG_LFD_PLAYER_LOCK_INFO_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgPlayerLockInfoRequestOpcode);
//DEFINE_OPCODE_HANDLER(SMSG_LFG_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
//DEFINE_OPCODE_HANDLER(CMSG_LFG_TELEPORT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgTeleportOpcode );
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 6421edaa7c6..db71fe0941b 100755
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -137,6 +137,9 @@ enum CharterTypes
ARENA_TEAM_CHARTER_5v5_TYPE = 5
};
+#define DB2_REPLY_SPARSE 2442913102
+#define DB2_REPLY_ITEM 1344507586
+
//class to deal with packet processing
//allows to determine if next packet is safe to be processed
class PacketFilter
@@ -478,7 +481,6 @@ class WorldSession
void HandleDelIgnoreOpcode(WorldPacket& recvPacket);
void HandleSetContactNotesOpcode(WorldPacket& recvPacket);
void HandleBugOpcode(WorldPacket& recvPacket);
- void HandleSetAmmoOpcode(WorldPacket& recvPacket);
void HandleItemNameQueryOpcode(WorldPacket& recvPacket);
void HandleAreaTriggerOpcode(WorldPacket& recvPacket);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 20ee5ce39e4..867ae80319f 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1992,7 +1992,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
{
case FORM_CAT:
{
- int32 basePoints = int32(std::min(oldPower, FurorChance));
+ int32 basePoints = std::min<int32>(oldPower, FurorChance);
target->SetPower(POWER_ENERGY, 0);
target->CastCustomSpell(target, 17099, &basePoints, NULL, NULL, true, NULL, this);
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index c1749867945..c47d6d08990 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -513,7 +513,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
// wand case
if ((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId() == TYPEID_PLAYER)
if (Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK))
- m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->Damage[0].DamageType);
+ m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->DamageType);
if (originalCasterGUID)
m_originalCasterGUID = originalCasterGUID;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index a3ff66f7b5b..f98d0ab3e46 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -694,8 +694,8 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
Item* item = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK);
if (item)
{
- float dmg_min = item->GetTemplate()->Damage->DamageMin;
- float dmg_max = item->GetTemplate()->Damage->DamageMax;
+ float dmg_min = item->GetTemplate()->DamageMin;
+ float dmg_max = item->GetTemplate()->DamageMax;
if (dmg_max == 0.0f && dmg_min > dmg_max)
damage += int32(dmg_min);
else
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index e4ee17e324d..64f4e40c32b 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1344,13 +1344,19 @@ void World::SetInitialWorldSettings()
sLog->outString("Loading Item Random Enchantments Table...");
LoadRandomEnchantmentsTable();
- sLog->outString("Loading Disables");
- DisableMgr::LoadDisables(); // must be before loading quests and items
+ sLog->outString("Loading Disables...");
+ DisableMgr::LoadDisables(); // must be before loading quests and items
- sLog->outString("Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
+ sLog->outString("Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
sObjectMgr->LoadItemTemplates();
- sLog->outString("Loading Item set names..."); // must be after LoadItemPrototypes
+ sLog->outString("Loading Item Extra Data..."); // must be after LoadItemPrototypes
+ sObjectMgr->LoadItemTemplateAddon();
+
+ sLog->outString("Loading Item Scripts..."); // must be after LoadItemPrototypes
+ sObjectMgr->LoadItemScriptNames();
+
+ sLog->outString("Loading Item set names..."); // must be after LoadItemPrototypes
sObjectMgr->LoadItemSetNames();
sLog->outString("Loading Creature Model Based Info Data...");