diff --git a/revision_data.h.in.cmake b/revision_data.h.in.cmake index a5ebbe6af4..d7d5d63e01 100644 --- a/revision_data.h.in.cmake +++ b/revision_data.h.in.cmake @@ -10,8 +10,9 @@ #define _BUILD_DIRECTORY R"(@BUILDDIR@)" #define _MYSQL_EXECUTABLE R"(@MYSQL_EXECUTABLE@)" #define _FULL_DATABASE "TDB_full_world_434.34_2018_09_15.sql" + #define _HOTFIXES_DATABASE "TDB_full_hotfixes_434.01_2020_02_21.sql" #define VER_COMPANYNAME_STR "TrinityCore Developers" - #define VER_LEGALCOPYRIGHT_STR "(c)2008-2018 TrinityCore" + #define VER_LEGALCOPYRIGHT_STR "(c)2008-2020 TrinityCore" #define VER_FILEVERSION 0,0,0 #define VER_FILEVERSION_STR "@rev_hash@ @rev_date@ (@rev_branch@ branch)" #define VER_PRODUCTVERSION VER_FILEVERSION diff --git a/sql/create/create_mysql.sql b/sql/create/create_mysql.sql index e182e06168..a5e00ed733 100644 --- a/sql/create/create_mysql.sql +++ b/sql/create/create_mysql.sql @@ -6,8 +6,12 @@ CREATE DATABASE `characters` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE DATABASE `auth` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +CREATE DATABASE `hotfixes` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; + GRANT ALL PRIVILEGES ON `world` . * TO 'trinity'@'localhost' WITH GRANT OPTION; GRANT ALL PRIVILEGES ON `characters` . * TO 'trinity'@'localhost' WITH GRANT OPTION; GRANT ALL PRIVILEGES ON `auth` . * TO 'trinity'@'localhost' WITH GRANT OPTION; + +GRANT ALL PRIVILEGES ON `hotfixes` . * TO 'trinity'@'localhost' WITH GRANT OPTION; diff --git a/sql/create/drop_mysql.sql b/sql/create/drop_mysql.sql index ee05439df9..29f0031d06 100644 --- a/sql/create/drop_mysql.sql +++ b/sql/create/drop_mysql.sql @@ -12,6 +12,10 @@ REVOKE ALL PRIVILEGES ON `auth` . * FROM 'trinity'@'localhost'; REVOKE GRANT OPTION ON `auth` . * FROM 'trinity'@'localhost'; +REVOKE ALL PRIVILEGES ON `hotfixes` . * FROM 'trinity'@'localhost'; + +REVOKE GRANT OPTION ON `hotfixes` . * FROM 'trinity'@'localhost'; + DROP USER 'trinity'@'localhost'; DROP DATABASE IF EXISTS `world`; @@ -19,3 +23,5 @@ DROP DATABASE IF EXISTS `world`; DROP DATABASE IF EXISTS `characters`; DROP DATABASE IF EXISTS `auth`; + +DROP DATABASE IF EXISTS `hotfixes`; diff --git a/sql/updates/world/custom/custom_2020_02_21_00_world.sql b/sql/updates/world/custom/custom_2020_02_21_00_world.sql new file mode 100644 index 0000000000..2795604df1 --- /dev/null +++ b/sql/updates/world/custom/custom_2020_02_21_00_world.sql @@ -0,0 +1,4 @@ +DROP TABLE IF EXISTS `hotfix_data`; +DROP TABLE IF EXISTS `keychain_db2`; +DROP TABLE IF EXISTS `item_template`; +DROP TABLE IF EXISTS `item_template_locale`; diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index b4dcb80196..04ba7fdf44 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -68,6 +68,11 @@ char const* GitRevision::GetFullDatabase() return _FULL_DATABASE; } +char const* GitRevision::GetHotfixesDatabase() +{ + return _HOTFIXES_DATABASE; +} + #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS # ifdef _WIN64 # define TRINITY_PLATFORM_STR "Win64" diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h index 029843d24b..6d834fd06a 100644 --- a/src/common/GitRevision.h +++ b/src/common/GitRevision.h @@ -32,6 +32,7 @@ namespace GitRevision TC_COMMON_API char const* GetSourceDirectory(); TC_COMMON_API char const* GetMySQLExecutable(); TC_COMMON_API char const* GetFullDatabase(); + TC_COMMON_API char const* GetHotfixesDatabase(); TC_COMMON_API char const* GetFullVersion(); TC_COMMON_API char const* GetCompanyNameStr(); TC_COMMON_API char const* GetLegalCopyrightStr(); diff --git a/src/server/database/Database/DatabaseEnv.cpp b/src/server/database/Database/DatabaseEnv.cpp index eb80b1d8ec..0b2a83ae77 100644 --- a/src/server/database/Database/DatabaseEnv.cpp +++ b/src/server/database/Database/DatabaseEnv.cpp @@ -20,3 +20,4 @@ DatabaseWorkerPool WorldDatabase; DatabaseWorkerPool CharacterDatabase; DatabaseWorkerPool LoginDatabase; +DatabaseWorkerPool HotfixDatabase; diff --git a/src/server/database/Database/DatabaseEnv.h b/src/server/database/Database/DatabaseEnv.h index 5178cc298e..b481368b84 100644 --- a/src/server/database/Database/DatabaseEnv.h +++ b/src/server/database/Database/DatabaseEnv.h @@ -24,6 +24,7 @@ #include "Implementation/LoginDatabase.h" #include "Implementation/CharacterDatabase.h" #include "Implementation/WorldDatabase.h" +#include "Implementation/HotfixDatabase.h" #include "Field.h" #include "PreparedStatement.h" @@ -37,5 +38,7 @@ TC_DATABASE_API extern DatabaseWorkerPool WorldDatabase TC_DATABASE_API extern DatabaseWorkerPool CharacterDatabase; /// Accessor to the realm/login database TC_DATABASE_API extern DatabaseWorkerPool LoginDatabase; +/// Accessor to the hotfix database +TC_DATABASE_API extern DatabaseWorkerPool HotfixDatabase; #endif diff --git a/src/server/database/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp index f7013a3907..b51d6da099 100644 --- a/src/server/database/Database/DatabaseLoader.cpp +++ b/src/server/database/Database/DatabaseLoader.cpp @@ -184,3 +184,5 @@ template TC_DATABASE_API DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool&, std::string const&); template TC_DATABASE_API DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool&, std::string const&); +template TC_DATABASE_API +DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool&, std::string const&); diff --git a/src/server/database/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h index b2606d24ff..d84bb22b58 100644 --- a/src/server/database/Database/DatabaseLoader.h +++ b/src/server/database/Database/DatabaseLoader.h @@ -48,8 +48,9 @@ public: DATABASE_LOGIN = 1, DATABASE_CHARACTER = 2, DATABASE_WORLD = 4, + DATABASE_HOTFIX = 5, - DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD + DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD | DATABASE_HOTFIX }; private: diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp index c7479c8128..05b3038c0a 100644 --- a/src/server/database/Database/DatabaseWorkerPool.cpp +++ b/src/server/database/Database/DatabaseWorkerPool.cpp @@ -22,6 +22,7 @@ #include "Implementation/LoginDatabase.h" #include "Implementation/WorldDatabase.h" #include "Implementation/CharacterDatabase.h" +#include "Implementation/HotfixDatabase.h" #include "Log.h" #include "PreparedStatement.h" #include "ProducerConsumerQueue.h" @@ -470,3 +471,5 @@ void DatabaseWorkerPool::ExecuteOrAppend(SQLTransaction& trans, PreparedState template class TC_DATABASE_API DatabaseWorkerPool; template class TC_DATABASE_API DatabaseWorkerPool; template class TC_DATABASE_API DatabaseWorkerPool; +template class TC_DATABASE_API DatabaseWorkerPool; + diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp new file mode 100644 index 0000000000..4a8ba7a8da --- /dev/null +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -0,0 +1,87 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +// DO NOT EDIT! +// Autogenerated from DB2Structure.h + +#include "HotfixDatabase.h" + +// Force locale statments to appear exactly in locale declaration order, right after normal data fetch statement +#define PREPARE_LOCALE_STMT(stmtBase, sql, con) \ + static_assert(stmtBase + 1 == stmtBase##_LOCALE, "Invalid prepared statement index for " #stmtBase "_LOCALE"); \ + PrepareStatement(stmtBase##_LOCALE, sql, con); + +void HotfixDatabaseConnection::DoPrepareStatements() +{ + if (!m_reconnecting) + m_stmts.resize(MAX_HOTFIXDATABASE_STATEMENTS); + + // KeyChain.db2 + PrepareStatement(HOTFIX_SEL_KEY_CHAIN, "SELECT Id, Key1, Key2, Key3, Key4, Key5, Key6, Key7, Key8, Key9, Key10, Key11, Key12, Key13, Key14, Key15, Key16, " + "Key17, Key18, Key19, Key20, Key21, Key22, Key23, Key24, Key25, Key26, Key27, Key28, Key29, Key30, Key31, Key32 FROM key_chain ORDER BY ID DESC", CONNECTION_SYNCH); + + // Item.db2 + PrepareStatement(HOTFIX_SEL_ITEM, "SELECT ID, Class, SubClass, SoundOverrideSubclass, Material, InventoryType, Sheath FROM item ORDER BY ID DESC", CONNECTION_SYNCH); + + // ItemCurrencyCost.db2 + PrepareStatement(HOTFIX_SEL_ITEM_CURRENCY_COST, "SELECT ID, ItemID FROM item_currency_cost ORDER BY ItemID DESC", CONNECTION_SYNCH); + + // ItemExtendedCost.db2 + PrepareStatement(HOTFIX_SEL_ITEM_EXTENDED_COST, "SELECT ID, RequiredHonorPoints, RequiredArenaPoints, RequiredArenaSlot, " + "RequiredItem1, RequiredItem2, RequiredItem3, RequiredItem4, RequiredItem5, " + "RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, " + "RequiredPersonalArenaRating, ItemPurchaseGroup, " + "RequiredCurrency1, RequiredCurrency2, RequiredCurrency3, RequiredCurrency4, RequiredCurrency5, " + "RequiredCurrencyCount1, RequiredCurrencyCount2, RequiredCurrencyCount3, RequiredCurrencyCount4, RequiredCurrencyCount5, " + "RequiredFactionId, RequiredFactionStanding, RequirementFlags, RequiredAchievement FROM item_extended_cost ORDER BY ID DESC", CONNECTION_SYNCH); + + // Item-sparse.db2 + PrepareStatement(HOTFIX_SEL_ITEM_SPARSE, "SELECT ID, Quality, Flags1, Flags2, Unk1, Unk2, BuyCount, BuyPrice, SellPrice, InventoryType, " + "AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, RequiredSpell, RequiredHonorRank, " + "RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, MaxCount, Stackable, ContainerSlots, " + "ItemStatType1, ItemStatType2, ItemStatType3, ItemStatType4, ItemStatType5, " + "ItemStatType6, ItemStatType7, ItemStatType8, ItemStatType9, ItemStatType10, " + "ItemStatValue1, ItemStatValue2, ItemStatValue3, ItemStatValue4, ItemStatValue5, " + "ItemStatValue6, ItemStatValue7, ItemStatValue8, ItemStatValue9, ItemStatValue10, " + "ItemStatAllocation1, ItemStatAllocation2, ItemStatAllocation3, ItemStatAllocation4, ItemStatAllocation5, " + "ItemStatAllocation6, ItemStatAllocation7, ItemStatAllocation8, ItemStatAllocation9, ItemStatAllocation10, " + "ItemStatSocketCostMultiplier1, ItemStatSocketCostMultiplier2, ItemStatSocketCostMultiplier3, ItemStatSocketCostMultiplier4, ItemStatSocketCostMultiplier5, " + "ItemStatSocketCostMultiplier6, ItemStatSocketCostMultiplier7, ItemStatSocketCostMultiplier8, ItemStatSocketCostMultiplier9, ItemStatSocketCostMultiplier10, " + "ScalingStatDistribution, DamageType, Delay, RangedModRange, " + "SpellID1, SpellID2, SpellID3, SpellID4, SpellID5, " + "SpellTrigger1, SpellTrigger2, SpellTrigger3, SpellTrigger4, SpellTrigger5, " + "SpellCharges1, SpellCharges2, SpellCharges3, SpellCharges4, SpellCharges5, " + "SpellCooldown1, SpellCooldown2, SpellCooldown3, SpellCooldown4, SpellCooldown5, " + "SpellCategory1, SpellCategory2, SpellCategory3, SpellCategory4, SpellCategory5, " + "SpellCategoryCooldown1, SpellCategoryCooldown2, SpellCategoryCooldown3, SpellCategoryCooldown4, SpellCategoryCooldown5, " + "Bonding, Name, Name2, Name3, Name4, Description, PageText, LanguageID, PageMaterial, StartQuest, LockID, Material, Sheath, RandomProperty, RandomSuffix, ItemSet, " + "Area, Map, BagFamily, TotemCategory, SocketColor1, SocketColor2, SocketColor3, Content1, Content2, Content3, SocketBonus, GemProperties, ArmorDamageModifier, " + "Duration, ItemLimitCategory, HolidayID, StatScalingFactor, CurrencySubstitutionID, CurrencySubstitutionCount FROM item_sparse ORDER BY ID DESC", CONNECTION_SYNCH); + PREPARE_LOCALE_STMT(HOTFIX_SEL_ITEM_SPARSE, "SELECT ID, Name_lang, Name2_lang, Name3_lang, Name4_lang, Description_lang FROM item_sparse_locale WHERE locale = ?", CONNECTION_SYNCH); +} + +HotfixDatabaseConnection::HotfixDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) +{ +} + +HotfixDatabaseConnection::HotfixDatabaseConnection(ProducerConsumerQueue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) +{ +} + +HotfixDatabaseConnection::~HotfixDatabaseConnection() +{ +} diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h new file mode 100644 index 0000000000..6207ce4694 --- /dev/null +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -0,0 +1,59 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +// DO NOT EDIT! +// Autogenerated from DB2Structure.h + +#ifndef _HOTFIXDATABASE_H +#define _HOTFIXDATABASE_H + +#include "MySQLConnection.h" + +enum HotfixDatabaseStatements : uint32 +{ + /* Naming standard for defines: + {DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed} + When updating more than one field, consider looking at the calling function + name for a suiting suffix. + + DB2 locale loading statements must have the name of base statement with locale enum value name suffix + */ + + HOTFIX_SEL_KEY_CHAIN, + HOTFIX_SEL_ITEM, + HOTFIX_SEL_ITEM_CURRENCY_COST, + HOTFIX_SEL_ITEM_EXTENDED_COST, + HOTFIX_SEL_ITEM_SPARSE, + HOTFIX_SEL_ITEM_SPARSE_LOCALE, + MAX_HOTFIXDATABASE_STATEMENTS +}; + +class TC_DATABASE_API HotfixDatabaseConnection : public MySQLConnection +{ +public: + typedef HotfixDatabaseStatements Statements; + + //- Constructors for sync and async connections + HotfixDatabaseConnection(MySQLConnectionInfo& connInfo); + HotfixDatabaseConnection(ProducerConsumerQueue* q, MySQLConnectionInfo& connInfo); + ~HotfixDatabaseConnection(); + + //- Loads database type specific prepared statements + void DoPrepareStatements() override; +}; + +#endif diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp index 98b2e0037d..992c01c7e6 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.cpp +++ b/src/server/database/Database/Implementation/WorldDatabase.cpp @@ -79,7 +79,6 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, femaleName, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM creature WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h index 662a697dd6..c913f46797 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.h +++ b/src/server/database/Database/Implementation/WorldDatabase.h @@ -84,7 +84,6 @@ enum WorldDatabaseStatements : uint32 WORLD_SEL_COMMANDS, WORLD_SEL_CREATURE_TEMPLATE, WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, - WORLD_SEL_ITEM_TEMPLATE_BY_NAME, WORLD_SEL_CREATURE_BY_ID, WORLD_SEL_GAMEOBJECT_NEAREST, WORLD_SEL_CREATURE_NEAREST, diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp index 6c1c4983ae..e7d01d8a10 100644 --- a/src/server/database/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp @@ -150,6 +150,38 @@ bool DBUpdater::IsEnabled(uint32 const updateMask) return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false; } +// Hotfix Database +template<> +std::string DBUpdater::GetConfigEntry() +{ + return "Updates.Hotfix"; +} + +template<> +std::string DBUpdater::GetTableName() +{ + return "Hotfixes"; +} + +template<> +std::string DBUpdater::GetBaseFile() +{ + return GitRevision::GetHotfixesDatabase(); +} + +template<> +bool DBUpdater::IsEnabled(uint32 const updateMask) +{ + // This way silences warnings under msvc + return (updateMask & DatabaseLoader::DATABASE_HOTFIX) ? true : false; +} + +template<> +BaseLocation DBUpdater::GetBaseLocationType() +{ + return LOCATION_DOWNLOAD; +} + // All template BaseLocation DBUpdater::GetBaseLocationType() @@ -391,3 +423,4 @@ void DBUpdater::ApplyFile(DatabaseWorkerPool& pool, std::string const& hos template class TC_DATABASE_API DBUpdater; template class TC_DATABASE_API DBUpdater; template class TC_DATABASE_API DBUpdater; +template class TC_DATABASE_API DBUpdater; diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp index 95ce20e570..7704044384 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.cpp +++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp @@ -509,7 +509,7 @@ bool PlayerAI::IsPlayerRangedAttacker(Player const* who) // check if we have a ranged weapon equipped Item const* rangedSlot = who->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); if (ItemTemplate const* rangedTemplate = rangedSlot ? rangedSlot->GetTemplate() : nullptr) - if ((1 << rangedTemplate->SubClass) & ITEM_SUBCLASS_MASK_WEAPON_RANGED) + if ((1 << rangedTemplate->GetSubClass()) & ITEM_SUBCLASS_MASK_WEAPON_RANGED) return true; return false; } @@ -640,7 +640,7 @@ void PlayerAI::DoRangedAttackIfReady() Item const* rangedItem = me->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); if (ItemTemplate const* rangedTemplate = rangedItem ? rangedItem->GetTemplate() : nullptr) { - switch (rangedTemplate->SubClass) + switch (rangedTemplate->GetSubClass()) { case ITEM_SUBCLASS_WEAPON_BOW: case ITEM_SUBCLASS_WEAPON_GUN: diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 756b5f9184..b9f9c329d5 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -559,7 +559,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_RELOAD_CRETURE_TEXT_LOCALE = 659, RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_TEMPLATE_LOCALE = 660, RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION_LOCALE = 661, - RBAC_PERM_COMMAND_RELOAD_ITEM_TEMPLATE_LOCALE = 662, + // UNUSED RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAME_LOCALE = 663, RBAC_PERM_COMMAND_RELOAD_NPC_TEXT_LOCALE = 664, RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT_LOCALE = 665, diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 6ba2143827..16d0c32f56 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -366,7 +366,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1); if (!pProto) return false; - return pProto->ItemLevel >= equipped_item.item_level && pProto->Quality >= equipped_item.item_quality; + return pProto->GetBaseItemLevel() >= equipped_item.item_level && pProto->GetQuality() >= equipped_item.item_quality; } case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID: return source->GetMapId() == map_id.mapId; @@ -382,7 +382,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1); if (!pProto) return false; - return pProto->Quality == item.item_quality; + return pProto->GetQuality() == item.item_quality; } default: break; @@ -2844,7 +2844,7 @@ bool AchievementMgr::RequirementsSatisfied(AchievementCriteriaEntry const* ac if (!go || go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) return false; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1)); - if (!proto || proto->Class == ITEM_CLASS_QUEST) + if (!proto || proto->GetClass() == ITEM_CLASS_QUEST) return false; break; } @@ -2867,7 +2867,7 @@ bool AchievementMgr::AdditionalRequirementsSatisfied(AchievementCriteriaEntry case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_LEVEL: // 3 { ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1)); - if (!item || item->ItemLevel < reqValue) + if (!item || item->GetBaseItemLevel() < reqValue) return false; break; } @@ -2902,7 +2902,7 @@ bool AchievementMgr::AdditionalRequirementsSatisfied(AchievementCriteriaEntry { // miscValue1 is itemid ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1)); - if (!item || item->Quality < reqValue) + if (!item || item->GetQuality() < reqValue) return false; break; } @@ -2910,7 +2910,7 @@ bool AchievementMgr::AdditionalRequirementsSatisfied(AchievementCriteriaEntry { // miscValue1 is itemid ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1)); - if (!item || item->Quality != reqValue) + if (!item || item->GetQuality() != reqValue) return false; break; } @@ -2972,14 +2972,14 @@ bool AchievementMgr::AdditionalRequirementsSatisfied(AchievementCriteriaEntry case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_CLASS: // 33 { ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1)); - if (!item || item->Class != reqValue) + if (!item || item->GetClass() != reqValue) return false; break; } case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_SUBCLASS: // 34 { ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1)); - if (!item || item->SubClass != reqValue) + if (!item || item->GetSubClass() != reqValue) return false; break; } diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index c44dbf246b..ec0d578b3a 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -88,7 +88,7 @@ AuctionHouseObject* AuctionHouseMgr::GetAuctionsMapByHouseId(uint8 auctionHouseI uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item* pItem, uint32 count) { - uint32 MSV = pItem->GetTemplate()->SellPrice; + uint32 MSV = pItem->GetTemplate()->GetSellPrice(); if (MSV <= 0) return AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT); @@ -158,7 +158,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction& uint32 ownerAccId = sCharacterCache->GetCharacterAccountIdByGuid(ownerGuid); sLog->outCommand(bidderAccId, "GM %s (Account: %u) won item in auction: %s (Entry: %u Count: %u) and pay money: %u. Original owner %s (Account: %u)", - bidderName.c_str(), bidderAccId, pItem->GetTemplate()->Name1.c_str(), pItem->GetEntry(), pItem->GetCount(), auction->bid, ownerName.c_str(), ownerAccId); + bidderName.c_str(), bidderAccId, pItem->GetTemplate()->GetDefaultLocaleName(), pItem->GetEntry(), pItem->GetCount(), auction->bid, ownerName.c_str(), ownerAccId); } // receiver exist @@ -707,9 +707,6 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& count, uint32& totalcount, bool getall) { - LocaleConstant localeConstant = player->GetSession()->GetSessionDbLocaleIndex(); - int locdbc_idx = player->GetSession()->GetSessionDbcLocale(); - time_t curTime = GameTime::GetGameTime(); PlayerGetAllThrottleMap::const_iterator itr = GetAllThrottleMap.find(player->GetGUID()); @@ -752,19 +749,19 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player ItemTemplate const* proto = item->GetTemplate(); - if (itemClass != 0xffffffff && proto->Class != itemClass) + if (itemClass != 0xffffffff && proto->GetClass() != itemClass) continue; - if (itemSubClass != 0xffffffff && proto->SubClass != itemSubClass) + if (itemSubClass != 0xffffffff && proto->GetSubClass() != itemSubClass) continue; - if (inventoryType != 0xffffffff && proto->InventoryType != inventoryType) + if (inventoryType != 0xffffffff && proto->GetInventoryType() != inventoryType) continue; - if (quality != 0xffffffff && proto->Quality != quality) + if (quality != 0xffffffff && proto->GetQuality() != quality) continue; - if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax))) + if (levelmin != 0x00 && (proto->GetRequiredLevel() < levelmin || (levelmax != 0 && proto->GetRequiredLevel() > levelmax))) continue; if (usable != 0x00 && player->CanUseItem(item) != EQUIP_ERR_OK) @@ -774,15 +771,10 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player // No need to do any of this if no search term was entered if (!wsearchedname.empty()) { - std::string name = proto->Name1; + std::string name = proto->GetName(player->GetSession()->GetSessionDbcLocale()); if (name.empty()) continue; - // local name - if (localeConstant != LOCALE_enUS) - if (ItemLocale const* il = sObjectMgr->GetItemLocale(proto->ItemId)) - ObjectMgr::GetLocaleString(il->Name, localeConstant, name); - // DO NOT use GetItemEnchantMod(proto->RandomProperty) as it may return a result // that matches the search but it may not equal item->GetItemRandomPropertyId() // used in BuildAuctionInfo() which then causes wrong items to be listed @@ -815,7 +807,7 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player // Append the suffix (ie: of the Monkey) to the name using localization // or default enUS if localization is invalid name += ' '; - name += suffix[locdbc_idx >= 0 ? locdbc_idx : LOCALE_enUS]; + name += suffix; } } diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp index 758efa040d..e746915a26 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp @@ -478,8 +478,8 @@ void AuctionHouseBot::PrepareStatusInfos(AuctionHouseBotStatusInfo& statusInfo) ItemTemplate const* prototype = item->GetTemplate(); if (!auctionEntry->owner || sAuctionBotConfig->IsBotChar(auctionEntry->owner)) // Add only ahbot items { - if (prototype->Quality < MAX_AUCTION_QUALITY) - ++statusInfo[i].QualityInfo[prototype->Quality]; + if (prototype->GetQuality() < MAX_AUCTION_QUALITY) + ++statusInfo[i].QualityInfo[prototype->GetQuality()]; ++statusInfo[i].ItemsCount; } diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp index 81b5f9b9d9..7f01407b48 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp @@ -164,7 +164,7 @@ bool AuctionBotBuyer::RollBuyChance(BuyerItemInfo const* ahInfo, Item const* ite return false; float itemBuyPrice = float(auction->buyout / item->GetCount()); - float itemPrice = float(item->GetTemplate()->SellPrice ? item->GetTemplate()->SellPrice : GetVendorPrice(item->GetTemplate()->Quality)); + float itemPrice = float(item->GetTemplate()->GetSellPrice() ? item->GetTemplate()->GetSellPrice() : GetVendorPrice(item->GetTemplate()->GetQuality())); // The AH cut needs to be added to the price, but we dont want a 100% chance to buy if the price is exactly AH default itemPrice *= 1.4f; @@ -188,7 +188,7 @@ bool AuctionBotBuyer::RollBuyChance(BuyerItemInfo const* ahInfo, Item const* ite } // Add config weigh in for quality - chance *= GetChanceMultiplier(item->GetTemplate()->Quality) / 100.0f; + chance *= GetChanceMultiplier(item->GetTemplate()->GetQuality()) / 100.0f; float rand = frand(0.f, 100.f); bool win = rand <= chance; @@ -200,7 +200,7 @@ bool AuctionBotBuyer::RollBuyChance(BuyerItemInfo const* ahInfo, Item const* ite bool AuctionBotBuyer::RollBidChance(BuyerItemInfo const* ahInfo, Item const* item, AuctionEntry const* auction, uint32 bidPrice) { float itemBidPrice = float(bidPrice / item->GetCount()); - float itemPrice = float(item->GetTemplate()->SellPrice ? item->GetTemplate()->SellPrice : GetVendorPrice(item->GetTemplate()->Quality)); + float itemPrice = float(item->GetTemplate()->GetSellPrice() ? item->GetTemplate()->GetSellPrice() : GetVendorPrice(item->GetTemplate()->GetQuality())); // The AH cut needs to be added to the price, but we dont want a 100% chance to buy if the price is exactly AH default itemPrice *= 1.4f; @@ -224,7 +224,7 @@ bool AuctionBotBuyer::RollBidChance(BuyerItemInfo const* ahInfo, Item const* ite chance = chance / 5.f; // Add config weigh in for quality - chance *= GetChanceMultiplier(item->GetTemplate()->Quality) / 100.0f; + chance *= GetChanceMultiplier(item->GetTemplate()->GetQuality()) / 100.0f; float rand = frand(0.f, 100.f); bool win = rand <= chance; diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp index 59f561502b..a857a4b9f1 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp @@ -118,7 +118,7 @@ bool AuctionBotSeller::Initialize() continue; // skip items with too high quality (code can't properly work with its) - if (prototype->Quality >= MAX_AUCTION_QUALITY) + if (prototype->GetQuality() >= MAX_AUCTION_QUALITY) continue; // forced exclude filter @@ -138,13 +138,13 @@ bool AuctionBotSeller::Initialize() if (isForcedIncludeItem) { - _itemPool[prototype->Quality][prototype->Class].push_back(itemId); + _itemPool[prototype->GetQuality()][prototype->GetClass()].push_back(itemId); ++itemsAdded; continue; } // bounding filters - switch (prototype->Bonding) + switch (prototype->GetBonding()) { case BIND_NONE: if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BIND_NO)) @@ -171,7 +171,7 @@ bool AuctionBotSeller::Initialize() } bool allowZero = false; - switch (prototype->Class) + switch (prototype->GetClass()) { case ITEM_CLASS_CONSUMABLE: allowZero = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_ALLOW_ZERO); break; @@ -210,12 +210,12 @@ bool AuctionBotSeller::Initialize() { if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_SELLER)) { - if (prototype->SellPrice == 0) + if (prototype->GetSellPrice() == 0) continue; } else { - if (prototype->BuyPrice == 0) + if (prototype->GetBuyPrice() == 0) continue; } } @@ -263,28 +263,28 @@ bool AuctionBotSeller::Initialize() } // item class/subclass specific filters - switch (prototype->Class) + switch (prototype->GetClass()) { case ITEM_CLASS_ARMOR: case ITEM_CLASS_WEAPON: { if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_ITEM_LEVEL)) - if (prototype->ItemLevel < value) + if (prototype->GetBaseItemLevel() < value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_ITEM_LEVEL)) - if (prototype->ItemLevel > value) + if (prototype->GetBaseItemLevel() > value) continue; - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL)) - if (prototype->RequiredLevel < value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL)) + if (prototype->GetRequiredLevel() < value) continue; - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL)) - if (prototype->RequiredLevel > value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL)) + if (prototype->GetRequiredLevel() > value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_SKILL_RANK)) - if (prototype->RequiredSkillRank < value) + if (prototype->GetRequiredSkillRank() < value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_SKILL_RANK)) - if (prototype->RequiredSkillRank > value) + if (prototype->GetRequiredSkillRank() > value) continue; break; } @@ -292,41 +292,41 @@ bool AuctionBotSeller::Initialize() case ITEM_CLASS_CONSUMABLE: case ITEM_CLASS_PROJECTILE: { - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL)) - if (prototype->RequiredLevel < value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_REQ_LEVEL)) + if (prototype->GetRequiredLevel() < value) continue; - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL)) - if (prototype->RequiredLevel > value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_REQ_LEVEL)) + if (prototype->GetRequiredLevel() > value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MIN_SKILL_RANK)) - if (prototype->RequiredSkillRank < value) + if (prototype->GetRequiredSkillRank() < value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_MAX_SKILL_RANK)) - if (prototype->RequiredSkillRank > value) + if (prototype->GetRequiredSkillRank() > value) continue; break; } case ITEM_CLASS_MISCELLANEOUS: - if (prototype->SubClass == ITEM_SUBCLASS_JUNK_MOUNT) + if (prototype->GetSubClass() == ITEM_SUBCLASS_JUNK_MOUNT) { - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_REQ_LEVEL)) - if (prototype->RequiredLevel < value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_REQ_LEVEL)) + if (prototype->GetRequiredLevel() < value) continue; - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_REQ_LEVEL)) - if (prototype->RequiredLevel > value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_REQ_LEVEL)) + if (prototype->GetRequiredLevel() > value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MIN_SKILL_RANK)) - if (prototype->RequiredSkillRank < value) + if (prototype->GetRequiredSkillRank() < value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_MISC_MOUNT_MAX_SKILL_RANK)) - if (prototype->RequiredSkillRank > value) + if (prototype->GetRequiredSkillRank() > value) continue; } - if (prototype->Flags & ITEM_FLAG_HAS_LOOT) + if (prototype->GetFlags() & ITEM_FLAG_HAS_LOOT) { // skip any not locked lootable items (mostly quest specific or reward cases) - if (!prototype->LockID) + if (!prototype->GetLockID()) continue; if (!sAuctionBotConfig->GetConfig(CONFIG_AHBOT_LOCKBOX_ENABLED)) @@ -336,27 +336,27 @@ bool AuctionBotSeller::Initialize() break; case ITEM_CLASS_GLYPH: { - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_REQ_LEVEL)) - if (prototype->RequiredLevel < value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_REQ_LEVEL)) + if (prototype->GetRequiredLevel() < value) continue; - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_REQ_LEVEL)) - if (prototype->RequiredLevel > value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_REQ_LEVEL)) + if (prototype->GetRequiredLevel() > value) continue; - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_ITEM_LEVEL)) - if (prototype->RequiredLevel < value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MIN_ITEM_LEVEL)) + if (prototype->GetRequiredLevel() < value) continue; - if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_ITEM_LEVEL)) - if (prototype->RequiredLevel > value) + if (int32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_GLYPH_MAX_ITEM_LEVEL)) + if (prototype->GetRequiredLevel() > value) continue; break; } case ITEM_CLASS_TRADE_GOODS: { if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MIN_ITEM_LEVEL)) - if (prototype->ItemLevel < value) + if (prototype->GetBaseItemLevel() < value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_TRADEGOOD_MAX_ITEM_LEVEL)) - if (prototype->ItemLevel > value) + if (prototype->GetBaseItemLevel() > value) continue; break; } @@ -364,16 +364,16 @@ bool AuctionBotSeller::Initialize() case ITEM_CLASS_QUIVER: { if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MIN_ITEM_LEVEL)) - if (prototype->ItemLevel < value) + if (prototype->GetBaseItemLevel() < value) continue; if (uint32 value = sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_MAX_ITEM_LEVEL)) - if (prototype->ItemLevel > value) + if (prototype->GetBaseItemLevel() > value) continue; break; } } - _itemPool[prototype->Quality][prototype->Class].push_back(itemId); + _itemPool[prototype->GetQuality()][prototype->GetClass()].push_back(itemId); ++itemsAdded; } @@ -644,7 +644,7 @@ uint32 AuctionBotSeller::SetStat(SellerConfiguration& config) ItemTemplate const* prototype = item->GetTemplate(); if (prototype) if (!auctionEntry->owner || sAuctionBotConfig->IsBotChar(auctionEntry->owner)) // Add only ahbot items - ++itemsSaved[prototype->Quality][prototype->Class]; + ++itemsSaved[prototype->GetQuality()][prototype->GetClass()]; } } @@ -702,12 +702,12 @@ bool AuctionBotSeller::GetItemsToSell(SellerConfiguration& config, ItemsToSellAr // Set items price. All important value are passed by address. void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConfiguration& config, uint32& buyp, uint32& bidp, uint32 stackCount) { - uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->Class)); - uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->Quality)); + uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->GetClass())); + uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->GetQuality())); float priceRatio = (classRatio * qualityRatio) / 10000.0f; - float buyPrice = itemProto->BuyPrice; - float sellPrice = itemProto->SellPrice; + float buyPrice = itemProto->GetBuyPrice(); + float sellPrice = itemProto->GetSellPrice(); if (buyPrice == 0) { @@ -715,9 +715,9 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf buyPrice = sellPrice * GetSellModifier(itemProto); else { - float divisor = ((itemProto->Class == ITEM_CLASS_WEAPON || itemProto->Class == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f); - float tempLevel = (itemProto->ItemLevel == 0 ? 1.0f : itemProto->ItemLevel); - float tempQuality = (itemProto->Quality == 0 ? 1.0f : itemProto->Quality); + float divisor = ((itemProto->GetClass() == ITEM_CLASS_WEAPON || itemProto->GetClass() == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f); + float tempLevel = (itemProto->GetBaseItemLevel() == 0 ? 1.0f : itemProto->GetBaseItemLevel()); + float tempQuality = (itemProto->GetQuality() == 0 ? 1.0f : itemProto->GetQuality()); buyPrice = tempLevel * tempQuality * static_cast(GetBuyModifier(itemProto))* tempLevel / divisor; } @@ -729,7 +729,7 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_SELLER)) buyPrice = sellPrice; - float basePriceFloat = buyPrice * stackCount / (itemProto->Class == 6 ? 200.0f : static_cast(itemProto->BuyCount)); + float basePriceFloat = buyPrice * stackCount / (itemProto->GetClass() == 6 ? 200.0f : static_cast(itemProto->GetBuyCount())); basePriceFloat *= priceRatio; float range = basePriceFloat * 0.04f; @@ -747,7 +747,7 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf // Determines the stack size to use for the item uint32 AuctionBotSeller::GetStackSizeForItem(ItemTemplate const* itemProto, SellerConfiguration& config) const { - if (config.GetRandomStackRatioPerClass(ItemClass(itemProto->Class)) > urand(0, 99)) + if (config.GetRandomStackRatioPerClass(ItemClass(itemProto->GetClass())) > urand(0, 99)) return urand(1, itemProto->GetMaxStackSize()); else return 1; @@ -756,7 +756,7 @@ uint32 AuctionBotSeller::GetStackSizeForItem(ItemTemplate const* itemProto, Sell // Determine the multiplier for the sell price of any weapon without a buy price. uint32 AuctionBotSeller::GetSellModifier(ItemTemplate const* prototype) { - switch (prototype->Class) + switch (prototype->GetClass()) { case ITEM_CLASS_WEAPON: case ITEM_CLASS_ARMOR: @@ -771,11 +771,11 @@ uint32 AuctionBotSeller::GetSellModifier(ItemTemplate const* prototype) // Return the modifier by which the item's level and quality will be modified by to derive a relatively accurate price. uint32 AuctionBotSeller::GetBuyModifier(ItemTemplate const* prototype) { - switch (prototype->Class) + switch (prototype->GetClass()) { case ITEM_CLASS_CONSUMABLE: { - switch (prototype->SubClass) + switch (prototype->GetSubClass()) { case ITEM_SUBCLASS_CONSUMABLE: return 100; @@ -793,7 +793,7 @@ uint32 AuctionBotSeller::GetBuyModifier(ItemTemplate const* prototype) } case ITEM_CLASS_WEAPON: { - switch (prototype->SubClass) + switch (prototype->GetSubClass()) { case ITEM_SUBCLASS_WEAPON_AXE: case ITEM_SUBCLASS_WEAPON_MACE: @@ -815,7 +815,7 @@ uint32 AuctionBotSeller::GetBuyModifier(ItemTemplate const* prototype) } case ITEM_CLASS_ARMOR: { - switch (prototype->SubClass) + switch (prototype->GetSubClass()) { case ITEM_SUBCLASS_ARMOR_MISCELLANEOUS: case ITEM_SUBCLASS_ARMOR_CLOTH: @@ -836,7 +836,7 @@ uint32 AuctionBotSeller::GetBuyModifier(ItemTemplate const* prototype) return 50; case ITEM_CLASS_TRADE_GOODS: { - switch (prototype->SubClass) + switch (prototype->GetSubClass()) { case ITEM_SUBCLASS_TRADE_GOODS: case ITEM_SUBCLASS_PARTS: diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp index 234b7a13ca..8c304faf22 100644 --- a/src/server/game/Chat/ChatLink.cpp +++ b/src/server/game/Chat/ChatLink.cpp @@ -122,9 +122,9 @@ bool ItemChatLink::Initialize(std::istringstream& iss) return false; } // Validate item's color - if (_color != ItemQualityColors[_item->Quality]) + if (_color != ItemQualityColors[_item->GetQuality()]) { - TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): linked item has color %u, but user claims %u", iss.str().c_str(), ItemQualityColors[_item->Quality], _color); + TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): linked item has color %u, but user claims %u", iss.str().c_str(), ItemQualityColors[_item->GetQuality()], _color); return false; } // Number of various item properties after item entry @@ -168,13 +168,10 @@ bool ItemChatLink::Initialize(std::istringstream& iss) return true; } -inline std::string ItemChatLink::FormatName(uint8 index, ItemLocale const* locale, char* suffixStrings) const +inline std::string ItemChatLink::FormatName(uint8 index, char* suffixStrings) const { std::stringstream ss; - if (locale == nullptr || index >= locale->Name.size()) - ss << _item->Name1; - else - ss << locale->Name[index]; + ss << _item->GetName(LocaleConstant(index)); if (suffixStrings) ss << ' ' << suffixStrings[index]; return ss.str(); @@ -186,13 +183,12 @@ bool ItemChatLink::ValidateName(char* buffer, char const* context) char* suffixStrings = _suffix ? _suffix->Name : (_property ? _property->Name : nullptr); - bool res = (FormatName(LOCALE_enUS, nullptr, suffixStrings) == buffer); + bool res = (FormatName(LOCALE_enUS, suffixStrings) == buffer); if (!res) { - ItemLocale const* il = sObjectMgr->GetItemLocale(_item->ItemId); for (uint8 index = LOCALE_koKR; index < TOTAL_LOCALES; ++index) { - if (FormatName(index, il, suffixStrings) == buffer) + if (FormatName(index, suffixStrings) == buffer) { res = true; break; @@ -200,7 +196,7 @@ bool ItemChatLink::ValidateName(char* buffer, char const* context) } } if (!res) - TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): linked item (id: %u) name wasn't found in any localization", context, _item->ItemId); + TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): linked item (id: %u) name wasn't found in any localization", context, _item->GetId()); return res; } diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h index 88dcdbd921..222067d64d 100644 --- a/src/server/game/Chat/ChatLink.h +++ b/src/server/game/Chat/ChatLink.h @@ -67,7 +67,7 @@ public: virtual bool ValidateName(char* buffer, char const* context) override; protected: - std::string FormatName(uint8 index, ItemLocale const* locale, char* suffixStrings) const; + std::string FormatName(uint8 index, char* suffixStrings) const; ItemTemplate const* _item; int32 _data[8]; diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 9a508a267a..d71b0288b7 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -18,91 +18,80 @@ #include "DB2Stores.h" #include "Common.h" #include "DB2fmt.h" -#include "DB2Utility.h" #include "Errors.h" #include "Log.h" #include "World.h" #include -DB2Storage sItemStore(Itemfmt, &DB2Utilities::HasItemEntry, &DB2Utilities::WriteItemDbReply); -DB2Storage sItemCurrencyCostStore(ItemCurrencyCostfmt); -DB2Storage sItemExtendedCostStore(ItemExtendedCostEntryfmt); -DB2Storage sItemSparseStore(ItemSparsefmt, &DB2Utilities::HasItemSparseEntry, &DB2Utilities::WriteItemSparseDbReply); -DB2Storage sKeyChainStore(KeyChainfmt); +DB2Storage sItemStore("Item.db2", Itemfmt, HOTFIX_SEL_ITEM); +DB2Storage sItemCurrencyCostStore("ItemCurrencyCost.db2", ItemCurrencyCostfmt, HOTFIX_SEL_ITEM_CURRENCY_COST); +DB2Storage sItemExtendedCostStore("ItemExtendedCost.db2", ItemExtendedCostEntryfmt, HOTFIX_SEL_ITEM_EXTENDED_COST); +DB2Storage sItemSparseStore("Item-sparse.db2", ItemSparsefmt, HOTFIX_SEL_ITEM_SPARSE); +DB2Storage sKeyChainStore("KeyChain.db2", KeyChainfmt, HOTFIX_SEL_KEY_CHAIN); typedef std::list DB2StoreProblemList; -typedef std::map DB2StorageMap; -DB2StorageMap DB2Stores; - uint32 DB2FilesCount = 0; -static bool LoadDB2_assert_print(uint32 fsize, uint32 rsize, std::string const& filename) -{ - TC_LOG_ERROR("misc", "Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).", filename.c_str(), fsize, rsize); - - // ASSERT must fail after function call - return false; -} - template -inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Storage& storage, std::string const& db2_path, std::string const& filename) +inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Manager::StorageMap& stores, DB2Storage* storage, std::string const& db2_path) { // compatibility format and C++ structure sizes - ASSERT(DB2FileLoader::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDB2_assert_print(DB2FileLoader::GetFormatRecordSize(storage.GetFormat()), sizeof(T), filename)); + ASSERT(DB2FileLoader::GetFormatRecordSize(storage->GetFormat()) == sizeof(T), + "Size of '%s' set by format string (%u) not equal size of C++ structure (" SZFMTD ").", + storage->GetFileName().c_str(), DB2FileLoader::GetFormatRecordSize(storage->GetFormat()), sizeof(T)); ++DB2FilesCount; - std::string db2_filename = db2_path + filename; - if (storage.Load(db2_filename.c_str(), LocaleConstant(sWorld->GetDefaultDbcLocale()))) + if (storage->Load(db2_path, uint32(sWorld->GetDefaultDbcLocale()))) { + storage->LoadFromDB(); + for (uint32 i = 0; i < TOTAL_LOCALES; ++i) { - if (!(availableDb2Locales & (1 << i))) - continue; - if (uint32(sWorld->GetDefaultDbcLocale()) == i) continue; - std::string localizedName(db2_path); - localizedName.append(localeNames[i]); - localizedName.push_back('/'); - localizedName.append(filename); + if (availableDb2Locales & (1 << i)) + if (!storage->LoadStringsFrom((db2_path + localeNames[i] + '/'), i)) + availableDb2Locales &= ~(1 << i); // mark as not available for speedup next checks - if (!storage.LoadStringsFrom(localizedName.c_str(), i)) - availableDb2Locales &= ~(1<LoadStringsFromDB(LocaleConstant(i)); } } else { // sort problematic db2 to (1) non compatible and (2) nonexistent - if (FILE* f = fopen(db2_filename.c_str(), "rb")) + if (FILE* f = fopen((db2_path + storage->GetFileName()).c_str(), "rb")) { std::ostringstream stream; - stream << db2_filename << " exists, and has " << storage.GetFieldCount() << " field(s) (expected " << strlen(storage.GetFormat()) << "). Extracted file might be from wrong client version."; + stream << storage->GetFileName() << " exists, and has " << storage->GetFieldCount() << " field(s) (expected " << strlen(storage->GetFormat()) + << "). Extracted file might be from wrong client version."; std::string buf = stream.str(); errlist.push_back(buf); fclose(f); } else - errlist.push_back(db2_filename); + errlist.push_back(storage->GetFileName()); } - DB2Stores[storage.GetHash()] = &storage; + stores[storage->GetHash()] = storage; } -void LoadDB2Stores(std::string const& dataPath) +void DB2Manager::LoadStores(std::string const& dataPath) { + uint32 oldMSTime = getMSTime(); + std::string db2Path = dataPath + "dbc/"; DB2StoreProblemList bad_db2_files; uint32 availableDb2Locales = 0xFF; - LoadDB2(availableDb2Locales, bad_db2_files, sItemStore, db2Path, "Item.db2"); - LoadDB2(availableDb2Locales, bad_db2_files, sItemCurrencyCostStore, db2Path, "ItemCurrencyCost.db2"); - LoadDB2(availableDb2Locales, bad_db2_files, sItemSparseStore, db2Path, "Item-sparse.db2"); - LoadDB2(availableDb2Locales, bad_db2_files, sItemExtendedCostStore, db2Path, "ItemExtendedCost.db2"); - LoadDB2(availableDb2Locales, bad_db2_files, sKeyChainStore, db2Path, "KeyChain.db2"); + LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemStore, db2Path); + LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemCurrencyCostStore, db2Path); + LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemSparseStore, db2Path); + LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sItemExtendedCostStore, db2Path); + LoadDB2(availableDb2Locales, bad_db2_files, _stores, &sKeyChainStore, db2Path); // error checks if (bad_db2_files.size() >= DB2FilesCount) @@ -128,14 +117,64 @@ void LoadDB2Stores(std::string const& dataPath) exit(1); } - TC_LOG_INFO("misc", ">> Initialized %d DB2 data stores.", DB2FilesCount); + TC_LOG_INFO("server.loading", ">> Initialized %d DB2 data stores in %u ms", DB2FilesCount, GetMSTimeDiffToNow(oldMSTime)); } -DB2StorageBase const* GetDB2Storage(uint32 type) +DB2StorageBase const* DB2Manager::GetStorage(uint32 type) const { - DB2StorageMap::const_iterator itr = DB2Stores.find(type); - if (itr != DB2Stores.end()) + StorageMap::const_iterator itr = _stores.find(type); + if (itr != _stores.end()) return itr->second; return nullptr; } + +void DB2Manager::LoadHotfixData() +{ + uint32 oldMSTime = getMSTime(); + + QueryResult result = HotfixDatabase.Query("SELECT TableHash, RecordID, `Timestamp`, Deleted FROM hotfix_data"); + + if (!result) + { + TC_LOG_INFO("misc", ">> Loaded 0 hotfix info entries."); + return; + } + + uint32 count = 0; + + _hotfixData.reserve(result->GetRowCount()); + + do + { + Field* fields = result->Fetch(); + + HotfixNotify info; + info.TableHash = fields[0].GetUInt32(); + info.Entry = fields[1].GetUInt32(); + info.Timestamp = fields[2].GetUInt32(); + _hotfixData.push_back(info); + + if (fields[3].GetBool()) + { + auto itr = _stores.find(info.TableHash); + if (itr != _stores.end()) + itr->second->EraseRecord(info.Entry); + } + + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("misc", ">> Loaded %u hotfix info entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + +time_t DB2Manager::GetHotfixDate(uint32 entry, uint32 type) const +{ + time_t ret = 0; + for (HotfixNotify const& hotfix : _hotfixData) + if (hotfix.Entry == entry && hotfix.TableHash == type) + if (time_t(hotfix.Timestamp) > ret) + ret = time_t(hotfix.Timestamp); + + return ret ? ret : time(nullptr); +} diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 955d58b2d7..c70729faa0 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -22,14 +22,44 @@ #include "DB2Structure.h" #include -extern DB2Storage sItemStore; -extern DB2Storage sItemCurrencyCostStore; -extern DB2Storage sItemExtendedCostStore; -extern DB2Storage sItemSparseStore; -extern DB2Storage sKeyChainStore; +TC_GAME_API extern DB2Storage sItemStore; +TC_GAME_API extern DB2Storage sItemCurrencyCostStore; +TC_GAME_API extern DB2Storage sItemExtendedCostStore; +TC_GAME_API extern DB2Storage sItemSparseStore; +TC_GAME_API extern DB2Storage sKeyChainStore; -void LoadDB2Stores(std::string const& dataPath); +struct HotfixNotify +{ + uint32 TableHash; + uint32 Timestamp; + uint32 Entry; +}; -DB2StorageBase const* GetDB2Storage(uint32 type); +typedef std::vector HotfixData; + +class TC_GAME_API DB2Manager +{ +public: + typedef std::map StorageMap; + + static DB2Manager& Instance() + { + static DB2Manager instance; + return instance; + } + + void LoadStores(std::string const& dataPath); + DB2StorageBase const* GetStorage(uint32 type) const; + + void LoadHotfixData(); + HotfixData const* GetHotfixData() const { return &_hotfixData; } + time_t GetHotfixDate(uint32 entry, uint32 type) const; + +private: + StorageMap _stores; + HotfixData _hotfixData; +}; + +#define sDB2Manager DB2Manager::Instance() #endif diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 43102d3195..fe72c69779 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -19,105 +19,102 @@ #define TRINITY_DB2STRUCTURE_H #include "Common.h" -#include "ItemTemplate.h" -// GCC has alternative #pragma pack(N) syntax and old gcc version does not support pack(push, N), also any gcc version does not support it at some platform -#if defined(__GNUC__) -#pragma pack(1) -#else #pragma pack(push, 1) -#endif -// Structures used to access raw DB2 data and required packing to portability +#define MAX_ITEM_PROTO_SOCKETS 3 +#define MAX_ITEM_PROTO_SPELLS 5 +#define MAX_ITEM_PROTO_STATS 10 + struct ItemEntry { uint32 ID; // 0 - uint32 Class; // 1 - uint32 SubClass; // 2 - int32 SoundOverrideSubclass; // 3 + uint32 ClassID; // 1 + uint32 SubclassID; // 2 + int32 SoundOverrideSubclassID; // 3 int32 Material; // 4 - uint32 DisplayId; // 5 + uint32 DisplayInfoID; // 5 uint32 InventoryType; // 6 - uint32 Sheath; // 7 + uint32 SheatheType; // 7 }; struct ItemCurrencyCostEntry { - //uint32 Id; - uint32 ItemId; + uint32 ID; + uint32 ItemID; }; struct ItemSparseEntry { - uint32 ID; // 0 - uint32 Quality; // 1 - uint32 Flags; // 2 - uint32 Flags2; // 3 - float Unk430_1; - float Unk430_2; - uint32 BuyCount; - uint32 BuyPrice; // 4 - uint32 SellPrice; // 5 - uint32 InventoryType; // 6 - int32 AllowableClass; // 7 - int32 AllowableRace; // 8 - uint32 ItemLevel; // 9 - int32 RequiredLevel; // 10 - uint32 RequiredSkill; // 11 - uint32 RequiredSkillRank; // 12 - uint32 RequiredSpell; // 13 - uint32 RequiredHonorRank; // 14 - uint32 RequiredCityRank; // 15 - uint32 RequiredReputationFaction; // 16 - uint32 RequiredReputationRank; // 17 - uint32 MaxCount; // 18 - uint32 Stackable; // 19 - uint32 ContainerSlots; // 20 - int32 ItemStatType[MAX_ITEM_PROTO_STATS]; // 21 - 30 - uint32 ItemStatValue[MAX_ITEM_PROTO_STATS]; // 31 - 40 - int32 ItemStatAllocation[MAX_ITEM_PROTO_STATS]; // 41 - 50 - int32 ItemStatSocketCostMultiplier[MAX_ITEM_PROTO_STATS]; // 51 - 60 - uint32 ScalingStatDistribution; // 61 - uint32 DamageType; // 62 - uint32 Delay; // 63 - float RangedModRange; // 64 - int32 SpellId[MAX_ITEM_PROTO_SPELLS]; // 65 - 69 - int32 SpellTrigger[MAX_ITEM_PROTO_SPELLS]; // 70 - 74 - int32 SpellCharges[MAX_ITEM_PROTO_SPELLS]; // 75 - 79 - int32 SpellCooldown[MAX_ITEM_PROTO_SPELLS]; // 80 - 84 - int32 SpellCategory[MAX_ITEM_PROTO_SPELLS]; // 85 - 89 - int32 SpellCategoryCooldown[MAX_ITEM_PROTO_SPELLS]; // 90 - 94 - uint32 Bonding; // 95 - LocalizedString* Name; // 96 - LocalizedString* Name2; // 97 - LocalizedString* Name3; // 98 - LocalizedString* Name4; // 99 - LocalizedString* Description; // 100 - uint32 PageText; // 101 - uint32 LanguageID; // 102 - uint32 PageMaterial; // 103 - uint32 StartQuest; // 104 - uint32 LockID; // 105 - int32 Material; // 106 - uint32 Sheath; // 107 - uint32 RandomProperty; // 108 - uint32 RandomSuffix; // 109 - uint32 ItemSet; // 110 - uint32 Area; // 112 - uint32 Map; // 113 - uint32 BagFamily; // 114 - uint32 TotemCategory; // 115 - uint32 Color[MAX_ITEM_PROTO_SOCKETS]; // 116 - 118 - uint32 Content[MAX_ITEM_PROTO_SOCKETS]; // 119 - 121 - int32 SocketBonus; // 122 - uint32 GemProperties; // 123 - float ArmorDamageModifier; // 124 - uint32 Duration; // 125 - uint32 ItemLimitCategory; // 126 - uint32 HolidayId; // 127 - float StatScalingFactor; // 128 - int32 CurrencySubstitutionId; // 129 - int32 CurrencySubstitutionCount; // 130 + uint32 ID; // 0 + uint32 Quality; // 1 + uint32 Flags; // 2 + uint32 Flags2; // 3 + float Unk1; // 4 + float Unk2; // 5 + uint32 BuyCount; // 6 + uint32 BuyPrice; // 7 + uint32 SellPrice; // 8 + uint32 InventoryType; // 9 + int32 AllowableClass; // 10 + int32 AllowableRace; // 11 + uint32 ItemLevel; // 12 + int32 RequiredLevel; // 13 + uint32 RequiredSkill; // 14 + uint32 RequiredSkillRank; // 15 + uint32 RequiredSpell; // 16 + uint32 RequiredHonorRank; // 17 + uint32 RequiredCityRank; // 18 + uint32 RequiredReputationFaction; // 19 + uint32 RequiredReputationRank; // 20 + uint32 MaxCount; // 21 + uint32 Stackable; // 22 + uint32 ContainerSlots; // 23 + int32 ItemStatType[MAX_ITEM_PROTO_STATS]; // 24 - 33 + int32 ItemStatValue[MAX_ITEM_PROTO_STATS]; // 34 - 43 + int32 ItemStatAllocation[MAX_ITEM_PROTO_STATS]; // 44 - 53 + float ItemStatSocketCostMultiplier[MAX_ITEM_PROTO_STATS]; // 54 - 63 + uint32 ScalingStatDistribution; // 64 + uint32 DamageType; // 65 + uint32 Delay; // 66 + float RangedModRange; // 67 + int32 SpellID[MAX_ITEM_PROTO_SPELLS]; // 68 - 72 + int32 SpellTrigger[MAX_ITEM_PROTO_SPELLS]; // 73 - 77 + int32 SpellCharges[MAX_ITEM_PROTO_SPELLS]; // 78 - 82 + int32 SpellCooldown[MAX_ITEM_PROTO_SPELLS]; // 83 - 87 + int32 SpellCategory[MAX_ITEM_PROTO_SPELLS]; // 88 - 92 + int32 SpellCategoryCooldown[MAX_ITEM_PROTO_SPELLS]; // 93 - 94 + uint32 Bonding; // 95 + LocalizedString* Name; // 96 + LocalizedString* Name2; // 97 + LocalizedString* Name3; // 98 + LocalizedString* Name4; // 99 + LocalizedString* Description; // 100 + uint32 PageText; // 101 + uint32 LanguageID; // 102 + uint32 PageMaterial; // 103 + uint32 StartQuest; // 104 + uint32 LockID; // 105 + int32 Material; // 106 + uint32 Sheath; // 107 + uint32 RandomProperty; // 108 + uint32 RandomSuffix; // 109 + uint32 ItemSet; // 110 + uint32 Area; // 112 + uint32 Map; // 113 + uint32 BagFamily; // 114 + uint32 TotemCategory; // 115 + uint32 SocketColor[MAX_ITEM_PROTO_SOCKETS]; // 116 - 118 + uint32 Content[MAX_ITEM_PROTO_SOCKETS]; // 119 - 121 + int32 SocketBonus; // 122 + uint32 GemProperties; // 123 + float ArmorDamageModifier; // 124 + uint32 Duration; // 125 + uint32 ItemLimitCategory; // 126 + uint32 HolidayID; // 127 + float StatScalingFactor; // 128 + int32 CurrencySubstitutionID; // 129 + int32 CurrencySubstitutionCount; // 130 }; #define MAX_ITEM_EXT_COST_ITEMS 5 @@ -125,15 +122,15 @@ struct ItemSparseEntry struct ItemExtendedCostEntry { - uint32 ID; // 0 extended-cost entry id - //uint32 reqhonorpoints; // 1 required honor points - //uint32 reqarenapoints; // 2 required arena points - uint32 RequiredArenaSlot; // 3 arena slot restrictions (min slot value) - uint32 RequiredItem[MAX_ITEM_EXT_COST_ITEMS]; // 4-8 required item id - uint32 RequiredItemCount[MAX_ITEM_EXT_COST_ITEMS]; // 9-13 required count of 1st item - uint32 RequiredPersonalArenaRating; // 14 required personal arena rating - //uint32 ItemPurchaseGroup; // 15 - uint32 RequiredCurrency[MAX_ITEM_EXT_COST_CURRENCIES];// 16-20 required curency id + uint32 ID; // 0 extended-cost entry id + uint32 RequiredHonorPoints; // 1 required honor points + uint32 RequiredArenaPoints; // 2 required arena points + uint32 RequiredArenaSlot; // 3 arena slot restrictions (min slot value) + uint32 RequiredItem[MAX_ITEM_EXT_COST_ITEMS]; // 4-8 required item id + uint32 RequiredItemCount[MAX_ITEM_EXT_COST_ITEMS]; // 9-13 required count of 1st item + uint32 RequiredPersonalArenaRating; // 14 required personal arena rating + uint32 ItemPurchaseGroup; // 15 + uint32 RequiredCurrency[MAX_ITEM_EXT_COST_CURRENCIES]; // 16-20 required curency id uint32 RequiredCurrencyCount[MAX_ITEM_EXT_COST_CURRENCIES];// 21-25 required curency count uint32 RequiredFactionId; uint32 RequiredFactionStanding; @@ -146,15 +143,10 @@ struct ItemExtendedCostEntry struct KeyChainEntry { - uint32 Id; + uint32 ID; uint8 Key[KEYCHAIN_SIZE]; }; -// GCC has alternative #pragma pack(N) syntax and old gcc version does not support pack(push, N), also any gcc version does not support it at some platform -#if defined(__GNUC__) -#pragma pack() -#else #pragma pack(pop) -#endif #endif diff --git a/src/server/game/DataStores/DB2Utility.cpp b/src/server/game/DataStores/DB2Utility.cpp deleted file mode 100644 index 82148a53aa..0000000000 --- a/src/server/game/DataStores/DB2Utility.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#include "DB2Utility.h" -#include "ObjectMgr.h" - -inline bool ItemExists(uint32 id) -{ - return sObjectMgr->GetItemTemplate(id) != nullptr; -} - -bool DB2Utilities::HasItemEntry(DB2Storage const& /*store*/, uint32 id) -{ - return ItemExists(id); -} - -bool DB2Utilities::HasItemSparseEntry(DB2Storage const& /*store*/, uint32 id) -{ - return ItemExists(id); -} - -void DB2Utilities::WriteItemDbReply(DB2Storage const& /*store*/, uint32 id, LocaleConstant /*localeConstant*/, ByteBuffer& buffer) -{ - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(id); - ASSERT(proto); - - buffer << uint32(proto->ItemId); - buffer << uint32(proto->Class); - buffer << uint32(proto->SubClass); - buffer << int32(proto->SoundOverrideSubclass); - buffer << uint32(proto->Material); - buffer << uint32(proto->DisplayInfoID); - buffer << uint32(proto->InventoryType); - buffer << uint32(proto->Sheath); -} - -void DB2Utilities::WriteItemSparseDbReply(DB2Storage const& /*store*/, uint32 id, LocaleConstant localeConstant, ByteBuffer& buffer) -{ - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(id); - ASSERT(proto); - - ItemLocale const* localeData = localeConstant ? sObjectMgr->GetItemLocale(id) : nullptr; - - buffer << uint32(proto->ItemId); - buffer << uint32(proto->Quality); - buffer << uint32(proto->Flags); - buffer << uint32(proto->Flags2); - buffer << float(proto->Unk430_1); - buffer << float(proto->Unk430_2); - buffer << uint32(proto->BuyCount); - buffer << int32(proto->BuyPrice); - buffer << uint32(proto->SellPrice); - buffer << uint32(proto->InventoryType); - buffer << int32(proto->AllowableClass); - buffer << int32(proto->AllowableRace); - buffer << uint32(proto->ItemLevel); - buffer << uint32(proto->RequiredLevel); - buffer << uint32(proto->RequiredSkill); - buffer << uint32(proto->RequiredSkillRank); - buffer << uint32(proto->RequiredSpell); - buffer << uint32(proto->RequiredHonorRank); - buffer << uint32(proto->RequiredCityRank); - buffer << uint32(proto->RequiredReputationFaction); - buffer << uint32(proto->RequiredReputationRank); - buffer << int32(proto->MaxCount); - buffer << int32(proto->Stackable); - buffer << uint32(proto->ContainerSlots); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - buffer << uint32(proto->ItemStat[x].ItemStatType); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - buffer << int32(proto->ItemStat[x].ItemStatValue); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - buffer << int32(proto->ItemStat[x].ItemStatAllocation); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_STATS; ++x) - buffer << int32(proto->ItemStat[x].ItemStatSocketCostMultiplier); - - buffer << uint32(proto->ScalingStatDistribution); - buffer << uint32(proto->DamageType); - buffer << uint32(proto->Delay); - buffer << float(proto->RangedModRange); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - buffer << int32(proto->Spells[x].SpellId); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - buffer << uint32(proto->Spells[x].SpellTrigger); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - buffer << int32(proto->Spells[x].SpellCharges); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - buffer << int32(proto->Spells[x].SpellCooldown); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - buffer << uint32(proto->Spells[x].SpellCategory); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - buffer << int32(proto->Spells[x].SpellCategoryCooldown); - - buffer << uint32(proto->Bonding); - - // item name - std::string name = proto->Name1; - if (localeData) - ObjectMgr::GetLocaleString(localeData->Name, localeConstant, name); - - buffer << uint16(name.length()); - if (name.length()) - buffer << name; - - for (uint32 i = 0; i < 3; ++i) // other 3 names - buffer << uint16(0); - - std::string desc = proto->Description; - if (localeData) - ObjectMgr::GetLocaleString(localeData->Description, localeConstant, desc); - - buffer << uint16(desc.length()); - if (desc.length()) - buffer << desc; - - buffer << uint32(proto->PageText); - buffer << uint32(proto->LanguageID); - buffer << uint32(proto->PageMaterial); - buffer << uint32(proto->StartQuest); - buffer << uint32(proto->LockID); - buffer << int32(proto->Material); - buffer << uint32(proto->Sheath); - buffer << int32(proto->RandomProperty); - buffer << int32(proto->RandomSuffix); - buffer << uint32(proto->ItemSet); - - buffer << uint32(proto->Area); - buffer << uint32(proto->Map); - buffer << uint32(proto->BagFamily); - buffer << uint32(proto->TotemCategory); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x) - buffer << uint32(proto->Socket[x].Color); - - for (uint32 x = 0; x < MAX_ITEM_PROTO_SOCKETS; ++x) - buffer << uint32(proto->Socket[x].Content); - - buffer << uint32(proto->socketBonus); - buffer << uint32(proto->GemProperties); - buffer << float(proto->ArmorDamageModifier); - buffer << int32(proto->Duration); - buffer << uint32(proto->ItemLimitCategory); - buffer << uint32(proto->HolidayId); - buffer << float(proto->StatScalingFactor); // StatScalingFactor - buffer << uint32(proto->CurrencySubstitutionId); - buffer << uint32(proto->CurrencySubstitutionCount); -} diff --git a/src/server/game/DataStores/DB2Utility.h b/src/server/game/DataStores/DB2Utility.h deleted file mode 100644 index cf9067e822..0000000000 --- a/src/server/game/DataStores/DB2Utility.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef DB2PACKETWRITER_H -#define DB2PACKETWRITER_H - -#include "Define.h" - -template -class DB2Storage; -class ByteBuffer; -struct ItemEntry; -struct ItemSparseEntry; -enum LocaleConstant : uint8; - -namespace DB2Utilities -{ - // - bool HasItemEntry(DB2Storage const& store, uint32 id); - bool HasItemSparseEntry(DB2Storage const& store, uint32 id); - - // - void WriteItemDbReply(DB2Storage const& store, uint32 id, LocaleConstant localeConstant, ByteBuffer& buffer); - void WriteItemSparseDbReply(DB2Storage const& store, uint32 id, LocaleConstant localeConstant, ByteBuffer& buffer); -} - -#endif // DB2PACKETWRITER_H diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h index b6e4b60d74..4fa9bc6783 100644 --- a/src/server/game/DataStores/DB2fmt.h +++ b/src/server/game/DataStores/DB2fmt.h @@ -19,9 +19,9 @@ #define TRINITY_DB2SFRM_H char const Itemfmt[]="niiiiiii"; -char const ItemCurrencyCostfmt[]="xn"; -char const ItemSparsefmt[]="niiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisssssiiiiiiiiiiiiiiiiiiiiiifiiifii"; -char const ItemExtendedCostEntryfmt[]="nxxiiiiiiiiiiiixiiiiiiiiiiiiiii"; +char const ItemCurrencyCostfmt[]="in"; +char const ItemSparsefmt[]="niiiffiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffffffiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisssssiiiiiiiiiiiiiiiiiiiiiifiiifii"; +char const ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiiii"; char const KeyChainfmt[]="nbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; #endif diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 8281e0dbcb..aaf9196d14 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -1342,10 +1342,10 @@ bool IsInArea(uint32 objectAreaId, uint32 areaId) uint32 ItemTemplate::GetEffectiveArmor(Player const* owner) const { - if (Quality > ITEM_QUALITY_ARTIFACT) + if (GetQuality() > ITEM_QUALITY_ARTIFACT) return 0; - uint32 level = ItemLevel; + uint32 level = GetBaseItemLevel(); if (owner) { uint32 maxItemLevel = owner->GetUInt32Value(UNIT_FIELD_MAXITEMLEVEL); @@ -1353,14 +1353,14 @@ uint32 ItemTemplate::GetEffectiveArmor(Player const* owner) const level = maxItemLevel; } - if (Class != ITEM_CLASS_ARMOR || SubClass != ITEM_SUBCLASS_ARMOR_SHIELD) + if (GetClass() != ITEM_CLASS_ARMOR || GetSubClass() != ITEM_SUBCLASS_ARMOR_SHIELD) { ItemArmorQualityEntry const* armorQuality = sItemArmorQualityStore.LookupEntry(level); ItemArmorTotalEntry const* armorTotal = sItemArmorTotalStore.LookupEntry(level); if (!armorQuality || !armorTotal) return 0; - uint32 invType = InventoryType; + uint32 invType = GetInventoryType(); if (invType == INVTYPE_ROBE) invType = INVTYPE_CHEST; @@ -1368,26 +1368,26 @@ uint32 ItemTemplate::GetEffectiveArmor(Player const* owner) const if (!location) return 0; - if (SubClass < ITEM_SUBCLASS_ARMOR_CLOTH || SubClass > ITEM_SUBCLASS_ARMOR_PLATE) + if (GetSubClass() < ITEM_SUBCLASS_ARMOR_CLOTH || GetSubClass() > ITEM_SUBCLASS_ARMOR_PLATE) return 0; - return uint32(armorQuality->Qualitymod[Quality] * armorTotal->Value[SubClass - ITEM_SUBCLASS_ARMOR_CLOTH] * location->Value[SubClass - ITEM_SUBCLASS_ARMOR_CLOTH] + 0.5f); + return uint32(armorQuality->Qualitymod[GetQuality()] * armorTotal->Value[GetSubClass() - ITEM_SUBCLASS_ARMOR_CLOTH] * location->Value[GetSubClass() - ITEM_SUBCLASS_ARMOR_CLOTH] + 0.5f); } ItemArmorShieldEntry const* shield = sItemArmorShieldStore.LookupEntry(level); if (!shield) return 0; - return uint32(shield->Quality[Quality] + 0.5f); + return uint32(shield->Quality[GetQuality()] + 0.5f); } bool ItemTemplate::GetWeaponDamage(Player const* owner, float& minValue, float& maxValue, float& dps) const { minValue = maxValue = 0.0f; - if (Class != ITEM_CLASS_WEAPON || Quality > ITEM_QUALITY_ARTIFACT) + if (GetClass() != ITEM_CLASS_WEAPON || GetQuality() > ITEM_QUALITY_ARTIFACT) return false; - uint32 level = ItemLevel; + uint32 level = GetBaseItemLevel(); if (owner) { uint32 maxItemLevel = owner->GetUInt32Value(UNIT_FIELD_MAXITEMLEVEL); @@ -1397,13 +1397,13 @@ bool ItemTemplate::GetWeaponDamage(Player const* owner, float& minValue, float& DBCStorage* store = nullptr; - switch (InventoryType) + switch (GetInventoryType()) { case INVTYPE_AMMO: store = &sItemDamageAmmoStore; break; case INVTYPE_2HWEAPON: - if (Flags2 & ITEM_FLAG2_CASTER_WEAPON) + if (GetFlags2() & ITEM_FLAG2_CASTER_WEAPON) store = &sItemDamageTwoHandCasterStore; else store = &sItemDamageTwoHandStore; @@ -1411,7 +1411,7 @@ bool ItemTemplate::GetWeaponDamage(Player const* owner, float& minValue, float& case INVTYPE_RANGED: case INVTYPE_THROWN: case INVTYPE_RANGEDRIGHT: - switch (SubClass) + switch (GetSubClass()) { case ITEM_SUBCLASS_WEAPON_WAND: store = &sItemDamageWandStore; @@ -1431,7 +1431,7 @@ bool ItemTemplate::GetWeaponDamage(Player const* owner, float& minValue, float& case INVTYPE_WEAPON: case INVTYPE_WEAPONMAINHAND: case INVTYPE_WEAPONOFFHAND: - if (Flags2 & ITEM_FLAG2_CASTER_WEAPON) + if (GetFlags2() & ITEM_FLAG2_CASTER_WEAPON) store = &sItemDamageOneHandCasterStore; else store = &sItemDamageOneHandStore; @@ -1447,25 +1447,25 @@ bool ItemTemplate::GetWeaponDamage(Player const* owner, float& minValue, float& if (!damageInfo) return false; - dps = damageInfo->Quality[Quality]; + dps = damageInfo->Quality[GetQuality()]; - float avgDamage = Delay * damageInfo->Quality[Quality] * 0.001f; - float scaled_stat = std::floor((StatScalingFactor * 0.5f + 1.f) * avgDamage + 0.5f); - if (Delay && ArmorDamageModifier != 0.f) + float avgDamage = GetDelay() * damageInfo->Quality[GetQuality()] * 0.001f; + float scaled_stat = std::floor((GetStatScalingFactor() * 0.5f + 1.f) * avgDamage + 0.5f); + if (GetDelay() && GetArmorDamageModifier() != 0.f) { - float invMsDelay = 1000.0f / float(Delay); + float invMsDelay = 1000.0f / float(GetDelay()); - float v16 = (invMsDelay * ((1.f - (StatScalingFactor * 0.5f)) * avgDamage)) + ArmorDamageModifier; + float v16 = (invMsDelay * ((1.f - (GetStatScalingFactor() * 0.5f)) * avgDamage)) + GetArmorDamageModifier(); v16 = std::max(v16, 1.f); minValue = (1.0f / invMsDelay) * v16; - maxValue = (1.0f / invMsDelay) * (((1000.f / float(Delay)) * scaled_stat) + ArmorDamageModifier); + maxValue = (1.0f / invMsDelay) * (((1000.f / float(GetDelay())) * scaled_stat) + GetArmorDamageModifier()); } else { maxValue = scaled_stat; - minValue = (1.f - (StatScalingFactor * 0.5f)) * avgDamage; + minValue = (1.f - (GetStatScalingFactor() * 0.5f)) * avgDamage; } return true; @@ -1548,9 +1548,9 @@ uint32 GetItemScalingModifier(uint32 maxIlvl, ItemQualities quality, InventoryTy uint32 ItemTemplate::GetStatValue(uint32 index, Player const* owner /*= nullptr*/) const { if (!owner) - return ItemStat[index].ItemStatValue; + return GetItemStatValue(index); - ScalingStatDistributionEntry const* ssd = ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(ScalingStatDistribution) : nullptr; + ScalingStatDistributionEntry const* ssd = GetScalingStatDistribution() ? sScalingStatDistributionStore.LookupEntry(GetScalingStatDistribution()) : nullptr; // req. check at equip, but allow use for extended range if range limit max level, set proper level uint32 ssdLevel = owner->getLevel(); @@ -1569,24 +1569,24 @@ uint32 ItemTemplate::GetStatValue(uint32 index, Player const* owner /*= nullptr* if (ssd->StatID[index] < 0) return 0; // What do we do ? - statBaseValue = ssv->GetStatMultiplier(InventoryType) * ssd->Bonus[index] / 10000; + statBaseValue = ssv->GetStatMultiplier(GetInventoryType()) * ssd->Bonus[index] / 10000; } else { - statBaseValue = ItemStat[index].ItemStatValue; + statBaseValue = GetItemStatValue(index); - uint32 itemLevel = ItemLevel; + uint32 itemLevel = GetBaseItemLevel(); uint32 maxItemLevel = owner->GetUInt32Value(UNIT_FIELD_MAXITEMLEVEL); if (!maxItemLevel || maxItemLevel >= itemLevel) // TODO: This might work if >=. Check. return statBaseValue; - float minScaler = GetItemScalingModifier(ItemLevel, ItemQualities(Quality), ::InventoryType(InventoryType)); - float maxScaler = GetItemScalingModifier(maxItemLevel, ItemQualities(Quality), ::InventoryType(InventoryType)); + float minScaler = GetItemScalingModifier(GetBaseItemLevel(), ItemQualities(GetQuality()), ::InventoryType(GetInventoryType())); + float maxScaler = GetItemScalingModifier(maxItemLevel, ItemQualities(GetQuality()), ::InventoryType(GetInventoryType())); if (maxScaler != 0.f && minScaler != 0.f) { - float statAllocation = ItemStat[index].ItemStatAllocation * maxScaler * 0.0001f; - return std::ceil(statAllocation - ((maxScaler / minScaler) * ItemStat[index].ItemStatSocketCostMultiplier)); + float statAllocation = GetItemStatAllocation(index) * maxScaler * 0.0001f; + return std::ceil(statAllocation - ((maxScaler / minScaler) * GetItemStatSocketCostMultiplier(index))); } } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index bf835644cc..3b9f4243ec 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -77,7 +77,7 @@ std::string CreatureMovementData::ToString() const bool VendorItem::IsGoldRequired(ItemTemplate const* pProto) const { - return (pProto->Flags2 & ITEM_FLAG2_DONT_IGNORE_BUY_PRICE) || !ExtendedCost; + return (pProto->GetFlags2() & ITEM_FLAG2_DONT_IGNORE_BUY_PRICE) || !ExtendedCost; } bool VendorItemData::RemoveItem(uint32 item_id, uint8 type) @@ -2700,13 +2700,13 @@ uint32 Creature::GetVendorItemCurrentCount(VendorItem const* vItem) if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item)) { uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime); - if ((vCount->count + diff * pProto->BuyCount) >= vItem->maxcount) + if ((vCount->count + diff * pProto->GetBuyCount()) >= vItem->maxcount) { m_vendorItemCounts.erase(itr); return vItem->maxcount; } - vCount->count += diff * pProto->BuyCount; + vCount->count += diff * pProto->GetBuyCount(); vCount->lastIncrementTime = ptime; } @@ -2738,8 +2738,8 @@ uint32 Creature::UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 us if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item)) { uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime); - if ((vCount->count + diff * pProto->BuyCount) < vItem->maxcount) - vCount->count += diff * pProto->BuyCount; + if ((vCount->count + diff * pProto->GetBuyCount()) < vItem->maxcount) + vCount->count += diff * pProto->GetBuyCount(); else vCount->count = vItem->maxcount; } diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 200c75366c..970ae18a2c 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -730,7 +730,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU uint32 displayId = 0; if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) - displayId = itemTemplate->DisplayInfoID; + displayId = itemTemplate->GetDisplayID(); if (data.ItemCount[i] < quest->RequiredItemCount[i] && !_session->GetPlayer()->HasItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i])) collectObjectiveComplete = false; diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp index 41ff1c0394..c02694ba73 100644 --- a/src/server/game/Entities/Item/Container/Bag.cpp +++ b/src/server/game/Entities/Item/Container/Bag.cpp @@ -72,7 +72,7 @@ bool Bag::Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owner { ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemid); - if (!itemProto || itemProto->ContainerSlots > MAX_BAG_SIZE) + if (!itemProto || itemProto->GetContainerSlots() > MAX_BAG_SIZE) return false; Object::_Create(guidlow, 0, HighGuid::Container); @@ -91,7 +91,7 @@ bool Bag::Create(ObjectGuid::LowType guidlow, uint32 itemid, Player const* owner SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1); // Setting the number of Slots the Container has - SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->ContainerSlots); + SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->GetContainerSlots()); // Cleaning 20 slots for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) @@ -114,7 +114,7 @@ bool Bag::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fie return false; ItemTemplate const* itemProto = GetTemplate(); // checked in Item::LoadFromDB - SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->ContainerSlots); + SetUInt32Value(CONTAINER_FIELD_NUM_SLOTS, itemProto->GetContainerSlots()); // cleanup bag content related item value fields (its will be filled correctly from `character_inventory`) for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) { @@ -201,12 +201,12 @@ uint32 Bag::GetItemCount(uint32 item, Item* eItem) const count += pItem->GetCount(); } - if (eItem && eItem->GetTemplate()->GemProperties) + if (eItem && eItem->GetTemplate()->GetGemProperties()) { for (uint32 i=0; i < GetBagSize(); ++i) { pItem = m_bagslot[i]; - if (pItem && pItem != eItem && pItem->GetTemplate()->Socket[0].Color) + if (pItem && pItem != eItem && pItem->GetTemplate()->ExtendedData->SocketColor[0]) count += pItem->GetGemCountWithID(item); } } @@ -221,7 +221,7 @@ uint32 Bag::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipItem) if (Item* pItem = m_bagslot[i]) if (pItem != skipItem) if (ItemTemplate const* pProto = pItem->GetTemplate()) - if (pProto->ItemLimitCategory == limitCategory) + if (pProto->GetItemLimitCategory() == limitCategory) count += m_bagslot[i]->GetCount(); return count; diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h index 6075391271..7ac4d60d30 100644 --- a/src/server/game/Entities/Item/Container/Bag.h +++ b/src/server/game/Entities/Item/Container/Bag.h @@ -66,6 +66,6 @@ class TC_GAME_API Bag : public Item inline Item* NewItemOrBag(ItemTemplate const* proto) { - return (proto->InventoryType == INVTYPE_BAG) ? new Bag : new Item; + return (proto->GetInventoryType() == INVTYPE_BAG) ? new Bag : new Item; } #endif diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 4284f64261..02c112bd27 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -40,13 +40,13 @@ void AddItemsSetItem(Player* player, Item* item) { ItemTemplate const* proto = item->GetTemplate(); - uint32 setid = proto->ItemSet; + uint32 setid = proto->GetItemSet(); ItemSetEntry const* set = sItemSetStore.LookupEntry(setid); if (!set) { - TC_LOG_ERROR("sql.sql", "Item set %u for item (id %u) not found, mods not applied.", setid, proto->ItemId); + TC_LOG_ERROR("sql.sql", "Item set %u for item (id %u) not found, mods not applied.", setid, proto->GetId()); return; } @@ -122,13 +122,13 @@ void AddItemsSetItem(Player* player, Item* item) void RemoveItemsSetItem(Player*player, ItemTemplate const* proto) { - uint32 setid = proto->ItemSet; + uint32 setid = proto->GetItemSet(); ItemSetEntry const* set = sItemSetStore.LookupEntry(setid); if (!set) { - TC_LOG_ERROR("sql.sql", "Item set #%u for item #%u not found, mods not removed.", setid, proto->ItemId); + TC_LOG_ERROR("sql.sql", "Item set #%u for item #%u not found, mods not removed.", setid, proto->GetId()); return; } @@ -183,61 +183,61 @@ bool ItemCanGoIntoBag(ItemTemplate const* pProto, ItemTemplate const* pBagProto) if (!pProto || !pBagProto) return false; - switch (pBagProto->Class) + switch (pBagProto->GetClass()) { case ITEM_CLASS_CONTAINER: - switch (pBagProto->SubClass) + switch (pBagProto->GetSubClass()) { case ITEM_SUBCLASS_CONTAINER: return true; case ITEM_SUBCLASS_SOUL_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_SOUL_SHARDS)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_SOUL_SHARDS)) return false; return true; case ITEM_SUBCLASS_HERB_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_HERBS)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_HERBS)) return false; return true; case ITEM_SUBCLASS_ENCHANTING_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_ENCHANTING_SUPP)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_ENCHANTING_SUPP)) return false; return true; case ITEM_SUBCLASS_MINING_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_MINING_SUPP)) return false; return true; case ITEM_SUBCLASS_ENGINEERING_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_ENGINEERING_SUPP)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_ENGINEERING_SUPP)) return false; return true; case ITEM_SUBCLASS_GEM_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_GEMS)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_GEMS)) return false; return true; case ITEM_SUBCLASS_LEATHERWORKING_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_LEATHERWORKING_SUPP)) return false; return true; case ITEM_SUBCLASS_INSCRIPTION_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_INSCRIPTION_SUPP)) return false; return true; case ITEM_SUBCLASS_TACKLE_CONTAINER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_FISHING_SUPP)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_FISHING_SUPP)) return false; return true; default: return false; } case ITEM_CLASS_QUIVER: - switch (pBagProto->SubClass) + switch (pBagProto->GetSubClass()) { case ITEM_SUBCLASS_QUIVER: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_ARROWS)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_ARROWS)) return false; return true; case ITEM_SUBCLASS_AMMO_POUCH: - if (!(pProto->BagFamily & BAG_FAMILY_MASK_BULLETS)) + if (!(pProto->GetBagFamily() & BAG_FAMILY_MASK_BULLETS)) return false; return true; default: @@ -288,10 +288,10 @@ bool Item::Create(ObjectGuid::LowType guidlow, uint32 itemId, Player const* owne SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability); SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - SetSpellCharges(i, itemProto->Spells[i].SpellCharges); + for (uint8 i = 0; i < itemProto->Effects.size(); ++i) + SetSpellCharges(i, itemProto->Effects[i].Charges); - SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Duration); + SetUInt32Value(ITEM_FIELD_DURATION, itemProto->GetDuration()); SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, owner ? owner->GetTotalPlayedTime() : 0); return true; } @@ -439,9 +439,9 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fi uint32 duration = fields[3].GetUInt32(); SetUInt32Value(ITEM_FIELD_DURATION, duration); // update duration if need, and remove if not need - if ((proto->Duration == 0) != (duration == 0)) + if ((proto->GetDuration() == 0) != (duration == 0)) { - SetUInt32Value(ITEM_FIELD_DURATION, proto->Duration); + SetUInt32Value(ITEM_FIELD_DURATION, proto->GetDuration()); need_save = true; } @@ -452,7 +452,7 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid owner_guid, Field* fi SetUInt32Value(ITEM_FIELD_FLAGS, fields[5].GetUInt32()); // Remove bind flag for items vs BIND_NONE set - if (IsSoulBound() && proto->Bonding == BIND_NONE) + if (IsSoulBound() && proto->GetBonding() == BIND_NONE) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND, false); need_save = true; @@ -753,7 +753,7 @@ InventoryResult Item::CanBeMergedPartlyWith(ItemTemplate const* proto) const return EQUIP_ERR_LOOT_GONE; // check item type - if (GetEntry() != proto->ItemId) + if (GetEntry() != proto->GetId()) return EQUIP_ERR_CANT_STACK; // check free space (full stacks can't be target of merge @@ -775,12 +775,12 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const if (spellInfo->IsAbilityOfSkillType(SKILL_ENCHANTING)) // only for enchanting spells return true; - if (spellInfo->EquippedItemClass != int32(proto->Class)) + if (spellInfo->EquippedItemClass != int32(proto->GetClass())) return false; // wrong item class if (spellInfo->EquippedItemSubClassMask != 0) // 0 == any subclass { - if ((spellInfo->EquippedItemSubClassMask & (1 << proto->SubClass)) == 0) + if ((spellInfo->EquippedItemSubClassMask & (1 << proto->GetSubClass())) == 0) return false; // subclass not present in mask } } @@ -788,11 +788,11 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const if (isEnchantSpell && spellInfo->EquippedItemInventoryTypeMask != 0) // 0 == any inventory type { // Special case - accept weapon type for main and offhand requirements - if (proto->InventoryType == INVTYPE_WEAPON && + if (proto->GetInventoryType() == INVTYPE_WEAPON && (spellInfo->EquippedItemInventoryTypeMask & (1 << INVTYPE_WEAPONMAINHAND) || spellInfo->EquippedItemInventoryTypeMask & (1 << INVTYPE_WEAPONOFFHAND))) return true; - else if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->InventoryType)) == 0) + else if ((spellInfo->EquippedItemInventoryTypeMask & (1 << proto->GetInventoryType())) == 0) return false; // inventory type not present in mask } @@ -854,7 +854,7 @@ bool Item::GemsFitSockets() const { for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) { - uint8 SocketColor = GetTemplate()->Socket[enchant_slot-SOCK_ENCHANTMENT_SLOT].Color; + uint8 SocketColor = GetTemplate()->GetSocketColor(enchant_slot - SOCK_ENCHANTMENT_SLOT); if (!SocketColor) // no socket slot continue; @@ -875,7 +875,7 @@ bool Item::GemsFitSockets() const ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemid); if (gemProto) { - GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GemProperties); + GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GetGemProperties()); if (gemProperty) GemColor = gemProperty->Type; } @@ -923,7 +923,7 @@ uint8 Item::GetGemCountWithLimitCategory(uint32 limitCategory) const if (!gemProto) continue; - if (gemProto->ItemLimitCategory == limitCategory) + if (gemProto->GetItemLimitCategory() == limitCategory) ++count; } return count; @@ -932,7 +932,7 @@ uint8 Item::GetGemCountWithLimitCategory(uint32 limitCategory) const bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) const { ItemTemplate const* proto = GetTemplate(); - return proto && ((proto->Map && proto->Map != cur_mapId) || (proto->Area && proto->Area != cur_zoneId)); + return proto && ((proto->GetMap() && proto->GetMap() != cur_mapId) || (proto->GetArea() && proto->GetArea() != cur_zoneId)); } void Item::SendUpdateSockets() @@ -1149,17 +1149,17 @@ bool Item::CanBeTransmogrified() const if (!proto) return false; - if (proto->Quality == ITEM_QUALITY_LEGENDARY) + if (proto->GetQuality() == ITEM_QUALITY_LEGENDARY) return false; - if (proto->Class != ITEM_CLASS_ARMOR && - proto->Class != ITEM_CLASS_WEAPON) + if (proto->GetClass() != ITEM_CLASS_ARMOR && + proto->GetClass() != ITEM_CLASS_WEAPON) return false; - if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE) + if (proto->GetClass() == ITEM_CLASS_WEAPON && proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_FISHING_POLE) return false; - if (proto->Flags2 & ITEM_FLAG2_NO_ALTER_ITEM_VISUAL) + if (proto->GetFlags2() & ITEM_FLAG2_NO_ALTER_ITEM_VISUAL) return false; if (!HasStats()) @@ -1175,20 +1175,20 @@ bool Item::CanTransmogrify() const if (!proto) return false; - if (proto->Flags2 & ITEM_FLAG2_NO_SOURCE_FOR_ITEM_VISUAL) + if (proto->GetFlags2() & ITEM_FLAG2_NO_SOURCE_FOR_ITEM_VISUAL) return false; - if (proto->Quality == ITEM_QUALITY_LEGENDARY) + if (proto->GetQuality() == ITEM_QUALITY_LEGENDARY) return false; - if (proto->Class != ITEM_CLASS_ARMOR && - proto->Class != ITEM_CLASS_WEAPON) + if (proto->GetClass() != ITEM_CLASS_ARMOR && + proto->GetClass() != ITEM_CLASS_WEAPON) return false; - if (proto->Class == ITEM_CLASS_WEAPON && proto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE) + if (proto->GetClass() == ITEM_CLASS_WEAPON && proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_FISHING_POLE) return false; - if (proto->Flags2 & ITEM_FLAG2_IGNORE_QUALITY_FOR_ITEM_VISUAL_SOURCE) + if (proto->GetFlags2() & ITEM_FLAG2_IGNORE_QUALITY_FOR_ITEM_VISUAL_SOURCE) return true; if (!HasStats()) @@ -1205,27 +1205,27 @@ bool Item::CanTransmogrifyItemWithItem(Item const* transmogrified, Item const* t ItemTemplate const* proto1 = transmogrifier->GetTemplate(); // source ItemTemplate const* proto2 = transmogrified->GetTemplate(); // dest - if (proto1->ItemId == proto2->ItemId) + if (proto1->GetId() == proto2->GetId()) return false; if (!transmogrified->CanTransmogrify() || !transmogrifier->CanBeTransmogrified()) return false; - if (proto1->InventoryType == INVTYPE_BAG || - proto1->InventoryType == INVTYPE_RELIC || - proto1->InventoryType == INVTYPE_BODY || - proto1->InventoryType == INVTYPE_FINGER || - proto1->InventoryType == INVTYPE_TRINKET || - proto1->InventoryType == INVTYPE_AMMO || - proto1->InventoryType == INVTYPE_QUIVER) + if (proto1->GetInventoryType() == INVTYPE_BAG || + proto1->GetInventoryType() == INVTYPE_RELIC || + proto1->GetInventoryType() == INVTYPE_BODY || + proto1->GetInventoryType() == INVTYPE_FINGER || + proto1->GetInventoryType() == INVTYPE_TRINKET || + proto1->GetInventoryType() == INVTYPE_AMMO || + proto1->GetInventoryType() == INVTYPE_QUIVER) return false; - if (proto1->SubClass != proto2->SubClass && (proto1->Class != ITEM_CLASS_WEAPON || !proto2->IsRangedWeapon() || !proto1->IsRangedWeapon())) + if (proto1->GetSubClass() != proto2->GetSubClass() && (proto1->GetClass() != ITEM_CLASS_WEAPON || !proto2->IsRangedWeapon() || !proto1->IsRangedWeapon())) return false; - if (proto1->InventoryType != proto2->InventoryType && - (proto1->Class != ITEM_CLASS_WEAPON || (proto2->InventoryType != INVTYPE_WEAPONMAINHAND && proto2->InventoryType != INVTYPE_WEAPONOFFHAND)) && - (proto1->Class != ITEM_CLASS_ARMOR || (proto1->InventoryType != INVTYPE_CHEST && proto2->InventoryType != INVTYPE_ROBE && proto1->InventoryType != INVTYPE_ROBE && proto2->InventoryType != INVTYPE_CHEST))) + if (proto1->GetInventoryType() != proto2->GetInventoryType() && + (proto1->GetClass() != ITEM_CLASS_WEAPON || (proto2->GetInventoryType() != INVTYPE_WEAPONMAINHAND && proto2->GetInventoryType() != INVTYPE_WEAPONOFFHAND)) && + (proto1->GetClass() != ITEM_CLASS_ARMOR || (proto1->GetInventoryType() != INVTYPE_CHEST && proto2->GetInventoryType() != INVTYPE_ROBE && proto1->GetInventoryType() != INVTYPE_ROBE && proto2->GetInventoryType() != INVTYPE_CHEST))) return false; return true; @@ -1238,7 +1238,7 @@ bool Item::HasStats() const ItemTemplate const* proto = GetTemplate(); for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - if (proto->ItemStat[i].ItemStatValue != 0) + if (proto->GetItemStatValue(i) != 0) return true; return false; @@ -1249,14 +1249,14 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) { normalSellPrice = true; - if (proto->Flags2 & ITEM_FLAG2_OVERRIDE_GOLD_COST) + if (proto->GetFlags2() & ITEM_FLAG2_OVERRIDE_GOLD_COST) { - return proto->BuyPrice; + return proto->GetBuyPrice(); } else { - ImportPriceQualityEntry const* qualityPrice = sImportPriceQualityStore.LookupEntry(proto->Quality + 1); - ItemPriceBaseEntry const* basePrice = sItemPriceBaseStore.LookupEntry(proto->ItemLevel); + ImportPriceQualityEntry const* qualityPrice = sImportPriceQualityStore.LookupEntry(proto->GetQuality() + 1); + ItemPriceBaseEntry const* basePrice = sItemPriceBaseStore.LookupEntry(proto->GetBaseItemLevel()); if (!qualityPrice || !basePrice) return 0; @@ -1264,7 +1264,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) float qualityFactor = qualityPrice->Factor; float baseFactor = 0.0f; - uint32 inventoryType = proto->InventoryType; + uint32 inventoryType = proto->GetInventoryType(); if (inventoryType == INVTYPE_WEAPON || inventoryType == INVTYPE_2HWEAPON || @@ -1299,7 +1299,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) if (!armorPrice) return 0; - switch (proto->SubClass) + switch (proto->GetSubClass()) { case ITEM_SUBCLASS_ARMOR_MISCELLANEOUS: case ITEM_SUBCLASS_ARMOR_CLOTH: @@ -1347,7 +1347,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) weapType = 4; break; default: - return proto->BuyPrice; + return proto->GetBuyPrice(); } if (weapType != -1) @@ -1360,7 +1360,7 @@ uint32 Item::GetSellPrice(ItemTemplate const* proto, bool& normalSellPrice) } normalSellPrice = false; - return uint32(qualityFactor * proto->Unk430_2 * proto->Unk430_1 * typeFactor * baseFactor); + return uint32(qualityFactor * proto->GetUnk1() * proto->GetUnk2() * typeFactor * baseFactor); } } @@ -1368,8 +1368,8 @@ uint32 Item::GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice /*= { uint32 cost = 0; - if (proto->Flags2 & ITEM_FLAG2_OVERRIDE_GOLD_COST) - cost = proto->SellPrice; + if (proto->GetFlags2() & ITEM_FLAG2_OVERRIDE_GOLD_COST) + cost = proto->GetSellPrice(); else { bool normalPrice; @@ -1377,19 +1377,19 @@ uint32 Item::GetSpecialPrice(ItemTemplate const* proto, uint32 minimumPrice /*= if (!normalPrice) { - if (proto->BuyCount <= 1) + if (proto->GetBuyCount() <= 1) { - ItemClassEntry const* classEntry = sItemClassStore.LookupEntry(proto->Class); + ItemClassEntry const* classEntry = sItemClassStore.LookupEntry(proto->GetClass()); if (classEntry) cost *= classEntry->PriceModifier; else cost = 0; } else - cost /= 4 * proto->BuyCount; + cost /= 4 * proto->GetBuyCount(); } else - cost = proto->SellPrice; + cost = proto->GetSellPrice(); } if (cost < minimumPrice) @@ -1402,8 +1402,8 @@ int32 Item::GetReforgableStat(ItemModType statType) const { ItemTemplate const* proto = GetTemplate(); for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - if (ItemModType(proto->ItemStat[i].ItemStatType) == statType) - return proto->ItemStat[i].ItemStatValue; + if (ItemModType(proto->GetItemStatType(i)) == statType) + return proto->GetItemStatValue(i); int32 randomPropId = GetItemRandomPropertyId(); if (!randomPropId) diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index a56596c933..51e12c63e8 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -79,8 +79,8 @@ class TC_GAME_API Item : public Object void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND, val); } bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_SOULBOUND); } - bool IsBoundAccountWide() const { return (GetTemplate()->Flags & ITEM_FLAG_IS_BOUND_TO_ACCOUNT) != 0; } - bool IsBattlenetAccountBound() const { return (GetTemplate()->Flags2 & ITEM_FLAG2_BNET_ACCOUNT_TRADE_OK) != 0; } + bool IsBoundAccountWide() const { return (GetTemplate()->GetFlags() & ITEM_FLAG_IS_BOUND_TO_ACCOUNT) != 0; } + bool IsBattlenetAccountBound() const { return (GetTemplate()->GetFlags2() & ITEM_FLAG2_BNET_ACCOUNT_TRADE_OK) != 0; } bool IsBindedNotWith(Player const* player) const; bool IsBoundByEnchant() const; virtual void SaveToDB(SQLTransaction& trans); @@ -97,7 +97,7 @@ class TC_GAME_API Item : public Object Bag const* ToBag() const { if (IsBag()) return reinterpret_cast(this); else return nullptr; } bool IsLocked() const { return !HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_UNLOCKED); } - bool IsBag() const { return GetTemplate()->InventoryType == INVTYPE_BAG; } + bool IsBag() const { return GetTemplate()->GetInventoryType() == INVTYPE_BAG; } bool IsCurrencyToken() const { return GetTemplate()->IsCurrencyToken(); } bool IsNotEmptyBag() const; bool IsBroken() const { return GetUInt32Value(ITEM_FIELD_MAXDURABILITY) > 0 && GetUInt32Value(ITEM_FIELD_DURABILITY) == 0; } @@ -169,13 +169,16 @@ class TC_GAME_API Item : public Object uState = state; } - bool hasQuest(uint32 quest_id) const override { return GetTemplate()->StartQuest == quest_id; } + bool hasQuest(uint32 quest_id) const override { return GetTemplate()->GetStartQuest() == quest_id; } bool hasInvolvedQuest(uint32 /*quest_id*/) const override { return false; } bool HasStats() const; bool IsPotion() const { return GetTemplate()->IsPotion(); } bool IsVellum() const { return GetTemplate()->IsVellum(); } bool IsConjuredConsumable() const { return GetTemplate()->IsConjuredConsumable(); } bool IsRangedWeapon() const { return GetTemplate()->IsRangedWeapon(); } + uint32 GetItemLevel() const { return GetTemplate()->GetBaseItemLevel(); } + uint32 GetDisplayId() const { return GetTemplate()->GetDisplayID(); } + // Item Refund system void SetNotRefundable(Player* owner, bool changestate = true, SQLTransaction* trans = nullptr); diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp index d50179f324..8d05d1eca4 100644 --- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp +++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp @@ -126,20 +126,20 @@ int32 GenerateItemRandomPropertyId(uint32 item_id) return 0; // item must have one from this field values not null if it can have random enchantments - if ((!itemProto->RandomProperty) && (!itemProto->RandomSuffix)) + if ((!itemProto->GetRandomProperty()) && (!itemProto->GetRandomSuffix())) return 0; // item can have not null only one from field values - if ((itemProto->RandomProperty) && (itemProto->RandomSuffix)) + if ((itemProto->GetRandomProperty()) && (itemProto->GetRandomSuffix())) { - TC_LOG_ERROR("sql.sql", "Item template %u have RandomProperty == %u and RandomSuffix == %u, but must have one from field =0", itemProto->ItemId, itemProto->RandomProperty, itemProto->RandomSuffix); + TC_LOG_ERROR("sql.sql", "Item template %u have RandomProperty == %u and RandomSuffix == %u, but must have one from field =0", itemProto->GetId(), itemProto->GetRandomSuffix(), itemProto->GetRandomSuffix()); return 0; } // RandomProperty case - if (itemProto->RandomProperty) + if (itemProto->GetRandomSuffix()) { - uint32 randomPropId = GetItemEnchantMod(itemProto->RandomProperty); + uint32 randomPropId = GetItemEnchantMod(itemProto->GetRandomSuffix()); ItemRandomPropertiesEntry const* random_id = sItemRandomPropertiesStore.LookupEntry(randomPropId); if (!random_id) { @@ -152,7 +152,7 @@ int32 GenerateItemRandomPropertyId(uint32 item_id) // RandomSuffix case else { - uint32 randomPropId = GetItemEnchantMod(itemProto->RandomSuffix); + uint32 randomPropId = GetItemEnchantMod(itemProto->GetRandomSuffix()); ItemRandomSuffixEntry const* random_id = sItemRandomSuffixStore.LookupEntry(randomPropId); if (!random_id) { @@ -170,15 +170,15 @@ uint32 GenerateEnchSuffixFactor(uint32 item_id) if (!itemProto) return 0; - if (!itemProto->RandomSuffix) + if (!itemProto->GetRandomSuffix()) return 0; - RandomPropertiesPointsEntry const* randomProperty = sRandomPropertiesPointsStore.LookupEntry(itemProto->ItemLevel); + RandomPropertiesPointsEntry const* randomProperty = sRandomPropertiesPointsStore.LookupEntry(itemProto->GetBaseItemLevel()); if (!randomProperty) return 0; uint32 suffixFactor; - switch (itemProto->InventoryType) + switch (itemProto->GetInventoryType()) { // Items of that type don`t have points case INVTYPE_NON_EQUIP: @@ -226,7 +226,7 @@ uint32 GenerateEnchSuffixFactor(uint32 item_id) return 0; } // Select rare/epic modifier - switch (itemProto->Quality) + switch (itemProto->GetQuality()) { case ITEM_QUALITY_UNCOMMON: return randomProperty->UncommonPropertiesPoints[suffixFactor]; diff --git a/src/server/game/Entities/Item/ItemTemplate.cpp b/src/server/game/Entities/Item/ItemTemplate.cpp index a014084aa0..eff4ee0eec 100644 --- a/src/server/game/Entities/Item/ItemTemplate.cpp +++ b/src/server/game/Entities/Item/ItemTemplate.cpp @@ -15,11 +15,27 @@ * with this program. If not, see . */ +#include "DBCStores.h" +#include "DB2Stores.h" +#include "World.h" #include "ItemTemplate.h" +char const* ItemTemplate::GetName(LocaleConstant locale) const +{ + if (!strlen(ExtendedData->Name->Str[locale])) + return GetDefaultLocaleName(); + + return ExtendedData->Name->Str[locale]; +} + +char const* ItemTemplate::GetDefaultLocaleName() const +{ + return ExtendedData->Name->Str[sWorld->GetDefaultDbcLocale()]; +} + bool ItemTemplate::CanChangeEquipStateInCombat() const { - switch (InventoryType) + switch (GetInventoryType()) { case INVTYPE_RELIC: case INVTYPE_SHIELD: @@ -27,7 +43,7 @@ bool ItemTemplate::CanChangeEquipStateInCombat() const return true; } - switch (Class) + switch (GetClass()) { case ITEM_CLASS_WEAPON: case ITEM_CLASS_PROJECTILE: @@ -39,8 +55,8 @@ bool ItemTemplate::CanChangeEquipStateInCombat() const float ItemTemplate::GetItemLevelIncludingQuality() const { - float itemLevel(ItemLevel); - switch (Quality) + float itemLevel(GetBaseItemLevel()); + switch (GetQuality()) { case ITEM_QUALITY_POOR: case ITEM_QUALITY_NORMAL: @@ -77,19 +93,19 @@ uint32 ItemTemplate::GetSkill() const 0, SKILL_CLOTH, SKILL_LEATHER, SKILL_MAIL, SKILL_PLATE_MAIL, 0, SKILL_SHIELD, 0, 0, 0, 0 }; - switch (Class) + switch (GetClass()) { case ITEM_CLASS_WEAPON: - if (SubClass >= MAX_ITEM_SUBCLASS_WEAPON) + if (GetSubClass() >= MAX_ITEM_SUBCLASS_WEAPON) return 0; else - return itemWeaponSkills[SubClass]; + return itemWeaponSkills[GetSubClass()]; case ITEM_CLASS_ARMOR: - if (SubClass >= MAX_ITEM_SUBCLASS_ARMOR) + if (GetSubClass() >= MAX_ITEM_SUBCLASS_ARMOR) return 0; else - return itemArmorSkills[SubClass]; + return itemArmorSkills[GetSubClass()]; default: return 0; diff --git a/src/server/game/Entities/Item/ItemTemplate.h b/src/server/game/Entities/Item/ItemTemplate.h index b253b490ba..3270987a0c 100644 --- a/src/server/game/Entities/Item/ItemTemplate.h +++ b/src/server/game/Entities/Item/ItemTemplate.h @@ -18,7 +18,7 @@ #ifndef _ITEMPROTOTYPE_H #define _ITEMPROTOTYPE_H -#include "Common.h" +#include "DB2Structure.h" #include "SharedDefines.h" #include "WorldPacket.h" #include @@ -607,28 +607,14 @@ inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemS #pragma pack(push, 1) -struct _ItemStat +struct ItemEffect { - int32 ItemStatType; - int32 ItemStatValue; - int32 ItemStatAllocation; - int32 ItemStatSocketCostMultiplier; -}; - -struct _Spell -{ - int32 SpellId; // id from Spell.dbc - uint32 SpellTrigger; - int32 SpellCharges; - int32 SpellCooldown; - uint32 SpellCategory; // id from SpellCategory.dbc - int32 SpellCategoryCooldown; -}; - -struct _Socket -{ - uint32 Color; - uint32 Content; + uint32 SpellID; + uint32 Trigger; + int32 Charges; + int32 Cooldown; + uint32 Category; + int32 CategoryCooldown; }; #pragma pack(pop) @@ -640,71 +626,66 @@ struct _Socket struct ItemTemplate { - uint32 ItemId; - uint32 Class; // id from ItemClass.dbc - uint32 SubClass; // id from ItemSubClass.dbc - int32 SoundOverrideSubclass; // < 0: id from ItemSubClass.dbc, used to override weapon sound from actual SubClass - std::string Name1; - uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc - uint32 Quality; - uint32 Flags; - uint32 Flags2; - float Unk430_1; - float Unk430_2; - uint32 BuyCount; - int32 BuyPrice; - uint32 SellPrice; - uint32 InventoryType; - uint32 AllowableClass; - uint32 AllowableRace; - uint32 ItemLevel; - uint32 RequiredLevel; - uint32 RequiredSkill; // id from SkillLine.dbc - uint32 RequiredSkillRank; - uint32 RequiredSpell; // id from Spell.dbc - uint32 RequiredHonorRank; - uint32 RequiredCityRank; - uint32 RequiredReputationFaction; // id from Faction.dbc - uint32 RequiredReputationRank; - int32 MaxCount; // <= 0: no limit - int32 Stackable; // 0: not allowed, -1: put in player coin info tab and don't limit stacking (so 1 slot) - uint32 ContainerSlots; - _ItemStat ItemStat[MAX_ITEM_PROTO_STATS]; - uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc - uint32 DamageType; // id from Resistances.dbc - uint32 Delay; - float RangedModRange; - _Spell Spells[MAX_ITEM_PROTO_SPELLS]; - uint32 Bonding; - std::string Description; - uint32 PageText; - uint32 LanguageID; - uint32 PageMaterial; - uint32 StartQuest; // id from QuestCache.wdb - uint32 LockID; - int32 Material; // id from Material.dbc - uint32 Sheath; - int32 RandomProperty; // id from ItemRandomProperties.dbc - int32 RandomSuffix; // id from ItemRandomSuffix.dbc - uint32 ItemSet; // id from ItemSet.dbc + ItemEntry const* BasicData; + ItemSparseEntry const* ExtendedData; + + uint32 GetId() const { return BasicData->ID; } + uint32 GetClass() const { return BasicData->ClassID; } + uint32 GetDisplayID() const { return BasicData->DisplayInfoID; } + uint32 GetSubClass() const { return BasicData->SubclassID; } + uint32 GetQuality() const { return ExtendedData->Quality; } + uint32 GetFlags() const { return ExtendedData->Flags; } + uint32 GetFlags2() const { return ExtendedData->Flags2; } + float GetUnk1() const { return ExtendedData->Unk1; } + float GetUnk2() const { return ExtendedData->Unk2; } + uint32 GetBuyCount() const { return std::max(ExtendedData->BuyCount, 1u); } + uint32 GetBuyPrice() const { return ExtendedData->BuyPrice; } + uint32 GetSellPrice() const { return ExtendedData->SellPrice; } + uint8 GetInventoryType() const { return uint8(ExtendedData->InventoryType); } + int32 GetAllowableClass() const { return ExtendedData->AllowableClass; } + int32 GetAllowableRace() const { return ExtendedData->AllowableRace; } + uint32 GetBaseItemLevel() const { return ExtendedData->ItemLevel; } + int32 GetRequiredLevel() const { return ExtendedData->RequiredLevel; } + uint32 GetRequiredSkill() const { return ExtendedData->RequiredSkill; } + uint32 GetRequiredSkillRank() const { return ExtendedData->RequiredSkillRank; } + uint32 GetRequiredSpell() const { return ExtendedData->RequiredSpell; } + uint32 GetRequiredReputationFaction() const { return ExtendedData->RequiredReputationFaction; } + uint32 GetRequiredReputationRank() const { return ExtendedData->RequiredReputationRank; } + uint32 GetMaxCount() const { return ExtendedData->MaxCount; } + uint32 GetContainerSlots() const { return ExtendedData->ContainerSlots; } + int32 GetItemStatType(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->ItemStatType[index]; } + int32 GetItemStatValue(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->ItemStatValue[index]; } + int32 GetItemStatAllocation(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->ItemStatAllocation[index]; } + float GetItemStatSocketCostMultiplier(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_STATS); return ExtendedData->ItemStatSocketCostMultiplier[index]; } + uint32 GetScalingStatDistribution() const { return ExtendedData->ScalingStatDistribution; } + uint32 GetDamageType() const { return ExtendedData->DamageType; } + uint32 GetDelay() const { return ExtendedData->Delay; } + ItemBondingType GetBonding() const { return ItemBondingType(ExtendedData->Bonding); } + char const* GetName(LocaleConstant locale) const; + uint32 GetPageText() const { return ExtendedData->PageText; } + uint32 GetStartQuest() const { return ExtendedData->StartQuest; } + uint32 GetLockID() const { return ExtendedData->LockID; } + uint32 GetRandomProperty() const { return ExtendedData->RandomProperty; } + uint32 GetRandomSuffix() const { return ExtendedData->RandomSuffix; } + uint32 GetItemSet() const { return ExtendedData->ItemSet; } + uint32 GetArea() const { return ExtendedData->Area; } + uint32 GetMap() const { return ExtendedData->Map; } + uint32 GetBagFamily() const { return ExtendedData->BagFamily; } + SocketColor GetSocketColor(uint32 index) const { ASSERT(index < MAX_ITEM_PROTO_SOCKETS); return SocketColor(ExtendedData->SocketColor[index]); } + uint32 GetSocketBonus() const { return ExtendedData->SocketBonus; } + uint32 GetGemProperties() const { return ExtendedData->GemProperties; } + float GetArmorDamageModifier() const { return ExtendedData->ArmorDamageModifier; } + uint32 GetDuration() const { return ExtendedData->Duration; } + uint32 GetItemLimitCategory() const { return ExtendedData->ItemLimitCategory; } + HolidayIds GetHolidayID() const { return HolidayIds(ExtendedData->HolidayID); } + float GetStatScalingFactor() const { return ExtendedData->StatScalingFactor; } + uint32 GetTotemCategory() const { return ExtendedData->TotemCategory; } + float GetRangedModRange() const { return ExtendedData->RangedModRange; } + uint32 MaxDurability; - uint32 Area; // id from AreaTable.dbc - uint32 Map; // id from Map.dbc - uint32 BagFamily; // bit mask (1 << id from ItemBagFamily.dbc) - uint32 TotemCategory; // id from TotemCategory.dbc - _Socket Socket[MAX_ITEM_PROTO_SOCKETS]; - uint32 socketBonus; // id from SpellItemEnchantment.dbc - uint32 GemProperties; // id from GemProperties.dbc - float ArmorDamageModifier; - uint32 Duration; - uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc - uint32 HolidayId; // id from Holidays.dbc - float StatScalingFactor; - uint32 CurrencySubstitutionId; // May be used instead of a currency - uint32 CurrencySubstitutionCount; + std::vector Effects; // extra fields, not part of db2 files - float SpellPPMRate; uint32 ScriptId; uint32 DisenchantID; uint32 RequiredDisenchantSkill; @@ -712,42 +693,38 @@ struct ItemTemplate uint32 MinMoneyLoot; uint32 MaxMoneyLoot; uint32 FlagsCu; + float SpellPPMRate; // helpers bool CanChangeEquipStateInCombat() const; - bool IsCurrencyToken() const { return (BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) != 0; } + bool IsCurrencyToken() const { return (GetBagFamily() & BAG_FAMILY_MASK_CURRENCY_TOKENS) != 0; } uint32 GetMaxStackSize() const { - return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF-1) : uint32(Stackable); + return (ExtendedData->Stackable == 2147483647 || ExtendedData->Stackable <= 0) ? uint32(0x7FFFFFFF - 1) : uint32(ExtendedData->Stackable); } float GetItemLevelIncludingQuality() const; uint32 GetSkill() const; - bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; } - bool IsVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_ENCHANTMENT; } - bool IsConjuredConsumable() const { return Class == ITEM_CLASS_CONSUMABLE && (Flags & ITEM_FLAG_CONJURED); } + bool IsPotion() const { return GetClass() == ITEM_CLASS_CONSUMABLE && GetSubClass() == ITEM_SUBCLASS_POTION; } + bool IsVellum() const { return GetClass() == ITEM_CLASS_TRADE_GOODS && GetSubClass() == ITEM_SUBCLASS_ENCHANTMENT; } + bool IsConjuredConsumable() const { return GetClass() == ITEM_CLASS_CONSUMABLE && (GetFlags() & ITEM_FLAG_CONJURED); } bool IsRangedWeapon() const { - return Class == ITEM_CLASS_WEAPON || - SubClass == ITEM_SUBCLASS_WEAPON_BOW || - SubClass == ITEM_SUBCLASS_WEAPON_GUN || - SubClass == ITEM_SUBCLASS_WEAPON_CROSSBOW; + return GetClass() == ITEM_CLASS_WEAPON || + GetSubClass() == ITEM_SUBCLASS_WEAPON_BOW || + GetSubClass() == ITEM_SUBCLASS_WEAPON_GUN || + GetSubClass() == ITEM_SUBCLASS_WEAPON_CROSSBOW; } + char const* GetDefaultLocaleName() const; uint32 GetStatValue(uint32 index, Player const* owner = nullptr) const; uint32 GetEffectiveArmor(Player const* owner) const; bool GetWeaponDamage(Player const* owner, float& minValue, float& maxValue, float& dps) const; }; -struct ItemLocale -{ - std::vector Name; - std::vector Description; -}; - #endif diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 92c80ffc0b..ca3867f970 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -598,19 +598,22 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo continue; // BuyCount by default - uint32 count = iProto->BuyCount; + uint32 count = iProto->GetBuyCount(); // special amount for food/drink - if (iProto->Class == ITEM_CLASS_CONSUMABLE && iProto->SubClass == ITEM_SUBCLASS_FOOD) + if (iProto->GetClass() == ITEM_CLASS_CONSUMABLE && iProto->GetSubClass() == ITEM_SUBCLASS_FOOD) { - switch (iProto->Spells[0].SpellCategory) + if (iProto->Effects.size() >= 1) { - case SPELL_CATEGORY_FOOD: // food - count = getClass() == CLASS_DEATH_KNIGHT ? 10 : 4; - break; - case SPELL_CATEGORY_DRINK: // drink - count = 2; - break; + switch (iProto->Effects[0].Category) + { + case SPELL_CATEGORY_FOOD: // food + count = getClass() == CLASS_DEATH_KNIGHT ? 10 : 4; + break; + case SPELL_CATEGORY_DRINK: // drink + count = 2; + break; + } } if (iProto->GetMaxStackSize() < count) count = iProto->GetMaxStackSize(); @@ -4626,8 +4629,8 @@ Corpse* Player::CreateCorpse() { if (m_items[i]) { - iDisplayID = m_items[i]->GetTemplate()->DisplayInfoID; - iIventoryType = m_items[i]->GetTemplate()->InventoryType; + iDisplayID = m_items[i]->GetDisplayId(); + iIventoryType = m_items[i]->GetTemplate()->GetInventoryType(); _cfi = iDisplayID | (iIventoryType << 24); corpse->SetUInt32Value(CORPSE_FIELD_ITEM + i, _cfi); @@ -4796,24 +4799,24 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g { ItemTemplate const* ditemProto = item->GetTemplate(); - DurabilityCostsEntry const* dcost = sDurabilityCostsStore.LookupEntry(ditemProto->ItemLevel); + DurabilityCostsEntry const* dcost = sDurabilityCostsStore.LookupEntry(ditemProto->GetBaseItemLevel()); if (!dcost) { TC_LOG_ERROR("entities.player.items", "Player::DurabilityRepair: Player '%s' (%s) tried to repair an item (ItemID: %u) with invalid item level %u", - GetName().c_str(), GetGUID().ToString().c_str(), ditemProto->ItemId, ditemProto->ItemLevel); + GetName().c_str(), GetGUID().ToString().c_str(), ditemProto->GetId(), ditemProto->GetBaseItemLevel()); return TotalCost; } - uint32 dQualitymodEntryId = (ditemProto->Quality+1)*2; + uint32 dQualitymodEntryId = (ditemProto->GetQuality() + 1) * 2; DurabilityQualityEntry const* dQualitymodEntry = sDurabilityQualityStore.LookupEntry(dQualitymodEntryId); if (!dQualitymodEntry) { TC_LOG_ERROR("entities.player.items", "Player::DurabilityRepair: Player '%s' (%s) tried to repair an item (ItemID: %u) with invalid QualitymodEntry %u", - GetName().c_str(), GetGUID().ToString().c_str(), ditemProto->ItemId, dQualitymodEntryId); + GetName().c_str(), GetGUID().ToString().c_str(), ditemProto->GetId(), dQualitymodEntryId); return TotalCost; } - uint32 dmultiplier = dcost->Multiplier[ItemSubClassToDurabilityMultiplierId(ditemProto->Class, ditemProto->SubClass)]; + uint32 dmultiplier = dcost->Multiplier[ItemSubClassToDurabilityMultiplierId(ditemProto->GetClass(), ditemProto->GetSubClass())]; uint32 costs = uint32(LostDurability*dmultiplier*double(dQualitymodEntry->Data)); costs = uint32(costs * discountMod * sWorld->getRate(RATE_REPAIRCOST)); @@ -5382,8 +5385,8 @@ void Player::SetRegularAttackTime() if (tmpitem && !tmpitem->IsBroken()) { ItemTemplate const* proto = tmpitem->GetTemplate(); - if (proto->Delay) - SetAttackTime(WeaponAttackType(i), proto->Delay); + if (proto->GetDelay()) + SetAttackTime(WeaponAttackType(i), proto->GetDelay()); } else SetAttackTime(WeaponAttackType(i), BASE_ATTACK_TIME); // If there is no weapon reset attack time to base (might have been changed from forms) @@ -7634,7 +7637,7 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply, bool updateItemA TC_LOG_DEBUG("entities.player.items", "Player::_ApplyItemMods: Applying mods for item %s", item->GetGUID().ToString().c_str()); - if (proto->Socket[0].Color) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items + if (proto->GetSocketColor(0)) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items CorrectMetaGemEnchants(slot, apply); _ApplyItemBonuses(proto, slot, apply); @@ -7652,7 +7655,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply if (slot >= INVENTORY_SLOT_BAG_END || !proto) return; - ScalingStatDistributionEntry const* ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : nullptr; + ScalingStatDistributionEntry const* ssd = proto->GetScalingStatDistribution() ? sScalingStatDistributionStore.LookupEntry(proto->GetScalingStatDistribution()) : nullptr; if (only_level_scale && !ssd) return; @@ -7667,7 +7670,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) { - int32 statID = proto->ItemStat[i].ItemStatType; + int32 statID = proto->GetItemStatType(i); if ((statID < 0 && !ssd) || (statID < 0 && ssd && ssd->StatID[i] < 0)) continue; @@ -7841,21 +7844,21 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply } // Apply Spell Power from ScalingStatValue if set - if (ssv && proto->Flags2 & ITEM_FLAG2_CASTER_WEAPON) + if (ssv && proto->GetFlags2() & ITEM_FLAG2_CASTER_WEAPON) if (int32 spellbonus = int32(ssv->Spellpower)) ApplySpellPowerBonus(spellbonus, apply); // If set ScalingStatValue armor get it or use item armor uint32 armor = proto->GetEffectiveArmor(this); - if (ssv && proto->Class == ITEM_CLASS_ARMOR) - armor = ssv->GetArmor(proto->InventoryType, proto->SubClass - 1); + if (ssv && proto->GetClass() == ITEM_CLASS_ARMOR) + armor = ssv->GetArmor(proto->GetInventoryType(), proto->GetSubClass() - 1); if (armor) { UnitModifierType modType = TOTAL_VALUE; - if (proto->Class == ITEM_CLASS_ARMOR) + if (proto->GetClass() == ITEM_CLASS_ARMOR) { - switch (proto->SubClass) + switch (proto->GetSubClass()) { case ITEM_SUBCLASS_ARMOR_CLOTH: case ITEM_SUBCLASS_ARMOR_LEATHER: @@ -7870,14 +7873,14 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply } // Add armor bonus from ArmorDamageModifier if > 0 - if (proto->ArmorDamageModifier > 0) - HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply); + if (proto->GetArmorDamageModifier() > 0) + HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->GetArmorDamageModifier()), apply); WeaponAttackType attType = BASE_ATTACK; if (slot == EQUIPMENT_SLOT_RANGED && ( - proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN || - proto->InventoryType == INVTYPE_RANGEDRIGHT)) + proto->GetInventoryType() == INVTYPE_RANGED || proto->GetInventoryType() == INVTYPE_THROWN || + proto->GetInventoryType() == INVTYPE_RANGEDRIGHT)) { attType = RANGED_ATTACK; } @@ -7896,8 +7899,8 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt float damage = 0.0f; if (slot == EQUIPMENT_SLOT_RANGED && ( - proto->InventoryType == INVTYPE_RANGED || proto->InventoryType == INVTYPE_THROWN || - proto->InventoryType == INVTYPE_RANGEDRIGHT)) + proto->GetInventoryType() == INVTYPE_RANGED || proto->GetInventoryType() == INVTYPE_THROWN || + proto->GetInventoryType() == INVTYPE_RANGEDRIGHT)) { attType = RANGED_ATTACK; } @@ -7914,10 +7917,10 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt if (ssv) { float damageMultiplier = 0.0f; - extraDPS = ssv->GetDPSAndDamageMultiplier(proto->SubClass, (proto->Flags2 & ITEM_FLAG2_CASTER_WEAPON) != 0, &damageMultiplier); + extraDPS = ssv->GetDPSAndDamageMultiplier(proto->GetSubClass(), (proto->GetFlags2() & ITEM_FLAG2_CASTER_WEAPON) != 0, &damageMultiplier); if (extraDPS) { - float average = extraDPS * proto->Delay / 1000.0f; + float average = extraDPS * proto->GetDelay() / 1000.0f; minDamage = (1.0f - damageMultiplier) * average; maxDamage = (1.0f + damageMultiplier) * average; } @@ -7935,17 +7938,17 @@ void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingSt SetBaseWeaponDamage(attType, MAXDAMAGE, damage); } - if (proto->Delay && !IsInFeralForm()) + if (proto->GetDelay() && !IsInFeralForm()) { if (slot == EQUIPMENT_SLOT_RANGED) - SetAttackTime(RANGED_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); + SetAttackTime(RANGED_ATTACK, apply ? proto->GetDelay() : BASE_ATTACK_TIME); else if (slot == EQUIPMENT_SLOT_MAINHAND) - SetAttackTime(BASE_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); + SetAttackTime(BASE_ATTACK, apply ? proto->GetDelay() : BASE_ATTACK_TIME); else if (slot == EQUIPMENT_SLOT_OFFHAND) - SetAttackTime(OFF_ATTACK, apply ? proto->Delay: BASE_ATTACK_TIME); + SetAttackTime(OFF_ATTACK, apply ? proto->GetDelay() : BASE_ATTACK_TIME); } - if (CanModifyStats() && (damage || proto->Delay)) + if (CanModifyStats() && (damage || proto->GetDelay())) UpdateDamagePhysical(attType); } @@ -7970,13 +7973,14 @@ void Player::CastAllObtainSpells() void Player::ApplyItemObtainSpells(Item* item, bool apply) { ItemTemplate const* itemTemplate = item->GetTemplate(); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + + for (ItemEffect const& effect : itemTemplate->Effects) { - if (itemTemplate->Spells[i].SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) // On obtain trigger + if (effect.Trigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) // On obtain trigger continue; - int32 const spellId = itemTemplate->Spells[i].SpellId; - if (spellId <= 0) + int32 spellId = effect.SpellID; + if (!spellId) continue; if (apply) @@ -8020,20 +8024,18 @@ void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change) if (!proto) return; - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (ItemEffect const& effect : proto->Effects) { - _Spell const& spellData = proto->Spells[i]; - // no spell - if (spellData.SpellId <= 0) + if (effect.SpellID <= 0) continue; // wrong triggering type - if (apply && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP) + if (apply && effect.Trigger != ITEM_SPELLTRIGGER_ON_EQUIP) continue; // check if it is valid spell - SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(spellData.SpellId); + SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(effect.SpellID); if (!spellproto) continue; @@ -8124,7 +8126,7 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo) if (ItemTemplate const* proto = item->GetTemplate()) { // Additional check for weapons - if (proto->Class == ITEM_CLASS_WEAPON) + if (proto->GetClass() == ITEM_CLASS_WEAPON) { // offhand item cannot proc from main hand hit etc EquipmentSlots slot; @@ -8165,23 +8167,21 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT bool canTrigger = (damageInfo.GetHitMask() & (PROC_HIT_NORMAL | PROC_HIT_CRITICAL | PROC_HIT_ABSORB)) != 0; if (canTrigger) { - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (ItemEffect const& effect : proto->Effects) { - _Spell const& spellData = proto->Spells[i]; - // no spell - if (spellData.SpellId <= 0) + if (effect.SpellID <= 0) continue; // wrong triggering type - if (spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) + if (effect.Trigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) continue; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellData.SpellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect.SpellID); if (!spellInfo) { TC_LOG_ERROR("entities.player.items", "Player::CastItemCombatSpell: Player '%s' (%s) cast unknown item spell (ID: %i)", - GetName().c_str(), GetGUID().ToString().c_str(), spellData.SpellId); + GetName().c_str(), GetGUID().ToString().c_str(), effect.SpellID); continue; } @@ -8247,7 +8247,7 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT if (entry) { if (entry->PPMChance) - chance = GetPPMProcChance(proto->Delay, entry->PPMChance, spellInfo); + chance = GetPPMProcChance(proto->GetDelay(), entry->PPMChance, spellInfo); else if (entry->customChance) chance = (float)entry->customChance; } @@ -8274,15 +8274,15 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 { ItemTemplate const* proto = item->GetTemplate(); // special learning case - if (proto->Spells[0].SpellId == 483 || proto->Spells[0].SpellId == 55884) + if (proto->Effects[0].SpellID == 483 || proto->Effects[0].SpellID == 55884) { - uint32 learn_spell_id = proto->Spells[0].SpellId; - uint32 learning_spell_id = proto->Spells[1].SpellId; + uint32 learn_spell_id = proto->Effects[0].SpellID; + uint32 learning_spell_id = proto->Effects[1].SpellID; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(learn_spell_id); if (!spellInfo) { - TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) has wrong spell id %u, ignoring.", proto->ItemId, learn_spell_id); + TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) has wrong spell id %u, ignoring.", proto->GetId(), learn_spell_id); SendEquipError(EQUIP_ERR_INTERNAL_BAG_ERROR, item, nullptr); return; } @@ -8295,23 +8295,20 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 return; } - // item spells cast at use - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (ItemEffect const& effect : proto->Effects) { - _Spell const& spellData = proto->Spells[i]; - // no spell - if (spellData.SpellId <= 0) + if (effect.SpellID <= 0) continue; // wrong triggering type - if (spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + if (effect.Trigger != ITEM_SPELLTRIGGER_ON_USE) continue; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellData.SpellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect.SpellID); if (!spellInfo) { - TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) has wrong spell id %u, ignoring", proto->ItemId, spellData.SpellId); + TC_LOG_ERROR("entities.player", "Player::CastItemUseSpell: Item (Entry: %u) has wrong spell id %u, ignoring", proto->GetId(), effect.SpellID); continue; } @@ -8368,7 +8365,7 @@ void Player::_RemoveAllItemMods() continue; // item set bonuses not dependent from item broken state - if (proto->ItemSet) + if (proto->GetItemSet()) RemoveItemsSetItem(this, proto); if (m_items[i]->IsBroken() || !CanUseAttackType(GetAttackBySlot(i))) @@ -8426,7 +8423,7 @@ void Player::_ApplyAllItemMods() continue; // item set bonuses not dependent from item broken state - if (proto->ItemSet) + if (proto->GetItemSet()) AddItemsSetItem(this, m_items[i]); if (m_items[i]->IsBroken() || !CanUseAttackType(GetAttackBySlot(i))) @@ -9699,7 +9696,7 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c slots[1] = NULL_SLOT; slots[2] = NULL_SLOT; slots[3] = NULL_SLOT; - switch (proto->InventoryType) + switch (proto->GetInventoryType()) { case INVTYPE_HEAD: slots[0] = EQUIPMENT_SLOT_HEAD; @@ -9767,7 +9764,7 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c { if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate()) { - if (mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF) + if (mhWeaponProto->GetSubClass() == ITEM_SUBCLASS_WEAPON_POLEARM || mhWeaponProto->GetSubClass() == ITEM_SUBCLASS_WEAPON_STAFF) { const_cast(this)->AutoUnequipOffhandIfNeed(true); break; @@ -9777,13 +9774,13 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c if (GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) { - if (proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF) + if (proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_POLEARM || proto->GetSubClass() == ITEM_SUBCLASS_WEAPON_STAFF) { const_cast(this)->AutoUnequipOffhandIfNeed(true); break; } } - if (CanDualWield() && CanTitanGrip() && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF) + if (CanDualWield() && CanTitanGrip() && proto->GetSubClass() != ITEM_SUBCLASS_WEAPON_POLEARM && proto->GetSubClass() != ITEM_SUBCLASS_WEAPON_STAFF) slots[1] = EQUIPMENT_SLOT_OFFHAND; break; case INVTYPE_TABARD: @@ -9905,10 +9902,10 @@ uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const if (Bag* pBag = GetBagByPos(i)) count += pBag->GetItemCount(item, skipItem); - if (skipItem && skipItem->GetTemplate()->GemProperties) + if (skipItem && skipItem->GetTemplate()->GetGemProperties()) for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) - if (pItem != skipItem && pItem->GetTemplate()->Socket[0].Color) + if (pItem != skipItem && pItem->GetTemplate()->GetSocketColor(0)) count += pItem->GetGemCountWithID(item); if (inBankAlso) @@ -9923,10 +9920,10 @@ uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const if (Bag* pBag = GetBagByPos(i)) count += pBag->GetItemCount(item, skipItem); - if (skipItem && skipItem->GetTemplate()->GemProperties) + if (skipItem && skipItem->GetTemplate()->GetGemProperties()) for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i) if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) - if (pItem != skipItem && pItem->GetTemplate()->Socket[0].Color) + if (pItem != skipItem && pItem->GetTemplate()->GetSocketColor(0)) count += pItem->GetGemCountWithID(item); } @@ -9940,7 +9937,7 @@ uint32 Player::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipIte if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pItem != skipItem) if (ItemTemplate const* pProto = pItem->GetTemplate()) - if (pProto->ItemLimitCategory == limitCategory) + if (pProto->GetItemLimitCategory() == limitCategory) count += pItem->GetCount(); for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) @@ -9951,7 +9948,7 @@ uint32 Player::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipIte if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pItem != skipItem) if (ItemTemplate const* pProto = pItem->GetTemplate()) - if (pProto->ItemLimitCategory == limitCategory) + if (pProto->GetItemLimitCategory() == limitCategory) count += pItem->GetCount(); for (int i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i) @@ -10039,7 +10036,7 @@ Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable /*= f item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, slot); else item = GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - if (!item || item->GetTemplate()->Class != ITEM_CLASS_WEAPON) + if (!item || item->GetTemplate()->GetClass() != ITEM_CLASS_WEAPON) return nullptr; if (!useable) @@ -10058,7 +10055,7 @@ Item* Player::GetShield(bool useable) const item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); else item = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); - if (!item || item->GetTemplate()->Class != ITEM_CLASS_ARMOR) + if (!item || item->GetTemplate()->GetClass() != ITEM_CLASS_ARMOR) return nullptr; if (!useable) @@ -10255,7 +10252,7 @@ bool Player::HasItemOrGemWithIdEquipped(uint32 item, uint32 count, uint8 except_ } ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item); - if (pProto && pProto->GemProperties) + if (pProto && pProto->GetGemProperties()) { for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) { @@ -10263,7 +10260,7 @@ bool Player::HasItemOrGemWithIdEquipped(uint32 item, uint32 count, uint8 except_ continue; Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i); - if (pItem && pItem->GetTemplate()->Socket[0].Color) + if (pItem && pItem->GetTemplate()->GetSocketColor(0)) { tempcount += pItem->GetGemCountWithID(item); if (tempcount >= count) @@ -10291,7 +10288,7 @@ bool Player::HasItemWithLimitCategoryEquipped(uint32 limitCategory, uint32 count if (!pProto) continue; - if (pProto->ItemLimitCategory == limitCategory) + if (pProto->GetItemLimitCategory() == limitCategory) { tempcount += pItem->GetCount(); if (tempcount >= count) @@ -10318,7 +10315,7 @@ bool Player::HasGemWithLimitCategoryEquipped(uint32 limitCategory, uint32 count, if (!pProto) continue; - if (pProto->Socket[0].Color || pItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) + if (pProto->GetSocketColor(0) || pItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) { tempcount += pItem->GetGemCountWithLimitCategory(limitCategory); if (tempcount >= count) @@ -10343,24 +10340,24 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item return EQUIP_ERR_LOOT_GONE; // no maximum - if ((pProto->MaxCount <= 0 && pProto->ItemLimitCategory == 0) || pProto->MaxCount == 2147483647) + if ((pProto->GetMaxCount() <= 0 && pProto->GetItemLimitCategory() == 0) || pProto->GetMaxCount() == 2147483647) return EQUIP_ERR_OK; - if (pProto->MaxCount > 0) + if (pProto->GetMaxCount() > 0) { - uint32 curcount = GetItemCount(pProto->ItemId, true, pItem); - if (curcount + count > uint32(pProto->MaxCount)) + uint32 curcount = GetItemCount(pProto->GetId(), true, pItem); + if (curcount + count > uint32(pProto->GetMaxCount())) { if (no_space_count) - *no_space_count = count + curcount - pProto->MaxCount; + *no_space_count = count + curcount - pProto->GetMaxCount(); return EQUIP_ERR_ITEM_MAX_COUNT; } } // check unique-equipped limit - if (pProto->ItemLimitCategory) + if (pProto->GetItemLimitCategory()) { - ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(pProto->ItemLimitCategory); + ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(pProto->GetItemLimitCategory()); if (!limitEntry) { if (no_space_count) @@ -10370,13 +10367,13 @@ InventoryResult Player::CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item if (limitEntry->Flags == ITEM_LIMIT_CATEGORY_MODE_HAVE) { - uint32 curcount = GetItemCountWithLimitCategory(pProto->ItemLimitCategory, pItem); + uint32 curcount = GetItemCountWithLimitCategory(pProto->GetItemLimitCategory(), pItem); if (curcount + count > uint32(limitEntry->Quantity)) { if (no_space_count) *no_space_count = count + curcount - limitEntry->Quantity; if (itemLimitCategory) - *itemLimitCategory = pProto->ItemLimitCategory; + *itemLimitCategory = pProto->GetItemLimitCategory(); return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED_IS; } } @@ -10409,7 +10406,7 @@ bool Player::HasItemTotemCategory(uint32 TotemCategory) const for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) { item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i); - if (item && IsTotemCategoryCompatibleWith(item->GetTemplate()->TotemCategory, TotemCategory)) + if (item && IsTotemCategoryCompatibleWith(item->GetTemplate()->GetTotemCategory(), TotemCategory)) return true; } @@ -10422,7 +10419,7 @@ bool Player::HasItemTotemCategory(uint32 TotemCategory) const for (uint32 j = 0; j < bag->GetBagSize(); ++j) { item = GetUseableItemByPos(i, j); - if (item && IsTotemCategoryCompatibleWith(item->GetTemplate()->TotemCategory, TotemCategory)) + if (item && IsTotemCategoryCompatibleWith(item->GetTemplate()->GetTotemCategory(), TotemCategory)) return true; } } @@ -10463,7 +10460,7 @@ InventoryResult Player::CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemP if (!pBagProto) return EQUIP_ERR_WRONG_BAG_TYPE; - if (slot >= pBagProto->ContainerSlots) + if (slot >= pBagProto->GetContainerSlots()) return EQUIP_ERR_WRONG_BAG_TYPE; if (!ItemCanGoIntoBag(pProto, pBagProto)) @@ -10516,7 +10513,7 @@ InventoryResult Player::CanStoreItem_InBag(uint8 bag, ItemPosCountVec &dest, Ite return EQUIP_ERR_WRONG_BAG_TYPE; // specialized bag mode or non-specilized - if (non_specialized != (pBagProto->Class == ITEM_CLASS_CONTAINER && pBagProto->SubClass == ITEM_SUBCLASS_CONTAINER)) + if (non_specialized != (pBagProto->GetClass() == ITEM_CLASS_CONTAINER && pBagProto->GetSubClass() == ITEM_SUBCLASS_CONTAINER)) return EQUIP_ERR_WRONG_BAG_TYPE; if (!ItemCanGoIntoBag(pProto, pBagProto)) @@ -10688,7 +10685,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des if (bag != NULL_BAG) { // search stack in bag for merge to - if (pProto->Stackable != 1) + if (pProto->GetMaxStackSize() != 1) { if (bag == INVENTORY_SLOT_BAG_0) // inventory { @@ -10785,7 +10782,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des // not specific bag or have space for partly store only in specific bag // search stack for merge to - if (pProto->Stackable != 1) + if (pProto->GetMaxStackSize() != 1) { res = CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START, INVENTORY_SLOT_ITEM_END, dest, pProto, count, true, pItem, bag, slot); if (res != EQUIP_ERR_OK) @@ -10805,7 +10802,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des return EQUIP_ERR_ITEM_MAX_COUNT; } - if (pProto->BagFamily) + if (pProto->GetBagFamily()) { for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { @@ -10844,7 +10841,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des } // search free slot - special bag case - if (pProto->BagFamily) + if (pProto->GetBagFamily()) { for (uint32 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { @@ -10870,8 +10867,8 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des // search free slot uint8 searchSlotStart = INVENTORY_SLOT_ITEM_START; // new bags can be directly equipped - if (!pItem && pProto->Class == ITEM_CLASS_CONTAINER && pProto->SubClass == ITEM_SUBCLASS_CONTAINER && - (pProto->Bonding == BIND_NONE || pProto->Bonding == BIND_ON_ACQUIRE)) + if (!pItem && pProto->GetClass() == ITEM_CLASS_CONTAINER && pProto->GetSubClass() == ITEM_SUBCLASS_CONTAINER && + (pProto->GetBonding() == BIND_NONE || pProto->GetBonding() == BIND_ON_ACQUIRE)) searchSlotStart = INVENTORY_SLOT_BAG_START; res = CanStoreItem_InInventorySlots(searchSlotStart, INVENTORY_SLOT_ITEM_END, dest, pProto, count, false, pItem, bag, slot); @@ -10975,7 +10972,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit return res; // search stack for merge to - if (pProto->Stackable != 1) + if (pProto->GetMaxStackSize() != 1) { bool b_found = false; @@ -11016,7 +11013,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit } // special bag case - if (pProto->BagFamily) + if (pProto->GetBagFamily()) { bool b_found = false; @@ -11027,7 +11024,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit pBagProto = bag->GetTemplate(); // not plain container check - if (pBagProto && (pBagProto->Class != ITEM_CLASS_CONTAINER || pBagProto->SubClass != ITEM_SUBCLASS_CONTAINER) && + if (pBagProto && (pBagProto->GetClass() != ITEM_CLASS_CONTAINER || pBagProto->GetSubClass() != ITEM_SUBCLASS_CONTAINER) && ItemCanGoIntoBag(pProto, pBagProto)) { for (uint32 j = 0; j < bag->GetBagSize(); j++) @@ -11068,7 +11065,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit pBagProto = bag->GetTemplate(); // special bag already checked - if (pBagProto && (pBagProto->Class != ITEM_CLASS_CONTAINER || pBagProto->SubClass != ITEM_SUBCLASS_CONTAINER)) + if (pBagProto && (pBagProto->GetClass() != ITEM_CLASS_CONTAINER || pBagProto->GetSubClass() != ITEM_SUBCLASS_CONTAINER)) continue; for (uint32 j = 0; j < bag->GetBagSize(); j++) @@ -11149,14 +11146,14 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool return EQUIP_ERR_NOT_DURING_ARENA_MATCH; } - if (IsInCombat()&& (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer != 0) + if (IsInCombat()&& (pProto->GetClass() == ITEM_CLASS_WEAPON || pProto->GetInventoryType() == INVTYPE_RELIC) && m_weaponChangeTimer != 0) return EQUIP_ERR_CLIENT_LOCKED_OUT; // maybe exist better err if (IsNonMeleeSpellCast(false)) return EQUIP_ERR_CLIENT_LOCKED_OUT; } - ScalingStatDistributionEntry const* ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0; + ScalingStatDistributionEntry const* ssd = pProto->GetScalingStatDistribution() ? sScalingStatDistributionStore.LookupEntry(pProto->GetScalingStatDistribution()) : 0; // check allowed level (extend range to upper values if MaxLevel more or equal max player level, this let GM set high level with 1...max range items) if (ssd && ssd->Maxlevel < DEFAULT_MAX_LEVEL && ssd->Maxlevel < getLevel()) return EQUIP_ERR_NOT_EQUIPPABLE; @@ -11207,22 +11204,22 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool return res2; // check unique-equipped special item classes - if (pProto->Class == ITEM_CLASS_QUIVER) + if (pProto->GetClass() == ITEM_CLASS_QUIVER) for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) if (Item* pBag = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pBag != pItem) if (ItemTemplate const* pBagProto = pBag->GetTemplate()) - if (pBagProto->Class == pProto->Class && (!swap || pBag->GetSlot() != eslot)) - return (pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH) + if (pBagProto->GetClass() == pProto->GetClass() && (!swap || pBag->GetSlot() != eslot)) + return (pBagProto->GetSubClass() == ITEM_SUBCLASS_AMMO_POUCH) ? EQUIP_ERR_ONLY_ONE_AMMO : EQUIP_ERR_ONLY_ONE_QUIVER; - uint32 type = pProto->InventoryType; + uint32 type = pProto->GetInventoryType(); if (eslot == EQUIPMENT_SLOT_OFFHAND) { // Do not allow polearm to be equipped in the offhand (rare case for the only 1h polearm 41750) - if (type == INVTYPE_WEAPON && pProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM) + if (type == INVTYPE_WEAPON && pProto->GetSubClass() == ITEM_SUBCLASS_WEAPON_POLEARM) return EQUIP_ERR_2HSKILLNOTFOUND; else if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND) { @@ -11335,7 +11332,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest if (pItem->IsCurrencyToken()) { TC_LOG_INFO("entities.player.cheat", "Possible hacking attempt: Player %s (%s) tried to move token [%s entry: %u] out of the currency bag!", - GetName().c_str(), GetGUID().ToString().c_str(), pItem->GetGUID().ToString().c_str(), pProto->ItemId); + GetName().c_str(), GetGUID().ToString().c_str(), pItem->GetGUID().ToString().c_str(), pProto->GetId()); return EQUIP_ERR_CANT_SWAP; } @@ -11377,7 +11374,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest return EQUIP_ERR_BAG_IN_BAG; // search stack in bag for merge to - if (pProto->Stackable != 1) + if (pProto->GetMaxStackSize() != 1) { if (bag == INVENTORY_SLOT_BAG_0) { @@ -11429,7 +11426,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest // not specific bag or have space for partly store only in specific bag // search stack for merge to - if (pProto->Stackable != 1) + if (pProto->GetMaxStackSize() != 1) { // in slots res = CanStoreItem_InInventorySlots(BANK_SLOT_ITEM_START, BANK_SLOT_ITEM_END, dest, pProto, count, true, pItem, bag, slot); @@ -11440,7 +11437,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest return EQUIP_ERR_OK; // in special bags - if (pProto->BagFamily) + if (pProto->GetBagFamily()) { for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) { @@ -11465,7 +11462,7 @@ InventoryResult Player::CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec &dest } // search free place in special bag - if (pProto->BagFamily) + if (pProto->GetBagFamily()) { for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) { @@ -11526,7 +11523,7 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const bool allowEquip = false; uint32 itemSkill = pItem->GetSkill(); // Armor that is binded to account can "morph" from plate to mail, etc. if skill is not learned yet. - if (pProto->Quality == ITEM_QUALITY_HEIRLOOM && pProto->Class == ITEM_CLASS_ARMOR && !HasSkill(itemSkill)) + if (pProto->GetQuality() == ITEM_QUALITY_HEIRLOOM && pProto->GetClass() == ITEM_CLASS_ARMOR && !HasSkill(itemSkill)) { /// @todo when you right-click already equipped item it throws EQUIP_ERR_PROFICIENCY_NEEDED. // In fact it's a visual bug, everything works properly... I need sniffs of operations with @@ -11548,7 +11545,7 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const return EQUIP_ERR_PROFICIENCY_NEEDED; } - if (pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank) + if (pProto->GetRequiredReputationFaction() && uint32(GetReputationRank(pProto->GetRequiredReputationFaction())) < pProto->GetRequiredReputationRank()) return EQUIP_ERR_CANT_EQUIP_REPUTATION; return EQUIP_ERR_OK; @@ -11564,34 +11561,34 @@ InventoryResult Player::CanUseItem(ItemTemplate const* proto) const if (!proto) return EQUIP_ERR_ITEM_NOT_FOUND; - if (((proto->Flags2 & ITEM_FLAG2_FACTION_HORDE) && GetTeam() != HORDE) || - (((proto->Flags2 & ITEM_FLAG2_FACTION_ALLIANCE) && GetTeam() != ALLIANCE))) + if (((proto->GetFlags2() & ITEM_FLAG2_FACTION_HORDE) && GetTeam() != HORDE) || + (((proto->GetFlags2() & ITEM_FLAG2_FACTION_ALLIANCE) && GetTeam() != ALLIANCE))) return EQUIP_ERR_CANT_EQUIP_EVER; - if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0) + if ((proto->GetAllowableClass() & getClassMask()) == 0 || (proto->GetAllowableRace() & getRaceMask()) == 0) return EQUIP_ERR_CANT_EQUIP_EVER; - if (proto->RequiredSkill != 0) + if (proto->GetRequiredSkill() != 0) { - if (GetSkillValue(proto->RequiredSkill) == 0) + if (GetSkillValue(proto->GetRequiredSkill()) == 0) return EQUIP_ERR_PROFICIENCY_NEEDED; - else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank) + else if (GetSkillValue(proto->GetRequiredSkill()) < proto->GetRequiredSkillRank()) return EQUIP_ERR_CANT_EQUIP_SKILL; } - if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell)) + if (proto->GetRequiredSpell() != 0 && !HasSpell(proto->GetRequiredSpell())) return EQUIP_ERR_PROFICIENCY_NEEDED; - if (getLevel() < proto->RequiredLevel) + if (getLevel() < proto->GetRequiredLevel()) return EQUIP_ERR_CANT_EQUIP_LEVEL_I; // If World Event is not active, prevent using event dependant items - if (proto->HolidayId && !IsHolidayActive((HolidayIds)proto->HolidayId)) + if (proto->GetHolidayID() && !IsHolidayActive((HolidayIds)proto->GetHolidayID())) return EQUIP_ERR_CLIENT_LOCKED_OUT; // learning (recipes, mounts, pets, etc.) - if (proto->Spells[0].SpellId == 483 || proto->Spells[0].SpellId == 55884) - if (HasSpell(proto->Spells[1].SpellId)) + if (proto->Effects[0].SpellID == 483 || proto->Effects[0].SpellID == 55884) + if (HasSpell(proto->Effects[1].SpellID)) return EQUIP_ERR_INTERNAL_BAG_ERROR; return EQUIP_ERR_OK; @@ -11620,54 +11617,54 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje SKILL_FISHING }; //Copy from function Item::GetSkill() - if ((proto->AllowableClass & getClassMask()) == 0 || (proto->AllowableRace & getRaceMask()) == 0) + if ((proto->GetAllowableClass() & getClassMask()) == 0 || (proto->GetAllowableRace() & getRaceMask()) == 0) return EQUIP_ERR_CANT_EQUIP_EVER; - if (proto->RequiredSpell != 0 && !HasSpell(proto->RequiredSpell)) + if (proto->GetRequiredSpell() != 0 && !HasSpell(proto->GetRequiredSpell())) return EQUIP_ERR_PROFICIENCY_NEEDED; - if (proto->RequiredSkill != 0) + if (proto->GetRequiredSkill() != 0) { - if (!GetSkillValue(proto->RequiredSkill)) + if (!GetSkillValue(proto->GetRequiredSkill())) return EQUIP_ERR_PROFICIENCY_NEEDED; - else if (GetSkillValue(proto->RequiredSkill) < proto->RequiredSkillRank) + else if (GetSkillValue(proto->GetRequiredSkill()) < proto->GetRequiredSkillRank()) return EQUIP_ERR_CANT_EQUIP_SKILL; } uint8 _class = getClass(); - if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0) + if (proto->GetClass() == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->GetSubClass()]) == 0) return EQUIP_ERR_PROFICIENCY_NEEDED; - if (proto->Class == ITEM_CLASS_ARMOR && proto->SubClass > ITEM_SUBCLASS_ARMOR_MISCELLANEOUS && proto->SubClass < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->InventoryType != INVTYPE_CLOAK) + if (proto->GetClass() == ITEM_CLASS_ARMOR && proto->GetSubClass() > ITEM_SUBCLASS_ARMOR_MISCELLANEOUS && proto->GetSubClass() < ITEM_SUBCLASS_ARMOR_BUCKLER && proto->GetInventoryType() != INVTYPE_CLOAK) { if (_class == CLASS_WARRIOR || _class == CLASS_PALADIN || _class == CLASS_DEATH_KNIGHT) { if (getLevel() < 40) { - if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL) + if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_MAIL) return EQUIP_ERR_CLIENT_LOCKED_OUT; } - else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_PLATE) + else if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_PLATE) return EQUIP_ERR_CLIENT_LOCKED_OUT; } else if (_class == CLASS_HUNTER || _class == CLASS_SHAMAN) { if (getLevel() < 40) { - if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER) + if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_LEATHER) return EQUIP_ERR_CLIENT_LOCKED_OUT; } - else if (proto->SubClass != ITEM_SUBCLASS_ARMOR_MAIL) + else if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_MAIL) return EQUIP_ERR_CLIENT_LOCKED_OUT; } if (_class == CLASS_ROGUE || _class == CLASS_DRUID) - if (proto->SubClass != ITEM_SUBCLASS_ARMOR_LEATHER) + if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_LEATHER) return EQUIP_ERR_CLIENT_LOCKED_OUT; if (_class == CLASS_MAGE || _class == CLASS_PRIEST || _class == CLASS_WARLOCK) - if (proto->SubClass != ITEM_SUBCLASS_ARMOR_CLOTH) + if (proto->GetSubClass() != ITEM_SUBCLASS_ARMOR_CLOTH) return EQUIP_ERR_CLIENT_LOCKED_OUT; } @@ -11761,9 +11758,9 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool if (!pItem) return nullptr; - if (pItem->GetTemplate()->Bonding == BIND_ON_ACQUIRE || - pItem->GetTemplate()->Bonding == BIND_QUEST || - (pItem->GetTemplate()->Bonding == BIND_ON_EQUIP && IsBagPos(pos))) + if (pItem->GetTemplate()->GetBonding() == BIND_ON_ACQUIRE || + pItem->GetTemplate()->GetBonding() == BIND_QUEST || + (pItem->GetTemplate()->GetBonding() == BIND_ON_EQUIP && IsBagPos(pos))) pItem->SetBinding(true); Bag* pBag = (bag == INVENTORY_SLOT_BAG_0) ? nullptr : GetBagByPos(bag); @@ -11800,9 +11797,9 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool } else { - if (pItem2->GetTemplate()->Bonding == BIND_ON_ACQUIRE || - pItem2->GetTemplate()->Bonding == BIND_QUEST || - (pItem2->GetTemplate()->Bonding == BIND_ON_EQUIP && IsBagPos(pos))) + if (pItem2->GetTemplate()->GetBonding() == BIND_ON_ACQUIRE || + pItem2->GetTemplate()->GetBonding() == BIND_QUEST || + (pItem2->GetTemplate()->GetBonding() == BIND_ON_EQUIP && IsBagPos(pos))) pItem2->SetBinding(true); pItem2->SetCount(pItem2->GetCount() + count); @@ -11870,12 +11867,12 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) ItemTemplate const* pProto = pItem->GetTemplate(); // item set bonuses applied only at equip and removed at unequip, and still active for broken items - if (pProto && pProto->ItemSet) + if (pProto && pProto->GetItemSet()) AddItemsSetItem(this, pItem); _ApplyItemMods(pItem, slot, true); - if (pProto && IsInCombat() && (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer == 0) + if (pProto && IsInCombat() && (pProto->GetClass() == ITEM_CLASS_WEAPON || pProto->GetInventoryType() == INVTYPE_RELIC) && m_weaponChangeTimer == 0) { uint32 cooldownSpell = getClass() == CLASS_ROGUE ? 6123 : 6119; SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cooldownSpell); @@ -12001,7 +11998,7 @@ void Player::VisualizeItem(uint8 slot, Item* pItem) return; // check also BIND_ON_ACQUIRE and BIND_QUEST for .additem or .additemset case by GM (not binded at adding to inventory) - if (pItem->GetTemplate()->Bonding == BIND_ON_EQUIP || pItem->GetTemplate()->Bonding == BIND_ON_ACQUIRE || pItem->GetTemplate()->Bonding == BIND_QUEST) + if (pItem->GetTemplate()->GetBonding() == BIND_ON_EQUIP || pItem->GetTemplate()->GetBonding() == BIND_ON_ACQUIRE || pItem->GetTemplate()->GetBonding() == BIND_QUEST) pItem->SetBinding(true); TC_LOG_DEBUG("entities.player.items", "Player::SetVisibleItemSlot: Player '%s' (%s), Slot: %u, Item: %u", @@ -12049,7 +12046,7 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update) ItemTemplate const* pProto = pItem->GetTemplate(); // item set bonuses applied only at equip and removed at unequip, and still active for broken items - if (pProto && pProto->ItemSet) + if (pProto && pProto->GetItemSet()) RemoveItemsSetItem(this, pProto); _ApplyItemMods(pItem, slot, false, update); @@ -12186,7 +12183,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) if (slot < INVENTORY_SLOT_BAG_END) { // item set bonuses applied only at equip and removed at unequip, and still active for broken items - if (pProto->ItemSet) + if (pProto->GetItemSet()) RemoveItemsSetItem(this, pProto); _ApplyItemMods(pItem, slot, false); @@ -12210,7 +12207,7 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update) // Delete rolled money / loot from db. // MUST be done before RemoveFromWorld() or GetTemplate() fails - if (pProto->Flags & ITEM_FLAG_HAS_LOOT) + if (pProto->GetFlags() & ITEM_FLAG_HAS_LOOT) sLootItemStorage->RemoveStoredLootForContainer(pItem->GetGUID().GetCounter()); if (IsInWorld() && update) @@ -13000,7 +12997,7 @@ void Player::AddItemToBuyBackSlot(Item* pItem) SetGuidValue(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (eslot * 2), pItem->GetGUID()); if (ItemTemplate const* proto = pItem->GetTemplate()) - SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, proto->SellPrice * pItem->GetCount()); + SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, proto->GetSellPrice() * pItem->GetCount()); else SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0); SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, (uint32)etime); @@ -13033,7 +13030,7 @@ void Player::RemoveItemFromBuyBackSlot(uint32 slot, bool del) if (del) { if (ItemTemplate const* itemTemplate = pItem->GetTemplate()) - if (itemTemplate->Flags & ITEM_FLAG_HAS_LOOT) + if (itemTemplate->GetFlags() & ITEM_FLAG_HAS_LOOT) sLootItemStorage->RemoveStoredLootForContainer(pItem->GetGUID().GetCounter()); pItem->SetState(ITEM_REMOVED, this); @@ -13070,7 +13067,7 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint case EQUIP_ERR_PURCHASE_LEVEL_TOO_LOW: { ItemTemplate const* proto = pItem ? pItem->GetTemplate() : sObjectMgr->GetItemTemplate(itemid); - data << uint32(proto ? proto->RequiredLevel : 0); + data << uint32(proto ? proto->GetRequiredLevel() : 0); break; } case EQUIP_ERR_NO_OUTPUT: // no idea about this one... @@ -13085,7 +13082,7 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS: { ItemTemplate const* proto = pItem ? pItem->GetTemplate() : sObjectMgr->GetItemTemplate(itemid); - data << uint32(proto ? proto->ItemLimitCategory : 0); + data << uint32(proto ? proto->GetItemLimitCategory() : 0); break; } default: @@ -13146,17 +13143,17 @@ void Player::CheckTitanGripPenalty() bool Player::IsTwoHandUsed() const { Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); - return mainItem && mainItem->GetTemplate()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip(); + return mainItem && mainItem->GetTemplate()->GetInventoryType() == INVTYPE_2HWEAPON && !CanTitanGrip(); } bool Player::IsUsingTwoHandedWeaponInOneHand() const { Item* offItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); - if (offItem && offItem->GetTemplate()->InventoryType == INVTYPE_2HWEAPON) + if (offItem && offItem->GetTemplate()->GetInventoryType() == INVTYPE_2HWEAPON) return true; Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); - if (!mainItem || mainItem->GetTemplate()->InventoryType != INVTYPE_2HWEAPON) + if (!mainItem || mainItem->GetTemplate()->GetInventoryType() != INVTYPE_2HWEAPON) return false; if (!offItem) @@ -13221,7 +13218,7 @@ void Player::UpdateItemDuration(uint32 time, bool realtimeonly) Item* item = *itr; ++itr; // current element can be erased in UpdateDuration - if (!realtimeonly || item->GetTemplate()->Flags & ITEM_FLAG_REAL_DURATION) + if (!realtimeonly || item->GetTemplate()->GetFlags() & ITEM_FLAG_REAL_DURATION) item->UpdateDuration(this, time); } } @@ -13651,13 +13648,13 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool // Cogwheel gems dont have requirement data set in SpellItemEnchantment.dbc, but they do have it in Item-sparse.db2 if (ItemTemplate const* gem = sObjectMgr->GetItemTemplate(pEnchant->Src_itemID)) - if (gem->RequiredSkill && GetSkillValue(gem->RequiredSkill) < gem->RequiredSkillRank) + if (gem->GetRequiredSkill() && GetSkillValue(gem->GetRequiredSkill()) < gem->GetRequiredSkillRank()) return; // If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements // rather than the gem requirements itself. If the socket has no color it is a prismatic socket. if ((slot == SOCK_ENCHANTMENT_SLOT || slot == SOCK_ENCHANTMENT_SLOT_2 || slot == SOCK_ENCHANTMENT_SLOT_3) - && !item->GetTemplate()->Socket[slot-SOCK_ENCHANTMENT_SLOT].Color) + && !item->GetTemplate()->GetSocketColor(slot-SOCK_ENCHANTMENT_SLOT)) { // Check if the requirements for the prismatic socket are met before applying the gem stats SpellItemEnchantmentEntry const* pPrismaticEnchant = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)); @@ -13948,12 +13945,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool float addValue; if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND) { - addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f); + addValue = float(enchant_amount * item->GetTemplate()->GetDelay() / 1000.0f); HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply); } else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND) { - addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f); + addValue = float(enchant_amount * item->GetTemplate()->GetDelay() / 1000.0f); HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply); } } @@ -14028,7 +14025,7 @@ void Player::UpdateSkillEnchantments(uint16 skill_id, uint16 curr_value, uint16 // If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements // rather than the gem requirements itself. If the socket has no color it is a prismatic socket. if ((slot == SOCK_ENCHANTMENT_SLOT || slot == SOCK_ENCHANTMENT_SLOT_2 || slot == SOCK_ENCHANTMENT_SLOT_3) - && !m_items[i]->GetTemplate()->Socket[slot-SOCK_ENCHANTMENT_SLOT].Color) + && !m_items[i]->GetTemplate()->GetSocketColor(slot-SOCK_ENCHANTMENT_SLOT)) { SpellItemEnchantmentEntry const* pPrismaticEnchant = sSpellItemEnchantmentStore.LookupEntry(m_items[i]->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)); @@ -14878,7 +14875,7 @@ void Player::AddQuestAndCheckCompletion(Quest const* quest, Object* questGiver) for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) { - if (quest->RequiredItemId[i] == item->GetEntry() && item->GetTemplate()->MaxCount > 0) + if (quest->RequiredItemId[i] == item->GetEntry() && item->GetTemplate()->GetMaxCount() > 0) { destroyItem = false; break; @@ -15086,7 +15083,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, { if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) { - if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST && !quest->IsRepeatable() && !HasQuestForItem(quest->RequiredItemId[i], quest_id, true)) + if (quest->RequiredItemCount[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST && !quest->IsRepeatable() && !HasQuestForItem(quest->RequiredItemId[i], quest_id, true)) DestroyItemCount(quest->RequiredItemId[i], 9999, true); else DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true); @@ -15100,7 +15097,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, { if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i])) { - if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST && !quest->IsRepeatable() && !HasQuestForItem(quest->ItemDrop[i], quest_id)) + if (quest->ItemDropQuantity[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST && !quest->IsRepeatable() && !HasQuestForItem(quest->ItemDrop[i], quest_id)) DestroyItemCount(quest->ItemDrop[i], 9999, true); else DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i], true); @@ -15346,12 +15343,12 @@ void Player::FailQuest(uint32 questId) // Destroy quest items on quest failure. for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) - if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST) + if (quest->RequiredItemCount[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST) DestroyItemCount(quest->RequiredItemId[i], 9999, true); for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i])) - if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST) + if (quest->ItemDropQuantity[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST) DestroyItemCount(quest->ItemDrop[i], 9999, true); } } @@ -15363,12 +15360,12 @@ void Player::AbandonQuest(uint32 questId) // Destroy quest items on quest abandon. for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) - if (quest->RequiredItemCount[i] > 0 && itemTemplate->Bonding == BIND_QUEST) + if (quest->RequiredItemCount[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST) DestroyItemCount(quest->RequiredItemId[i], 9999, true); for (uint8 i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i])) - if (quest->ItemDropQuantity[i] > 0 && itemTemplate->Bonding == BIND_QUEST) + if (quest->ItemDropQuantity[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST) DestroyItemCount(quest->ItemDrop[i], 9999, true); } } @@ -15826,7 +15823,7 @@ bool Player::GiveQuestSourceItem(Quest const* quest) { // Don't give source item if it is the same item used to start the quest ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(srcitem); - if (quest->GetQuestId() == itemTemplate->StartQuest) + if (quest->GetQuestId() == itemTemplate->GetStartQuest()) return true; uint32 count = quest->GetSrcItemCount(); @@ -15878,7 +15875,7 @@ bool Player::TakeQuestSourceItem(uint32 questId, bool msg) } ASSERT(item); - if (item->StartQuest != questId) + if (item->GetStartQuest() != questId) DestroyItemCount(srcItemId, count, true, true); } } @@ -16764,7 +16761,7 @@ bool Player::HasQuestForItem(uint32 itemid, uint32 excludeQuestId /* 0 */, bool uint32 ownedCount = GetItemCount(itemid, true); // 'unique' item - if ((pProto->MaxCount && int32(ownedCount) < pProto->MaxCount) || (turnIn && int32(ownedCount) >= pProto->MaxCount)) + if ((pProto->GetMaxCount() && ownedCount < pProto->GetMaxCount()) || (turnIn && ownedCount >= pProto->GetMaxCount())) return true; // allows custom amount drop when not 0 @@ -18420,7 +18417,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F remove = true; } // "Conjured items disappear if you are logged out for more than 15 minutes" - else if (timeDiff > 15 * MINUTE && proto->Flags & ITEM_FLAG_CONJURED) + else if (timeDiff > 15 * MINUTE && proto->GetFlags() & ITEM_FLAG_CONJURED) { TC_LOG_DEBUG("entities.player.loading", "Player::_LoadInventory: player (GUID: %u, name: '%s', diff: %u) has conjured item (GUID: %u, entry: %u) with expired lifetime (15 minutes). Deleting item.", GetGUID().GetCounter(), GetName().c_str(), timeDiff, item->GetGUID().GetCounter(), item->GetEntry()); @@ -18486,14 +18483,14 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_BOP_TRADEABLE); } } - else if (proto->HolidayId) + else if (proto->GetHolidayID()) { remove = true; GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); GameEventMgr::ActiveEvents const& activeEventsList = sGameEventMgr->GetActiveEventList(); for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) { - if (uint32(events[*itr].holiday_id) == proto->HolidayId) + if (uint32(events[*itr].holiday_id) == proto->GetHolidayID()) { remove = false; break; @@ -20127,7 +20124,7 @@ void Player::_SaveInventory(SQLTransaction& trans) if (item->GetState() == ITEM_NEW) { if (ItemTemplate const* itemTemplate = item->GetTemplate()) - if (itemTemplate->Flags & ITEM_FLAG_HAS_LOOT) + if (itemTemplate->GetFlags() & ITEM_FLAG_HAS_LOOT) sLootItemStorage->RemoveStoredLootForContainer(item->GetGUID().GetCounter()); continue; @@ -20143,7 +20140,7 @@ void Player::_SaveInventory(SQLTransaction& trans) m_items[i]->FSetState(ITEM_NEW); if (ItemTemplate const* itemTemplate = item->GetTemplate()) - if (itemTemplate->Flags & ITEM_FLAG_HAS_LOOT) + if (itemTemplate->GetFlags() & ITEM_FLAG_HAS_LOOT) sLootItemStorage->RemoveStoredLootForContainer(item->GetGUID().GetCounter()); } @@ -22217,7 +22214,7 @@ void Player::InitDisplayIds() inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot, int32 price, ItemTemplate const* pProto, Creature* pVendor, VendorItem const* crItem, bool bStore) { - uint32 stacks = count / pProto->BuyCount; + uint32 stacks = count / pProto->GetBuyCount(); ItemPosCountVec vDest; uint16 uiDest = 0; InventoryResult msg = bStore ? @@ -22269,7 +22266,7 @@ inline bool Player::_StoreOrEquipNewItem(uint32 vendorslot, uint32 item, uint8 c if (!bStore) AutoUnequipOffhandIfNeed(); - if (pProto->Flags & ITEM_FLAG_ITEM_PURCHASE_RECORD && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1) + if (pProto->GetFlags() & ITEM_FLAG_ITEM_PURCHASE_RECORD && crItem->ExtendedCost && pProto->GetMaxStackSize() == 1) { it->SetFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE); it->SetRefundRecipient(GetGUID().GetCounter()); @@ -22461,13 +22458,13 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin return false; } - if (!(pProto->AllowableClass & getClassMask()) && pProto->Bonding == BIND_ON_ACQUIRE && !IsGameMaster()) + if (!(pProto->GetAllowableClass() & getClassMask()) && pProto->GetBonding() == BIND_ON_ACQUIRE && !IsGameMaster()) { SendBuyError(BUY_ERR_CANT_FIND_ITEM, nullptr, item, 0); return false; } - if (!IsGameMaster() && ((pProto->Flags2 & ITEM_FLAG2_FACTION_HORDE && GetTeam() == ALLIANCE) || (pProto->Flags2 == ITEM_FLAG2_FACTION_ALLIANCE && GetTeam() == HORDE))) + if (!IsGameMaster() && ((pProto->GetFlags2() & ITEM_FLAG2_FACTION_HORDE && GetTeam() == ALLIANCE) || (pProto->GetFlags2() == ITEM_FLAG2_FACTION_ALLIANCE && GetTeam() == HORDE))) return false; Creature* creature = GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); @@ -22511,14 +22508,14 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin // check current item amount if it limited if (crItem->maxcount != 0) { - if (creature->GetVendorItemCurrentCount(crItem) < pProto->BuyCount * count) + if (creature->GetVendorItemCurrentCount(crItem) < pProto->GetBuyCount() * count) { SendBuyError(BUY_ERR_ITEM_ALREADY_SOLD, creature, item, 0); return false; } } - if (pProto->RequiredReputationFaction && (uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)) + if (pProto->GetRequiredReputationFaction() && (uint32(GetReputationRank(pProto->GetRequiredReputationFaction())) < pProto->GetRequiredReputationRank())) { SendBuyError(BUY_ERR_REPUTATION_REQUIRE, creature, item, 0); return false; @@ -22527,17 +22524,17 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin if (crItem->ExtendedCost) { // Can only buy full stacks for extended cost - if (count % pProto->BuyCount) + if (count % pProto->GetBuyCount()) { SendEquipError(EQUIP_ERR_CANT_BUY_QUANTITY, nullptr, nullptr); return false; } - uint32 stacks = count / pProto->BuyCount; + uint32 stacks = count / pProto->GetBuyCount(); ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost); if (!iece) { - TC_LOG_ERROR("entities.player", "Player::BuyItemFromVendorSlot: Item %u has wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost); + TC_LOG_ERROR("entities.player", "Player::BuyItemFromVendorSlot: Item %u has wrong ExtendedCost field value %u", pProto->GetId(), crItem->ExtendedCost); return false; } @@ -22617,18 +22614,18 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin } uint32 price = 0; - if (crItem->IsGoldRequired(pProto) && pProto->BuyPrice > 0) //Assume price cannot be negative (do not know why it is int32) + if (crItem->IsGoldRequired(pProto) && pProto->GetBuyPrice() > 0) //Assume price cannot be negative (do not know why it is int32) { - uint32 maxCount = MAX_MONEY_AMOUNT / pProto->BuyPrice; + uint32 maxCount = MAX_MONEY_AMOUNT / pProto->GetBuyPrice(); if ((uint32)count > maxCount) { TC_LOG_INFO("entities.player.cheat", "Player::BuyItemFromVendorSlot: Player '%s' (%s) tried to buy item (ItemID: %u, Count: %u), causing overflow", - GetName().c_str(), GetGUID().ToString().c_str(), pProto->ItemId, (uint32)count); + GetName().c_str(), GetGUID().ToString().c_str(), pProto->GetId(), (uint32)count); count = (uint8)maxCount; } - price = pProto->BuyPrice * count; //it should not exceed MAX_MONEY_AMOUNT + price = pProto->GetBuyPrice() * count; //it should not exceed MAX_MONEY_AMOUNT - price /= pProto->BuyCount; + price /= pProto->GetBuyCount(); // reputation discount price = uint32(floor(price * GetReputationPriceDiscount(creature))); @@ -22666,7 +22663,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin if (crItem->maxcount != 0) // bought { - if (pProto->Quality > ITEM_QUALITY_EPIC || (pProto->Quality == ITEM_QUALITY_EPIC && pProto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) + if (pProto->GetQuality() > ITEM_QUALITY_EPIC || (pProto->GetQuality() == ITEM_QUALITY_EPIC && pProto->GetBaseItemLevel() >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) if (Guild* guild = GetGuild()) guild->AddGuildNews(GUILD_NEWS_ITEM_PURCHASED, GetGUID(), 0, item); return true; @@ -22803,9 +22800,9 @@ void Player::UpdatePotionCooldown(Spell* spell) { // spell/item pair let set proper cooldown (except non-existing charged spell cooldown spellmods for potions) if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(m_lastPotionId)) - for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx) - if (proto->Spells[idx].SpellId && proto->Spells[idx].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE) - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[idx].SpellId)) + for (ItemEffect const& effect : proto->Effects) + if (effect.SpellID && effect.Trigger== ITEM_SPELLTRIGGER_ON_USE) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect.SpellID)) GetSpellHistory()->SendCooldownEvent(spellInfo, m_lastPotionId); } // from spell cases (m_lastPotionId set in Spell::SendSpellCooldown) @@ -22849,7 +22846,7 @@ bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) if (i == slot) continue; Item* pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i); - if (pItem2 && !pItem2->IsBroken() && pItem2->GetTemplate()->Socket[0].Color) + if (pItem2 && !pItem2->IsBroken() && pItem2->GetTemplate()->GetSocketColor(0)) { for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) { @@ -22869,7 +22866,7 @@ bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) if (!gemProto) continue; - GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GemProperties); + GemPropertiesEntry const* gemProperty = sGemPropertiesStore.LookupEntry(gemProto->GetGemProperties()); if (!gemProperty) continue; @@ -22927,7 +22924,7 @@ void Player::CorrectMetaGemEnchants(uint8 exceptslot, bool apply) Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - if (!pItem || !pItem->GetTemplate()->Socket[0].Color) + if (!pItem || !pItem->GetTemplate()->GetSocketColor(0)) continue; for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) @@ -22969,7 +22966,7 @@ void Player::ToggleMetaGemsActive(uint8 exceptslot, bool apply) Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, slot); - if (!pItem || !pItem->GetTemplate()->Socket[0].Color) //if item has no sockets or no item is equipped go to next item + if (!pItem || !pItem->GetTemplate()->GetSocketColor(0)) //if item has no sockets or no item is equipped go to next item continue; //cycle all (gem)enchants @@ -23764,43 +23761,41 @@ void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint3 void Player::ApplyEquipCooldown(Item* pItem) { - if (pItem->GetTemplate()->Flags & ITEM_FLAG_NO_EQUIP_COOLDOWN) + if (pItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_EQUIP_COOLDOWN) return; std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (ItemEffect const& effect : pItem->GetTemplate()->Effects) { - _Spell const& spellData = pItem->GetTemplate()->Spells[i]; - // no spell - if (spellData.SpellId <= 0) + if (effect.SpellID <= 0) continue; // apply proc cooldown to equip auras if we have any - if (spellData.SpellTrigger == ITEM_SPELLTRIGGER_ON_EQUIP) + if (effect.Trigger == ITEM_SPELLTRIGGER_ON_EQUIP) { - SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(spellData.SpellId); + SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(effect.SpellID); if (!procEntry) continue; - if (Aura* itemAura = GetAura(spellData.SpellId, GetGUID(), pItem->GetGUID())) + if (Aura* itemAura = GetAura(effect.SpellID, GetGUID(), pItem->GetGUID())) itemAura->AddProcCooldown(now + procEntry->Cooldown); continue; } // wrong triggering type (note: ITEM_SPELLTRIGGER_ON_NO_DELAY_USE not have cooldown) - if (spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) + if (effect.Trigger != ITEM_SPELLTRIGGER_ON_USE) continue; // Don't replace longer cooldowns by equip cooldown if we have any. - if (GetSpellHistory()->GetRemainingCooldown(sSpellMgr->AssertSpellInfo(spellData.SpellId)) > 30 * IN_MILLISECONDS) + if (GetSpellHistory()->GetRemainingCooldown(sSpellMgr->AssertSpellInfo(effect.SpellID)) > 30 * IN_MILLISECONDS) continue; - GetSpellHistory()->AddCooldown(spellData.SpellId, pItem->GetEntry(), std::chrono::seconds(30)); + GetSpellHistory()->AddCooldown(effect.SpellID, pItem->GetEntry(), std::chrono::seconds(30)); WorldPacket data(SMSG_ITEM_COOLDOWN, 8 + 4); data << uint64(pItem->GetGUID()); - data << uint32(spellData.SpellId); + data << uint32(effect.SpellID); SendDirectMessage(&data); } } @@ -24634,11 +24629,11 @@ void Player::AutoUnequipOffhandIfNeed(bool force /*= false*/) return; // unequip offhand weapon if player doesn't have dual wield anymore - if (!CanDualWield() && (offItem->GetTemplate()->InventoryType == INVTYPE_WEAPONOFFHAND || offItem->GetTemplate()->InventoryType == INVTYPE_WEAPON)) + if (!CanDualWield() && (offItem->GetTemplate()->GetInventoryType() == INVTYPE_WEAPONOFFHAND || offItem->GetTemplate()->GetInventoryType() == INVTYPE_WEAPON)) force = true; // need unequip offhand for 2h-weapon without TitanGrip (in any from hands) - if (!force && (CanTitanGrip() || (offItem->GetTemplate()->InventoryType != INVTYPE_2HWEAPON && !IsTwoHandUsed()))) + if (!force && (CanTitanGrip() || (offItem->GetTemplate()->GetInventoryType() != INVTYPE_2HWEAPON && !IsTwoHandUsed()))) return; ItemPosCountVec off_dest; @@ -25815,7 +25810,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot, GameObject* go) --loot->unlootedCount; if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item->itemid)) - if (proto->Quality > ITEM_QUALITY_EPIC || (proto->Quality == ITEM_QUALITY_EPIC && proto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) + if (proto->GetQuality() > ITEM_QUALITY_EPIC || (proto->GetQuality() == ITEM_QUALITY_EPIC && proto->GetBaseItemLevel() >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) if (Guild* guild = GetGuild()) guild->AddGuildNews(GUILD_NEWS_ITEM_LOOTED, GetGUID(), 0, item->itemid); @@ -25986,8 +25981,8 @@ InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limi continue; // include for check equip another gems with same limit category for not equipped item (and then not counted) - uint32 gem_limit_count = !pItem->IsEquipped() && pGem->ItemLimitCategory - ? pItem->GetGemCountWithLimitCategory(pGem->ItemLimitCategory) : 1; + uint32 gem_limit_count = !pItem->IsEquipped() && pGem->GetItemLimitCategory() + ? pItem->GetGemCountWithLimitCategory(pGem->GetItemLimitCategory()) : 1; if (InventoryResult res = CanEquipUniqueItem(pGem, eslot, gem_limit_count)) return res; @@ -25999,17 +25994,17 @@ InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limi InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8 except_slot, uint32 limit_count) const { // check unique-equipped on item - if (itemProto->Flags & ITEM_FLAG_UNIQUE_EQUIPPABLE) + if (itemProto->GetFlags() & ITEM_FLAG_UNIQUE_EQUIPPABLE) { // there is an equip limit on this item - if (HasItemOrGemWithIdEquipped(itemProto->ItemId, 1, except_slot)) + if (HasItemOrGemWithIdEquipped(itemProto->GetId(), 1, except_slot)) return EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE; } // check unique-equipped limit - if (itemProto->ItemLimitCategory) + if (itemProto->GetItemLimitCategory()) { - ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(itemProto->ItemLimitCategory); + ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(itemProto->GetItemLimitCategory()); if (!limitEntry) return EQUIP_ERR_NOT_EQUIPPABLE; @@ -26019,9 +26014,9 @@ InventoryResult Player::CanEquipUniqueItem(ItemTemplate const* itemProto, uint8 return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS; // there is an equip limit on this item - if (HasItemWithLimitCategoryEquipped(itemProto->ItemLimitCategory, limitEntry->Quantity - limit_count + 1, except_slot)) + if (HasItemWithLimitCategoryEquipped(itemProto->GetItemLimitCategory(), limitEntry->Quantity - limit_count + 1, except_slot)) return EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_EQUIPPED_EXCEEDED_IS; - else if (HasGemWithLimitCategoryEquipped(itemProto->ItemLimitCategory, limitEntry->Quantity - limit_count + 1, except_slot)) + else if (HasGemWithLimitCategoryEquipped(itemProto->GetItemLimitCategory(), limitEntry->Quantity - limit_count + 1, except_slot)) return EQUIP_ERR_ITEM_MAX_COUNT_EQUIPPED_SOCKETED; } @@ -27590,7 +27585,7 @@ float Player::GetAverageItemLevel() const continue; uint32* pEffective = nullptr; - switch (itemTemplate->InventoryType) + switch (itemTemplate->GetInventoryType()) { case INVTYPE_FINGER: pEffective = &fingerItemLevel; break; case INVTYPE_TRINKET: pEffective = &trinketItemLevel; break; @@ -27598,7 +27593,7 @@ float Player::GetAverageItemLevel() const case INVTYPE_2HWEAPON: pEffective = &weapon2HItemLevel; break; } - getEffectiveItemLevel(static_cast(itemTemplate->ItemLevel), &itemLevelPerInvType[itemTemplate->InventoryType], pEffective); + getEffectiveItemLevel(static_cast(itemTemplate->GetBaseItemLevel()), &itemLevelPerInvType[itemTemplate->GetInventoryType()], pEffective); } uint32 maxRangedThrownRelicRangedRight = std::max( diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 7140b08cb6..27f3c3b84d 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -413,7 +413,7 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo { float weaponSpeed = BASE_ATTACK_TIME / 1000.f; if (Item* weapon = GetWeaponForAttack(BASE_ATTACK, true)) - weaponSpeed = weapon->GetTemplate()->Delay / 1000; + weaponSpeed = weapon->GetTemplate()->GetDelay() / 1000; if (GetShapeshiftForm() == FORM_CAT) { diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ce34e44686..4a61a8871d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11466,9 +11466,9 @@ float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) return BASE_ATTACK_TIME / 1000.0f; if (!normalized) - return weapon->GetTemplate()->Delay / 1000.0f; + return weapon->GetTemplate()->GetDelay() / 1000.0f; - switch (weapon->GetTemplate()->SubClass) + switch (weapon->GetTemplate()->GetSubClass()) { case ITEM_SUBCLASS_WEAPON_AXE2: case ITEM_SUBCLASS_WEAPON_MACE2: @@ -11492,7 +11492,7 @@ float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) case ITEM_SUBCLASS_WEAPON_DAGGER: return 1.7f; default: - return weapon->GetTemplate()->Delay / 1000.0f; + return weapon->GetTemplate()->GetDelay() / 1000.0f; } } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 365c743315..621f7a9ebc 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2735,38 +2735,6 @@ void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectDat } } -void ObjectMgr::LoadItemLocales() -{ - uint32 oldMSTime = getMSTime(); - - _itemLocaleStore.clear(); // need for reload case - - // 0 1 2 3 - QueryResult result = WorldDatabase.Query("SELECT ID, locale, Name, Description FROM item_template_locale"); - if (!result) - return; - - do - { - Field* fields = result->Fetch(); - - uint32 id = fields[0].GetUInt32(); - std::string localeName = fields[1].GetString(); - std::string Name = fields[2].GetString(); - std::string Description = fields[3].GetString(); - - ItemLocale& data = _itemLocaleStore[id]; - LocaleConstant locale = GetLocaleByName(localeName); - if (locale == LOCALE_enUS) - continue; - - AddLocaleString(Name, locale, data.Name); - AddLocaleString(Description, locale, data.Description); - } while (result->NextRow()); - - TC_LOG_INFO("server.loading", ">> Loaded %u Item locale strings in %u ms", uint32(_itemLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime)); -} - uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventoryType, uint32 quality, uint32 itemLevel) { if (itemClass != ITEM_CLASS_ARMOR && itemClass != ITEM_CLASS_WEAPON) @@ -2854,12 +2822,12 @@ void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, { *disenchantID = 0; *(int32*)requiredDisenchantSkill = -1; - if ((itemTemplate.Flags & (ITEM_FLAG_CONJURED | ITEM_FLAG_NO_DISENCHANT)) || - itemTemplate.Bonding == BIND_QUEST || itemTemplate.Area || itemTemplate.Map || - itemTemplate.Stackable > 1 || - itemTemplate.Quality < ITEM_QUALITY_UNCOMMON || itemTemplate.Quality > ITEM_QUALITY_EPIC || - !(itemTemplate.Class == ITEM_CLASS_ARMOR || itemTemplate.Class == ITEM_CLASS_WEAPON) || - !(Item::GetSpecialPrice(&itemTemplate) || sItemCurrencyCostStore.LookupEntry(itemTemplate.ItemId))) + if ((itemTemplate.GetFlags() & (ITEM_FLAG_CONJURED | ITEM_FLAG_NO_DISENCHANT)) || + itemTemplate.GetBonding() == BIND_QUEST || itemTemplate.GetArea() || itemTemplate.GetMap() || + itemTemplate.GetMaxStackSize() > 1 || + itemTemplate.GetQuality() < ITEM_QUALITY_UNCOMMON || itemTemplate.GetQuality() > ITEM_QUALITY_EPIC || + !(itemTemplate.GetClass() == ITEM_CLASS_ARMOR || itemTemplate.GetClass() == ITEM_CLASS_WEAPON) || + !(Item::GetSpecialPrice(&itemTemplate) || sItemCurrencyCostStore.LookupEntry(itemTemplate.GetId()))) return; for (uint32 i = 0; i < sItemDisenchantLootStore.GetNumRows(); ++i) @@ -2868,19 +2836,19 @@ void FillDisenchantFields(uint32* disenchantID, uint32* requiredDisenchantSkill, if (!disenchant) continue; - if (disenchant->Class == itemTemplate.Class && - disenchant->Quality == itemTemplate.Quality && - disenchant->MinLevel <= itemTemplate.ItemLevel && - disenchant->MaxLevel >= itemTemplate.ItemLevel) + if (disenchant->Class == itemTemplate.GetClass() && + disenchant->Quality == itemTemplate.GetQuality() && + disenchant->MinLevel <= itemTemplate.GetBaseItemLevel() && + disenchant->MaxLevel >= itemTemplate.GetBaseItemLevel()) { if (disenchant->ID == 60 || disenchant->ID == 61) // epic item disenchant ilvl range 66-99 (classic) { - if (itemTemplate.RequiredLevel > 60 || itemTemplate.RequiredSkillRank > 300) + if (itemTemplate.GetRequiredLevel() > 60 || itemTemplate.GetRequiredSkillRank() > 300) continue; // skip to epic item disenchant ilvl range 90-199 (TBC) } else if (disenchant->ID == 66 || disenchant->ID == 67) // epic item disenchant ilvl range 90-199 (TBC) { - if (itemTemplate.RequiredLevel <= 60 || (itemTemplate.RequiredSkill && itemTemplate.RequiredSkillRank <= 300)) + if (itemTemplate.GetRequiredLevel() <= 60 || (itemTemplate.GetRequiredSkill() && itemTemplate.GetRequiredSkillRank() <= 300)) continue; } @@ -2895,260 +2863,40 @@ void ObjectMgr::LoadItemTemplates() { uint32 oldMSTime = getMSTime(); uint32 sparseCount = 0; - uint32 dbCount = 0; - for (uint32 itemId = 0; itemId < sItemSparseStore.GetNumRows(); ++itemId) + for (ItemSparseEntry const* sparse : sItemSparseStore) { - ItemSparseEntry const* sparse = sItemSparseStore.LookupEntry(itemId); - ItemEntry const* db2Data = sItemStore.LookupEntry(itemId); - if (!sparse || !db2Data) + ItemEntry const* db2Data = sItemStore.LookupEntry(sparse->ID); + if (!db2Data) continue; - ItemTemplate& itemTemplate = _itemTemplateStore[itemId]; - itemTemplate.ItemId = itemId; - itemTemplate.Class = db2Data->Class; - itemTemplate.SubClass = db2Data->SubClass; - itemTemplate.SoundOverrideSubclass = db2Data->SoundOverrideSubclass; - itemTemplate.Name1 = sparse->Name->Str[sWorld->GetDefaultDbcLocale()]; - itemTemplate.DisplayInfoID = db2Data->DisplayId; - itemTemplate.Quality = sparse->Quality; - itemTemplate.Flags = sparse->Flags; - itemTemplate.Flags2 = sparse->Flags2; - itemTemplate.Unk430_1 = sparse->Unk430_1; - itemTemplate.Unk430_2 = sparse->Unk430_2; - itemTemplate.BuyCount = std::max(sparse->BuyCount, 1u); - 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; + ItemTemplate& itemTemplate = _itemTemplateStore[sparse->ID]; - 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].ItemStatAllocation = sparse->ItemStatAllocation[i]; - itemTemplate.ItemStat[i].ItemStatSocketCostMultiplier = sparse->ItemStatSocketCostMultiplier[i]; - } + itemTemplate.BasicData = db2Data; + itemTemplate.ExtendedData = sparse; - itemTemplate.ScalingStatDistribution = sparse->ScalingStatDistribution; - - // cache item damage - itemTemplate.DamageType = sparse->DamageType; - 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->Str[sWorld->GetDefaultDbcLocale()]; - 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 = FillMaxDurability(db2Data->Class, db2Data->SubClass, sparse->InventoryType, sparse->Quality, sparse->ItemLevel); - 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; + itemTemplate.MaxDurability = FillMaxDurability(db2Data->ClassID, db2Data->SubclassID, sparse->InventoryType, sparse->Quality, sparse->ItemLevel); FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill, itemTemplate); - - itemTemplate.ArmorDamageModifier = sparse->ArmorDamageModifier; - itemTemplate.Duration = sparse->Duration; - itemTemplate.ItemLimitCategory = sparse->ItemLimitCategory; - itemTemplate.HolidayId = sparse->HolidayId; - itemTemplate.StatScalingFactor = sparse->StatScalingFactor; - itemTemplate.CurrencySubstitutionId = sparse->CurrencySubstitutionId; - itemTemplate.CurrencySubstitutionCount = sparse->CurrencySubstitutionCount; itemTemplate.ScriptId = 0; itemTemplate.FoodType = 0; itemTemplate.MinMoneyLoot = 0; itemTemplate.MaxMoneyLoot = 0; - ++sparseCount; - } + itemTemplate.FlagsCu = 0; + itemTemplate.SpellPPMRate = 0.f; - // Load missing items from item_template AND overwrite data from Item-sparse.db2 (item_template is supposed to contain Item-sparse.adb data) - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 - QueryResult result = WorldDatabase.Query("SELECT entry, Class, SubClass, SoundOverrideSubclass, Name, DisplayId, Quality, Flags, FlagsExtra, Unk430_1, Unk430_2, BuyCount, BuyPrice, SellPrice, " - // 14 15 16 17 18 19 20 21 - "InventoryType, AllowableClass, AllowableRace, ItemLevel, RequiredLevel, RequiredSkill, RequiredSkillRank, RequiredSpell, " - // 22 23 24 25 26 27 28 - "RequiredHonorRank, RequiredCityRank, RequiredReputationFaction, RequiredReputationRank, MaxCount, Stackable, ContainerSlots, " - // 29 30 31 32 33 34 35 36 - "stat_type1, stat_value1, stat_unk1_1, stat_unk2_1, stat_type2, stat_value2, stat_unk1_2, stat_unk2_2, " - // 37 38 39 40 41 42 43 44 - "stat_type3, stat_value3, stat_unk1_3, stat_unk2_3, stat_type4, stat_value4, stat_unk1_4, stat_unk2_4, " - // 45 46 47 48 49 50 51 52 - "stat_type5, stat_value5, stat_unk1_5, stat_unk2_5, stat_type6, stat_value6, stat_unk1_6, stat_unk2_6, " - // 53 54 55 56 57 58 59 60 - "stat_type7, stat_value7, stat_unk1_7, stat_unk2_7, stat_type8, stat_value8, stat_unk1_8, stat_unk2_8, " - // 61 62 63 64 65 66 67 68 - "stat_type9, stat_value9, stat_unk1_9, stat_unk2_9, stat_type10, stat_value10, stat_unk1_10, stat_unk2_10, " - // 69 70 71 72 - "ScalingStatDistribution, DamageType, Delay, RangedModRange, " - // 73 74 75 76 77 78 - "spellid_1, spelltrigger_1, spellcharges_1, spellcooldown_1, spellcategory_1, spellcategorycooldown_1, " - // 79 80 81 82 83 84 - "spellid_2, spelltrigger_2, spellcharges_2, spellcooldown_2, spellcategory_2, spellcategorycooldown_2, " - // 85 86 87 88 89 90 - "spellid_3, spelltrigger_3, spellcharges_3, spellcooldown_3, spellcategory_3, spellcategorycooldown_3, " - // 91 92 93 94 95 96 - "spellid_4, spelltrigger_4, spellcharges_4, spellcooldown_4, spellcategory_4, spellcategorycooldown_4, " - // 97 98 99 100 101 102 - "spellid_5, spelltrigger_5, spellcharges_5, spellcooldown_5, spellcategory_5, spellcategorycooldown_5, " - // 103 104 105 106 107 108 109 110 - "Bonding, Description, PageText, LanguageID, PageMaterial, StartQuest, LockID, Material, " - // 111 112 113 114 115 116 117 118 - "Sheath, RandomProperty, RandomSuffix, ItemSet, Area, Map, BagFamily, TotemCategory, " - // 119 120 121 122 123 124 125 - "SocketColor_1, SocketContent_1, SocketColor_2, SocketContent_2, SocketColor_3, SocketContent_3, SocketBonus, " - // 126 127 128 129 130 131 - "GemProperties, ArmorDamageModifier, Duration, ItemLimitCategory, HolidayId, StatScalingFactor, " - // 132 133 - "CurrencySubstitutionId, CurrencySubstitutionCount " - "FROM item_template"); - - if (result) - { - do + for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { - Field* fields = result->Fetch(); - uint32 itemId = fields[0].GetUInt32(); - if (_itemTemplateStore.find(itemId) != _itemTemplateStore.end()) - --sparseCount; + ItemEffect effect; + effect.SpellID = sparse->SpellID[i]; + effect.Trigger = sparse->SpellTrigger[i]; + effect.Charges = sparse->SpellCharges[i]; + effect.Cooldown = sparse->SpellCooldown[i]; + effect.Category = sparse->SpellCategory[i]; + effect.CategoryCooldown = sparse->SpellCategoryCooldown[i]; + itemTemplate.Effects.push_back(effect); + } - ItemTemplate& itemTemplate = _itemTemplateStore[itemId]; - - itemTemplate.ItemId = itemId; - itemTemplate.Class = uint32(fields[1].GetUInt8()); - itemTemplate.SubClass = uint32(fields[2].GetUInt8()); - itemTemplate.SoundOverrideSubclass = fields[3].GetInt32(); - itemTemplate.Name1 = fields[4].GetString(); - itemTemplate.DisplayInfoID = fields[5].GetUInt32(); - itemTemplate.Quality = uint32(fields[6].GetUInt8()); - itemTemplate.Flags = fields[7].GetUInt32(); - itemTemplate.Flags2 = fields[8].GetUInt32(); - itemTemplate.Unk430_1 = fields[9].GetFloat(); - itemTemplate.Unk430_2 = fields[10].GetFloat(); - itemTemplate.BuyCount = uint32(fields[11].GetUInt8()); - itemTemplate.BuyPrice = int32(fields[12].GetInt64()); - itemTemplate.SellPrice = fields[13].GetUInt32(); - - itemTemplate.InventoryType = uint32(fields[14].GetUInt8()); - itemTemplate.AllowableClass = fields[15].GetInt32(); - itemTemplate.AllowableRace = fields[16].GetInt32(); - itemTemplate.ItemLevel = uint32(fields[17].GetUInt16()); - itemTemplate.RequiredLevel = uint32(fields[18].GetUInt8()); - itemTemplate.RequiredSkill = uint32(fields[19].GetUInt16()); - itemTemplate.RequiredSkillRank = uint32(fields[20].GetUInt16()); - itemTemplate.RequiredSpell = fields[21].GetUInt32(); - itemTemplate.RequiredHonorRank = fields[22].GetUInt32(); - itemTemplate.RequiredCityRank = fields[23].GetUInt32(); - itemTemplate.RequiredReputationFaction = uint32(fields[24].GetUInt16()); - itemTemplate.RequiredReputationRank = uint32(fields[25].GetUInt16()); - itemTemplate.MaxCount = fields[26].GetInt32(); - itemTemplate.Stackable = fields[27].GetInt32(); - itemTemplate.ContainerSlots = uint32(fields[28].GetUInt8()); - for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i) - { - itemTemplate.ItemStat[i].ItemStatType = uint32(fields[29 + i * 4 + 0].GetUInt8()); - itemTemplate.ItemStat[i].ItemStatValue = int32(fields[29 + i * 4 + 1].GetInt16()); - itemTemplate.ItemStat[i].ItemStatAllocation = fields[29 + i * 4 + 2].GetInt32(); - itemTemplate.ItemStat[i].ItemStatSocketCostMultiplier = fields[29 + i * 4 + 3].GetInt32(); - } - - itemTemplate.ScalingStatDistribution = uint32(fields[69].GetUInt16()); - itemTemplate.DamageType = fields[70].GetUInt8(); - - itemTemplate.Delay = fields[71].GetUInt16(); - itemTemplate.RangedModRange = fields[72].GetFloat(); - for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - itemTemplate.Spells[i].SpellId = fields[73 + 6 * i + 0].GetInt32(); - itemTemplate.Spells[i].SpellTrigger = uint32(fields[73 + 6 * i + 1].GetUInt8()); - itemTemplate.Spells[i].SpellCharges = int32(fields[73 + 6 * i + 2].GetInt16()); - itemTemplate.Spells[i].SpellCooldown = fields[73 + 6 * i + 3].GetInt32(); - itemTemplate.Spells[i].SpellCategory = uint32(fields[73 + 6 * i + 4].GetUInt16()); - itemTemplate.Spells[i].SpellCategoryCooldown = fields[73 + 6 * i + 5].GetInt32(); - } - - itemTemplate.SpellPPMRate = 0.0f; - itemTemplate.Bonding = uint32(fields[103].GetUInt8()); - itemTemplate.Description = fields[104].GetString(); - itemTemplate.PageText = fields[105].GetUInt32(); - itemTemplate.LanguageID = uint32(fields[106].GetUInt8()); - itemTemplate.PageMaterial = uint32(fields[107].GetUInt8()); - itemTemplate.StartQuest = fields[108].GetUInt32(); - itemTemplate.LockID = fields[109].GetUInt32(); - itemTemplate.Material = int32(fields[110].GetInt8()); - itemTemplate.Sheath = uint32(fields[111].GetUInt8()); - itemTemplate.RandomProperty = fields[112].GetUInt32(); - itemTemplate.RandomSuffix = fields[113].GetInt32(); - itemTemplate.ItemSet = fields[114].GetUInt32(); - itemTemplate.MaxDurability = FillMaxDurability(itemTemplate.Class, itemTemplate.SubClass, - itemTemplate.InventoryType, itemTemplate.Quality, itemTemplate.ItemLevel); - - itemTemplate.Area = fields[115].GetUInt32(); - itemTemplate.Map = uint32(fields[116].GetUInt16()); - itemTemplate.BagFamily = fields[117].GetUInt32(); - itemTemplate.TotemCategory = fields[118].GetUInt32(); - for (uint32 i = 0; i < MAX_ITEM_PROTO_SOCKETS; ++i) - { - itemTemplate.Socket[i].Color = uint32(fields[119 + i*2].GetUInt8()); - itemTemplate.Socket[i].Content = fields[119 + i * 2 + 1].GetUInt32(); - } - - itemTemplate.socketBonus = fields[125].GetUInt32(); - itemTemplate.GemProperties = fields[126].GetUInt32(); - FillDisenchantFields(&itemTemplate.DisenchantID, &itemTemplate.RequiredDisenchantSkill, itemTemplate); - - itemTemplate.ArmorDamageModifier = fields[127].GetFloat(); - itemTemplate.Duration = fields[128].GetUInt32(); - itemTemplate.ItemLimitCategory = uint32(fields[129].GetInt16()); - itemTemplate.HolidayId = fields[130].GetUInt32(); - itemTemplate.StatScalingFactor = fields[131].GetFloat(); - itemTemplate.CurrencySubstitutionId = fields[132].GetInt32(); - itemTemplate.CurrencySubstitutionCount = fields[133].GetInt32(); - itemTemplate.ScriptId = 0; - itemTemplate.FoodType = 0; - itemTemplate.MinMoneyLoot = 0; - itemTemplate.MaxMoneyLoot = 0; - ++dbCount; - } while (result->NextRow()); + ++sparseCount; } // Check if item templates for DBC referenced character start outfit are present @@ -3172,9 +2920,9 @@ void ObjectMgr::LoadItemTemplates() } for (std::set::const_iterator itr = notFoundOutfit.begin(); itr != notFoundOutfit.end(); ++itr) - TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not exist in `item_template` but is referenced in `CharStartOutfit.dbc`", *itr); + TC_LOG_ERROR("sql.sql", "Item (Entry: %u) does not exist in `item.db2` but is referenced in `CharStartOutfit.dbc`", *itr); - TC_LOG_INFO("server.loading", ">> Loaded %u item templates from Item-sparse.db2 and %u from database in %u ms", sparseCount, dbCount, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u item templates in %u ms", sparseCount, GetMSTimeDiffToNow(oldMSTime)); } void ObjectMgr::LoadItemTemplateAddon() @@ -7284,17 +7032,6 @@ inline void CheckGOConsumable(GameObjectTemplate const* goInfo, uint32 dataN, ui goInfo->entry, goInfo->type, N, dataN); } -time_t ObjectMgr::GetHotfixDate(uint32 entry, uint32 type) const -{ - time_t ret = 0; - for (HotfixData::const_iterator itr = _hotfixData.begin(); itr != _hotfixData.end(); ++itr) - if (itr->Entry == entry && itr->Type == type) - if (time_t(itr->Timestamp) > ret) - ret = time_t(itr->Timestamp); - - return ret ? ret : GameTime::GetGameTime(); -} - void ObjectMgr::LoadGameObjectTemplate() { uint32 oldMSTime = getMSTime(); @@ -9907,74 +9644,6 @@ void ObjectMgr::LoadFactionChangeReputations() TC_LOG_INFO("server.loading", ">> Loaded %u faction change reputation pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -void ObjectMgr::LoadHotfixData() -{ - uint32 oldMSTime = getMSTime(); - - QueryResult result = WorldDatabase.Query("SELECT entry, type, UNIX_TIMESTAMP(hotfixDate) FROM hotfix_data"); - - if (!result) - { - TC_LOG_INFO("server.loading", ">> Loaded 0 hotfix info entries. DB table `hotfix_data` is empty."); - return; - } - - uint32 count = 0; - - _hotfixData.reserve(result->GetRowCount()); - - do - { - Field* fields = result->Fetch(); - - HotfixInfo info; - info.Entry = fields[0].GetUInt32(); - info.Type = fields[1].GetUInt32(); - info.Timestamp = fields[2].GetUInt64(); - _hotfixData.push_back(info); - - ++count; - } - while (result->NextRow()); - - TC_LOG_INFO("server.loading", ">> Loaded %u hotfix info entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); -} - -void ObjectMgr::LoadMissingKeyChains() -{ - uint32 oldMSTime = getMSTime(); - - QueryResult result = WorldDatabase.Query("SELECT keyId, k1, k2, k3, k4, k5, k6, k7, k8, " - "k9, k10, k11, k12, k13, k14, k15, k16, " - "k17, k18, k19, k20, k21, k22, k23, k24, " - "k25, k26, k27, k28, k29, k30, k31, k32 " - "FROM keychain_db2 ORDER BY keyId DESC"); - - if (!result) - { - TC_LOG_INFO("server.loading", ">> Loaded 0 KeyChain entries. DB table `keychain_db2` is empty."); - return; - } - - uint32 count = 0; - - do - { - Field* fields = result->Fetch(); - uint32 id = fields[0].GetUInt32(); - - KeyChainEntry* kce = sKeyChainStore.CreateEntry(id, true); - kce->Id = id; - for (uint32 i = 0; i < KEYCHAIN_SIZE; ++i) - kce->Key[i] = fields[1 + i].GetUInt8(); - - ++count; - } - while (result->NextRow()); - - TC_LOG_INFO("server.loading", ">> Loaded %u KeyChain entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); -} - void ObjectMgr::LoadFactionChangeSpells() { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index a0ab157554..692aa83e6e 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -23,6 +23,7 @@ #include "Corpse.h" #include "CreatureData.h" #include "DatabaseEnvFwd.h" +#include "DB2Stores.h" #include "Errors.h" #include "GameObjectData.h" #include "ItemTemplate.h" @@ -555,7 +556,6 @@ typedef std::map> TempSummonData typedef std::unordered_map CreatureLocaleContainer; typedef std::unordered_map GameObjectLocaleContainer; typedef std::unordered_map ItemTemplateContainer; -typedef std::unordered_map ItemLocaleContainer; typedef std::unordered_map QuestLocaleContainer; typedef std::unordered_map NpcTextLocaleContainer; typedef std::unordered_map PageTextLocaleContainer; @@ -864,15 +864,6 @@ struct DungeonEncounter typedef std::list DungeonEncounterList; typedef std::unordered_map DungeonEncounterContainer; -struct HotfixInfo -{ - uint32 Type; - uint32 Timestamp; - uint32 Entry; -}; - -typedef std::vector HotfixData; - struct TerrainSwapInfo { uint32 Id; @@ -1168,7 +1159,6 @@ class TC_GAME_API ObjectMgr void LoadItemTemplates(); void LoadItemTemplateAddon(); void LoadItemScriptNames(); - void LoadItemLocales(); void LoadQuestLocales(); void LoadNpcTextLocales(); void LoadPageTextLocales(); @@ -1361,12 +1351,6 @@ class TC_GAME_API ObjectMgr if (itr == _gameObjectLocaleStore.end()) return nullptr; return &itr->second; } - ItemLocale const* GetItemLocale(uint32 entry) const - { - ItemLocaleContainer::const_iterator itr = _itemLocaleStore.find(entry); - if (itr == _itemLocaleStore.end()) return nullptr; - return &itr->second; - } QuestLocale const* GetQuestLocale(uint32 entry) const { QuestLocaleContainer::const_iterator itr = _questLocaleStore.find(entry); @@ -1548,12 +1532,6 @@ class TC_GAME_API ObjectMgr bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId) != 0; } - void LoadHotfixData(); - HotfixData const& GetHotfixData() const { return _hotfixData; } - time_t GetHotfixDate(uint32 entry, uint32 type) const; - - void LoadMissingKeyChains(); - uint32 GetGameObjectTypeByEntry(uint32 entry) const; VehicleSeatAddon const* GetVehicleSeatAddon(uint32 seatId) const @@ -1713,7 +1691,6 @@ class TC_GAME_API ObjectMgr BroadcastTextContainer _broadcastTextStore; ItemTemplateContainer _itemTemplateStore; - ItemLocaleContainer _itemLocaleStore; QuestLocaleContainer _questLocaleStore; NpcTextLocaleContainer _npcTextLocaleStore; PageTextLocaleContainer _pageTextLocaleStore; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index b99acb4ac5..c94a5894f9 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1050,7 +1050,7 @@ void Group::GroupLoot(Loot* loot, WorldObject* pLootedObject) } //roll for over-threshold item if it's one-player loot - if (item->Quality >= uint32(m_lootThreshold)) + if (item->GetQuality() >= uint32(m_lootThreshold)) { ObjectGuid newitemGUID = ObjectGuid::Create(sObjectMgr->GetGenerator().Generate()); @@ -1191,7 +1191,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) item = sObjectMgr->GetItemTemplate(i->itemid); //roll for over-threshold item if it's one-player loot - if (item->Quality >= uint32(m_lootThreshold)) + if (item->GetQuality() >= uint32(m_lootThreshold)) { ObjectGuid newitemGUID = ObjectGuid::Create(sObjectMgr->GetGenerator().Generate()); @@ -1224,7 +1224,7 @@ void Group::NeedBeforeGreed(Loot* loot, WorldObject* lootedObject) if (item->DisenchantID && m_maxEnchantingLevel >= item->RequiredDisenchantSkill) r->rollVoteMask |= ROLL_FLAG_TYPE_DISENCHANT; - if (item->Flags2 & ITEM_FLAG2_CAN_ONLY_ROLL_GREED) + if (item->GetFlags2() & ITEM_FLAG2_CAN_ONLY_ROLL_GREED) r->rollVoteMask &= ~ROLL_FLAG_TYPE_NEED; loot->items[itemSlot].is_blocked = true; diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 65aa9f48f2..80f39e4611 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1264,7 +1264,7 @@ void Guild::BankMoveItemData::LogAction(MoveItemData* pFrom) const sLog->outCommand(m_pPlayer->GetSession()->GetAccountId(), "GM %s (Guid: %u) (Account: %u) deposit item: %s (Entry: %d Count: %u) to guild bank named: %s (Guild ID: %u)", m_pPlayer->GetName().c_str(), m_pPlayer->GetGUID().GetCounter(), m_pPlayer->GetSession()->GetAccountId(), - pFrom->GetItem()->GetTemplate()->Name1.c_str(), pFrom->GetItem()->GetEntry(), pFrom->GetItem()->GetCount(), + pFrom->GetItem()->GetTemplate()->GetDefaultLocaleName(), pFrom->GetItem()->GetEntry(), pFrom->GetItem()->GetCount(), m_pGuild->GetName().c_str(), m_pGuild->GetId()); } } diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 305038ba5c..d2be122408 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -230,11 +230,11 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) } if (itemEntry == 0) - itemEntry = item->GetTemplate()->ItemId; + itemEntry = item->GetTemplate()->GetId(); if (sAuctionMgr->GetAItem(item->GetGUID().GetCounter()) || !item->CanBeTraded() || item->IsNotEmptyBag() || - (item->GetTemplate()->Flags & ITEM_FLAG_CONJURED) || item->GetUInt32Value(ITEM_FIELD_DURATION) || - item->GetCount() < count[i] || itemEntry != item->GetTemplate()->ItemId) + (item->GetTemplate()->GetFlags() & ITEM_FLAG_CONJURED) || item->GetUInt32Value(ITEM_FIELD_DURATION) || + item->GetCount() < count[i] || itemEntry != item->GetTemplate()->GetId()) { SendAuctionCommandResult(nullptr, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; @@ -320,7 +320,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", - GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount()); + GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->GetDefaultLocaleName(), item->GetEntry(), item->GetCount()); } AH->Id = sObjectMgr->GenerateAuctionID(); @@ -338,7 +338,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", - _player->GetName().c_str(), _player->GetGUID().GetCounter(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUID().GetCounter(), item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); + _player->GetName().c_str(), _player->GetGUID().GetCounter(), item->GetTemplate()->GetDefaultLocaleName(), item->GetEntry(), item->GetGUID().GetCounter(), item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); // Add to pending auctions, or fail with insufficient funds error if (!sAuctionMgr->PendingAuctionAdd(_player, AH, item)) @@ -377,7 +377,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", - GetPlayerName().c_str(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount()); + GetPlayerName().c_str(), GetAccountId(), newItem->GetTemplate()->GetDefaultLocaleName(), newItem->GetEntry(), newItem->GetCount()); } AH->Id = sObjectMgr->GenerateAuctionID(); @@ -395,7 +395,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", - _player->GetName().c_str(), _player->GetGUID().GetCounter(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUID().GetCounter(), newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); + _player->GetName().c_str(), _player->GetGUID().GetCounter(), newItem->GetTemplate()->GetDefaultLocaleName(), newItem->GetEntry(), newItem->GetGUID().GetCounter(), newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); // Add to pending auctions, or fail with insufficient funds error if (!sAuctionMgr->PendingAuctionAdd(_player, AH, newItem)) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index d8e693f9f5..47aa0ceedd 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -46,6 +46,7 @@ #include "Opcodes.h" #include "Pet.h" #include "Player.h" +#include "QueryPackets.h" #include "PlayerDump.h" #include "QueryHolder.h" #include "ReputationMgr.h" @@ -933,17 +934,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) data << uint64(0); SendPacket(&data); - data.Initialize(SMSG_HOTFIX_INFO); - HotfixData const& hotfix = sObjectMgr->GetHotfixData(); - data.WriteBits(hotfix.size(), 22); - data.FlushBits(); - for (uint32 i = 0; i < hotfix.size(); ++i) - { - data << uint32(hotfix[i].Type); - data << uint32(hotfix[i].Timestamp); - data << uint32(hotfix[i].Entry); - } - SendPacket(&data); + WorldPackets::Query::HotfixNotifyBlob hotfixInfo; + hotfixInfo.Hotfixes = sDB2Manager.GetHotfixData(); + SendPacket(hotfixInfo.Write()); pCurrChar->SendInitialPacketsBeforeAddToMap(); diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 9edbfd72f5..6cdb80d2d4 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -292,7 +292,7 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData) return; } - if (pItem->GetTemplate()->Flags & ITEM_FLAG_NO_USER_DESTROY) + if (pItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_USER_DESTROY) { _player->SendEquipError(EQUIP_ERR_DROP_BOUND_ITEM, nullptr, nullptr); return; @@ -314,7 +314,7 @@ void WorldSession::HandleReadItem(WorldPacket& recvData) Item* pItem = _player->GetItemByPos(bag, slot); - if (pItem && pItem->GetTemplate()->PageText) + if (pItem && pItem->GetTemplate()->GetPageText()) { WorldPacket data; @@ -412,7 +412,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData) ItemTemplate const* pProto = pItem->GetTemplate(); if (pProto) { - if (pProto->SellPrice > 0) + if (pProto->GetSellPrice() > 0) { if (count < pItem->GetCount()) // need split items { @@ -442,7 +442,7 @@ void WorldSession::HandleSellItemOpcode(WorldPacket& recvData) _player->AddItemToBuyBackSlot(pItem); } - uint32 money = pProto->SellPrice * count; + uint32 money = pProto->GetSellPrice() * count; _player->ModifyMoney(money); _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money); } @@ -642,12 +642,12 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid) if (!_player->IsGameMaster()) // ignore conditions if GM on { // Respect allowed class - if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_ON_ACQUIRE) + if (!(itemTemplate->GetAllowableClass() & _player->getClassMask()) && itemTemplate->GetBonding() == BIND_ON_ACQUIRE) continue; // Only display items in vendor lists for the team the player is on - if ((itemTemplate->Flags2 & ITEM_FLAG2_FACTION_HORDE && _player->GetTeam() == ALLIANCE) || - (itemTemplate->Flags2 & ITEM_FLAG2_FACTION_ALLIANCE && _player->GetTeam() == HORDE)) + if ((itemTemplate->GetFlags2() & ITEM_FLAG2_FACTION_HORDE && _player->GetTeam() == ALLIANCE) || + (itemTemplate->GetFlags2() & ITEM_FLAG2_FACTION_ALLIANCE && _player->GetTeam() == HORDE)) continue; // Items sold out are not displayed in list @@ -661,7 +661,7 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid) continue; } - int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0; + int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->GetBuyPrice() * discountMod)) : 0; if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES)) price -= CalculatePct(price, priceMod); @@ -682,10 +682,10 @@ void WorldSession::SendListInventory(ObjectGuid vendorGuid) itemsData << uint32(vendorItem->item); itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency itemsData << uint32(price); - itemsData << uint32(itemTemplate->DisplayInfoID); + itemsData << uint32(itemTemplate->GetDisplayID()); // if (!unk "enabler") data << uint32(something); itemsData << int32(leftInStock); - itemsData << uint32(itemTemplate->BuyCount); + itemsData << uint32(itemTemplate->GetBuyCount()); if (++count >= MAX_VENDOR_ITEMS) break; @@ -989,7 +989,7 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) return; } - if (!(gift->GetTemplate()->Flags & ITEM_FLAG_IS_WRAPPER)) // cheating: non-wrapper wrapper + if (!(gift->GetTemplate()->GetFlags() & ITEM_FLAG_IS_WRAPPER)) // cheating: non-wrapper wrapper { _player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, gift, nullptr); return; @@ -1040,7 +1040,7 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recvData) } // maybe not correct check (it is better than nothing) - if (item->GetTemplate()->MaxCount > 0) + if (item->GetTemplate()->GetMaxCount() > 0) { _player->SendEquipError(EQUIP_ERR_CANT_WRAP_UNIQUE, item, nullptr); return; @@ -1118,11 +1118,11 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) GemPropertiesEntry const* GemProps[MAX_GEM_SOCKETS]; for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //get geminfo from dbc storage - GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetTemplate()->GemProperties) : nullptr; + GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetTemplate()->GetGemProperties()) : nullptr; // Find first prismatic socket int32 firstPrismatic = 0; - while (firstPrismatic < MAX_GEM_SOCKETS && itemProto->Socket[firstPrismatic].Color) + while (firstPrismatic < MAX_GEM_SOCKETS && itemProto->GetSocketColor(firstPrismatic)) ++firstPrismatic; for (int i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe @@ -1131,7 +1131,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) continue; // tried to put gem in socket where no socket exists (take care about prismatic sockets) - if (!itemProto->Socket[i].Color) + if (!itemProto->GetSocketColor(i)) { // no prismatic socket if (!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) @@ -1142,19 +1142,19 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) } // tried to put normal gem in meta socket - if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->Type != SOCKET_COLOR_META) + if (itemProto->GetSocketColor(i) == SOCKET_COLOR_META && GemProps[i]->Type != SOCKET_COLOR_META) return; // tried to put meta gem in normal socket - if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->Type == SOCKET_COLOR_META) + if (itemProto->GetSocketColor(i) != SOCKET_COLOR_META && GemProps[i]->Type == SOCKET_COLOR_META) return; // tried to put normal gem in cogwheel socket - if (itemProto->Socket[i].Color == SOCKET_COLOR_COGWHEEL && GemProps[i]->Type != SOCKET_COLOR_COGWHEEL) + if (itemProto->GetSocketColor(i) == SOCKET_COLOR_COGWHEEL && GemProps[i]->Type != SOCKET_COLOR_COGWHEEL) return; // tried to put cogwheel gem in normal socket - if (itemProto->Socket[i].Color != SOCKET_COLOR_COGWHEEL && GemProps[i]->Type == SOCKET_COLOR_COGWHEEL) + if (itemProto->GetSocketColor(i) != SOCKET_COLOR_COGWHEEL && GemProps[i]->Type == SOCKET_COLOR_COGWHEEL) return; } @@ -1176,7 +1176,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) ItemTemplate const* iGemProto = Gems[i]->GetTemplate(); // unique item (for new and already placed bit removed enchantments - if (iGemProto->Flags & ITEM_FLAG_UNIQUE_EQUIPPABLE) + if (iGemProto->GetFlags() & ITEM_FLAG_UNIQUE_EQUIPPABLE) { for (int j = 0; j < MAX_GEM_SOCKETS; ++j) { @@ -1185,7 +1185,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) if (Gems[j]) { - if (iGemProto->ItemId == Gems[j]->GetEntry()) + if (iGemProto->GetId() == Gems[j]->GetEntry()) { _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, nullptr); return; @@ -1195,7 +1195,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) { if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) { - if (iGemProto->ItemId == enchantEntry->Src_itemID) + if (iGemProto->GetId() == enchantEntry->Src_itemID) { _player->SendEquipError(EQUIP_ERR_ITEM_UNIQUE_EQUIPPABLE_SOCKETED, itemTarget, nullptr); return; @@ -1207,9 +1207,9 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) // unique limit type item int32 limit_newcount = 0; - if (iGemProto->ItemLimitCategory) + if (iGemProto->GetItemLimitCategory()) { - if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->ItemLimitCategory)) + if (ItemLimitCategoryEntry const* limitEntry = sItemLimitCategoryStore.LookupEntry(iGemProto->GetItemLimitCategory())) { // NOTE: limitEntry->mode is not checked because if item has limit then it is applied in equip case for (int j = 0; j < MAX_GEM_SOCKETS; ++j) @@ -1217,7 +1217,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) if (Gems[j]) { // new gem - if (iGemProto->ItemLimitCategory == Gems[j]->GetTemplate()->ItemLimitCategory) + if (iGemProto->GetItemLimitCategory() == Gems[j]->GetTemplate()->GetItemLimitCategory()) ++limit_newcount; } else if (OldEnchants[j]) @@ -1225,7 +1225,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) // existing gem if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(OldEnchants[j])) if (ItemTemplate const* jProto = sObjectMgr->GetItemTemplate(enchantEntry->Src_itemID)) - if (iGemProto->ItemLimitCategory == jProto->ItemLimitCategory) + if (iGemProto->GetItemLimitCategory() == jProto->GetItemLimitCategory()) ++limit_newcount; } } @@ -1278,7 +1278,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) if (SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... { _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false); - itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->socketBonus : 0), 0, 0, _player->GetGUID()); + itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->GetSocketBonus() : 0), 0, 0, _player->GetGUID()); _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, true); //it is not displayed, client has an inbuilt system to determine if the bonus is activated } @@ -1542,7 +1542,7 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData) transmogrified[i]->SetNotRefundable(player); transmogrified[i]->ClearSoulboundTradeable(player); - if (transmogrifier[i]->GetTemplate()->Bonding == BIND_ON_EQUIP || transmogrifier[i]->GetTemplate()->Bonding == BIND_ON_USE) + if (transmogrifier[i]->GetTemplate()->GetBonding() == BIND_ON_EQUIP || transmogrifier[i]->GetTemplate()->GetBonding() == BIND_ON_USE) transmogrifier[i]->SetBinding(true); transmogrifier[i]->SetOwnerGUID(player->GetGUID()); diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index 0352845c44..4026958fc5 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -378,7 +378,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid) ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling - if (proto->Flags & (ITEM_FLAG_IS_PROSPECTABLE | ITEM_FLAG_IS_MILLABLE)) + if (proto->GetFlags() & (ITEM_FLAG_IS_PROSPECTABLE | ITEM_FLAG_IS_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); @@ -394,7 +394,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid) else { // Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item - if (pItem->loot.isLooted() || !(proto->Flags & ITEM_FLAG_HAS_LOOT)) + if (pItem->loot.isLooted() || !(proto->GetFlags() & ITEM_FLAG_HAS_LOOT)) player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } return; // item can be looted only single player diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 8c83728bb0..456aa14dee 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -251,7 +251,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) if (Item* item = player->GetItemByGuid(itemGUIDs[i])) { ItemTemplate const* itemProto = item->GetTemplate(); - if (!itemProto || !(itemProto->Flags & ITEM_FLAG_IS_BOUND_TO_ACCOUNT)) + if (!itemProto || !(itemProto->GetFlags() & ITEM_FLAG_IS_BOUND_TO_ACCOUNT)) { accountBound = false; break; @@ -305,7 +305,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) } } - if (item->GetTemplate()->Flags & ITEM_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) + if (item->GetTemplate()->GetFlags() & ITEM_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; @@ -349,7 +349,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) { sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail item: %s (Entry: %u Count: %u) " "to: %s (%s) (Account: %u)", GetPlayerName().c_str(), GetGUIDLow(), GetAccountId(), - item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), + item->GetTemplate()->GetDefaultLocaleName(), item->GetEntry(), item->GetCount(), receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId); } @@ -575,7 +575,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData) sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); } sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: " UI64FMTD " to player: %s (Account: %u)", - GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId); + GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->GetDefaultLocaleName(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId); } else if (!receiver) sender_accId = sCharacterCache->GetCharacterAccountIdByGuid(sender_guid); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 6782f2631c..33b5cb981e 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1641,74 +1641,6 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket) _player->SetPendingBind(0, 0); } -void WorldSession::HandleRequestHotfix(WorldPacket& recvPacket) -{ - uint32 type, count; - recvPacket >> type; - - DB2StorageBase const* store = GetDB2Storage(type); - if (!store) - { - TC_LOG_ERROR("network", "CMSG_REQUEST_HOTFIX: Received unknown hotfix type: %u", type); - recvPacket.rfinish(); - return; - } - - count = recvPacket.ReadBits(23); - - ObjectGuid* guids = new ObjectGuid[count]; - for (uint32 i = 0; i < count; ++i) - { - guids[i][0] = recvPacket.ReadBit(); - guids[i][4] = recvPacket.ReadBit(); - guids[i][7] = recvPacket.ReadBit(); - guids[i][2] = recvPacket.ReadBit(); - guids[i][5] = recvPacket.ReadBit(); - guids[i][3] = recvPacket.ReadBit(); - guids[i][6] = recvPacket.ReadBit(); - guids[i][1] = recvPacket.ReadBit(); - } - - uint32 entry; - for (uint32 i = 0; i < count; ++i) - { - recvPacket.ReadByteSeq(guids[i][5]); - recvPacket.ReadByteSeq(guids[i][6]); - recvPacket.ReadByteSeq(guids[i][7]); - recvPacket.ReadByteSeq(guids[i][0]); - recvPacket.ReadByteSeq(guids[i][1]); - recvPacket.ReadByteSeq(guids[i][3]); - recvPacket.ReadByteSeq(guids[i][4]); - recvPacket >> entry; - recvPacket.ReadByteSeq(guids[i][2]); - - if (!store->HasRecord(entry)) - { - WorldPacket data(SMSG_DB_REPLY, 4 * 4); - data << -int32(entry); - data << uint32(store->GetHash()); - data << uint32(GameTime::GetGameTime()); - data << uint32(0); - SendPacket(&data); - continue; - } - - WorldPacket data(SMSG_DB_REPLY); - data << int32(entry); - data << uint32(store->GetHash()); - data << uint32(sObjectMgr->GetHotfixDate(entry, store->GetHash())); - - size_t sizePos = data.wpos(); - data << uint32(0); // size of next block - store->WriteRecord(entry, LocaleConstant(GetSessionDbcLocale()), data); - data.put(sizePos, data.wpos() - sizePos - 4); - - SendPacket(&data); - } - - delete[] guids; -} - void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket) { TC_LOG_DEBUG("network", "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY"); diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp index 0471756156..5a43bf4dbd 100644 --- a/src/server/game/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Handlers/PetitionsHandler.cpp @@ -184,7 +184,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) } ItemPosCountVec dest; - InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); + InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->GetBuyCount()); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, nullptr, nullptr, charterid); diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 3bd48289d6..fba437af35 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -27,6 +27,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" +#include "QueryPackets.h" #include "UpdateMask.h" #include "World.h" #include "WorldPacket.h" @@ -542,3 +543,34 @@ void WorldSession::HandleQuestPOIQuery(WorldPacket& recvData) SendPacket(&data); } + +void WorldSession::HandleDBQueryBulk(WorldPackets::Query::DBQueryBulk& packet) +{ + DB2StorageBase const* store = sDB2Manager.GetStorage(packet.TableHash); + if (!store) + { + TC_LOG_ERROR("network", "CMSG_DB_QUERY_BULK: Received unknown hotfix type: %u", packet.TableHash); + return; + } + + for (WorldPackets::Query::DBQueryRecord const& rec : packet.Queries) + { + WorldPackets::Query::DBReply response; + response.TableHash = packet.TableHash; + + if (store->HasRecord(rec.RecordID)) + { + response.RecordID = rec.RecordID; + response.Timestamp = sDB2Manager.GetHotfixDate(rec.RecordID, packet.TableHash); + store->WriteRecord(rec.RecordID, GetSessionDbcLocale(), response.Data); + } + else + { + TC_LOG_ERROR("network", "CMSG_DB_QUERY_BULK: Entry %u does not exist in datastore: %u", rec.RecordID, packet.TableHash); + response.RecordID = -int32(rec.RecordID); + response.Timestamp = GameTime::GetGameTime(); + } + + SendPacket(response.Write()); + } +} diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 1c200777e3..e89a6adeea 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -133,7 +133,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) } // some item classes can be used only in equipped state - if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) + if (proto->GetInventoryType() != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, nullptr); return; @@ -147,14 +147,14 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) } // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) - if (proto->Class == ITEM_CLASS_CONSUMABLE && !(proto->Flags & ITEM_FLAG_IGNORE_DEFAULT_ARENA_RESTRICTIONS) && pUser->InArena()) + if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && !(proto->GetFlags() & ITEM_FLAG_IGNORE_DEFAULT_ARENA_RESTRICTIONS) && pUser->InArena()) { pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, nullptr); return; } // don't allow items banned in arena - if ((proto->Flags & ITEM_FLAG_NOT_USEABLE_IN_ARENA) && pUser->InArena()) + if ((proto->GetFlags() & ITEM_FLAG_NOT_USEABLE_IN_ARENA) && pUser->InArena()) { pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, nullptr); return; @@ -162,9 +162,9 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) if (pUser->IsInCombat()) { - for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (ItemEffect const& effect : proto->Effects) { - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId)) + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(effect.SpellID)) { if (!spellInfo->CanBeUsedInCombat()) { @@ -176,7 +176,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) } // check also BIND_ON_ACQUIRE and BIND_QUEST for .additem or .additemset case by GM (not binded at adding to inventory) - if (pItem->GetTemplate()->Bonding == BIND_ON_USE || pItem->GetTemplate()->Bonding == BIND_ON_ACQUIRE || pItem->GetTemplate()->Bonding == BIND_QUEST) + if (pItem->GetTemplate()->GetBonding() == BIND_ON_USE || pItem->GetTemplate()->GetBonding() == BIND_ON_ACQUIRE || pItem->GetTemplate()->GetBonding() == BIND_QUEST) { if (!pItem->IsSoulBound()) { @@ -234,16 +234,16 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) } // Verify that the bag is an actual bag or wrapped item that can be used "normally" - if (!(proto->Flags & ITEM_FLAG_HAS_LOOT) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) + if (!(proto->GetFlags() & ITEM_FLAG_HAS_LOOT) && !item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_WRAPPED)) { player->SendEquipError(EQUIP_ERR_CLIENT_LOCKED_OUT, item, nullptr); TC_LOG_INFO("entities.player.cheat", "Possible hacking attempt: Player %s [guid: %u] tried to open item [guid: %u, entry: %u] which is not openable!", - player->GetName().c_str(), player->GetGUID().GetCounter(), item->GetGUID().GetCounter(), proto->ItemId); + player->GetName().c_str(), player->GetGUID().GetCounter(), item->GetGUID().GetCounter(), proto->GetId()); return; } // locked item - uint32 lockId = proto->LockID; + uint32 lockId = proto->GetLockID(); if (lockId) { LockEntry const* lockInfo = sLockStore.LookupEntry(lockId); @@ -724,7 +724,7 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData) else if (*itr == EQUIPMENT_SLOT_BACK && player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK)) data << uint32(0); else if (Item const* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, *itr)) - data << uint32(item->GetTemplate()->DisplayInfoID); + data << uint32(item->GetTemplate()->GetDisplayID()); else data << uint32(0); } diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 28f6d487e6..178bbd6c0b 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -140,7 +140,7 @@ void WorldSession::SendUpdateTrade(bool trader_data /*= true*/) data.WriteBit(creatorGuid[2]); data.WriteBit(creatorGuid[3]); data.WriteBit(creatorGuid[5]); - data.WriteBit(item->GetTemplate()->LockID != 0); + data.WriteBit(item->GetTemplate()->GetLockID() != 0); data.WriteBit(creatorGuid[0]); itemData.WriteByteSeq(creatorGuid[1]); @@ -182,7 +182,7 @@ void WorldSession::SendUpdateTrade(bool trader_data /*= true*/) itemData.WriteByteSeq(giftCreatorGuid[7]); itemData.WriteByteSeq(giftCreatorGuid[4]); - itemData << uint32(item->GetTemplate()->ItemId); + itemData << uint32(item->GetTemplate()->GetId()); itemData.WriteByteSeq(giftCreatorGuid[0]); @@ -230,7 +230,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) { sLog->outCommand(_player->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", _player->GetName().c_str(), _player->GetSession()->GetAccountId(), - myItems[i]->GetTemplate()->Name1.c_str(), myItems[i]->GetEntry(), myItems[i]->GetCount(), + myItems[i]->GetTemplate()->GetDefaultLocaleName(), myItems[i]->GetEntry(), myItems[i]->GetCount(), trader->GetName().c_str(), trader->GetSession()->GetAccountId()); } @@ -248,7 +248,7 @@ void WorldSession::moveItems(Item* myItems[], Item* hisItems[]) { sLog->outCommand(trader->GetSession()->GetAccountId(), "GM %s (Account: %u) trade: %s (Entry: %d Count: %u) to player: %s (Account: %u)", trader->GetName().c_str(), trader->GetSession()->GetAccountId(), - hisItems[i]->GetTemplate()->Name1.c_str(), hisItems[i]->GetEntry(), hisItems[i]->GetCount(), + hisItems[i]->GetTemplate()->GetDefaultLocaleName(), hisItems[i]->GetEntry(), hisItems[i]->GetCount(), _player->GetName().c_str(), _player->GetSession()->GetAccountId()); } diff --git a/src/server/game/Loot/Loot.cpp b/src/server/game/Loot/Loot.cpp index 121c71bac8..11db358095 100644 --- a/src/server/game/Loot/Loot.cpp +++ b/src/server/game/Loot/Loot.cpp @@ -41,7 +41,7 @@ LootItem::LootItem(LootStoreItem const& li) if (!is_currency) { ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemid); - freeforall = proto && (proto->Flags & ITEM_FLAG_MULTI_DROP); + freeforall = proto && (proto->GetFlags() & ITEM_FLAG_MULTI_DROP); follow_loot_rules = proto && (proto->FlagsCu & ITEM_FLAGS_CU_FOLLOW_LOOT_RULES); } else @@ -74,18 +74,18 @@ bool LootItem::AllowedForPlayer(Player const* player) const return false; // not show loot for players without profession or those who already know the recipe - if ((pProto->Flags & ITEM_FLAG_HIDE_UNUSABLE_RECIPE) && (!player->HasSkill(pProto->RequiredSkill) || player->HasSpell(pProto->Spells[1].SpellId))) + if ((pProto->GetFlags() & ITEM_FLAG_HIDE_UNUSABLE_RECIPE) && (!player->HasSkill(pProto->GetRequiredSkill()) || player->HasSpell(pProto->Effects[1].SpellID))) return false; // not show loot for not own team - if ((pProto->Flags2 & ITEM_FLAG2_FACTION_HORDE) && player->GetTeam() != HORDE) + if ((pProto->GetFlags2() & ITEM_FLAG2_FACTION_HORDE) && player->GetTeam() != HORDE) return false; - if ((pProto->Flags2 & ITEM_FLAG2_FACTION_ALLIANCE) && player->GetTeam() != ALLIANCE) + if ((pProto->GetFlags2() & ITEM_FLAG2_FACTION_ALLIANCE) && player->GetTeam() != ALLIANCE) return false; // check quest requirements - if (!(pProto->FlagsCu & ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && ((needs_quest || (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE)) && !player->HasQuestForItem(itemid))) + if (!(pProto->FlagsCu & ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && ((needs_quest || (pProto->GetStartQuest() && player->GetQuestStatus(pProto->GetStartQuest()) != QUEST_STATUS_NONE)) && !player->HasQuestForItem(itemid))) return false; return true; @@ -156,7 +156,7 @@ void Loot::AddItem(LootStoreItem const& item) // non-conditional one-player only items are counted here, // free for all items are counted in FillFFALoot(), // non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot() - if (!item.needs_quest && item.conditions.empty() && !(proto->Flags & ITEM_FLAG_MULTI_DROP)) + if (!item.needs_quest && item.conditions.empty() && !(proto->GetFlags() & ITEM_FLAG_MULTI_DROP)) ++unlootedCount; } } @@ -212,7 +212,7 @@ bool Loot::FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bo for (uint8 i = 0; i < items.size(); ++i) { if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(items[i].itemid)) - if (proto->Quality < uint32(group->GetLootThreshold())) + if (proto->GetQuality() < uint32(group->GetLootThreshold())) items[i].is_underthreshold = true; } } @@ -575,7 +575,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li) { b << uint32(li.itemid); b << uint32(li.count); // nr of items of this type - b << uint32(ASSERT_NOTNULL(sObjectMgr->GetItemTemplate(li.itemid))->DisplayInfoID); + b << uint32(ASSERT_NOTNULL(sObjectMgr->GetItemTemplate(li.itemid))->GetDisplayID()); b << uint32(li.randomSuffix); b << uint32(li.randomPropertyId); //b << uint8(0); // slot type - will send after this function call diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 8ef56142a2..6db682550f 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -296,7 +296,7 @@ bool LootStoreItem::Roll(bool rate) const ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid); - float qualityModifier = pProto && rate ? sWorld->getRate(qualityToRate[pProto->Quality]) : 1.0f; + float qualityModifier = pProto && rate ? sWorld->getRate(qualityToRate[pProto->GetQuality()]) : 1.0f; return roll_chance_f(chance*qualityModifier); } @@ -935,8 +935,8 @@ void LoadLootTemplates_Item() // remove real entries and check existence loot ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) - if (lootIdSet.find(itr->second.ItemId) != lootIdSet.end() && itr->second.Flags & ITEM_FLAG_HAS_LOOT) - lootIdSet.erase(itr->second.ItemId); + if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end() && itr->second.GetFlags() & ITEM_FLAG_HAS_LOOT) + lootIdSet.erase(itr->second.GetId()); // output error for any still listed (not referenced from appropriate table) ids LootTemplates_Item.ReportUnusedIds(lootIdSet); @@ -960,11 +960,11 @@ void LoadLootTemplates_Milling() ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - if (!(itr->second.Flags & ITEM_FLAG_IS_MILLABLE)) + if (!(itr->second.GetFlags() & ITEM_FLAG_IS_MILLABLE)) continue; - if (lootIdSet.find(itr->second.ItemId) != lootIdSet.end()) - lootIdSet.erase(itr->second.ItemId); + if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end()) + lootIdSet.erase(itr->second.GetId()); } // output error for any still listed (not referenced from appropriate table) ids @@ -1023,11 +1023,11 @@ void LoadLootTemplates_Prospecting() ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - if (!(itr->second.Flags & ITEM_FLAG_IS_PROSPECTABLE)) + if (!(itr->second.GetFlags() & ITEM_FLAG_IS_PROSPECTABLE)) continue; - if (lootIdSet.find(itr->second.ItemId) != lootIdSet.end()) - lootIdSet.erase(itr->second.ItemId); + if (lootIdSet.find(itr->second.GetId()) != lootIdSet.end()) + lootIdSet.erase(itr->second.GetId()); } // output error for any still listed (not referenced from appropriate table) ids diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 6c213c88a7..1f797331c5 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -297,7 +297,7 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player rewards.ChoiceItems[i].ItemID = RewardChoiceItemId[i]; rewards.ChoiceItems[i].Quantity = RewardChoiceItemCount[i]; if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardChoiceItemId[i])) - rewards.ChoiceItems[i].DisplayID = itemTemplate->DisplayInfoID; + rewards.ChoiceItems[i].DisplayID = itemTemplate->GetDisplayID(); } for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i) @@ -305,7 +305,7 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player rewards.ItemID[i] = RewardItemId[i]; rewards.ItemQty[i] = RewardItemIdCount[i]; if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(RewardItemId[i])) - rewards.ItemDisplayID[i] = itemTemplate->DisplayInfoID; + rewards.ItemDisplayID[i] = itemTemplate->GetDisplayID(); } for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) diff --git a/src/server/game/Server/Packets/AllPackets.h b/src/server/game/Server/Packets/AllPackets.h index 3df8ba1680..01d20024b1 100644 --- a/src/server/game/Server/Packets/AllPackets.h +++ b/src/server/game/Server/Packets/AllPackets.h @@ -26,6 +26,7 @@ #include "MovementPackets.h" #include "NPCPackets.h" #include "QuestPackets.h" +#include "QueryPackets.h" #include "SystemPackets.h" #endif // AllPackets_h__ diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index 0fdcfc62ac..826a36a0bf 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -114,8 +114,8 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel break; } - VisualItems[slot].InvType = proto->InventoryType; - VisualItems[slot].DisplayID = proto->DisplayInfoID; + VisualItems[slot].InvType = proto->GetInventoryType(); + VisualItems[slot].DisplayID = proto->GetDisplayID(); VisualItems[slot].DisplayEnchantID = enchant ? enchant->ItemVisual : 0; } } diff --git a/src/server/game/Server/Packets/LFGPackets.cpp b/src/server/game/Server/Packets/LFGPackets.cpp index cb460c938c..038f7ca145 100644 --- a/src/server/game/Server/Packets/LFGPackets.cpp +++ b/src/server/game/Server/Packets/LFGPackets.cpp @@ -162,7 +162,7 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerQuestReward { ItemTemplate const* item = sObjectMgr->GetItemTemplate(playerQuestRewardItem.ItemID); data << int32(playerQuestRewardItem.ItemID); - data << int32(item ? item->DisplayInfoID : 0); + data << int32(item ? item->GetDisplayID() : 0); data << int32(playerQuestRewardItem.Quantity); data << uint8(0); @@ -452,7 +452,7 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGPlayerRewards con { ItemTemplate const* item = !lfgPlayerRewards.IsCurrency ? sObjectMgr->GetItemTemplate(lfgPlayerRewards.RewardItem) : nullptr; data << uint32(lfgPlayerRewards.RewardItem); - data << uint32(item ? item->DisplayInfoID : 0); + data << uint32(item ? item->GetDisplayID() : 0); data << uint32(lfgPlayerRewards.RewardItemQuantity); data << uint8(lfgPlayerRewards.IsCurrency); diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp new file mode 100644 index 0000000000..33334ea966 --- /dev/null +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -0,0 +1,78 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + + +#include "QueryPackets.h" + +void WorldPackets::Query::DBQueryBulk::Read() +{ + _worldPacket >> TableHash; + + uint32 count = _worldPacket.ReadBits(23); + Queries.resize(count); + + for (uint32 i = 0; i < count; ++i) + { + Queries[i].GUID[0] = _worldPacket.ReadBit(); + Queries[i].GUID[4] = _worldPacket.ReadBit(); + Queries[i].GUID[7] = _worldPacket.ReadBit(); + Queries[i].GUID[2] = _worldPacket.ReadBit(); + Queries[i].GUID[5] = _worldPacket.ReadBit(); + Queries[i].GUID[3] = _worldPacket.ReadBit(); + Queries[i].GUID[6] = _worldPacket.ReadBit(); + Queries[i].GUID[1] = _worldPacket.ReadBit(); + } + + for (uint32 i = 0; i < count; ++i) + { + _worldPacket.ReadByteSeq(Queries[i].GUID[5]); + _worldPacket.ReadByteSeq(Queries[i].GUID[6]); + _worldPacket.ReadByteSeq(Queries[i].GUID[7]); + _worldPacket.ReadByteSeq(Queries[i].GUID[0]); + _worldPacket.ReadByteSeq(Queries[i].GUID[1]); + _worldPacket.ReadByteSeq(Queries[i].GUID[3]); + _worldPacket.ReadByteSeq(Queries[i].GUID[4]); + _worldPacket >> Queries[i].RecordID; + _worldPacket.ReadByteSeq(Queries[i].GUID[2]); + } +} + +WorldPacket const* WorldPackets::Query::DBReply::Write() +{ + _worldPacket << RecordID; + _worldPacket << TableHash; + _worldPacket << Timestamp; + _worldPacket << uint32(Data.size()); + _worldPacket.append(Data); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Query::HotfixNotifyBlob::Write() +{ + _worldPacket.WriteBits(Hotfixes->size(), 22); + _worldPacket.FlushBits(); + + for (HotfixNotify const& hotfix : *Hotfixes) + { + _worldPacket << uint32(hotfix.TableHash); + _worldPacket << uint32(hotfix.Timestamp); + _worldPacket << int32(hotfix.Entry); + } + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/QueryPackets.h b/src/server/game/Server/Packets/QueryPackets.h new file mode 100644 index 0000000000..413d406312 --- /dev/null +++ b/src/server/game/Server/Packets/QueryPackets.h @@ -0,0 +1,69 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef QueryPackets_h__ +#define QueryPackets_h__ + +#include "Packet.h" + +namespace WorldPackets +{ + namespace Query + { + struct DBQueryRecord + { + ObjectGuid GUID; + uint32 RecordID; + }; + + class DBQueryBulk final : public ClientPacket + { + public: + DBQueryBulk(WorldPacket&& packet) : ClientPacket(CMSG_DB_QUERY_BULK, std::move(packet)) { } + + void Read() override; + + uint32 TableHash = 0; + std::vector Queries; + }; + + class DBReply final : public ServerPacket + { + public: + DBReply() : ServerPacket(SMSG_DB_REPLY, 12) { } + + WorldPacket const* Write() override; + + uint32 TableHash = 0; + uint32 Timestamp = 0; + int32 RecordID = 0; + ByteBuffer Data; + }; + + class HotfixNotifyBlob final : public ServerPacket + { + public: + HotfixNotifyBlob() : ServerPacket(SMSG_HOTFIX_NOTIFY_BLOB, 4) { } + + WorldPacket const* Write() override; + + HotfixData const* Hotfixes = nullptr; + }; + } +} + +#endif // QueryPackets_h__ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 5e7cc41d99..4d07937e40 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -283,6 +283,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_CORPSE_MAP_POSITION_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseMapPositionQuery ); DEFINE_HANDLER(CMSG_CREATURE_QUERY, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleCreatureQueryOpcode ); DEFINE_HANDLER(CMSG_DANCE_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_HANDLER(CMSG_DB_QUERY_BULK, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleDBQueryBulk ); DEFINE_HANDLER(CMSG_DEL_FRIEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelFriendOpcode ); DEFINE_HANDLER(CMSG_DEL_IGNORE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleDelIgnoreOpcode ); DEFINE_HANDLER(CMSG_DEL_VOICE_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -539,7 +540,6 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_REQUEST_CATEGORY_COOLDOWNS, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestCategoryCooldowns ); DEFINE_HANDLER(CMSG_REQUEST_CEMETERY_LIST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestCemeteryList ); DEFINE_HANDLER(CMSG_REQUEST_GUILD_REWARDS_LIST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleRequestGuildRewardsList ); - DEFINE_HANDLER(CMSG_REQUEST_HOTFIX, STATUS_AUTHED, PROCESS_INPLACE, &WorldSession::HandleRequestHotfix ); DEFINE_HANDLER(CMSG_REQUEST_INSPECT_RATED_BG_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_HANDLER(CMSG_REQUEST_PARTY_MEMBER_STATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPartyMemberStatsOpcode); DEFINE_HANDLER(CMSG_REQUEST_PET_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleRequestPetInfoOpcode ); @@ -932,8 +932,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_XP_GAIN, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_HEALTH_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_HIGHEST_THREAT_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_INFO, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_NOTIFY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_NOTIFY, STATUS_NEVER, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_HOTFIX_NOTIFY_BLOB, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_INITIALIZE_FACTIONS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_INITIAL_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SETUP_CURRENCY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index ea23163d49..5440c77aca 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -174,6 +174,7 @@ enum OpcodeClient : uint16 CMSG_CORPSE_MAP_POSITION_QUERY = 0x6205, CMSG_CREATURE_QUERY = 0x2706, CMSG_DANCE_QUERY = 0x4E07, + CMSG_DB_QUERY_BULK = 0x2401, CMSG_DECLINE_CHANNEL_INVITE = 0x0000, CMSG_DEL_FRIEND = 0x6A15, CMSG_DEL_IGNORE = 0x6D26, @@ -456,7 +457,6 @@ enum OpcodeClient : uint16 CMSG_REQUEST_CATEGORY_COOLDOWNS = 0x7102, CMSG_REQUEST_CEMETERY_LIST = 0x720A, CMSG_REQUEST_GUILD_REWARDS_LIST = 0x3012, - CMSG_REQUEST_HOTFIX = 0x2401, CMSG_REQUEST_INSPECT_RATED_BG_STATS = 0x3010, CMSG_REQUEST_PARTY_MEMBER_STATS = 0x0C04, CMSG_REQUEST_PET_INFO = 0x4924, @@ -874,8 +874,8 @@ enum OpcodeServer SMSG_GUILD_XP_UPDATE = 0x0000, SMSG_HEALTH_UPDATE = 0x4734, SMSG_HIGHEST_THREAT_UPDATE = 0x4104, - SMSG_HOTFIX_INFO = 0x19B5, SMSG_HOTFIX_NOTIFY = 0x55A7, + SMSG_HOTFIX_NOTIFY_BLOB = 0x19B5, SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x0125, SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x4E36, SMSG_INITIALIZE_FACTIONS = 0x4634, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 51718bf910..4c2322729f 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -164,6 +164,11 @@ namespace WorldPackets class QuestConfirmAccept; class QueryQuestInfo; } + + namespace Query + { + class DBQueryBulk; + } } enum AccountDataType @@ -1166,7 +1171,6 @@ class TC_GAME_API WorldSession void HandleEjectPassenger(WorldPacket& data); void HandleEnterPlayerVehicle(WorldPacket& data); void HandleUpdateProjectilePosition(WorldPacket& recvPacket); - void HandleRequestHotfix(WorldPacket& recvPacket); void HandleUpdateMissileTrajectory(WorldPacket& recvPacket); void HandleViolenceLevel(WorldPacket& recvPacket); void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket); @@ -1175,6 +1179,9 @@ class TC_GAME_API WorldSession void HandleRequestResearchHistory(WorldPacket& recv_data); int32 HandleEnableNagleAlgorithm(); + // Query + void HandleDBQueryBulk(WorldPackets::Query::DBQueryBulk& packet); + union ConnectToKey { struct diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 7e66c1a823..c203c3b912 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -583,7 +583,7 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO // 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()->DamageType); + m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->GetDamageType()); if (originalCasterGUID) m_originalCasterGUID = originalCasterGUID; @@ -4032,8 +4032,8 @@ void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo con item = itemType; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); - if (proto && proto->ItemLimitCategory) - data << uint32(proto->ItemLimitCategory); + if (proto && proto->GetItemLimitCategory()) + data << uint32(proto->GetItemLimitCategory()); } break; } @@ -4422,9 +4422,9 @@ void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo) Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK); if (pItem) { - ammoInventoryType = pItem->GetTemplate()->InventoryType; + ammoInventoryType = pItem->GetTemplate()->GetInventoryType(); if (ammoInventoryType == INVTYPE_THROWN) - ammoDisplayID = pItem->GetTemplate()->DisplayInfoID; + ammoDisplayID = pItem->GetTemplate()->GetDisplayID(); else if (m_caster->HasAura(46699)) // Requires No Ammo { ammoDisplayID = 5996; // normal arrow @@ -4440,12 +4440,12 @@ void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo) { if (ItemEntry const* itemEntry = sItemStore.LookupEntry(item_id)) { - if (itemEntry->Class == ITEM_CLASS_WEAPON) + if (itemEntry->ClassID == ITEM_CLASS_WEAPON) { - switch (itemEntry->SubClass) + switch (itemEntry->SubclassID) { case ITEM_SUBCLASS_WEAPON_THROWN: - ammoDisplayID = itemEntry->DisplayId; + ammoDisplayID = itemEntry->DisplayInfoID; ammoInventoryType = itemEntry->InventoryType; break; case ITEM_SUBCLASS_WEAPON_BOW: @@ -4786,30 +4786,27 @@ void Spell::TakeCastItem() bool expendable = false; bool withoutCharges = false; - for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + for (uint8 i = 0; i < proto->Effects.size(); ++i) { - if (proto->Spells[i].SpellId > 0) + // item has limited charges + if (proto->Effects[i].Charges) { - // item has limited charges - if (proto->Spells[i].SpellCharges) + if (proto->Effects[i].Charges < 0) + expendable = true; + + int32 charges = m_CastItem->GetSpellCharges(i); + + // item has charges left + if (charges) { - if (proto->Spells[i].SpellCharges < 0) - expendable = true; - - int32 charges = m_CastItem->GetSpellCharges(i); - - // item has charges left - if (charges) - { - (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use - if (proto->Stackable == 1) - m_CastItem->SetSpellCharges(i, charges); - m_CastItem->SetState(ITEM_CHANGED, player); - } - - // all charges used - withoutCharges = (charges == 0); + (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use + if (proto->GetMaxStackSize() == 1) + m_CastItem->SetSpellCharges(i, charges); + m_CastItem->SetState(ITEM_CHANGED, player); } + + // all charges used + withoutCharges = (charges == 0); } } @@ -4912,12 +4909,12 @@ void Spell::TakeAmmo() Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK); // wands don't have ammo - if (!pItem || pItem->IsBroken() || pItem->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_WAND) + if (!pItem || pItem->IsBroken() || pItem->GetTemplate()->GetSubClass() == ITEM_SUBCLASS_WEAPON_WAND) return; - if ((pItem->GetTemplate()->InventoryType == INVTYPE_THROWN || - pItem->GetTemplate()->InventoryType == INVTYPE_RANGED || - pItem->GetTemplate()->InventoryType == INVTYPE_RANGEDRIGHT) + if ((pItem->GetTemplate()->GetInventoryType() == INVTYPE_THROWN || + pItem->GetTemplate()->GetInventoryType() == INVTYPE_RANGED || + pItem->GetTemplate()->GetInventoryType() == INVTYPE_RANGEDRIGHT) && roll_chance_f(sWorld->getRate(RATE_DURABILITY_LOSS_DAMAGE))) { if (pItem->GetMaxStackCount() == 1) @@ -5092,7 +5089,7 @@ void Spell::TakeReagents() ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : nullptr; // do not take reagents for these item casts - if (castItemTemplate && castItemTemplate->Flags & ITEM_FLAG_NO_REAGENT_COST) + if (castItemTemplate && castItemTemplate->GetFlags() & ITEM_FLAG_NO_REAGENT_COST) return; Player* p_caster = m_caster->ToPlayer(); @@ -5108,13 +5105,13 @@ void Spell::TakeReagents() uint32 itemcount = m_spellInfo->ReagentCount[x]; // if CastItem is also spell reagent - if (castItemTemplate && castItemTemplate->ItemId == itemid) + if (castItemTemplate && castItemTemplate->GetId() == itemid) { - for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) + for (uint8 s = 0; s < castItemTemplate->Effects.size(); ++s) { // CastItem will be used up and does not count as reagent int32 charges = m_CastItem->GetSpellCharges(s); - if (castItemTemplate->Spells[s].SpellCharges < 0 && abs(charges) < 2) + if (castItemTemplate->Effects[s].Charges < 0 && abs(charges) < 2) { ++itemcount; break; @@ -5665,7 +5662,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (!pet->HaveInDiet(foodItem->GetTemplate())) return SPELL_FAILED_WRONG_PET_FOOD; - if (!pet->GetCurrentFoodBenefitLevel(foodItem->GetTemplate()->ItemLevel)) + if (!pet->GetCurrentFoodBenefitLevel(foodItem->GetTemplate()->GetBaseItemLevel())) return SPELL_FAILED_FOOD_LOWLEVEL; if (m_caster->IsInCombat() || pet->IsInCombat()) @@ -5769,7 +5766,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint // we need a go target, or an openable item target in case of TARGET_GAMEOBJECT_ITEM_TARGET if (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && !m_targets.GetGOTarget() && - (!pTempItem || !pTempItem->GetTemplate()->LockID || !pTempItem->IsLocked())) + (!pTempItem || !pTempItem->GetTemplate()->GetLockID() || !pTempItem->IsLocked())) return SPELL_FAILED_BAD_TARGETS; if (m_spellInfo->Id != 1842 || (m_targets.GetGOTarget() && @@ -5787,7 +5784,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint return SPELL_FAILED_BAD_TARGETS; } else if (Item* itm = m_targets.GetItemTarget()) - lockId = itm->GetTemplate()->LockID; + lockId = itm->GetTemplate()->GetLockID(); SkillType skillId = SKILL_NONE; int32 reqSkillValue = 0; @@ -6526,7 +6523,7 @@ std::pair Spell::GetMinMaxRange(bool strict) const if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && m_caster->GetTypeId() == TYPEID_PLAYER) if (Item* ranged = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK, true)) - maxRange *= ranged->GetTemplate()->RangedModRange * 0.01f; + maxRange *= ranged->GetTemplate()->GetRangedModRange() * 0.01f; if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, maxRange, const_cast(this)); @@ -6593,13 +6590,13 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (!proto) return SPELL_FAILED_ITEM_NOT_READY; - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - if (proto->Spells[i].SpellCharges) + for (uint8 i = 0; i < proto->Effects.size(); ++i) + if (proto->Effects[i].Charges) if (m_CastItem->GetSpellCharges(i) == 0) return SPELL_FAILED_NO_CHARGES_REMAIN; // consumable cast item checks - if (proto->Class == ITEM_CLASS_CONSUMABLE && m_targets.GetUnitTarget()) + if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && m_targets.GetUnitTarget()) { // such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example SpellCastResult failReason = SPELL_CAST_OK; @@ -6669,7 +6666,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / } // do not take reagents for these item casts - if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_FLAG_NO_REAGENT_COST)) + if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_REAGENT_COST)) { bool checkReagents = !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST) && !player->CanNoReagentCast(m_spellInfo); // Not own traded item (in trader trade slot) requires reagents even if triggered spell @@ -6695,11 +6692,11 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / ItemTemplate const* proto = m_CastItem->GetTemplate(); if (!proto) return SPELL_FAILED_ITEM_NOT_READY; - for (uint8 s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s) + for (uint8 s = 0; s < proto->Effects.size(); ++s) { // CastItem will be used up and does not count as reagent int32 charges = m_CastItem->GetSpellCharges(s); - if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2) + if (proto->Effects[s].Charges < 0 && abs(charges) < 2) { ++itemcount; break; @@ -6735,7 +6732,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / { ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(m_spellInfo->Effects[i].ItemType); /// @todo Needs review - if (pProto && !(pProto->ItemLimitCategory)) + if (pProto && !(pProto->GetItemLimitCategory())) { player->SendEquipError(msg, nullptr, nullptr, m_spellInfo->Effects[i].ItemType); return SPELL_FAILED_DONT_REPORT; @@ -6765,7 +6762,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (m_targets.GetItemTarget()->GetOwner() != m_caster) return SPELL_FAILED_NOT_TRADEABLE; // do not allow to enchant vellum from scroll made by vellum-prevent exploit - if (m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_FLAG_NO_REAGENT_COST) + if (m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_REAGENT_COST) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1); @@ -6783,16 +6780,16 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / return SPELL_FAILED_ITEM_NOT_FOUND; // required level has to be checked also! Exploit fix - if (targetItem->GetTemplate()->ItemLevel < m_spellInfo->BaseLevel) + if (targetItem->GetTemplate()->GetBaseItemLevel() < m_spellInfo->BaseLevel) return SPELL_FAILED_LOWLEVEL; bool isItemUsable = false; - for (uint8 e = 0; e < MAX_ITEM_PROTO_SPELLS; ++e) + ItemTemplate const* proto = targetItem->GetTemplate(); + for (uint8 e = 0; e < proto->Effects.size(); ++e) { - ItemTemplate const* proto = targetItem->GetTemplate(); - if (proto->Spells[e].SpellId > 0 && ( - proto->Spells[e].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE || - proto->Spells[e].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)) + if (proto->Effects[e].SpellID && ( + proto->Effects[e].Trigger == ITEM_SPELLTRIGGER_ON_USE || + proto->Effects[e].Trigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)) { isItemUsable = true; break; @@ -6815,7 +6812,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / { uint32 numSockets = 0; for (uint32 socket = 0; socket < MAX_ITEM_PROTO_SOCKETS; ++socket) - if (targetItem->GetTemplate()->Socket[socket].Color) + if (targetItem->GetTemplate()->GetSocketColor(socket)) ++numSockets; if (numSockets == MAX_ITEM_PROTO_SOCKETS || targetItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) @@ -6855,9 +6852,9 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / // Apply item level restriction if the enchanting spell has max level restrition set if (m_CastItem && m_spellInfo->MaxLevel > 0) { - if (item->GetTemplate()->ItemLevel < m_CastItem->GetTemplate()->RequiredLevel) + if (int32(item->GetTemplate()->GetBaseItemLevel()) < m_CastItem->GetTemplate()->GetRequiredLevel()) return SPELL_FAILED_LOWLEVEL; - if (item->GetTemplate()->ItemLevel > m_spellInfo->MaxLevel) + if (item->GetTemplate()->GetBaseItemLevel() > m_spellInfo->MaxLevel) return SPELL_FAILED_HIGHLEVEL; } break; @@ -6878,7 +6875,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (!itemProto) return SPELL_FAILED_CANT_BE_DISENCHANTED; - uint32 item_quality = itemProto->Quality; + uint32 item_quality = itemProto->GetQuality(); // 2.0.x addon: Check player enchanting level against the item disenchanting requirements uint32 item_disenchantskilllevel = itemProto->RequiredDisenchantSkill; if (item_disenchantskilllevel == uint32(-1)) @@ -6887,7 +6884,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / return SPELL_FAILED_LOW_CASTLEVEL; if (item_quality > 4 || item_quality < 2) return SPELL_FAILED_CANT_BE_DISENCHANTED; - if (itemProto->Class != ITEM_CLASS_WEAPON && itemProto->Class != ITEM_CLASS_ARMOR) + if (itemProto->GetClass() != ITEM_CLASS_WEAPON && itemProto->GetClass() != ITEM_CLASS_ARMOR) return SPELL_FAILED_CANT_BE_DISENCHANTED; if (!itemProto->DisenchantID) return SPELL_FAILED_CANT_BE_DISENCHANTED; @@ -6899,13 +6896,13 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (!item) return SPELL_FAILED_CANT_BE_PROSPECTED; //ensure item is a prospectable ore - if (!(item->GetTemplate()->Flags & ITEM_FLAG_IS_PROSPECTABLE)) + if (!(item->GetTemplate()->GetFlags() & ITEM_FLAG_IS_PROSPECTABLE)) return SPELL_FAILED_CANT_BE_PROSPECTED; //prevent prospecting in trade slot if (item->GetOwnerGUID() != m_caster->GetGUID()) return SPELL_FAILED_CANT_BE_PROSPECTED; //Check for enough skill in jewelcrafting - uint32 item_prospectingskilllevel = item->GetTemplate()->RequiredSkillRank; + uint32 item_prospectingskilllevel = item->GetTemplate()->GetRequiredSkillRank(); if (item_prospectingskilllevel > player->GetSkillValue(SKILL_JEWELCRAFTING)) return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required ores in inventory @@ -6930,13 +6927,13 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (!item) return SPELL_FAILED_CANT_BE_MILLED; //ensure item is a millable herb - if (!(item->GetTemplate()->Flags & ITEM_FLAG_IS_MILLABLE)) + if (!(item->GetTemplate()->GetFlags() & ITEM_FLAG_IS_MILLABLE)) return SPELL_FAILED_CANT_BE_MILLED; //prevent milling in trade slot if (item->GetOwnerGUID() != m_caster->GetGUID()) return SPELL_FAILED_CANT_BE_MILLED; //Check for enough skill in inscription - uint32 item_millingskilllevel = item->GetTemplate()->RequiredSkillRank; + uint32 item_millingskilllevel = item->GetTemplate()->GetRequiredSkillRank(); if (item_millingskilllevel > player->GetSkillValue(SKILL_INSCRIPTION)) return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required herbs in inventory @@ -6965,7 +6962,7 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (!pItem || pItem->IsBroken()) return SPELL_FAILED_EQUIPPED_ITEM; - switch (pItem->GetTemplate()->SubClass) + switch (pItem->GetTemplate()->GetSubClass()) { case ITEM_SUBCLASS_WEAPON_THROWN: { @@ -6994,8 +6991,8 @@ SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 / if (Item* pitem = player->GetItemByEntry(item_id)) { - for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - if (pProto->Spells[x].SpellCharges != 0 && pitem->GetSpellCharges(x) == pProto->Spells[x].SpellCharges) + for (uint8 x = 0; x < pProto->Effects.size(); ++x) + if (pProto->Effects[x].Charges != 0 && pitem->GetSpellCharges(x) == pProto->Effects[x].Charges) return SPELL_FAILED_ITEM_AT_MAX_CHARGES; } break; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index f11b937a74..cf5d58e256 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1289,7 +1289,7 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype) player->CompleteArchProject(projectId); // set the "Crafted by ..." property of the item - if (pItem->GetTemplate()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetTemplate()->Class != ITEM_CLASS_QUEST && newitemid != 6265 && newitemid != 6948) + if (pItem->GetTemplate()->GetClass() != ITEM_CLASS_CONSUMABLE && pItem->GetTemplate()->GetClass() != ITEM_CLASS_QUEST && newitemid != 6265 && newitemid != 6948) pItem->SetGuidValue(ITEM_FIELD_CREATOR, player->GetGUID()); // send info to the client @@ -1297,8 +1297,8 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype) if (Guild* guild = player->GetGuild()) { - if (pProto->Quality > ITEM_QUALITY_EPIC || (pProto->Quality == ITEM_QUALITY_EPIC && pProto->ItemLevel >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) - guild->AddGuildNews(GUILD_NEWS_ITEM_CRAFTED, player->GetGUID(), 0, pProto->ItemId); + if (pProto->GetQuality() > ITEM_QUALITY_EPIC || (pProto->GetQuality() == ITEM_QUALITY_EPIC && pProto->GetBaseItemLevel() >= MinNewsItemLevel[sWorld->getIntConfig(CONFIG_EXPANSION)])) + guild->AddGuildNews(GUILD_NEWS_ITEM_CRAFTED, player->GetGUID(), 0, pProto->GetId()); guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD, pItem->GetEntry(), num_to_add, 0, nullptr, player); } @@ -1626,7 +1626,7 @@ void Spell::EffectOpenLock(SpellEffIndex effIndex) } else if (itemTarget) { - lockId = itemTarget->GetTemplate()->LockID; + lockId = itemTarget->GetTemplate()->GetLockID(); guid = itemTarget->GetGUID(); } else @@ -2298,7 +2298,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) else { // do not increase skill if vellum used - if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_FLAG_NO_REAGENT_COST)) + if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_REAGENT_COST)) player->UpdateCraftSkill(m_spellInfo->Id); uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; @@ -2318,7 +2318,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) { sLog->outCommand(player->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", player->GetName().c_str(), player->GetSession()->GetAccountId(), - itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(), + itemTarget->GetTemplate()->GetDefaultLocaleName(), itemTarget->GetEntry(), item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId()); } @@ -2383,7 +2383,7 @@ void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex) { sLog->outCommand(player->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", player->GetName().c_str(), player->GetSession()->GetAccountId(), - itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(), + itemTarget->GetTemplate()->GetDefaultLocaleName(), itemTarget->GetEntry(), item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId()); } @@ -2464,7 +2464,7 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) { sLog->outCommand(player->GetSession()->GetAccountId(), "GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)", player->GetName().c_str(), player->GetSession()->GetAccountId(), - itemTarget->GetTemplate()->Name1.c_str(), itemTarget->GetEntry(), + itemTarget->GetTemplate()->GetDefaultLocaleName(), itemTarget->GetEntry(), item_owner->GetName().c_str(), item_owner->GetSession()->GetAccountId()); } @@ -2741,7 +2741,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // 45% more damage with daggers if (m_caster->GetTypeId() == TYPEID_PLAYER) if (Item* item = m_caster->ToPlayer()->GetWeaponForAttack(m_attackType, true)) - if (item->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER) + if (item->GetTemplate()->GetSubClass() == ITEM_SUBCLASS_WEAPON_DAGGER) totalDamagePercentMod *= 1.45f; } break; @@ -3988,7 +3988,7 @@ void Spell::EffectFeedPet(SpellEffIndex effIndex) if (!pet->IsAlive()) return; - int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetTemplate()->ItemLevel); + int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetTemplate()->GetBaseItemLevel()); if (benefit <= 0) return; @@ -4888,7 +4888,7 @@ void Spell::EffectProspecting(SpellEffIndex /*effIndex*/) if (!player) return; - if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_FLAG_IS_PROSPECTABLE)) + if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_FLAG_IS_PROSPECTABLE)) return; if (itemTarget->GetCount() < 5) @@ -4897,7 +4897,7 @@ void Spell::EffectProspecting(SpellEffIndex /*effIndex*/) if (sWorld->getBoolConfig(CONFIG_SKILL_PROSPECTING)) { uint32 SkillValue = player->GetPureSkillValue(SKILL_JEWELCRAFTING); - uint32 reqSkillValue = itemTarget->GetTemplate()->RequiredSkillRank; + uint32 reqSkillValue = itemTarget->GetTemplate()->GetRequiredSkillRank(); player->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue); } @@ -4913,7 +4913,7 @@ void Spell::EffectMilling(SpellEffIndex /*effIndex*/) if (!player) return; - if (!itemTarget || !(itemTarget->GetTemplate()->Flags & ITEM_FLAG_IS_MILLABLE)) + if (!itemTarget || !(itemTarget->GetTemplate()->GetFlags() & ITEM_FLAG_IS_MILLABLE)) return; if (itemTarget->GetCount() < 5) @@ -4922,7 +4922,7 @@ void Spell::EffectMilling(SpellEffIndex /*effIndex*/) if (sWorld->getBoolConfig(CONFIG_SKILL_MILLING)) { uint32 SkillValue = player->GetPureSkillValue(SKILL_INSCRIPTION); - uint32 reqSkillValue = itemTarget->GetTemplate()->RequiredSkillRank; + uint32 reqSkillValue = itemTarget->GetTemplate()->GetRequiredSkillRank(); player->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue); } @@ -5302,7 +5302,7 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* // level of pet summoned using engineering item based at engineering skill level if (m_CastItem && caster->GetTypeId() == TYPEID_PLAYER) if (ItemTemplate const* proto = m_CastItem->GetTemplate()) - if (proto->RequiredSkill == SKILL_ENGINEERING) + if (proto->GetRequiredSkill() == SKILL_ENGINEERING) if (uint16 skill202 = caster->ToPlayer()->GetSkillValue(SKILL_ENGINEERING)) level = skill202 / 5; @@ -5545,8 +5545,8 @@ void Spell::EffectRechargeManaGem(SpellEffIndex /*effIndex*/) if (Item* pItem = player->GetItemByEntry(item_id)) { - for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x) - pItem->SetSpellCharges(x, pProto->Spells[x].SpellCharges); + for (uint8 x = 0; x < pProto->Effects.size(); ++x) + pItem->SetSpellCharges(x, pProto->Effects[x].Charges); pItem->SetState(ITEM_CHANGED, player); } } diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index 98463bcd06..65177813ab 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -705,11 +705,11 @@ void SpellHistory::GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemI { for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx) { - if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id) + if (uint32(proto->Effects[idx].SpellID) == spellInfo->Id) { - tmpCooldown = proto->Spells[idx].SpellCooldown; - tmpCategoryId = proto->Spells[idx].SpellCategory; - tmpCategoryCooldown = proto->Spells[idx].SpellCategoryCooldown; + tmpCooldown = proto->Effects[idx].Cooldown; + tmpCategoryId = proto->Effects[idx].Category; + tmpCategoryCooldown = proto->Effects[idx].CategoryCooldown; break; } } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index cd2b75a5f9..4c5316b29f 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1652,7 +1652,13 @@ void World::SetInitialWorldSettings() ///- Load the DBC files TC_LOG_INFO("server.loading", "Initialize data stores..."); LoadDBCStores(m_dataPath); - LoadDB2Stores(m_dataPath); + sDB2Manager.LoadStores(m_dataPath); + + TC_LOG_INFO("misc", "Loading hotfix info..."); + sDB2Manager.LoadHotfixData(); + + // Close hotfix database - it is only used during DB2 loading + HotfixDatabase.Close(); // Load M2 fly by cameras LoadM2Cameras(m_dataPath); @@ -1725,7 +1731,6 @@ void World::SetInitialWorldSettings() uint32 oldMSTime = getMSTime(); sObjectMgr->LoadCreatureLocales(); sObjectMgr->LoadGameObjectLocales(); - sObjectMgr->LoadItemLocales(); sObjectMgr->LoadQuestLocales(); sObjectMgr->LoadNpcTextLocales(); sObjectMgr->LoadPageTextLocales(); @@ -2274,12 +2279,6 @@ void World::SetInitialWorldSettings() }); } - TC_LOG_INFO("misc", "Loading hotfix info..."); - sObjectMgr->LoadHotfixData(); - - TC_LOG_INFO("server.loading", "Loading missing KeyChains..."); - sObjectMgr->LoadMissingKeyChains(); - uint32 startupDuration = GetMSTimeDiffToNow(startupBegin); TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000)); diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index b545bf0af6..6723922714 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -374,39 +374,7 @@ public: ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - int localeIndex = handler->GetSessionDbLocaleIndex(); - if (localeIndex >= 0) - { - uint8 ulocaleIndex = uint8(localeIndex); - if (ItemLocale const* il = sObjectMgr->GetItemLocale(itr->second.ItemId)) - { - if (il->Name.size() > ulocaleIndex && !il->Name[ulocaleIndex].empty()) - { - std::string name = il->Name[ulocaleIndex]; - - if (Utf8FitTo(name, wNamePart)) - { - if (maxResults && count++ == maxResults) - { - handler->PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults); - return true; - } - - if (handler->GetSession()) - handler->PSendSysMessage(LANG_ITEM_LIST_CHAT, itr->second.ItemId, itr->second.ItemId, name.c_str()); - else - handler->PSendSysMessage(LANG_ITEM_LIST_CONSOLE, itr->second.ItemId, name.c_str()); - - if (!found) - found = true; - - continue; - } - } - } - } - - std::string name = itr->second.Name1; + std::string name = itr->second.GetName(handler->GetSessionDbcLocale()); if (name.empty()) continue; @@ -419,9 +387,9 @@ public: } if (handler->GetSession()) - handler->PSendSysMessage(LANG_ITEM_LIST_CHAT, itr->second.ItemId, itr->second.ItemId, name.c_str()); + handler->PSendSysMessage(LANG_ITEM_LIST_CHAT, itr->second.GetId(), itr->second.GetId(), name.c_str()); else - handler->PSendSysMessage(LANG_ITEM_LIST_CONSOLE, itr->second.ItemId, name.c_str()); + handler->PSendSysMessage(LANG_ITEM_LIST_CONSOLE, itr->second.GetId(), name.c_str()); if (!found) found = true; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index b6dac13c32..99e6fb93ef 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -23,6 +23,7 @@ #include "ChaseMovementGenerator.h" #include "Chat.h" #include "DatabaseEnv.h" +#include "DB2Stores.h" #include "DisableMgr.h" #include "FollowMovementGenerator.h" #include "GridNotifiers.h" @@ -1226,20 +1227,23 @@ public: if (itemNameStr && itemNameStr[0]) { - std::string itemName = itemNameStr+1; - WorldDatabase.EscapeString(itemName); - - PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME); - stmt->setString(0, itemName); - PreparedQueryResult result = WorldDatabase.Query(stmt); - - if (!result) + std::string itemName = itemNameStr + 1; + auto itr = std::find_if(sItemSparseStore.begin(), sItemSparseStore.end(), [&itemName](ItemSparseEntry const* sparse) { - handler->PSendSysMessage(LANG_COMMAND_COULDNOTFIND, itemNameStr+1); + for (uint32 i = 0; i < MAX_LOCALES; ++i) + if (itemName == sparse->Name->Str[i]) + return true; + return false; + }); + + if (itr == sItemSparseStore.end()) + { + handler->PSendSysMessage(LANG_COMMAND_COULDNOTFIND, itemNameStr + 1); handler->SetSentErrorMessage(true); return false; } - itemId = result->Fetch()->GetUInt32(); + + itemId = itr->ID; } else return false; @@ -1352,14 +1356,14 @@ public: ItemTemplateContainer const* its = sObjectMgr->GetItemTemplateStore(); for (ItemTemplateContainer::const_iterator itr = its->begin(); itr != its->end(); ++itr) { - if (itr->second.ItemSet == itemSetId) + if (itr->second.GetItemSet() == itemSetId) { found = true; ItemPosCountVec dest; - InventoryResult msg = playerTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itr->second.ItemId, 1); + InventoryResult msg = playerTarget->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itr->second.GetId(), 1); if (msg == EQUIP_ERR_OK) { - Item* item = playerTarget->StoreNewItem(dest, itr->second.ItemId, true); + Item* item = playerTarget->StoreNewItem(dest, itr->second.GetId(), true); // remove binding (let GM give it to another player later) if (player == playerTarget) @@ -1371,8 +1375,8 @@ public: } else { - player->SendEquipError(msg, nullptr, nullptr, itr->second.ItemId); - handler->PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itr->second.ItemId, 1); + player->SendEquipError(msg, nullptr, nullptr, itr->second.GetId()); + handler->PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itr->second.GetId(), 1); } } } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 7355561efc..63c637760a 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -446,7 +446,7 @@ public: ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId); - handler->PSendSysMessage(LANG_ITEM_ADDED_TO_LIST, itemId, itemTemplate->Name1.c_str(), maxcount, incrtime, extendedcost); + handler->PSendSysMessage(LANG_ITEM_ADDED_TO_LIST, itemId, itemTemplate->GetDefaultLocaleName(), maxcount, incrtime, extendedcost); return true; } @@ -636,7 +636,7 @@ public: ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId); - handler->PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST, itemId, itemTemplate->Name1.c_str()); + handler->PSendSysMessage(LANG_ITEM_DELETED_FROM_LIST, itemId, itemTemplate->GetDefaultLocaleName()); return true; } @@ -1579,16 +1579,11 @@ public: static void _ShowLootEntry(ChatHandler* handler, uint32 itemId, uint8 itemCount, bool alternateString = false) { ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId); - ItemLocale const* itemLocale = sObjectMgr->GetItemLocale(itemId); - char const* name = nullptr; - if (itemLocale) - name = itemLocale->Name[handler->GetSessionDbcLocale()].c_str(); - if ((!name || !*name) && itemTemplate) - name = itemTemplate->Name1.c_str(); + char const* name = itemTemplate->GetName(handler->GetSessionDbcLocale()); if (!name) name = "Unknown item"; handler->PSendSysMessage(alternateString ? LANG_COMMAND_NPC_SHOWLOOT_ENTRY_2 : LANG_COMMAND_NPC_SHOWLOOT_ENTRY, - itemCount, ItemQualityColors[itemTemplate ? itemTemplate->Quality : ITEM_QUALITY_POOR], itemId, name, itemId); + itemCount, ItemQualityColors[itemTemplate ? itemTemplate->GetQuality() : ITEM_QUALITY_POOR], itemId, name, itemId); } static void _IterateNotNormalLootMap(ChatHandler* handler, NotNormalLootItemMap const& map, std::vector const& items) { diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index afb4f2aaba..3cf7d12a0e 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -85,12 +85,12 @@ public: ItemTemplateContainer const* itc = sObjectMgr->GetItemTemplateStore(); ItemTemplateContainer::const_iterator result = std::find_if(itc->begin(), itc->end(), [quest](ItemTemplateContainer::value_type const& value) { - return value.second.StartQuest == quest->GetQuestId(); + return value.second.GetStartQuest() == quest->GetQuestId(); }); if (result != itc->end()) { - handler->PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, result->second.ItemId); + handler->PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, result->second.GetId()); handler->SetSentErrorMessage(true); return false; } diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 3d3336a277..85313d5419 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -113,7 +113,6 @@ public: { "creature_text_locale", rbac::RBAC_PERM_COMMAND_RELOAD_CRETURE_TEXT_LOCALE, true, &HandleReloadLocalesCreatureTextCommand, "" }, { "gameobject_template_locale", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_TEMPLATE_LOCALE, true, &HandleReloadLocalesGameobjectCommand, "" }, { "gossip_menu_option_locale", rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION_LOCALE, true, &HandleReloadLocalesGossipMenuOptionCommand, "" }, - { "item_template_locale", rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_TEMPLATE_LOCALE, true, &HandleReloadLocalesItemCommand, "" }, { "npc_text_locale", rbac::RBAC_PERM_COMMAND_RELOAD_NPC_TEXT_LOCALE, true, &HandleReloadLocalesNpcTextCommand, "" }, { "page_text_locale", rbac::RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT_LOCALE, true, &HandleReloadLocalesPageTextCommand, "" }, { "points_of_interest_locale", rbac::RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST_LOCALE, true, &HandleReloadLocalesPointsOfInterestCommand, "" }, @@ -315,7 +314,6 @@ public: HandleReloadLocalesCreatureTextCommand(handler, "a"); HandleReloadLocalesGameobjectCommand(handler, "a"); HandleReloadLocalesGossipMenuOptionCommand(handler, "a"); - HandleReloadLocalesItemCommand(handler, "a"); HandleReloadLocalesNpcTextCommand(handler, "a"); HandleReloadLocalesPageTextCommand(handler, "a"); HandleReloadLocalesPointsOfInterestCommand(handler, "a"); @@ -1062,14 +1060,6 @@ public: return true; } - static bool HandleReloadLocalesItemCommand(ChatHandler* handler, char const* /*args*/) - { - TC_LOG_INFO("misc", "Re-Loading Item Template Locale... "); - sObjectMgr->LoadItemLocales(); - handler->SendGlobalGMSysMessage("DB table `item_template_locale` reloaded."); - return true; - } - static bool HandleReloadLocalesNpcTextCommand(ChatHandler* handler, char const* /*args*/) { TC_LOG_INFO("misc", "Re-Loading NPC Text Locale... "); diff --git a/src/server/scripts/Commands/cs_send.cpp b/src/server/scripts/Commands/cs_send.cpp index d020acc6fc..c8331e34a8 100644 --- a/src/server/scripts/Commands/cs_send.cpp +++ b/src/server/scripts/Commands/cs_send.cpp @@ -155,7 +155,7 @@ public: } uint32 itemCount = itemCountStr ? atoi(itemCountStr) : 1; - if (itemCount < 1 || (item_proto->MaxCount > 0 && itemCount > uint32(item_proto->MaxCount))) + if (itemCount < 1 || (item_proto->GetMaxCount() > 0 && itemCount > uint32(item_proto->GetMaxCount()))) { handler->PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, itemCount, itemId); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index e0d74c2af6..f08247ebb2 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -721,8 +721,8 @@ class instance_ulduar : public InstanceMapScript if (Player* player = itr->GetSource()) for (uint8 slot = EQUIPMENT_SLOT_MAINHAND; slot <= EQUIPMENT_SLOT_RANGED; ++slot) if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) - if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel) - _maxWeaponItemLevel = item->GetTemplate()->ItemLevel; + if (item->GetTemplate()->GetBaseItemLevel() > _maxWeaponItemLevel) + _maxWeaponItemLevel = item->GetTemplate()->GetBaseItemLevel(); } else if (state == IN_PROGRESS) { @@ -741,11 +741,11 @@ class instance_ulduar : public InstanceMapScript { if (slot >= EQUIPMENT_SLOT_MAINHAND && slot <= EQUIPMENT_SLOT_RANGED) { - if (item->GetTemplate()->ItemLevel > _maxWeaponItemLevel) - _maxWeaponItemLevel = item->GetTemplate()->ItemLevel; + if (item->GetTemplate()->GetBaseItemLevel() > _maxWeaponItemLevel) + _maxWeaponItemLevel = item->GetTemplate()->GetBaseItemLevel(); } - else if (item->GetTemplate()->ItemLevel > _maxArmorItemLevel) - _maxArmorItemLevel = item->GetTemplate()->ItemLevel; + else if (item->GetTemplate()->GetBaseItemLevel() > _maxArmorItemLevel) + _maxArmorItemLevel = item->GetTemplate()->GetBaseItemLevel(); } } } diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp index 00d1ea31f0..6cd76ef17a 100644 --- a/src/server/scripts/World/npc_professions.cpp +++ b/src/server/scripts/World/npc_professions.cpp @@ -253,7 +253,7 @@ bool EquippedOk(Player* player, uint32 spellId) for (uint8 j = EQUIPMENT_SLOT_START; j < EQUIPMENT_SLOT_END; ++j) { item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, j); - if (item && item->GetTemplate()->RequiredSpell == reqSpell) + if (item && item->GetTemplate()->GetRequiredSpell() == reqSpell) { //player has item equipped that require specialty. Not allow to unlearn, player has to unequip first TC_LOG_DEBUG("scripts", "player attempt to unlearn spell %u, but item %u is equipped.", reqSpell, item->GetEntry()); diff --git a/src/server/shared/DataStores/DB2FileLoader.cpp b/src/server/shared/DataStores/DB2FileLoader.cpp deleted file mode 100644 index 0d47c3b5a4..0000000000 --- a/src/server/shared/DataStores/DB2FileLoader.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#include "Common.h" - -#include -#include -#include -#include "DB2FileLoader.h" - -DB2FileLoader::DB2FileLoader() -{ - recordSize = 0; - recordCount = 0; - fieldCount = 0; - stringSize = 0; - stringTable = nullptr; - - tableHash = 0; - build = 0; - - unk1 = 0; - minIndex = 0; - maxIndex = 0; - locale = 0; - unk5 = 0; - - data = nullptr; - fieldsOffset = nullptr; -} - -bool DB2FileLoader::Load(char const* filename, char const* fmt) -{ - if (data) - { - delete [] data; - data = nullptr; - } - - FILE* f = fopen(filename, "rb"); - if (!f) - return false; - - uint32 header; - if (fread(&header, 4, 1, f) != 1) // Signature - { - fclose(f); - return false; - } - - EndianConvert(header); - - if (header != 0x32424457) - { - fclose(f); - return false; //'WDB2' - } - - if (fread(&recordCount, 4, 1, f) != 1) // Number of records - { - fclose(f); - return false; - } - - EndianConvert(recordCount); - - if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields - { - fclose(f); - return false; - } - - EndianConvert(fieldCount); - - if (fread(&recordSize, 4, 1, f) != 1) // Size of a record - { - fclose(f); - return false; - } - - EndianConvert(recordSize); - - if (fread(&stringSize, 4, 1, f) != 1) // String size - { - fclose(f); - return false; - } - - EndianConvert(stringSize); - - /* NEW WDB2 FIELDS*/ - if (fread(&tableHash, 4, 1, f) != 1) // Table hash - { - fclose(f); - return false; - } - - EndianConvert(tableHash); - - if (fread(&build, 4, 1, f) != 1) // Build - { - fclose(f); - return false; - } - - EndianConvert(build); - - if (fread(&unk1, 4, 1, f) != 1) // Unknown WDB2 - { - fclose(f); - return false; - } - - EndianConvert(unk1); - - if (build > 12880) - { - if (fread(&minIndex, 4, 1, f) != 1) // MinIndex WDB2 - { - fclose(f); - return false; - } - EndianConvert(minIndex); - - if (fread(&maxIndex, 4, 1, f) != 1) // MaxIndex WDB2 - { - fclose(f); - return false; - } - EndianConvert(maxIndex); - - if (fread(&locale, 4, 1, f) != 1) // Locales - { - fclose(f); - return false; - } - EndianConvert(locale); - - if (fread(&unk5, 4, 1, f) != 1) // Unknown WDB2 - { - fclose(f); - return false; - } - EndianConvert(unk5); - } - - if (maxIndex != 0) - { - int32 diff = maxIndex - minIndex + 1; - fseek(f, diff * 4 + diff * 2, SEEK_CUR); // diff * 4: an index for rows, diff * 2: a memory allocation bank - } - - fieldsOffset = new uint32[fieldCount]; - fieldsOffset[0] = 0; - for (uint32 i = 1; i < fieldCount; i++) - { - fieldsOffset[i] = fieldsOffset[i - 1]; - if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') - fieldsOffset[i] += 1; - else - fieldsOffset[i] += 4; - } - - data = new unsigned char[recordSize*recordCount+stringSize]; - stringTable = data + recordSize*recordCount; - - if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1) - { - fclose(f); - return false; - } - - fclose(f); - return true; -} - -DB2FileLoader::~DB2FileLoader() -{ - if (data) - delete [] data; - if (fieldsOffset) - delete [] fieldsOffset; -} - -DB2FileLoader::Record DB2FileLoader::getRecord(size_t id) -{ - assert(data); - return Record(*this, data + id*recordSize); -} - -uint32 DB2FileLoader::GetFormatRecordSize(char const* format, int32* index_pos) -{ - uint32 recordsize = 0; - int32 i = -1; - for (uint32 x=0; format[x]; ++x) - { - switch (format[x]) - { - case FT_FLOAT: - case FT_INT: - recordsize += 4; - break; - case FT_STRING: - recordsize += sizeof(char*); - break; - case FT_SORT: - i = x; - break; - case FT_IND: - i = x; - recordsize += 4; - break; - case FT_BYTE: - recordsize += 1; - break; - } - } - - if (index_pos) - *index_pos = i; - - return recordsize; -} - -uint32 DB2FileLoader::GetFormatStringsFields(char const* format) -{ - uint32 stringfields = 0; - for (uint32 x=0; format[x]; ++x) - if (format[x] == FT_STRING) - ++stringfields; - - return stringfields; -} - -char* DB2FileLoader::AutoProduceData(char const* format, uint32& records, char**& indexTable) -{ - typedef char * ptr; - if (strlen(format) != fieldCount) - return nullptr; - - //get struct size and index pos - int32 i; - uint32 recordsize=GetFormatRecordSize(format, &i); - - if (i >= 0) - { - uint32 maxi = 0; - //find max index - for (uint32 y = 0; y < recordCount; y++) - { - uint32 ind=getRecord(y).getUInt(i); - if (ind>maxi) - maxi = ind; - } - - ++maxi; - records = maxi; - indexTable = new ptr[maxi]; - memset(indexTable, 0, maxi * sizeof(ptr)); - } - else - { - records = recordCount; - indexTable = new ptr[recordCount]; - } - - char* dataTable = new char[recordCount * recordsize]; - - uint32 offset=0; - - for (uint32 y =0; y < recordCount; y++) - { - if (i>=0) - { - indexTable[getRecord(y).getUInt(i)] = &dataTable[offset]; - } - else - indexTable[y] = &dataTable[offset]; - - for (uint32 x = 0; x < fieldCount; x++) - { - switch (format[x]) - { - case FT_FLOAT: - *((float*)(&dataTable[offset])) = getRecord(y).getFloat(x); - offset += 4; - break; - case FT_IND: - case FT_INT: - *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x); - offset += 4; - break; - case FT_BYTE: - *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x); - offset += 1; - break; - case FT_STRING: - *((char**)(&dataTable[offset])) = nullptr; // will be replaces non-empty or "" strings in AutoProduceStrings - offset += sizeof(char*); - break; - } - } - } - - return dataTable; -} - -static char const* const nullStr = ""; - -char* DB2FileLoader::AutoProduceStringsArrayHolders(char const* format, char* dataTable) -{ - if (strlen(format) != fieldCount) - return nullptr; - - // we store flat holders pool as single memory block - size_t stringFields = GetFormatStringsFields(format); - // each string field at load have array of string for each locale - size_t stringHolderSize = sizeof(char*) * TOTAL_LOCALES; - size_t stringHoldersRecordPoolSize = stringFields * stringHolderSize; - size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * recordCount; - - char* stringHoldersPool = new char[stringHoldersPoolSize]; - - // DB2 strings expected to have at least empty string - for (size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) - ((char const**)stringHoldersPool)[i] = nullStr; - - uint32 offset=0; - - // assign string holders to string field slots - for (uint32 y = 0; y < recordCount; y++) - { - uint32 stringFieldNum = 0; - - for (uint32 x = 0; x < fieldCount; x++) - switch (format[x]) - { - case FT_FLOAT: - case FT_IND: - case FT_INT: - offset += 4; - break; - case FT_BYTE: - offset += 1; - break; - case FT_STRING: - { - // init db2 string field slots by pointers to string holders - char const*** slot = (char const***)(&dataTable[offset]); - *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * y + stringHolderSize*stringFieldNum]); - ++stringFieldNum; - offset += sizeof(char*); - break; - } - case FT_NA: - case FT_NA_BYTE: - case FT_SORT: - break; - default: - assert(false && "unknown format character"); - } - } - - //send as char* for store in char* pool list for free at unload - return stringHoldersPool; -} - -char* DB2FileLoader::AutoProduceStrings(char const* format, char* dataTable, uint32 locale) -{ - if (strlen(format) != fieldCount) - return nullptr; - - char* stringPool= new char[stringSize]; - memcpy(stringPool, stringTable, stringSize); - - uint32 offset = 0; - - for (uint32 y =0; y < recordCount; y++) - { - for (uint32 x = 0; x < fieldCount; x++) - switch (format[x]) - { - case FT_FLOAT: - case FT_IND: - case FT_INT: - offset += 4; - break; - case FT_BYTE: - offset += 1; - break; - case FT_STRING: - { - // fill only not filled entries - LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]); - if (db2str->Str[locale] == nullStr) - { - const char * st = getRecord(y).getString(x); - db2str->Str[locale] = stringPool + (st - (char const*)stringTable); - } - - offset += sizeof(char*); - break; - } - } - } - - return stringPool; -} diff --git a/src/server/shared/DataStores/DB2StorageLoader.cpp b/src/server/shared/DataStores/DB2StorageLoader.cpp new file mode 100644 index 0000000000..7a266d29e4 --- /dev/null +++ b/src/server/shared/DataStores/DB2StorageLoader.cpp @@ -0,0 +1,651 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "Common.h" +#include "DB2StorageLoader.h" +#include "Database/Implementation/HotfixDatabase.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" + +DB2FileLoader::DB2FileLoader() +{ + recordSize = 0; + recordCount = 0; + fieldCount = 0; + stringSize = 0; + stringTable = nullptr; + + tableHash = 0; + build = 0; + + unk1 = 0; + minIndex = 0; + maxIndex = 0; + locale = 0; + unk5 = 0; + + data = nullptr; + fieldsOffset = nullptr; +} + +bool DB2FileLoader::Load(char const* filename, char const* fmt) +{ + if (data) + { + delete [] data; + data = nullptr; + } + + FILE* f = fopen(filename, "rb"); + if (!f) + return false; + + uint32 header; + if (fread(&header, 4, 1, f) != 1) // Signature + { + fclose(f); + return false; + } + + EndianConvert(header); + + if (header != 0x32424457) + { + fclose(f); + return false; //'WDB2' + } + + if (fread(&recordCount, 4, 1, f) != 1) // Number of records + { + fclose(f); + return false; + } + + EndianConvert(recordCount); + + if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields + { + fclose(f); + return false; + } + + EndianConvert(fieldCount); + + if (fread(&recordSize, 4, 1, f) != 1) // Size of a record + { + fclose(f); + return false; + } + + EndianConvert(recordSize); + + if (fread(&stringSize, 4, 1, f) != 1) // String size + { + fclose(f); + return false; + } + + EndianConvert(stringSize); + + /* NEW WDB2 FIELDS*/ + if (fread(&tableHash, 4, 1, f) != 1) // Table hash + { + fclose(f); + return false; + } + + EndianConvert(tableHash); + + if (fread(&build, 4, 1, f) != 1) // Build + { + fclose(f); + return false; + } + + EndianConvert(build); + + if (fread(&unk1, 4, 1, f) != 1) // Unknown WDB2 + { + fclose(f); + return false; + } + + EndianConvert(unk1); + + if (build > 12880) + { + if (fread(&minIndex, 4, 1, f) != 1) // MinIndex WDB2 + { + fclose(f); + return false; + } + EndianConvert(minIndex); + + if (fread(&maxIndex, 4, 1, f) != 1) // MaxIndex WDB2 + { + fclose(f); + return false; + } + EndianConvert(maxIndex); + + if (fread(&locale, 4, 1, f) != 1) // Locales + { + fclose(f); + return false; + } + EndianConvert(locale); + + if (fread(&unk5, 4, 1, f) != 1) // Unknown WDB2 + { + fclose(f); + return false; + } + EndianConvert(unk5); + } + + if (maxIndex != 0) + { + int32 diff = maxIndex - minIndex + 1; + fseek(f, diff * 4 + diff * 2, SEEK_CUR); // diff * 4: an index for rows, diff * 2: a memory allocation bank + } + + fieldsOffset = new uint32[fieldCount]; + fieldsOffset[0] = 0; + for (uint32 i = 1; i < fieldCount; i++) + { + fieldsOffset[i] = fieldsOffset[i - 1]; + if (fmt[i - 1] == 'b') + fieldsOffset[i] += 1; + else + fieldsOffset[i] += 4; + } + + data = new unsigned char[recordSize * recordCount + stringSize]; + stringTable = data + recordSize * recordCount; + + if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1) + { + fclose(f); + return false; + } + + fclose(f); + return true; +} + +DB2FileLoader::~DB2FileLoader() +{ + if (data) + delete [] data; + if (fieldsOffset) + delete [] fieldsOffset; +} + +DB2FileLoader::Record DB2FileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id*recordSize); +} + +uint32 DB2FileLoader::GetFormatRecordSize(char const* format, int32* index_pos) +{ + uint32 recordsize = 0; + int32 i = -1; + for (uint32 x=0; format[x]; ++x) + { + switch (format[x]) + { + case FT_FLOAT: + case FT_INT: + recordsize += 4; + break; + case FT_STRING: + recordsize += sizeof(char*); + break; + case FT_SORT: + i = x; + break; + case FT_IND: + i = x; + recordsize += 4; + break; + case FT_BYTE: + recordsize += 1; + break; + } + } + + if (index_pos) + *index_pos = i; + + return recordsize; +} + +uint32 DB2FileLoader::GetFormatStringFieldCount(char const* format) +{ + uint32 stringfields = 0; + for (uint32 x = 0; format[x]; ++x) + if (format[x] == FT_STRING) + ++stringfields; + + return stringfields; +} + +char* DB2FileLoader::AutoProduceData(char const* format, uint32& records, char**& indexTable) +{ + typedef char * ptr; + if (strlen(format) != fieldCount) + return nullptr; + + //get struct size and index pos + int32 indexField; + uint32 recordsize = GetFormatRecordSize(format, &indexField); + + if (indexField >= 0) + { + uint32 maxi = 0; + //find max index + for (uint32 y = 0; y < recordCount; y++) + { + uint32 ind = getRecord(y).getUInt(indexField); + if (ind > maxi) + maxi = ind; + } + + ++maxi; + records = maxi; + indexTable = new ptr[maxi]; + memset(indexTable, 0, maxi * sizeof(ptr)); + } + else + { + records = recordCount; + indexTable = new ptr[recordCount]; + } + + char* dataTable = new char[recordCount * recordsize]; + + uint32 offset = 0; + + for (uint32 y = 0; y < recordCount; y++) + { + if (indexField >= 0) + indexTable[getRecord(y).getUInt(indexField)] = &dataTable[offset]; + else + indexTable[y] = &dataTable[offset]; + + for (uint32 x = 0; x < fieldCount; x++) + { + switch (format[x]) + { + case FT_FLOAT: + *((float*)(&dataTable[offset])) = getRecord(y).getFloat(x); + offset += 4; + break; + case FT_IND: + case FT_INT: + *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x); + offset += 4; + break; + case FT_BYTE: + *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x); + offset += 1; + break; + case FT_STRING: + *((char**)(&dataTable[offset])) = nullptr; // will be replaces non-empty or "" strings in AutoProduceStrings + offset += sizeof(char*); + break; + } + } + } + + return dataTable; +} + +static char const* const nullStr = ""; + +char* DB2FileLoader::AutoProduceStringsArrayHolders(char const* format, char* dataTable) +{ + if (strlen(format) != fieldCount) + return nullptr; + + // we store flat holders pool as single memory block + size_t stringFields = GetFormatStringFieldCount(format); + if (!stringFields) + return nullptr; + + // each string field at load have array of string for each locale + size_t stringHolderSize = sizeof(char*) * TOTAL_LOCALES; + size_t stringHoldersRecordPoolSize = stringFields * stringHolderSize; + size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * recordCount; + + char* stringHoldersPool = new char[stringHoldersPoolSize]; + + // DB2 strings expected to have at least empty string + for (size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) + ((char const**)stringHoldersPool)[i] = nullStr; + + uint32 offset = 0; + + // assign string holders to string field slots + for (uint32 y = 0; y < recordCount; y++) + { + uint32 stringFieldNum = 0; + + for (uint32 x = 0; x < fieldCount; x++) + { + switch (format[x]) + { + case FT_FLOAT: + case FT_IND: + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_STRING: + { + // init db2 string field slots by pointers to string holders + char const*** slot = (char const***)(&dataTable[offset]); + *slot = (char const**)(&stringHoldersPool[stringHoldersRecordPoolSize * y + stringHolderSize * stringFieldNum]); + ++stringFieldNum; + offset += sizeof(char*); + break; + } + default: + ASSERT(false, "unknown format character %c", format[x]); + } + } + } + + //send as char* for store in char* pool list for free at unload + return stringHoldersPool; +} + +char* DB2FileLoader::AutoProduceStrings(char const* format, char* dataTable, uint32 locale) +{ + if (strlen(format) != fieldCount) + return nullptr; + + char* stringPool = new char[stringSize]; + memcpy(stringPool, stringTable, stringSize); + + uint32 offset = 0; + + for (uint32 y = 0; y < recordCount; y++) + { + for (uint32 x = 0; x < fieldCount; x++) + { + switch (format[x]) + { + case FT_FLOAT: + case FT_IND: + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_STRING: + { + // fill only not filled entries + LocalizedString* db2str = *(LocalizedString**)(&dataTable[offset]); + if (db2str->Str[locale] == nullStr) + { + const char* st = getRecord(y).getString(x); + db2str->Str[locale] = stringPool + (st - (const char*)stringTable); + } + + offset += sizeof(char*); + break; + } + } + } + } + + return stringPool; +} + +char* DB2DatabaseLoader::Load(const char* format, int32 preparedStatement, uint32& records, char**& indexTable, char*& stringHolders, std::list& stringPool) +{ + // Even though this query is executed only once, prepared statement is used to send data from mysql server in binary format + PreparedQueryResult result = HotfixDatabase.Query(HotfixDatabase.GetPreparedStatement(HotfixDatabaseStatements(preparedStatement))); + if (!result) + return nullptr; + + uint32 const fieldCount = strlen(format); + if (fieldCount != result->GetFieldCount()) + return nullptr; + + // get struct size and index pos + int32 indexField; + uint32 recordSize = DB2FileLoader::GetFormatRecordSize(format, &indexField); + + // we store flat holders pool as single memory block + size_t stringFields = DB2FileLoader::GetFormatStringFieldCount(format); + + // each string field at load have array of string for each locale + size_t stringHolderSize = sizeof(char*) * TOTAL_LOCALES; + size_t stringHoldersRecordPoolSize = stringFields * stringHolderSize; + + if (stringFields) + { + size_t stringHoldersPoolSize = stringHoldersRecordPoolSize * result->GetRowCount(); + stringHolders = new char[stringHoldersPoolSize]; + + // DB2 strings expected to have at least empty string + for (size_t i = 0; i < stringHoldersPoolSize / sizeof(char*); ++i) + ((char const**)stringHolders)[i] = nullStr; + } + else + stringHolders = nullptr; + + // Resize index table + // database query *MUST* contain ORDER BY `index_field` DESC clause + uint32 indexTableSize; + if (indexField >= 0) + { + indexTableSize = (*result)[indexField].GetUInt32() + 1; + if (indexTableSize < records) + indexTableSize = records; + } + else + indexTableSize = records + result->GetRowCount(); + + if (indexTableSize > records) + { + char** tmpIdxTable = new char* [indexTableSize]; + memset(tmpIdxTable, 0, indexTableSize * sizeof(char*)); + memcpy(tmpIdxTable, indexTable, records * sizeof(char*)); + delete[] indexTable; + indexTable = tmpIdxTable; + } + + char* tempDataTable = new char[result->GetRowCount() * recordSize]; + uint32* newIndexes = new uint32[result->GetRowCount()]; + uint32 rec = 0; + uint32 newRecords = 0; + + do + { + Field* fields = result->Fetch(); + uint32 offset = 0; + uint32 stringFieldNumInRecord = 0; + + uint32 indexValue; + if (indexField >= 0) + indexValue = fields[indexField].GetUInt32(); + else + indexValue = records + rec; + + // Attempt to overwrite existing data + char* dataValue = indexTable[indexValue]; + if (!dataValue) + { + newIndexes[newRecords] = indexValue; + dataValue = &tempDataTable[newRecords++ * recordSize]; + } + + for (uint32 f = 0; f < fieldCount; f++) + { + switch (format[f]) + { + case FT_FLOAT: + *((float*)(&dataValue[offset])) = fields[f].GetFloat(); + offset += 4; + break; + case FT_IND: + case FT_INT: + *((int32*)(&dataValue[offset])) = fields[f].GetInt32(); + offset += 4; + break; + case FT_BYTE: + *((int8*)(&dataValue[offset])) = fields[f].GetInt8(); + offset += 1; + break; + case FT_STRING: + { + LocalizedString** slot = (LocalizedString**)(&dataValue[offset]); + *slot = (LocalizedString*)(&stringHolders[stringHoldersRecordPoolSize * rec + stringHolderSize * stringFieldNumInRecord]); + ASSERT(*slot); + + // Value in database in main table field must be for enUS locale + if (char* str = AddLocaleString(*slot, LOCALE_enUS, fields[f].GetString())) + stringPool.push_back(str); + + ++stringFieldNumInRecord; + offset += sizeof(char*); + break; + } + } + } + + ASSERT(offset == recordSize); + ++rec; + } while (result->NextRow()); + + if (!newRecords) + { + delete[] tempDataTable; + delete[] newIndexes; + return nullptr; + } + + // Compact new data table to only contain new records not previously loaded from file + char* dataTable = new char[newRecords * recordSize]; + memcpy(dataTable, tempDataTable, newRecords * recordSize); + + // insert new records to index table + for (uint32 i = 0; i < newRecords; ++i) + indexTable[newIndexes[i]] = &dataTable[i * recordSize]; + + delete[] tempDataTable; + delete[] newIndexes; + + records = indexTableSize; + + return dataTable; +} + +void DB2DatabaseLoader::LoadStrings(const char* format, int32 preparedStatement, uint32 locale, char**& indexTable, std::list& stringPool) +{ + PreparedStatement* stmt = HotfixDatabase.GetPreparedStatement(HotfixDatabaseStatements(preparedStatement)); + stmt->setString(0, localeNames[locale]); + PreparedQueryResult result = HotfixDatabase.Query(stmt); + if (!result) + return; + + size_t stringFields = DB2FileLoader::GetFormatStringFieldCount(format); + if (result->GetFieldCount() != stringFields + 1 /*ID*/) + return; + + uint32 const fieldCount = strlen(format); + int32 indexField; + uint32 recordSize = DB2FileLoader::GetFormatRecordSize(format, &indexField); + ASSERT(indexField >= 0, "DB2Storage must be indexed to load localized strings"); + + do + { + Field* fields = result->Fetch(); + uint32 offset = 0; + uint32 stringFieldNumInRecord = 0; + uint32 indexValue = fields[0].GetUInt32(); + + // Attempt to overwrite existing data + if (char* dataValue = indexTable[indexValue]) + { + for (uint32 x = 0; x < fieldCount; x++) + { + switch (format[x]) + { + case FT_FLOAT: + case FT_IND: + case FT_INT: + offset += 4; + break; + case FT_BYTE: + offset += 1; + break; + case FT_STRING: + { + // fill only not filled entries + LocalizedString* db2str = *(LocalizedString**)(&dataValue[offset]); + if (db2str->Str[locale] == nullStr) + if (char* str = AddLocaleString(db2str, locale, fields[1 + stringFieldNumInRecord].GetString())) + stringPool.push_back(str); + + ++stringFieldNumInRecord; + offset += sizeof(char*); + break; + } + } + } + + ASSERT(offset == recordSize); + } + else + TC_LOG_ERROR("sql.sql", "Hotfix locale table for storage %s references row that does not exist %u!", _storageName.c_str(), indexValue); + + } while (result->NextRow()); + + return; +} + +char* DB2DatabaseLoader::AddLocaleString(LocalizedString* holder, uint32 locale, std::string const& value) +{ + if (!value.empty()) + { + std::size_t existingLength = strlen(holder->Str[locale]); + if (existingLength >= value.length()) + { + // Reuse existing storage if there is enough space + char* str = const_cast(holder->Str[locale]); + memcpy(str, value.c_str(), value.length()); + str[value.length()] = '\0'; + return nullptr; + } + + char* str = new char[value.length() + 1]; + memcpy(str, value.c_str(), value.length()); + str[value.length()] = '\0'; + holder->Str[locale] = str; + return str; + } + + return nullptr; +} diff --git a/src/server/shared/DataStores/DB2FileLoader.h b/src/server/shared/DataStores/DB2StorageLoader.h similarity index 84% rename from src/server/shared/DataStores/DB2FileLoader.h rename to src/server/shared/DataStores/DB2StorageLoader.h index e54f68f0b9..95346f04f4 100644 --- a/src/server/shared/DataStores/DB2FileLoader.h +++ b/src/server/shared/DataStores/DB2StorageLoader.h @@ -21,6 +21,7 @@ #include "Define.h" #include "Utilities/ByteConverter.h" #include +#include class TC_SHARED_API DB2FileLoader { @@ -82,7 +83,7 @@ class TC_SHARED_API DB2FileLoader char* AutoProduceStringsArrayHolders(char const* fmt, char* dataTable); char* AutoProduceStrings(char const* fmt, char* dataTable, uint32 locale); static uint32 GetFormatRecordSize(char const* format, int32* index_pos = nullptr); - static uint32 GetFormatStringsFields(char const* format); + static uint32 GetFormatStringFieldCount(const char* format); private: uint32 recordSize; @@ -104,4 +105,17 @@ private: int unk5; // WDB2 }; +class DB2DatabaseLoader +{ +public: + explicit DB2DatabaseLoader(std::string const& storageName) : _storageName(storageName) { } + + char* Load(const char* format, int32 preparedStatement, uint32& records, char**& indexTable, char*& stringHolders, std::list& stringPool); + void LoadStrings(const char* format, int32 preparedStatement, uint32 locale, char**& indexTable, std::list& stringPool); + static char* AddLocaleString(LocalizedString* holder, uint32 locale, std::string const& value); + +private: + std::string _storageName; +}; + #endif diff --git a/src/server/shared/DataStores/DB2Store.h b/src/server/shared/DataStores/DB2Store.h index 0ce0d5280d..581bd2c600 100644 --- a/src/server/shared/DataStores/DB2Store.h +++ b/src/server/shared/DataStores/DB2Store.h @@ -18,8 +18,9 @@ #ifndef DB2STORE_H #define DB2STORE_H +#include "DB2StorageLoader.h" +#include "DBStorageIterator.h" #include "Common.h" -#include "DB2FileLoader.h" #include "Errors.h" #include "ByteBuffer.h" #include @@ -30,203 +31,180 @@ class DB2StorageBase public: virtual ~DB2StorageBase() { } - uint32 GetHash() const { return tableHash; } + uint32 GetHash() const { return _tableHash; } virtual bool HasRecord(uint32 id) const = 0; - virtual void WriteRecord(uint32 id, LocaleConstant localeConstant, ByteBuffer& buffer) const = 0; + virtual void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const = 0; + + virtual void EraseRecord(uint32 id) = 0; protected: - uint32 tableHash; + uint32 _tableHash; }; -template -class DB2Storage; - -template -bool DB2StorageHasEntry(DB2Storage const& store, uint32 id) -{ - return store.LookupEntry(id) != nullptr; -} - -template -void WriteDB2RecordToPacket(DB2Storage const& store, uint32 id, uint32 locale, ByteBuffer& buffer) -{ - uint8 const* entry = (uint8 const*)store.LookupEntry(id); - ASSERT(entry); - - std::string format = store.GetFormat(); - for (uint32 i = 0; i < format.length(); ++i) - { - switch (format[i]) - { - case FT_IND: - case FT_INT: - buffer << *(uint32*)entry; - entry += 4; - break; - case FT_FLOAT: - buffer << *(float*)entry; - entry += 4; - break; - case FT_BYTE: - buffer << *(uint8*)entry; - entry += 1; - break; - case FT_STRING: - { - LocalizedString* locStr = *(LocalizedString**)entry; - if (locStr->Str[locale][0] == '\0') - locale = 0; - - char const* str = locStr->Str[locale]; - size_t len = strlen(str); - buffer << uint16(len); - if (len) - buffer << str; - entry += sizeof(char*); - break; - } - case FT_NA: - case FT_SORT: - buffer << uint32(0); - break; - case FT_NA_BYTE: - buffer << uint8(0); - break; - } - } -} - template class DB2Storage : public DB2StorageBase { - typedef std::vector StringPoolList; - typedef std::vector DataTableEx; - typedef bool(*EntryChecker)(DB2Storage const&, uint32); - typedef void(*PacketWriter)(DB2Storage const&, uint32, LocaleConstant, ByteBuffer&); + typedef std::list StringPoolList; public: - DB2Storage(char const* f, EntryChecker checkEntry = nullptr, PacketWriter writePacket = nullptr) : - nCount(0), fieldCount(0), fmt(f), m_dataTable(nullptr) + typedef DBStorageIterator iterator; + + DB2Storage(char const* fileName, char const* format, uint32 preparedStmtIndex = -1) + : _fileName(fileName), _indexTableSize(0), _fieldCount(0), _format(format), _dataTable(nullptr), _dataTableEx(nullptr), _hotfixStatement(preparedStmtIndex) { - indexTable.asT = nullptr; - CheckEntry = checkEntry ? checkEntry : (EntryChecker)&DB2StorageHasEntry; - WritePacket = writePacket ? writePacket : (PacketWriter)&WriteDB2RecordToPacket; + _indexTable.AsT = nullptr; } - ~DB2Storage() { Clear(); } - - bool HasRecord(uint32 id) const { return CheckEntry(*this, id); } - T const* LookupEntry(uint32 id) const { return (id >= nCount) ? nullptr : indexTable.asT[id]; } - uint32 GetNumRows() const { return nCount; } - char const* GetFormat() const { return fmt; } - uint32 GetFieldCount() const { return fieldCount; } - void WriteRecord(uint32 id, LocaleConstant localeConstant, ByteBuffer& buffer) const + ~DB2Storage() { - WritePacket(*this, id, localeConstant, buffer); + delete[] reinterpret_cast(_indexTable.AsT); + delete[] reinterpret_cast(_dataTable); + delete[] reinterpret_cast(_dataTableEx); + for (char* stringPool : _stringPoolList) + delete[] stringPool; } - T* CreateEntry(uint32 id, bool evenIfExists = false) + bool HasRecord(uint32 id) const override { return id < _indexTableSize && _indexTable.AsT[id] != nullptr; } + void WriteRecord(uint32 id, uint32 locale, ByteBuffer& buffer) const override { - if (evenIfExists && LookupEntry(id)) - return nullptr; + ASSERT(id < _indexTableSize); + char const* entry = _indexTable.AsChar[id]; + ASSERT(entry); - if (id >= nCount) + std::size_t fields = strlen(_format); + for (uint32 i = 0; i < fields; ++i) { - // reallocate index table - char** tmpIdxTable = new char*[id + 1]; - memset(tmpIdxTable, 0, (id + 1) * sizeof(char*)); - memcpy(tmpIdxTable, indexTable.asChar, nCount * sizeof(char*)); - delete[] reinterpret_cast(indexTable.asT); - nCount = id + 1; - indexTable.asChar = tmpIdxTable; - } + switch (_format[i]) + { + case FT_IND: + case FT_INT: + buffer << *(uint32*)entry; + entry += 4; + break; + case FT_FLOAT: + buffer << *(float*)entry; + entry += 4; + break; + case FT_BYTE: + buffer << *(uint8*)entry; + entry += 1; + break; + case FT_STRING: + { + LocalizedString* locStr = *(LocalizedString**)entry; + if (locStr->Str[locale][0] == '\0') + locale = 0; - T* entryDst = new T; - m_dataTableEx.push_back(entryDst); - indexTable.asT[id] = entryDst; - return entryDst; + char const* str = locStr->Str[locale]; + std::size_t len = strlen(str); + buffer << uint16(len ? len + 1 : 0); + if (len) + { + buffer.append(str, len); + buffer << uint8(0); + } + entry += sizeof(LocalizedString*); + break; + } + } + } } - void EraseEntry(uint32 id) { indexTable.asT[id] = nullptr; } + void EraseRecord(uint32 id) override { if (id < _indexTableSize) _indexTable.AsT[id] = nullptr; } - bool Load(char const* fn, LocaleConstant localeConstant) + T const* LookupEntry(uint32 id) const { return (id >= _indexTableSize) ? nullptr : _indexTable.AsT[id]; } + std::string const& GetFileName() const { return _fileName; } + uint32 GetNumRows() const { return _indexTableSize; } + char const* GetFormat() const { return _format; } + uint32 GetFieldCount() const { return _fieldCount; } + + bool Load(std::string const& path, uint32 locale) { DB2FileLoader db2; - // Check if load was sucessful, only then continue - if (!db2.Load(fn, fmt)) + // Check if load was successful, only then continue + if (!db2.Load((path + _fileName).c_str(), _format)) return false; - fieldCount = db2.GetCols(); - tableHash = db2.GetHash(); + _fieldCount = db2.GetCols(); + _tableHash = db2.GetHash(); // load raw non-string data - m_dataTable = reinterpret_cast(db2.AutoProduceData(fmt, nCount, indexTable.asChar)); + _dataTable = reinterpret_cast(db2.AutoProduceData(_format, _indexTableSize, _indexTable.AsChar)); // create string holders for loaded string fields - m_stringPoolList.push_back(db2.AutoProduceStringsArrayHolders(fmt, (char*)m_dataTable)); + if (char* stringHolders = db2.AutoProduceStringsArrayHolders(_format, (char*)_dataTable)) + { + _stringPoolList.push_back(stringHolders); - // load strings from dbc data - m_stringPoolList.push_back(db2.AutoProduceStrings(fmt, (char*)m_dataTable, localeConstant)); + // load strings from db2 data + if (char* stringBlock = db2.AutoProduceStrings(_format, (char*)_dataTable, locale)) + _stringPoolList.push_back(stringBlock); + } - // error in dbc file at loading if nullptr - return indexTable.asT != nullptr; + // error in db2 file at loading if nullptr + return _indexTable.AsT != nullptr; } - bool LoadStringsFrom(char const* fn, uint32 locale) + bool LoadStringsFrom(std::string const& path, uint32 locale) { - // DBC must be already loaded using Load - if (!indexTable.asT) + // DB2 must be already loaded using Load + if (!_indexTable.AsT) return false; DB2FileLoader db2; // Check if load was successful, only then continue - if (!db2.Load(fn, fmt)) + if (!db2.Load((path + _fileName).c_str(), _format)) return false; - // load strings from another locale dbc data - m_stringPoolList.push_back(db2.AutoProduceStrings(fmt, (char*)m_dataTable, locale)); - + // load strings from another locale db2 data + if (DB2FileLoader::GetFormatStringFieldCount(_format)) + if (char* stringBlock = db2.AutoProduceStrings(_format, (char*)_dataTable, locale)) + _stringPoolList.push_back(stringBlock); return true; } - void Clear() + void LoadFromDB() { - if (!indexTable.asT) + if (_hotfixStatement == -1) return; - delete[] reinterpret_cast(indexTable.asT); - indexTable.asT = nullptr; + char* extraStringHolders = nullptr; + if (char* dataTable = DB2DatabaseLoader(_fileName).Load(_format, _hotfixStatement, _indexTableSize, _indexTable.AsChar, extraStringHolders, _stringPoolList)) + _dataTableEx = reinterpret_cast(dataTable); - delete[] reinterpret_cast(m_dataTable); - m_dataTable = nullptr; - - for (typename DataTableEx::iterator itr = m_dataTableEx.begin(); itr != m_dataTableEx.end(); ++itr) - delete *itr; - m_dataTableEx.clear(); - - for (char* strings : m_stringPoolList) - delete[] strings; - m_stringPoolList.clear(); - - nCount = 0; + if (extraStringHolders) + _stringPoolList.push_back(extraStringHolders); } - EntryChecker CheckEntry; - PacketWriter WritePacket; + void LoadStringsFromDB(LocaleConstant locale) + { + if (_hotfixStatement == -1) + return; + + if (!DB2FileLoader::GetFormatStringFieldCount(_format)) + return; + + DB2DatabaseLoader(_fileName).LoadStrings(_format, _hotfixStatement + 1, locale, _indexTable.AsChar, _stringPoolList); + } + + iterator begin() { return iterator(_indexTable.AsT, _indexTableSize); } + iterator end() { return iterator(_indexTable.AsT, _indexTableSize, _indexTableSize); } private: - uint32 nCount; - uint32 fieldCount; - char const* fmt; + std::string _fileName; + uint32 _indexTableSize; + uint32 _fieldCount; + char const* _format; union { - T** asT; - char** asChar; - } indexTable; - T* m_dataTable; - DataTableEx m_dataTableEx; - StringPoolList m_stringPoolList; + T** AsT; + char** AsChar; + } _indexTable; + T* _dataTable; + T* _dataTableEx; + StringPoolList _stringPoolList; + int32 _hotfixStatement; }; #endif diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 68eb6dd5dd..5cbbe4c729 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -565,7 +565,8 @@ bool StartDB() loader .AddDatabase(LoginDatabase, "Login") .AddDatabase(CharacterDatabase, "Character") - .AddDatabase(WorldDatabase, "World"); + .AddDatabase(WorldDatabase, "World") + .AddDatabase(HotfixDatabase, "Hotfix"); if (!loader.Load()) return false; @@ -607,6 +608,7 @@ void StopDB() CharacterDatabase.Close(); WorldDatabase.Close(); LoginDatabase.Close(); + HotfixDatabase.Close(); MySQL::Library_End(); } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 17fb0c73ea..4525afc85f 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -97,6 +97,7 @@ LogsDir = "" # Default: "127.0.0.1;3306;trinity;trinity;auth" - (LoginDatabaseInfo) # "127.0.0.1;3306;trinity;trinity;world" - (WorldDatabaseInfo) # "127.0.0.1;3306;trinity;trinity;characters" - (CharacterDatabaseInfo) +# "127.0.0.1;3306;trinity;trinity;hotfixes" - (HotfixDatabaseInfo) # # Don't change hostname unless you are hosting mysql on a different machine, if you need help # with configuration allowing to connect from diferent machine than the one running server @@ -107,6 +108,7 @@ LogsDir = "" LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" WorldDatabaseInfo = "127.0.0.1;3306;trinity;trinity;world" CharacterDatabaseInfo = "127.0.0.1;3306;trinity;trinity;characters" +HotfixDatabaseInfo = "127.0.0.1;3306;trinity;trinity;hotfixes" # # LoginDatabase.WorkerThreads @@ -118,10 +120,12 @@ CharacterDatabaseInfo = "127.0.0.1;3306;trinity;trinity;characters" # Default: 1 - (LoginDatabase.WorkerThreads) # 1 - (WorldDatabase.WorkerThreads) # 1 - (CharacterDatabase.WorkerThreads) +# 1 - (HotfixDatabase.WorkerThreads) LoginDatabase.WorkerThreads = 1 WorldDatabase.WorkerThreads = 1 CharacterDatabase.WorkerThreads = 1 +HotfixDatabase.WorkerThreads = 1 # # LoginDatabase.SynchThreads @@ -135,6 +139,7 @@ CharacterDatabase.WorkerThreads = 1 LoginDatabase.SynchThreads = 1 WorldDatabase.SynchThreads = 1 CharacterDatabase.SynchThreads = 2 +HotfixDatabase.SynchThreads = 1 # # MaxPingTime @@ -1276,12 +1281,13 @@ BirthdayTime = 1222964635 # DATABASE_LOGIN = 1, // Auth database # DATABASE_CHARACTER = 2, // Character database # DATABASE_WORLD = 4, // World database +# DATABASE_HOTFIX = 8, // Hotfixes database # -# Default: 7 - (All enabled) +# Default: 15 - (All enabled) # 4 - (Enable world only) -# 0 - (All disabled) +# 0 - (All Disabled) -Updates.EnableDatabases = 7 +Updates.EnableDatabases = 15 # # Updates.AutoSetup