diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.cpp | 15 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/CharacterDatabase.h | 3 | ||||
-rw-r--r-- | src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp | 51 | ||||
-rw-r--r-- | src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h | 12 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Item.cpp | 69 | ||||
-rw-r--r-- | src/server/game/Entities/Item/Item.h | 29 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 196 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 6 | ||||
-rw-r--r-- | src/server/game/Guilds/Guild.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Guilds/GuildMgr.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 4 |
11 files changed, 246 insertions, 151 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index c4ac7a42aa1..ba56adc790a 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -28,7 +28,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() "iit.itemModifiedAppearanceAllSpecs, iit.itemModifiedAppearanceSpec1, iit.itemModifiedAppearanceSpec2, iit.itemModifiedAppearanceSpec3, iit.itemModifiedAppearanceSpec4, " \ "iit.spellItemEnchantmentAllSpecs, iit.spellItemEnchantmentSpec1, iit.spellItemEnchantmentSpec2, iit.spellItemEnchantmentSpec3, iit.spellItemEnchantmentSpec4, " \ "ig.gemItemId1, ig.gemBonuses1, ig.gemContext1, ig.gemScalingLevel1, ig.gemItemId2, ig.gemBonuses2, ig.gemContext2, ig.gemScalingLevel2, ig.gemItemId3, ig.gemBonuses3, ig.gemContext3, ig.gemScalingLevel3, " \ - "im.fixedScalingLevel, im.artifactKnowledgeLevel, iz.xp, iz.level, iz.knowledgeLevel" + "im.fixedScalingLevel, im.artifactKnowledgeLevel" PrepareStatement(CHAR_DEL_QUEST_POOL_SAVE, "DELETE FROM pool_quest_save WHERE pool_id = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_QUEST_POOL_SAVE, "INSERT INTO pool_quest_save (pool_id, quest_id) VALUES (?, ?)", CONNECTION_ASYNC); @@ -112,7 +112,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT, "DELETE FROM character_queststatus_seasonal WHERE event = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_INVENTORY, "SELECT " SelectItemInstanceContent ", bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid LEFT JOIN item_instance_azerite iz ON ii.guid = iz.itemGuid WHERE ci.guid = ? ORDER BY (ii.flags & 0x80000) ASC, bag ASC, slot ASC", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_INVENTORY, "SELECT " SelectItemInstanceContent ", bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ci.guid = ? ORDER BY (ii.flags & 0x80000) ASC, bag ASC, slot ASC", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS, "SELECT a.button, a.action, a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activeTalentGroup AND a.guid = ? ORDER BY button", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_MAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = ? AND (checked & 1) = 0 AND deliver_time <= ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_MAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = ? AND (checked & 1) = 0", CONNECTION_ASYNC); @@ -144,8 +144,10 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES, "SELECT instanceId, releaseTime FROM account_instance_times WHERE accountId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT " SelectItemInstanceContent ", ii.owner_guid FROM mail_items mi JOIN item_instance ii ON mi.item_guid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid LEFT JOIN item_instance_azerite iz ON ii.guid = iz.itemGuid WHERE mail_id = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_AUCTION_ITEMS, "SELECT " SelectItemInstanceContent " FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid LEFT JOIN item_instance_azerite iz ON ii.guid = iz.itemGuid", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT " SelectItemInstanceContent ", ii.owner_guid, m.id FROM mail_items mi INNER JOIN mail m ON mi.mail_id = m.id LEFT JOIN item_instance ii ON mi.item_guid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE m.receiver = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_MAILITEMS_ARTIFACT, "SELECT a.itemGuid, a.xp, a.artifactAppearanceId, a.artifactTierId, ap.artifactPowerId, ap.purchasedRank FROM item_instance_artifact_powers ap LEFT JOIN item_instance_artifact a ON ap.itemGuid = a.itemGuid INNER JOIN mail_items mi ON a.itemGuid = mi.item_guid INNER JOIN mail m ON mi.mail_id = m.id WHERE m.receiver = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_MAILITEMS_AZERITE, "SELECT iz.itemGuid, iz.xp, iz.level, iz.knowledgeLevel FROM item_instance_azerite iz INNER JOIN mail_items mi ON iz.itemGuid = mi.item_guid INNER JOIN mail m ON mi.mail_id = m.id WHERE m.receiver = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_AUCTION_ITEMS, "SELECT " SelectItemInstanceContent " FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_AUCTIONS, "SELECT id, auctioneerguid, itemguid, itemEntry, count, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid", CONNECTION_SYNCH); PrepareStatement(CHAR_INS_AUCTION, "INSERT INTO auctionhouse (id, auctioneerguid, itemguid, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_AUCTION, "DELETE FROM auctionhouse WHERE id = ?", CONNECTION_ASYNC); @@ -189,6 +191,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_INS_ITEM_INSTANCE_MODIFIERS, "INSERT INTO item_instance_modifiers (itemGuid, fixedScalingLevel, artifactKnowledgeLevel) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS, "DELETE FROM item_instance_modifiers WHERE itemGuid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS_BY_OWNER, "DELETE im FROM item_instance_modifiers im LEFT JOIN item_instance ii ON im.itemGuid = ii.guid WHERE ii.owner_guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_ITEM_INSTANCE_AZERITE, "SELECT iz.itemGuid, iz.xp, iz.level, iz.knowledgeLevel FROM item_instance_azerite iz INNER JOIN character_inventory ci ON iz.itemGuid = ci.item WHERE ci.guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_ITEM_INSTANCE_AZERITE, "INSERT INTO item_instance_azerite (itemGuid, xp, level, knowledgeLevel) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_ITEM_INSTANCE_AZERITE_ON_LOAD, "UPDATE item_instance_azerite SET xp = ?, knowledgeLevel = ? WHERE itemGuid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ITEM_INSTANCE_AZERITE, "DELETE FROM item_instance_azerite WHERE itemGuid = ?", CONNECTION_ASYNC); @@ -224,7 +227,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() // 0: uint32, 1: uint8, 2: uint8, 3: uint32, 4: uint32 PrepareStatement(CHAR_INS_GUILD_BANK_ITEM, "INSERT INTO guild_bank_item (guildid, TabId, SlotId, item_guid) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8, 2: uint8 - PrepareStatement(CHAR_SEL_GUILD_BANK_ITEMS, "SELECT " SelectItemInstanceContent ", guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid LEFT JOIN item_instance_azerite iz ON ii.guid = iz.itemGuid", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_GUILD_BANK_ITEMS, "SELECT " SelectItemInstanceContent ", guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_GUILD_BANK_ITEMS, "DELETE FROM guild_bank_item WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32 // 0: uint32, 1: uint8, 2: uint8, 3: uint8, 4: uint32 PrepareStatement(CHAR_INS_GUILD_BANK_RIGHT, "INSERT INTO guild_bank_right (guildid, TabId, rid, gbright, SlotPerDay) VALUES (?, ?, ?, ?, ?) " @@ -506,7 +509,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHAR_COD_ITEM_MAIL, "SELECT id, messageType, mailTemplateId, sender, subject, body, money, has_items FROM mail WHERE receiver = ? AND has_items <> 0 AND cod <> 0", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_SOCIAL, "SELECT DISTINCT guid FROM character_social WHERE friend = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_OLD_CHARS, "SELECT guid, deleteInfos_Account FROM characters WHERE deleteDate IS NOT NULL AND deleteDate < ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_MAIL, "SELECT id, messageType, sender, receiver, subject, body, has_items, expire_time, deliver_time, money, cod, checked, stationery, mailTemplateId FROM mail WHERE receiver = ? ORDER BY id DESC", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_MAIL, "SELECT id, messageType, sender, receiver, subject, body, expire_time, deliver_time, money, cod, checked, stationery, mailTemplateId FROM mail WHERE receiver = ? ORDER BY id DESC", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_MAIL_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index b66594c82ab..63e2aac6833 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -116,6 +116,8 @@ enum CharacterDatabaseStatements : uint32 CHAR_SEL_CHARACTER_QUESTSTATUSREW, CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES, CHAR_SEL_MAILITEMS, + CHAR_SEL_MAILITEMS_ARTIFACT, + CHAR_SEL_MAILITEMS_AZERITE, CHAR_SEL_AUCTION_ITEMS, CHAR_INS_AUCTION, CHAR_DEL_AUCTION, @@ -158,6 +160,7 @@ enum CharacterDatabaseStatements : uint32 CHAR_INS_ITEM_INSTANCE_MODIFIERS, CHAR_DEL_ITEM_INSTANCE_MODIFIERS, CHAR_DEL_ITEM_INSTANCE_MODIFIERS_BY_OWNER, + CHAR_SEL_ITEM_INSTANCE_AZERITE, CHAR_INS_ITEM_INSTANCE_AZERITE, CHAR_UPD_ITEM_INSTANCE_AZERITE_ON_LOAD, CHAR_DEL_ITEM_INSTANCE_AZERITE, diff --git a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp index 599aadede43..8d9367d839a 100644 --- a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp +++ b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp @@ -58,60 +58,51 @@ void AzeriteItem::SaveToDB(CharacterDatabaseTransaction& trans) trans->Append(stmt); } -bool AzeriteItem::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry) +void AzeriteItem::LoadAzeriteItemData(AzeriteItemData& azeriteItemData) { - if (!Item::LoadFromDB(guid, ownerGuid, fields, entry)) - return false; - bool needSave = false; - uint64 xp = fields[43].GetUInt64(); - uint32 level = fields[44].GetUInt32(); - uint32 knowledgeLevel = fields[45].GetUInt32(); - - if (!sAzeriteLevelInfoStore.LookupEntry(level)) + if (!sAzeriteLevelInfoStore.LookupEntry(azeriteItemData.Level)) { - xp = 0; - level = 1; - knowledgeLevel = GetCurrentKnowledgeLevel(); + azeriteItemData.Xp = 0; + azeriteItemData.Level = 1; + azeriteItemData.KnowledgeLevel = GetCurrentKnowledgeLevel(); needSave = true; } - else if (level > MAX_AZERITE_ITEM_LEVEL) + else if (azeriteItemData.Level > MAX_AZERITE_ITEM_LEVEL) { - xp = 0; - level = MAX_AZERITE_ITEM_LEVEL; + azeriteItemData.Xp = 0; + azeriteItemData.Level = MAX_AZERITE_ITEM_LEVEL; needSave = true; } - if (knowledgeLevel != GetCurrentKnowledgeLevel()) + if (azeriteItemData.KnowledgeLevel != GetCurrentKnowledgeLevel()) { // rescale XP to maintain same progress % - uint64 oldMax = CalcTotalXPToNextLevel(level, knowledgeLevel); - knowledgeLevel = GetCurrentKnowledgeLevel(); - uint64 newMax = CalcTotalXPToNextLevel(level, knowledgeLevel); - xp = uint64(xp / double(oldMax) * newMax); + uint64 oldMax = CalcTotalXPToNextLevel(azeriteItemData.Level, azeriteItemData.KnowledgeLevel); + azeriteItemData.KnowledgeLevel = GetCurrentKnowledgeLevel(); + uint64 newMax = CalcTotalXPToNextLevel(azeriteItemData.Level, azeriteItemData.KnowledgeLevel); + azeriteItemData.Xp = uint64(azeriteItemData.Xp / double(oldMax) * newMax); needSave = true; } - else if (knowledgeLevel > MAX_AZERITE_ITEM_KNOWLEDGE_LEVEL) + else if (azeriteItemData.KnowledgeLevel > MAX_AZERITE_ITEM_KNOWLEDGE_LEVEL) { - knowledgeLevel = MAX_AZERITE_ITEM_KNOWLEDGE_LEVEL; + azeriteItemData.KnowledgeLevel = MAX_AZERITE_ITEM_KNOWLEDGE_LEVEL; needSave = true; } - SetUpdateFieldValue(m_values.ModifyValue(&AzeriteItem::m_azeriteItemData).ModifyValue(&UF::AzeriteItemData::Xp), xp); - SetUpdateFieldValue(m_values.ModifyValue(&AzeriteItem::m_azeriteItemData).ModifyValue(&UF::AzeriteItemData::Level), level); - SetUpdateFieldValue(m_values.ModifyValue(&AzeriteItem::m_azeriteItemData).ModifyValue(&UF::AzeriteItemData::KnowledgeLevel), knowledgeLevel); + SetUpdateFieldValue(m_values.ModifyValue(&AzeriteItem::m_azeriteItemData).ModifyValue(&UF::AzeriteItemData::Xp), azeriteItemData.Xp); + SetUpdateFieldValue(m_values.ModifyValue(&AzeriteItem::m_azeriteItemData).ModifyValue(&UF::AzeriteItemData::Level), azeriteItemData.Level); + SetUpdateFieldValue(m_values.ModifyValue(&AzeriteItem::m_azeriteItemData).ModifyValue(&UF::AzeriteItemData::KnowledgeLevel), azeriteItemData.KnowledgeLevel); if (needSave) { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ITEM_INSTANCE_AZERITE_ON_LOAD); - stmt->setUInt64(0, xp); - stmt->setUInt32(1, knowledgeLevel); - stmt->setUInt64(2, guid); + stmt->setUInt64(0, azeriteItemData.Xp); + stmt->setUInt32(1, azeriteItemData.KnowledgeLevel); + stmt->setUInt64(2, GetGUID().GetCounter()); CharacterDatabase.Execute(stmt); } - - return true; } void AzeriteItem::DeleteFromDB(CharacterDatabaseTransaction& trans) diff --git a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h index f9afbf2e0df..6c08ab57f9e 100644 --- a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h +++ b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h @@ -32,11 +32,21 @@ public: bool Create(ObjectGuid::LowType guidlow, uint32 itemId, Player const* owner) override; void SaveToDB(CharacterDatabaseTransaction& trans) override; - bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry) override; + void LoadAzeriteItemData(AzeriteItemData& azeriteItem); void DeleteFromDB(CharacterDatabaseTransaction& trans) override; uint32 GetItemLevel(Player const* owner) const override; + uint32 GetLevel() const { return m_azeriteItemData->Level; } + uint32 GetEffectiveLevel() const + { + uint32 level = m_azeriteItemData->AuraLevel; + if (!level) + level = m_azeriteItemData->Level; + + return level; + } + static uint32 GetCurrentKnowledgeLevel(); static uint64 CalcTotalXPToNextLevel(uint32 level, uint32 knowledgeLevel); void GiveXP(uint64 xp); diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 6329195f439..f0ec7dbd383 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -283,6 +283,61 @@ static uint32 const IllusionModifierMaskSpecSpecific = (1 << ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_3) | (1 << ITEM_MODIFIER_ENCHANT_ILLUSION_SPEC_4); +void ItemAdditionalLoadInfo::Init(std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo>* loadInfo, + PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult) +{ + // 0 1 2 3 4 5 + // SELECT a.itemGuid, a.xp, a.artifactAppearanceId, a.artifactTierId, ap.artifactPowerId, ap.purchasedRank FROM item_instance_artifact_powers ap LEFT JOIN item_instance_artifact a ON ap.itemGuid = a.itemGuid ... + if (artifactResult) + { + do + { + Field* fields = artifactResult->Fetch(); + ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()]; + if (!info.Artifact) + info.Artifact = boost::in_place(); + info.Artifact->Xp = fields[1].GetUInt64(); + info.Artifact->ArtifactAppearanceId = fields[2].GetUInt32(); + info.Artifact->ArtifactTierId = fields[3].GetUInt32(); + ArtifactPowerData artifactPowerData; + artifactPowerData.ArtifactPowerId = fields[4].GetUInt32(); + artifactPowerData.PurchasedRank = fields[5].GetUInt8(); + if (ArtifactPowerEntry const* artifactPower = sArtifactPowerStore.LookupEntry(artifactPowerData.ArtifactPowerId)) + { + uint32 maxRank = artifactPower->MaxPurchasableRank; + // allow ARTIFACT_POWER_FLAG_FINAL to overflow maxrank here - needs to be handled in Item::CheckArtifactUnlock (will refund artifact power) + if (artifactPower->Flags & ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER && artifactPower->Tier < info.Artifact->ArtifactTierId) + maxRank += info.Artifact->ArtifactTierId - artifactPower->Tier; + + if (artifactPowerData.PurchasedRank > maxRank) + artifactPowerData.PurchasedRank = maxRank; + + artifactPowerData.CurrentRankWithBonus = (artifactPower->Flags & ARTIFACT_POWER_FLAG_FIRST) == ARTIFACT_POWER_FLAG_FIRST ? 1 : 0; + + info.Artifact->ArtifactPowers.push_back(artifactPowerData); + } + + } while (artifactResult->NextRow()); + } + + // 0 1 2 3 + // SELECT iz.itemGuid, iz.xp, iz.level, iz.knowledgeLevel FROM item_instance_azerite iz INNER JOIN ... + if (azeriteItemResult) + { + do + { + Field* fields = azeriteItemResult->Fetch(); + ItemAdditionalLoadInfo& info = (*loadInfo)[fields[0].GetUInt64()]; + if (!info.AzeriteItem) + info.AzeriteItem = boost::in_place(); + info.AzeriteItem->Xp = fields[1].GetUInt64(); + info.AzeriteItem->Level = fields[2].GetUInt32(); + info.AzeriteItem->KnowledgeLevel = fields[3].GetUInt32(); + + } while (azeriteItemResult->NextRow()); + } +} + Item::Item() { m_objectType |= TYPEMASK_ITEM; @@ -640,8 +695,8 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie // spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, // 29 30 31 32 33 34 35 36 37 38 39 40 // gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3 - // 41 42 43 44 45 - // fixedScalingLevel, artifactKnowledgeLevel, iz.xp, iz.level, iz.knowledgeLevel FROM item_instance + // 41 42 + // fixedScalingLevel, artifactKnowledgeLevel FROM item_instance // create item before any checks for store correct guid // and allow use "FSetState(ITEM_REMOVED); SaveToDB();" for deleting item from DB @@ -784,7 +839,7 @@ bool Item::LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fie return true; } -void Item::LoadArtifactData(Player* owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector<ArtifactPowerLoadInfo>& powers) +void Item::LoadArtifactData(Player* owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector<ArtifactPowerData>& powers) { for (uint8 i = 0; i <= artifactTier; ++i) InitArtifactPowers(GetTemplate()->GetArtifactID(), i); @@ -797,7 +852,7 @@ void Item::LoadArtifactData(Player* owner, uint64 xp, uint32 artifactAppearanceI SetAppearanceModId(artifactAppearance->ItemAppearanceModifierID); uint8 totalPurchasedRanks = 0; - for (ArtifactPowerLoadInfo& power : powers) + for (ArtifactPowerData& power : powers) { power.CurrentRankWithBonus += power.PurchasedRank; totalPurchasedRanks += power.PurchasedRank; @@ -841,7 +896,7 @@ void Item::LoadArtifactData(Player* owner, uint64 xp, uint32 artifactAppearanceI SetArtifactPower(power.ArtifactPowerId, power.PurchasedRank, power.CurrentRankWithBonus); } - for (ArtifactPowerLoadInfo& power : powers) + for (ArtifactPowerData& power : powers) { ArtifactPowerEntry const* scaledArtifactPowerEntry = sArtifactPowerStore.AssertEntry(power.ArtifactPowerId); if (!(scaledArtifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS)) @@ -2381,7 +2436,7 @@ UF::ArtifactPower const* Item::GetArtifactPower(uint32 artifactPowerId) const return nullptr; } -void Item::AddArtifactPower(ArtifactPowerLoadInfo const* artifactPower) +void Item::AddArtifactPower(ArtifactPowerData const* artifactPower) { uint16 index = uint16(m_artifactPowerIdToIndex.size()); m_artifactPowerIdToIndex[artifactPower->ArtifactPowerId] = index; @@ -2417,7 +2472,7 @@ void Item::InitArtifactPowers(uint8 artifactId, uint8 artifactTier) if (m_artifactPowerIdToIndex.find(artifactPower->ID) != m_artifactPowerIdToIndex.end()) continue; - ArtifactPowerLoadInfo powerData; + ArtifactPowerData powerData; memset(&powerData, 0, sizeof(powerData)); powerData.ArtifactPowerId = artifactPower->ID; powerData.PurchasedRank = 0; diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 695bccfb9dc..e029bc0ee05 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -108,13 +108,36 @@ private: } _state; }; -struct ArtifactPowerLoadInfo +struct ArtifactPowerData { uint32 ArtifactPowerId; uint8 PurchasedRank; uint8 CurrentRankWithBonus; }; +struct ArtifactData +{ + uint64 Xp; + uint32 ArtifactAppearanceId; + uint32 ArtifactTierId; + std::vector<ArtifactPowerData> ArtifactPowers; +}; + +struct AzeriteItemData +{ + uint64 Xp; + uint32 Level; + uint32 KnowledgeLevel; +}; + +struct ItemAdditionalLoadInfo +{ + static void Init(std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo>* loadInfo, PreparedQueryResult artifactResult, PreparedQueryResult azeriteItemResult); + + Optional<ArtifactData> Artifact; + Optional<AzeriteItemData> AzeriteItem; +}; + struct ItemDynamicFieldGems { uint32 ItemId; @@ -174,7 +197,7 @@ class TC_GAME_API Item : public Object bool IsBoundByEnchant() const; virtual void SaveToDB(CharacterDatabaseTransaction& trans); virtual bool LoadFromDB(ObjectGuid::LowType guid, ObjectGuid ownerGuid, Field* fields, uint32 entry); - void LoadArtifactData(Player* owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector<ArtifactPowerLoadInfo>& powers); // must be called after LoadFromDB to have gems (relics) initialized + void LoadArtifactData(Player* owner, uint64 xp, uint32 artifactAppearanceId, uint32 artifactTier, std::vector<ArtifactPowerData>& powers); // must be called after LoadFromDB to have gems (relics) initialized void CheckArtifactRelicSlotUnlock(Player const* owner); void AddBonuses(uint32 bonusListID); @@ -355,7 +378,7 @@ class TC_GAME_API Item : public Object void SetChildItem(ObjectGuid childItem) { m_childItem = childItem; } UF::ArtifactPower const* GetArtifactPower(uint32 artifactPowerId) const; - void AddArtifactPower(ArtifactPowerLoadInfo const* artifactPower); + void AddArtifactPower(ArtifactPowerData const* artifactPower); void SetArtifactPower(uint16 artifactPowerId, uint8 purchasedRank, uint8 currentRankWithBonus); void InitArtifactPowers(uint8 artifactId, uint8 artifactTier); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4666423626a..3b1eebbc10b 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -18185,7 +18185,10 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder* holder) // must be before inventory (some items required reputation check) m_reputationMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_REPUTATION)); - _LoadInventory(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INVENTORY), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ARTIFACTS), time_diff); + _LoadInventory(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_INVENTORY), + holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ARTIFACTS), + holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_AZERITE), + time_diff); if (IsVoidStorageUnlocked()) _LoadVoidStorage(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE)); @@ -18582,7 +18585,7 @@ void Player::LoadCorpse(PreparedQueryResult result) RemoveAtLoginFlag(AT_LOGIN_RESURRECT); } -void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult artifactsResult, uint32 timeDiff) +void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult artifactsResult, PreparedQueryResult azeriteResult, uint32 timeDiff) { // 0 1 2 3 4 5 6 7 8 9 10 11 12 // SELECT guid, itemEntry, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, @@ -18594,9 +18597,9 @@ void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult arti // spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, // 29 30 31 32 33 34 35 36 37 38 39 40 // gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3 - // 41 42 43 44 45 - // fixedScalingLevel, artifactKnowledgeLevel, iz.xp, iz.level, iz.knowledgeLevel FROM item_instance - // 46 47 + // 41 42 + // fixedScalingLevel, artifactKnowledgeLevel FROM item_instance + // 43 44 // bag, slot // FROM character_inventory ci // JOIN item_instance ii ON ci.item = ii.guid @@ -18612,38 +18615,8 @@ void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult arti //NOTE2: the "order by `slot`" is needed because mainhand weapons are (wrongly?) //expected to be equipped before offhand items (@todo fixme) - // 0 1 2 3 4 5 - // SELECT a.itemGuid, a.xp, a.artifactAppearanceId, a.artifactTierId, ap.artifactPowerId, ap.purchasedRank FROM item_instance_artifact_powers ap LEFT JOIN item_instance_artifact a ON ap.itemGuid = a.itemGuid INNER JOIN character_inventory ci ON ci.item = ap.guid WHERE ci.guid = ? - std::unordered_map<ObjectGuid, std::tuple<uint64, uint32, uint32, std::vector<ArtifactPowerLoadInfo>>> artifactData; - if (artifactsResult) - { - do - { - Field* fields = artifactsResult->Fetch(); - auto& artifactDataEntry = artifactData[ObjectGuid::Create<HighGuid::Item>(fields[0].GetUInt64())]; - std::get<0>(artifactDataEntry) = fields[1].GetUInt64(); - std::get<1>(artifactDataEntry) = fields[2].GetUInt32(); - std::get<2>(artifactDataEntry) = fields[3].GetUInt32(); - ArtifactPowerLoadInfo artifactPowerData; - artifactPowerData.ArtifactPowerId = fields[4].GetUInt32(); - artifactPowerData.PurchasedRank = fields[5].GetUInt8(); - if (ArtifactPowerEntry const* artifactPower = sArtifactPowerStore.LookupEntry(artifactPowerData.ArtifactPowerId)) - { - uint32 maxRank = artifactPower->MaxPurchasableRank; - // allow ARTIFACT_POWER_FLAG_FINAL to overflow maxrank here - needs to be handled in Item::CheckArtifactUnlock (will refund artifact power) - if (artifactPower->Flags & ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER && artifactPower->Tier < std::get<2>(artifactDataEntry)) - maxRank += std::get<2>(artifactDataEntry) - artifactPower->Tier; - - if (artifactPowerData.PurchasedRank > maxRank) - artifactPowerData.PurchasedRank = maxRank; - - artifactPowerData.CurrentRankWithBonus = (artifactPower->Flags & ARTIFACT_POWER_FLAG_FIRST) == ARTIFACT_POWER_FLAG_FIRST ? 1 : 0; - - std::get<3>(artifactDataEntry).push_back(artifactPowerData); - } - - } while (artifactsResult->NextRow()); - } + std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo> additionalData; + ItemAdditionalLoadInfo::Init(&additionalData, artifactsResult, azeriteResult); if (result) { @@ -18661,12 +18634,19 @@ void Player::_LoadInventory(PreparedQueryResult result, PreparedQueryResult arti Field* fields = result->Fetch(); if (Item* item = _LoadItem(trans, zoneId, timeDiff, fields)) { - auto artifactDataItr = artifactData.find(item->GetGUID()); - if (item->GetTemplate()->GetArtifactID() && artifactDataItr != artifactData.end()) - item->LoadArtifactData(this, std::get<0>(artifactDataItr->second), std::get<1>(artifactDataItr->second), std::get<2>(artifactDataItr->second), std::get<3>(artifactDataItr->second)); + if (ItemAdditionalLoadInfo* addionalDataPtr = Trinity::Containers::MapGetValuePtr(additionalData, fields[0].GetUInt64())) + { + if (item->GetTemplate()->GetArtifactID() && addionalDataPtr->Artifact) + item->LoadArtifactData(this, addionalDataPtr->Artifact->Xp, addionalDataPtr->Artifact->ArtifactAppearanceId, + addionalDataPtr->Artifact->ArtifactTierId, addionalDataPtr->Artifact->ArtifactPowers); + + if (addionalDataPtr->AzeriteItem) + if (AzeriteItem* azeriteItem = item->ToAzeriteItem()) + azeriteItem->LoadAzeriteItemData(*addionalDataPtr->AzeriteItem); + } - ObjectGuid bagGuid = fields[46].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[46].GetUInt64()) : ObjectGuid::Empty; - uint8 slot = fields[47].GetUInt8(); + ObjectGuid bagGuid = fields[43].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[43].GetUInt64()) : ObjectGuid::Empty; + uint8 slot = fields[44].GetUInt8(); GetSession()->GetCollectionMgr()->CheckHeirloomUpgrades(item); GetSession()->GetCollectionMgr()->AddItemAppearance(item); @@ -18971,61 +18951,59 @@ Item* Player::_LoadItem(CharacterDatabaseTransaction& trans, uint32 zoneId, uint } // load mailed item which should receive current player -void Player::_LoadMailedItems(Mail* mail) +void Player::_LoadMailedItem(Mail* mail, Field* fields, ItemAdditionalLoadInfo* addionalData) { - // data needs to be at first place for Item::LoadFromDB - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS); - stmt->setUInt32(0, mail->messageID); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - if (!result) - return; - - do - { - Field* fields = result->Fetch(); + ObjectGuid::LowType itemGuid = fields[0].GetUInt64(); + uint32 itemEntry = fields[1].GetUInt32(); - ObjectGuid::LowType itemGuid = fields[0].GetUInt64(); - uint32 itemEntry = fields[1].GetUInt32(); + mail->AddItem(itemGuid, itemEntry); - mail->AddItem(itemGuid, itemEntry); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry); + if (!proto) + { + TC_LOG_ERROR("entities.player", "Player '%s' (%s) has unknown item_template in mailed items (GUID: " UI64FMTD ", Entry: %u) in mail (%u), deleted.", + GetName().c_str(), GetGUID().ToString().c_str(), itemGuid, itemEntry, mail->messageID); - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry); - if (!proto) - { - TC_LOG_ERROR("entities.player", "Player '%s' (%s) has unknown item_template in mailed items (GUID: " UI64FMTD ", Entry: %u) in mail (%u), deleted.", - GetName().c_str(), GetGUID().ToString().c_str(), itemGuid, itemEntry, mail->messageID); + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_MAIL_ITEM); + stmt->setUInt64(0, itemGuid); + CharacterDatabase.Execute(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_MAIL_ITEM); - stmt->setUInt64(0, itemGuid); - CharacterDatabase.Execute(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE); + stmt->setUInt64(0, itemGuid); + CharacterDatabase.Execute(stmt); + return; + } - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE); - stmt->setUInt64(0, itemGuid); - CharacterDatabase.Execute(stmt); - continue; - } + Item* item = NewItemOrBag(proto); - Item* item = NewItemOrBag(proto); + ObjectGuid ownerGuid = fields[43].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[43].GetUInt64()) : ObjectGuid::Empty; + if (!item->LoadFromDB(itemGuid, ownerGuid, fields, itemEntry)) + { + TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems: Item (GUID: " UI64FMTD ") in mail (%u) doesn't exist, deleted from mail.", itemGuid, mail->messageID); - ObjectGuid ownerGuid = fields[46].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[46].GetUInt64()) : ObjectGuid::Empty; - if (!item->LoadFromDB(itemGuid, ownerGuid, fields, itemEntry)) - { - TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems: Item (GUID: " UI64FMTD ") in mail (%u) doesn't exist, deleted from mail.", itemGuid, mail->messageID); + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM); + stmt->setUInt64(0, itemGuid); + CharacterDatabase.Execute(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM); - stmt->setUInt64(0, itemGuid); - CharacterDatabase.Execute(stmt); + item->FSetState(ITEM_REMOVED); - item->FSetState(ITEM_REMOVED); + CharacterDatabaseTransaction temp = CharacterDatabaseTransaction(nullptr); + item->SaveToDB(temp); // it also deletes item object ! + return; + } - CharacterDatabaseTransaction temp = CharacterDatabaseTransaction(nullptr); - item->SaveToDB(temp); // it also deletes item object ! - continue; - } + if (addionalData) + { + if (item->GetTemplate()->GetArtifactID() && addionalData->Artifact) + item->LoadArtifactData(this, addionalData->Artifact->Xp, addionalData->Artifact->ArtifactAppearanceId, + addionalData->Artifact->ArtifactTierId, addionalData->Artifact->ArtifactPowers); - AddMItem(item); + if (addionalData->AzeriteItem) + if (AzeriteItem* azeriteItem = item->ToAzeriteItem()) + azeriteItem->LoadAzeriteItemData(*addionalData->AzeriteItem); } - while (result->NextRow()); + + AddMItem(item); } void Player::_LoadMailInit(PreparedQueryResult resultUnread, PreparedQueryResult resultDelivery) @@ -19049,12 +19027,14 @@ void Player::_LoadMail() stmt->setUInt64(0, GetGUID().GetCounter()); PreparedQueryResult result = CharacterDatabase.Query(stmt); + std::unordered_map<uint32, Mail*> mailById; + if (result) { do { Field* fields = result->Fetch(); - Mail* m = new Mail; + Mail* m = new Mail(); m->messageID = fields[0].GetUInt32(); m->messageType = fields[1].GetUInt8(); @@ -19062,14 +19042,13 @@ void Player::_LoadMail() m->receiver = fields[3].GetUInt64(); m->subject = fields[4].GetString(); m->body = fields[5].GetString(); - bool has_items = fields[6].GetBool(); - m->expire_time = time_t(fields[7].GetUInt32()); - m->deliver_time = time_t(fields[8].GetUInt32()); - m->money = fields[9].GetUInt64(); - m->COD = fields[10].GetUInt64(); - m->checked = fields[11].GetUInt8(); - m->stationery = fields[12].GetUInt8(); - m->mailTemplateId = fields[13].GetInt16(); + m->expire_time = time_t(fields[6].GetUInt32()); + m->deliver_time = time_t(fields[7].GetUInt32()); + m->money = fields[8].GetUInt64(); + m->COD = fields[9].GetUInt64(); + m->checked = fields[10].GetUInt8(); + m->stationery = fields[11].GetUInt8(); + m->mailTemplateId = fields[12].GetInt16(); if (m->mailTemplateId && !sMailTemplateStore.LookupEntry(m->mailTemplateId)) { @@ -19079,13 +19058,38 @@ void Player::_LoadMail() m->state = MAIL_STATE_UNCHANGED; - if (has_items) - _LoadMailedItems(m); - m_mail.push_back(m); + mailById[m->messageID] = m; } while (result->NextRow()); } + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS); + stmt->setUInt64(0, GetGUID().GetCounter()); + result = CharacterDatabase.Query(stmt); + + if (result) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS_ARTIFACT); + stmt->setUInt64(0, GetGUID().GetCounter()); + PreparedQueryResult artifactResult = CharacterDatabase.Query(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS_AZERITE); + stmt->setUInt64(0, GetGUID().GetCounter()); + PreparedQueryResult azeriteResult = CharacterDatabase.Query(stmt); + + std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo> additionalData; + ItemAdditionalLoadInfo::Init(&additionalData, artifactResult, azeriteResult); + + do + { + Field* fields = result->Fetch(); + uint32 mailId = fields[44].GetUInt32(); + _LoadMailedItem(mailById[mailId], fields, Trinity::Containers::MapGetValuePtr(additionalData, fields[0].GetUInt64())); + } + while (result->NextRow()); + } + m_mailsLoaded = true; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 679ff1fa40e..07c2f7030c1 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -46,6 +46,7 @@ struct ChrSpecializationEntry; struct CreatureTemplate; struct CurrencyTypesEntry; struct FactionEntry; +struct ItemAdditionalLoadInfo; struct ItemExtendedCostEntry; struct ItemLimitCategoryEntry; struct ItemSetEffect; @@ -749,6 +750,7 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOAD_REPUTATION, PLAYER_LOGIN_QUERY_LOAD_INVENTORY, PLAYER_LOGIN_QUERY_LOAD_ARTIFACTS, + PLAYER_LOGIN_QUERY_LOAD_AZERITE, PLAYER_LOGIN_QUERY_LOAD_ACTIONS, PLAYER_LOGIN_QUERY_LOAD_MAIL_COUNT, PLAYER_LOGIN_QUERY_LOAD_MAIL_DATE, @@ -2487,11 +2489,11 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void _LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effectResult, uint32 timediff); void _LoadGlyphAuras(); void _LoadBoundInstances(PreparedQueryResult result); - void _LoadInventory(PreparedQueryResult result, PreparedQueryResult artifactsResult, uint32 timeDiff); + void _LoadInventory(PreparedQueryResult result, PreparedQueryResult artifactsResult, PreparedQueryResult azeriteResult, uint32 timeDiff); void _LoadVoidStorage(PreparedQueryResult result); void _LoadMailInit(PreparedQueryResult resultUnread, PreparedQueryResult resultDelivery); void _LoadMail(); - void _LoadMailedItems(Mail* mail); + void _LoadMailedItem(Mail* mail, Field* fields, ItemAdditionalLoadInfo* addionalData); void _LoadQuestStatus(PreparedQueryResult result); void _LoadQuestStatusObjectives(PreparedQueryResult result); void _LoadQuestStatusRewarded(PreparedQueryResult result); diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 33f74a4c9de..6133fa2cf95 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -374,7 +374,7 @@ void Guild::BankTab::LoadFromDB(Field* fields) bool Guild::BankTab::LoadItemFromDB(Field* fields) { - uint8 slotId = fields[48].GetUInt8(); + uint8 slotId = fields[45].GetUInt8(); ObjectGuid::LowType itemGuid = fields[0].GetUInt64(); uint32 itemEntry = fields[1].GetUInt32(); if (slotId >= GUILD_BANK_MAX_SLOTS) @@ -2498,7 +2498,7 @@ void Guild::LoadBankTabFromDB(Field* fields) bool Guild::LoadBankItemFromDB(Field* fields) { - uint8 tabId = fields[47].GetUInt8(); + uint8 tabId = fields[44].GetUInt8(); if (tabId >= _GetPurchasedTabsSize()) { TC_LOG_ERROR("guild", "Invalid tab for item (GUID: %u, id: #%u) in guild bank, skipped.", diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp index 938f317eb65..4c1fc45c5f9 100644 --- a/src/server/game/Guilds/GuildMgr.cpp +++ b/src/server/game/Guilds/GuildMgr.cpp @@ -418,9 +418,9 @@ void GuildMgr::LoadGuilds() // spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4, // 29 30 31 32 33 34 35 36 37 38 39 40 // gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3 - // 41 42 43 44 45 - // fixedScalingLevel, artifactKnowledgeLevel, iz.xp, iz.level, iz.knowledgeLevel - // 46 47 48 + // 41 42 + // fixedScalingLevel, artifactKnowledgeLevel + // 43 44 45 // guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_ITEMS)); @@ -434,7 +434,7 @@ void GuildMgr::LoadGuilds() do { Field* fields = result->Fetch(); - uint64 guildId = fields[46].GetUInt64(); + uint64 guildId = fields[43].GetUInt64(); if (Guild* guild = GetGuildById(guildId)) guild->LoadBankItemFromDB(fields); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 1a5f587be00..9dab59597e3 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -152,6 +152,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_ARTIFACTS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ITEM_INSTANCE_AZERITE); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_AZERITE, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_VOID_STORAGE); stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_VOID_STORAGE, stmt); |