diff options
| author | Shauren <shauren.trinity@gmail.com> | 2011-11-25 23:24:40 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2011-11-25 23:24:40 +0100 |
| commit | e8c3a3ac9c032cf56ec11620ba7dd33efed487c5 (patch) | |
| tree | 03cb750cfc0028b053b07dd5f2b50bc1b4d0c247 /src/server/game | |
| parent | 8d3bc5e8b9515499f366ec7173d70978bb0009e7 (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-x | src/server/game/DataStores/DBCStores.cpp | 22 | ||||
| -rwxr-xr-x | src/server/game/DataStores/DBCStores.h | 1 | ||||
| -rwxr-xr-x | src/server/game/DataStores/DBCStructure.h | 14 | ||||
| -rwxr-xr-x | src/server/game/DataStores/DBCfmt.h | 1 | ||||
| -rwxr-xr-x | src/server/game/Entities/Item/ItemPrototype.h | 54 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 55 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.h | 4 | ||||
| -rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 4 | ||||
| -rwxr-xr-x | src/server/game/Globals/ObjectMgr.cpp | 971 | ||||
| -rwxr-xr-x | src/server/game/Globals/ObjectMgr.h | 3 | ||||
| -rw-r--r-- | src/server/game/Guilds/GuildMgr.cpp | 2 | ||||
| -rwxr-xr-x | src/server/game/Loot/LootMgr.cpp | 21 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Handlers/ItemHandler.cpp | 294 | ||||
| -rwxr-xr-x | src/server/game/Server/Protocol/Opcodes.cpp | 8 | ||||
| -rwxr-xr-x | src/server/game/Server/WorldSession.h | 4 | ||||
| -rwxr-xr-x | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 | ||||
| -rwxr-xr-x | src/server/game/Spells/Spell.cpp | 2 | ||||
| -rwxr-xr-x | src/server/game/Spells/SpellEffects.cpp | 4 | ||||
| -rwxr-xr-x | src/server/game/World/World.cpp | 14 |
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..."); |
