Core/Datastores: backported hotfix system implementation

This commit is contained in:
Ovahlord committed 2020-02-21 23:13:38 +01:00
1 parent 4bc9c07407
commit d9b854ad59
87 files changed
+2227 -2251

No files matched your search

+2 -1
View File
@@ -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
+4
View File
@@ -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;
+6
View File
@@ -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`;
@@ -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`;
+5
View File
@@ -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"
+1
View File
@@ -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();
@@ -20,3 +20,4 @@
DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabase;
DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase;
DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
DatabaseWorkerPool<HotfixDatabaseConnection> HotfixDatabase;
@@ -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<WorldDatabaseConnection> WorldDatabase
TC_DATABASE_API extern DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabase;
/// Accessor to the realm/login database
TC_DATABASE_API extern DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabase;
/// Accessor to the hotfix database
TC_DATABASE_API extern DatabaseWorkerPool<HotfixDatabaseConnection> HotfixDatabase;
#endif
@@ -184,3 +184,5 @@ template TC_DATABASE_API
DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>&, std::string const&);
template TC_DATABASE_API
DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>&, std::string const&);
template TC_DATABASE_API
DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(DatabaseWorkerPool<HotfixDatabaseConnection>&, std::string const&);
@@ -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:
@@ -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<T>::ExecuteOrAppend(SQLTransaction& trans, PreparedState
template class TC_DATABASE_API DatabaseWorkerPool<LoginDatabaseConnection>;
template class TC_DATABASE_API DatabaseWorkerPool<WorldDatabaseConnection>;
template class TC_DATABASE_API DatabaseWorkerPool<CharacterDatabaseConnection>;
template class TC_DATABASE_API DatabaseWorkerPool<HotfixDatabaseConnection>;
@@ -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 <http://www.gnu.org/licenses/>.
*/
// 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<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo)
{
}
HotfixDatabaseConnection::~HotfixDatabaseConnection()
{
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
// 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<SQLOperation*>* q, MySQLConnectionInfo& connInfo);
~HotfixDatabaseConnection();
//- Loads database type specific prepared statements
void DoPrepareStatements() override;
};
#endif
@@ -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);
@@ -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,
+33
View File
@@ -150,6 +150,38 @@ bool DBUpdater<CharacterDatabaseConnection>::IsEnabled(uint32 const updateMask)
return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false;
}
// Hotfix Database
template<>
std::string DBUpdater<HotfixDatabaseConnection>::GetConfigEntry()
{
return "Updates.Hotfix";
}
template<>
std::string DBUpdater<HotfixDatabaseConnection>::GetTableName()
{
return "Hotfixes";
}
template<>
std::string DBUpdater<HotfixDatabaseConnection>::GetBaseFile()
{
return GitRevision::GetHotfixesDatabase();
}
template<>
bool DBUpdater<HotfixDatabaseConnection>::IsEnabled(uint32 const updateMask)
{
// This way silences warnings under msvc
return (updateMask & DatabaseLoader::DATABASE_HOTFIX) ? true : false;
}
template<>
BaseLocation DBUpdater<HotfixDatabaseConnection>::GetBaseLocationType()
{
return LOCATION_DOWNLOAD;
}
// All
template<class T>
BaseLocation DBUpdater<T>::GetBaseLocationType()
@@ -391,3 +423,4 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
template class TC_DATABASE_API DBUpdater<LoginDatabaseConnection>;
template class TC_DATABASE_API DBUpdater<WorldDatabaseConnection>;
template class TC_DATABASE_API DBUpdater<CharacterDatabaseConnection>;
template class TC_DATABASE_API DBUpdater<HotfixDatabaseConnection>;
+2 -2
View File
@@ -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:
+1 -1
View File
@@ -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,
@@ -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<T>::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<T>::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<T>::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<T>::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<T>::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;
}
@@ -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;
}
}
@@ -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;
}
@@ -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;
@@ -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<float>(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<float>(itemProto->BuyCount));
float basePriceFloat = buyPrice * stackCount / (itemProto->GetClass() == 6 ? 200.0f : static_cast<float>(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:
+7 -11
View File
@@ -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;
}
+1 -1
View File
@@ -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];
+83 -44
View File
@@ -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 <sstream>
DB2Storage<ItemEntry> sItemStore(Itemfmt, &DB2Utilities::HasItemEntry, &DB2Utilities::WriteItemDbReply);
DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore(ItemCurrencyCostfmt);
DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
DB2Storage<ItemSparseEntry> sItemSparseStore(ItemSparsefmt, &DB2Utilities::HasItemSparseEntry, &DB2Utilities::WriteItemSparseDbReply);
DB2Storage<KeyChainEntry> sKeyChainStore(KeyChainfmt);
DB2Storage<ItemEntry> sItemStore("Item.db2", Itemfmt, HOTFIX_SEL_ITEM);
DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore("ItemCurrencyCost.db2", ItemCurrencyCostfmt, HOTFIX_SEL_ITEM_CURRENCY_COST);
DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore("ItemExtendedCost.db2", ItemExtendedCostEntryfmt, HOTFIX_SEL_ITEM_EXTENDED_COST);
DB2Storage<ItemSparseEntry> sItemSparseStore("Item-sparse.db2", ItemSparsefmt, HOTFIX_SEL_ITEM_SPARSE);
DB2Storage<KeyChainEntry> sKeyChainStore("KeyChain.db2", KeyChainfmt, HOTFIX_SEL_KEY_CHAIN);
typedef std::list<std::string> DB2StoreProblemList;
typedef std::map<uint32 /*hash*/, DB2StorageBase*> 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<class T>
inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Storage<T>& storage, std::string const& db2_path, std::string const& filename)
inline void LoadDB2(uint32& availableDb2Locales, DB2StoreProblemList& errlist, DB2Manager::StorageMap& stores, DB2Storage<T>* 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<<i); // mark as not available for speedup next checks
storage->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);
}
+37 -7
View File
@@ -22,14 +22,44 @@
#include "DB2Structure.h"
#include <string>
extern DB2Storage<ItemEntry> sItemStore;
extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore;
extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore;
extern DB2Storage<ItemSparseEntry> sItemSparseStore;
extern DB2Storage<KeyChainEntry> sKeyChainStore;
TC_GAME_API extern DB2Storage<ItemEntry> sItemStore;
TC_GAME_API extern DB2Storage<ItemCurrencyCostEntry> sItemCurrencyCostStore;
TC_GAME_API extern DB2Storage<ItemExtendedCostEntry> sItemExtendedCostStore;
TC_GAME_API extern DB2Storage<ItemSparseEntry> sItemSparseStore;
TC_GAME_API extern DB2Storage<KeyChainEntry> sKeyChainStore;
void LoadDB2Stores(std::string const& dataPath);
struct HotfixNotify
{
uint32 TableHash;
uint32 Timestamp;
uint32 Entry;
};
DB2StorageBase const* GetDB2Storage(uint32 type);
typedef std::vector<HotfixNotify> HotfixData;
class TC_GAME_API DB2Manager
{
public:
typedef std::map<uint32 /*hash*/, DB2StorageBase*> 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
+90 -98
View File
@@ -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
-171
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include "DB2Utility.h"
#include "ObjectMgr.h"
inline bool ItemExists(uint32 id)
{
return sObjectMgr->GetItemTemplate(id) != nullptr;
}
bool DB2Utilities::HasItemEntry(DB2Storage<ItemEntry> const& /*store*/, uint32 id)
{
return ItemExists(id);
}
bool DB2Utilities::HasItemSparseEntry(DB2Storage<ItemSparseEntry> const& /*store*/, uint32 id)
{
return ItemExists(id);
}
void DB2Utilities::WriteItemDbReply(DB2Storage<ItemEntry> 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<ItemSparseEntry> 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);
}
-41
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef DB2PACKETWRITER_H
#define DB2PACKETWRITER_H
#include "Define.h"
template<class T>
class DB2Storage;
class ByteBuffer;
struct ItemEntry;
struct ItemSparseEntry;
enum LocaleConstant : uint8;
namespace DB2Utilities
{
//
bool HasItemEntry(DB2Storage<ItemEntry> const& store, uint32 id);
bool HasItemSparseEntry(DB2Storage<ItemSparseEntry> const& store, uint32 id);
//
void WriteItemDbReply(DB2Storage<ItemEntry> const& store, uint32 id, LocaleConstant localeConstant, ByteBuffer& buffer);
void WriteItemSparseDbReply(DB2Storage<ItemSparseEntry> const& store, uint32 id, LocaleConstant localeConstant, ByteBuffer& buffer);
}
#endif // DB2PACKETWRITER_H
+3 -3
View File
@@ -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
+30 -30
View File
@@ -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<ItemDamageEntry>* 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)));
}
}
@@ -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;
}
@@ -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;
@@ -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;
@@ -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
+73 -73
View File
@@ -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)
+7 -4
View File
@@ -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<Bag const*>(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);
@@ -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];
+25 -9
View File
@@ -15,11 +15,27 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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;
+76 -99
View File
@@ -18,7 +18,7 @@
#ifndef _ITEMPROTOTYPE_H
#define _ITEMPROTOTYPE_H
#include "Common.h"
#include "DB2Structure.h"
#include "SharedDefines.h"
#include "WorldPacket.h"
#include <vector>
@@ -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<ItemEffect> 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<std::string> Name;
std::vector<std::string> Description;
};
#endif
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -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)
{
+3 -3
View File
@@ -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;
}
}
+34 -365
View File
@@ -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<uint32>::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();
+1 -24
View File
@@ -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<TempSummonGroupKey, std::vector<TempSummonData>> TempSummonData
typedef std::unordered_map<uint32, CreatureLocale> CreatureLocaleContainer;
typedef std::unordered_map<uint32, GameObjectLocale> GameObjectLocaleContainer;
typedef std::unordered_map<uint32, ItemTemplate> ItemTemplateContainer;
typedef std::unordered_map<uint32, ItemLocale> ItemLocaleContainer;
typedef std::unordered_map<uint32, QuestLocale> QuestLocaleContainer;
typedef std::unordered_map<uint32, NpcTextLocale> NpcTextLocaleContainer;
typedef std::unordered_map<uint32, PageTextLocale> PageTextLocaleContainer;
@@ -864,15 +864,6 @@ struct DungeonEncounter
typedef std::list<DungeonEncounter const*> DungeonEncounterList;
typedef std::unordered_map<uint32, DungeonEncounterList> DungeonEncounterContainer;
struct HotfixInfo
{
uint32 Type;
uint32 Timestamp;
uint32 Entry;
};
typedef std::vector<HotfixInfo> 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;
+3 -3
View File
@@ -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<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().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<HighGuid::Item>(sObjectMgr->GetGenerator<HighGuid::Item>().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;
+1 -1
View File
@@ -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());
}
}
@@ -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))
+4 -11
View File
@@ -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();
+28 -28
View File
@@ -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());
+2 -2
View File
@@ -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
+4 -4
View File
@@ -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);
-68
View File
@@ -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<uint32>(sizePos, data.wpos() - sizePos - 4);
SendPacket(&data);
}
delete[] guids;
}
void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY");
@@ -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);
+32
View File
@@ -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());
}
}
+10 -10
View File
@@ -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);
}
+4 -4
View File
@@ -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());
}
+8 -8
View File
@@ -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
+9 -9
View File
@@ -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
+2 -2
View File
@@ -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)
@@ -26,6 +26,7 @@
#include "MovementPackets.h"
#include "NPCPackets.h"
#include "QuestPackets.h"
#include "QueryPackets.h"
#include "SystemPackets.h"
#endif // AllPackets_h__
@@ -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;
}
}
@@ -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);
@@ -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 <http://www.gnu.org/licenses/>.
*/
#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;
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<DBQueryRecord> 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__
+3 -3
View File
@@ -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);
+2 -2
View File
@@ -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,
+8 -1
View File
@@ -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
+63 -66
View File
@@ -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<float, float> 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<Spell*>(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;
+17 -17
View File
@@ -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);
}
}
+4 -4
View File
@@ -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;
}
}
+7 -8
View File
@@ -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));
+3 -35
View File
@@ -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;
+19 -15
View File
@@ -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);
}
}
}
+4 -9
View File
@@ -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<LootItem> const& items)
{
+2 -2
View File
@@ -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;
}
-10
View File
@@ -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... ");
+1 -1
View File
@@ -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);
@@ -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();
}
}
}
+1 -1
View File
@@ -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());
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include "Common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<char*>& 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<char*>& 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<char*>(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;
}
@@ -21,6 +21,7 @@
#include "Define.h"
#include "Utilities/ByteConverter.h"
#include <cassert>
#include <list>
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<char*>& stringPool);
void LoadStrings(const char* format, int32 preparedStatement, uint32 locale, char**& indexTable, std::list<char*>& stringPool);
static char* AddLocaleString(LocalizedString* holder, uint32 locale, std::string const& value);
private:
std::string _storageName;
};
#endif
+120 -142
View File
@@ -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 <vector>
@@ -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 T>
class DB2Storage;
template<class T>
bool DB2StorageHasEntry(DB2Storage<T> const& store, uint32 id)
{
return store.LookupEntry(id) != nullptr;
}
template<class T>
void WriteDB2RecordToPacket(DB2Storage<T> 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 T>
class DB2Storage : public DB2StorageBase
{
typedef std::vector<char*> StringPoolList;
typedef std::vector<T*> DataTableEx;
typedef bool(*EntryChecker)(DB2Storage<T> const&, uint32);
typedef void(*PacketWriter)(DB2Storage<T> const&, uint32, LocaleConstant, ByteBuffer&);
typedef std::list<char*> StringPoolList;
public:
DB2Storage(char const* f, EntryChecker checkEntry = nullptr, PacketWriter writePacket = nullptr) :
nCount(0), fieldCount(0), fmt(f), m_dataTable(nullptr)
typedef DBStorageIterator<T> 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<T>;
WritePacket = writePacket ? writePacket : (PacketWriter)&WriteDB2RecordToPacket<T>;
_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<char*>(_indexTable.AsT);
delete[] reinterpret_cast<char*>(_dataTable);
delete[] reinterpret_cast<char*>(_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<char*>(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<T*>(db2.AutoProduceData(fmt, nCount, indexTable.asChar));
_dataTable = reinterpret_cast<T*>(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<char*>(indexTable.asT);
indexTable.asT = nullptr;
char* extraStringHolders = nullptr;
if (char* dataTable = DB2DatabaseLoader(_fileName).Load(_format, _hotfixStatement, _indexTableSize, _indexTable.AsChar, extraStringHolders, _stringPoolList))
_dataTableEx = reinterpret_cast<T*>(dataTable);
delete[] reinterpret_cast<char*>(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
+3 -1
View File
@@ -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();
}
+9 -3
View File
@@ -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