diff --git a/Source/Framework/Constants/ItemConst.cs b/Source/Framework/Constants/ItemConst.cs index 36fb4e8b7..f31a63d5b 100644 --- a/Source/Framework/Constants/ItemConst.cs +++ b/Source/Framework/Constants/ItemConst.cs @@ -829,6 +829,11 @@ namespace Framework.Constants Unk26 = 0x80000000 // ? } + public enum ItemFieldFlags2 + { + HeartOfAzerothEquipped = 0x1 + } + public enum ItemFlags : long { NoPickup = 0x01, @@ -1141,6 +1146,7 @@ namespace Framework.Constants JusticePoints = 395, ValorPoints = 396, ApexisCrystals = 823, + Azerite = 1553 } public enum PlayerCurrencyState diff --git a/Source/Framework/Constants/PlayerConst.cs b/Source/Framework/Constants/PlayerConst.cs index de9580318..ac7b11fa6 100644 --- a/Source/Framework/Constants/PlayerConst.cs +++ b/Source/Framework/Constants/PlayerConst.cs @@ -64,6 +64,11 @@ namespace Framework.Constants public const int MaxHonorLevel = 500; public const byte LevelMinHonor = 110; public const uint SpellPvpRulesEnabled = 134735; + + //Azerite + public const uint ItemIdHeartOfAzeroth = 158075; + public const uint MaxAzeriteItemLevel = 70; + public const uint MaxAzeriteItemKnowledgeLevel = 30; } public struct MoneyConstants diff --git a/Source/Framework/Database/Databases/CharacterDatabase.cs b/Source/Framework/Database/Databases/CharacterDatabase.cs index 6392e9dcb..844da7b02 100644 --- a/Source/Framework/Database/Databases/CharacterDatabase.cs +++ b/Source/Framework/Database/Databases/CharacterDatabase.cs @@ -26,7 +26,7 @@ namespace Framework.Database "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"; + "im.fixedScalingLevel, im.artifactKnowledgeLevel, iz.xp, iz.level, iz.knowledgeLevel"; PrepareStatement(CharStatements.DEL_QUEST_POOL_SAVE, "DELETE FROM pool_quest_save WHERE pool_id = ?"); PrepareStatement(CharStatements.INS_QUEST_POOL_SAVE, "INSERT INTO pool_quest_save (pool_id, quest_id) VALUES (?, ?)"); @@ -109,7 +109,7 @@ namespace Framework.Database PrepareStatement(CharStatements.DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT, "DELETE FROM character_queststatus_seasonal WHERE event = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?"); - PrepareStatement(CharStatements.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"); + PrepareStatement(CharStatements.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"); PrepareStatement(CharStatements.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"); PrepareStatement(CharStatements.SEL_CHARACTER_MAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = ? AND (checked & 1) = 0 AND deliver_time <= ?"); PrepareStatement(CharStatements.SEL_CHARACTER_MAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = ? AND (checked & 1) = 0"); @@ -141,8 +141,8 @@ namespace Framework.Database PrepareStatement(CharStatements.SEL_ACCOUNT_INSTANCELOCKTIMES, "SELECT instanceId, releaseTime FROM account_instance_times WHERE accountId = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button"); - PrepareStatement(CharStatements.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 WHERE mail_id = ?"); - PrepareStatement(CharStatements.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"); + PrepareStatement(CharStatements.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 = ?"); + PrepareStatement(CharStatements.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"); PrepareStatement(CharStatements.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"); PrepareStatement(CharStatements.INS_AUCTION, "INSERT INTO auctionhouse (id, auctioneerguid, itemguid, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); PrepareStatement(CharStatements.DEL_AUCTION, "DELETE FROM auctionhouse WHERE id = ?"); @@ -186,6 +186,10 @@ namespace Framework.Database PrepareStatement(CharStatements.INS_ITEM_INSTANCE_MODIFIERS, "INSERT INTO item_instance_modifiers (itemGuid, fixedScalingLevel, artifactKnowledgeLevel) VALUES (?, ?, ?)"); PrepareStatement(CharStatements.DEL_ITEM_INSTANCE_MODIFIERS, "DELETE FROM item_instance_modifiers WHERE itemGuid = ?"); PrepareStatement(CharStatements.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 = ?"); + PrepareStatement(CharStatements.INS_ITEM_INSTANCE_AZERITE, "INSERT INTO item_instance_azerite (itemGuid, xp, level, knowledgeLevel) VALUES (?, ?, ?, ?)"); + PrepareStatement(CharStatements.UPD_ITEM_INSTANCE_AZERITE_ON_LOAD, "UPDATE item_instance_azerite SET xp = ?, knowledgeLevel = ? WHERE itemGuid = ?"); + PrepareStatement(CharStatements.DEL_ITEM_INSTANCE_AZERITE, "DELETE FROM item_instance_azerite WHERE itemGuid = ?"); + PrepareStatement(CharStatements.DEL_ITEM_INSTANCE_MODIFIERS_BY_OWNER, "DELETE iz FROM item_instance_azerite iz LEFT JOIN item_instance ii ON iz.itemGuid = ii.guid WHERE ii.owner_guid = ?"); PrepareStatement(CharStatements.UPD_GIFT_OWNER, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?"); PrepareStatement(CharStatements.DEL_GIFT, "DELETE FROM character_gifts WHERE item_guid = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_GIFT_BY_ITEM, "SELECT entry, flags FROM character_gifts WHERE item_guid = ?"); @@ -217,7 +221,7 @@ namespace Framework.Database // 0: uint32, 1: uint8, 2: uint8, 3: uint32, 4: uint32 PrepareStatement(CharStatements.INS_GUILD_BANK_ITEM, "INSERT INTO guild_bank_item (guildid, TabId, SlotId, item_guid) VALUES (?, ?, ?, ?)"); PrepareStatement(CharStatements.DEL_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?"); // 0: uint32, 1: uint8, 2: uint8 - PrepareStatement(CharStatements.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"); + PrepareStatement(CharStatements.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"); PrepareStatement(CharStatements.DEL_GUILD_BANK_ITEMS, "DELETE FROM guild_bank_item WHERE guildid = ?"); // 0: uint32 // 0: uint32, 1: uint8, 2: uint8, 3: uint8, 4: uint32 PrepareStatement(CharStatements.INS_GUILD_BANK_RIGHT, "INSERT INTO guild_bank_right (guildid, TabId, rid, gbright, SlotPerDay) VALUES (?, ?, ?, ?, ?) " + @@ -871,6 +875,10 @@ namespace Framework.Database INS_ITEM_INSTANCE_MODIFIERS, DEL_ITEM_INSTANCE_MODIFIERS, DEL_ITEM_INSTANCE_MODIFIERS_BY_OWNER, + INS_ITEM_INSTANCE_AZERITE, + UPD_ITEM_INSTANCE_AZERITE_ON_LOAD, + DEL_ITEM_INSTANCE_AZERITE, + DEL_ITEM_INSTANCE_AZERITE_BY_OWNER, UPD_GIFT_OWNER, DEL_GIFT, SEL_CHARACTER_GIFT_BY_ITEM, diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index 766bfd629..e79fcc6d3 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -100,6 +100,16 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_AUCTION_HOUSE, "SELECT ID, Name, FactionID, DepositRate, ConsignmentRate FROM auction_house ORDER BY ID DESC"); PrepareStatement(HotfixStatements.SEL_AUCTION_HOUSE_LOCALE, "SELECT ID, Name_lang FROM auction_house_locale WHERE locale = ?"); + // AzeriteItem.db2 + PrepareStatement(HotfixStatements.SEL_AZERITE_ITEM, "SELECT ID, ItemID FROM azerite_item ORDER BY ID DESC"); + + // AzeriteKnowledgeMultiplier.db2 + PrepareStatement(HotfixStatements.SEL_AZERITE_KNOWLEDGE_MULTIPLIER, "SELECT ID, Multiplier FROM azerite_knowledge_multiplier ORDER BY ID DESC"); + + // AzeriteLevelInfo.db2 + PrepareStatement(HotfixStatements.SEL_AZERITE_LEVEL_INFO, "SELECT ID, BaseExperienceToNextLevel, MinimumExperienceToNextLevel, ItemLevel" + + " FROM azerite_level_info ORDER BY ID DESC"); + // BankBagSlotPrices.db2 PrepareStatement(HotfixStatements.SEL_BANK_BAG_SLOT_PRICES, "SELECT ID, Cost FROM bank_bag_slot_prices ORDER BY ID DESC"); @@ -898,8 +908,8 @@ namespace Framework.Database " FROM spell_levels ORDER BY ID DESC"); // SpellMisc.db2 - PrepareStatement(HotfixStatements.SEL_SPELL_MISC, "SELECT Attributes1, Attributes2, Attributes3, Attributes4, Attributes5, Attributes6, Attributes7, " + - "Attributes8, Attributes9, Attributes10, Attributes11, Attributes12, Attributes13, Attributes14, ID, DifficultyID, CastingTimeIndex, " + + PrepareStatement(HotfixStatements.SEL_SPELL_MISC, "SELECT ID, Attributes1, Attributes2, Attributes3, Attributes4, Attributes5, Attributes6, Attributes7, " + + "Attributes8, Attributes9, Attributes10, Attributes11, Attributes12, Attributes13, Attributes14, DifficultyID, CastingTimeIndex, " + "DurationIndex, RangeIndex, SchoolMask, Speed, LaunchDelay, MinDuration, SpellIconFileDataID, ActiveIconFileDataID, ContentTuningID, SpellID" + " FROM spell_misc ORDER BY ID DESC"); @@ -1127,6 +1137,12 @@ namespace Framework.Database SEL_AUCTION_HOUSE, SEL_AUCTION_HOUSE_LOCALE, + SEL_AZERITE_ITEM, + + SEL_AZERITE_KNOWLEDGE_MULTIPLIER, + + SEL_AZERITE_LEVEL_INFO, + SEL_BANK_BAG_SLOT_PRICES, SEL_BANNED_ADDONS, diff --git a/Source/Game/Achievements/CriteriaHandler.cs b/Source/Game/Achievements/CriteriaHandler.cs index 4643378f8..634f0e7be 100644 --- a/Source/Game/Achievements/CriteriaHandler.cs +++ b/Source/Game/Achievements/CriteriaHandler.cs @@ -151,6 +151,7 @@ namespace Game.Achievements case CriteriaTypes.CompleteBattleground: case CriteriaTypes.DamageDone: case CriteriaTypes.HealingDone: + case CriteriaTypes.HeartOfAzerothArtifactPowerEarned: SetCriteriaProgress(criteria, miscValue1, referencePlayer, ProgressType.Accumulate); break; case CriteriaTypes.KillCreature: @@ -168,6 +169,7 @@ namespace Game.Achievements case CriteriaTypes.HighestHitReceived: case CriteriaTypes.HighestHealCasted: case CriteriaTypes.HighestHealingReceived: + case CriteriaTypes.HeartOfAzerothLevelReached: SetCriteriaProgress(criteria, miscValue1, referencePlayer, ProgressType.Highest); break; case CriteriaTypes.ReachLevel: @@ -425,8 +427,6 @@ namespace Game.Achievements case CriteriaTypes.EarnHonorXp: case CriteriaTypes.RelicTalentUnlocked: case CriteriaTypes.ReachAccountHonorLevel: - case CriteriaTypes.HeartOfAzerothArtifactPowerEarned: - case CriteriaTypes.HeartOfAzerothLevelReached: break; // Not implemented yet :( } diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index 6d0812614..d056d6e9f 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -51,9 +51,12 @@ namespace Game.DataStorage ArtifactPowerPickerStorage = DBReader.Read("ArtifactPowerPicker.db2", HotfixStatements.SEL_ARTIFACT_POWER_PICKER); ArtifactPowerRankStorage = DBReader.Read("ArtifactPowerRank.db2", HotfixStatements.SEL_ARTIFACT_POWER_RANK); //ArtifactQuestXPStorage = DBReader.Read("ArtifactQuestXP.db2", HotfixStatements.SEL_ARTIFACT_QUEST_XP); - ArtifactTierStorage = DBReader.Read ("ArtifactTier.db2", HotfixStatements.SEL_ARTIFACT_TIER); - ArtifactUnlockStorage = DBReader.Read ("ArtifactUnlock.db2", HotfixStatements.SEL_ARTIFACT_UNLOCK); + ArtifactTierStorage = DBReader.Read("ArtifactTier.db2", HotfixStatements.SEL_ARTIFACT_TIER); + ArtifactUnlockStorage = DBReader.Read("ArtifactUnlock.db2", HotfixStatements.SEL_ARTIFACT_UNLOCK); AuctionHouseStorage = DBReader.Read("AuctionHouse.db2", HotfixStatements.SEL_AUCTION_HOUSE, HotfixStatements.SEL_AUCTION_HOUSE_LOCALE); + AzeriteItemStorage = DBReader.Read("AzeriteItem.db2", HotfixStatements.SEL_AZERITE_ITEM); + AzeriteKnowledgeMultiplierStorage = DBReader.Read("AzeriteKnowledgeMultiplier.db2", HotfixStatements.SEL_AZERITE_KNOWLEDGE_MULTIPLIER); + AzeriteLevelInfoStorage = DBReader.Read("AzeriteLevelInfo.db2", HotfixStatements.SEL_AZERITE_LEVEL_INFO); BankBagSlotPricesStorage = DBReader.Read("BankBagSlotPrices.db2", HotfixStatements.SEL_BANK_BAG_SLOT_PRICES); //BannedAddOnsStorage = DBReader.Read("BannedAddons.db2", HotfixStatements.SEL_BANNED_ADDONS); BarberShopStyleStorage = DBReader.Read("BarberShopStyle.db2", HotfixStatements.SEL_BARBER_SHOP_STYLE, HotfixStatements.SEL_BARBER_SHOP_STYLE_LOCALE); @@ -97,8 +100,8 @@ namespace Game.DataStorage EmotesStorage = DBReader.Read("Emotes.db2", HotfixStatements.SEL_EMOTES); EmotesTextStorage = DBReader.Read("EmotesText.db2", HotfixStatements.SEL_EMOTES_TEXT); EmotesTextSoundStorage = DBReader.Read("EmotesTextSound.db2", HotfixStatements.SEL_EMOTES_TEXT_SOUND); - ExpectedStatStorage = DBReader.Read ("ExpectedStat.db2", HotfixStatements.SEL_EXPECTED_STAT); - ExpectedStatModStorage = DBReader.Read ("ExpectedStatMod.db2", HotfixStatements.SEL_EXPECTED_STAT_MOD); + ExpectedStatStorage = DBReader.Read("ExpectedStat.db2", HotfixStatements.SEL_EXPECTED_STAT); + ExpectedStatModStorage = DBReader.Read("ExpectedStatMod.db2", HotfixStatements.SEL_EXPECTED_STAT_MOD); FactionStorage = DBReader.Read("Faction.db2", HotfixStatements.SEL_FACTION, HotfixStatements.SEL_FACTION_LOCALE); FactionTemplateStorage = DBReader.Read("FactionTemplate.db2", HotfixStatements.SEL_FACTION_TEMPLATE); GameObjectDisplayInfoStorage = DBReader.Read("GameObjectDisplayInfo.db2", HotfixStatements.SEL_GAMEOBJECT_DISPLAY_INFO); @@ -397,6 +400,9 @@ namespace Game.DataStorage public static DB6Storage ArtifactTierStorage; public static DB6Storage ArtifactUnlockStorage; public static DB6Storage AuctionHouseStorage; + public static DB6Storage AzeriteItemStorage; + public static DB6Storage AzeriteKnowledgeMultiplierStorage; + public static DB6Storage AzeriteLevelInfoStorage; public static DB6Storage BankBagSlotPricesStorage; //public static DB6Storage BannedAddOnsStorage; public static DB6Storage BarberShopStyleStorage; diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index 9aa82cb4d..6a05bf280 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -722,6 +722,11 @@ namespace Game.DataStorage return _artifactPowerRanks.LookupByKey(Tuple.Create(artifactPowerId, rank)); } + public bool IsAzeriteItem(uint itemId) + { + return CliDB.AzeriteItemStorage.Any(pair => pair.Value.ItemID == itemId); + } + public string GetBroadcastTextValue(BroadcastTextRecord broadcastText, LocaleConstant locale = LocaleConstant.enUS, Gender gender = Gender.Male, bool forceGender = false) { if ((gender == Gender.Female || gender == Gender.None) && (forceGender || broadcastText.Text1.HasString(SharedConst.DefaultLocale))) diff --git a/Source/Game/DataStorage/Structs/A_Records.cs b/Source/Game/DataStorage/Structs/A_Records.cs index ece11ce81..784aff753 100644 --- a/Source/Game/DataStorage/Structs/A_Records.cs +++ b/Source/Game/DataStorage/Structs/A_Records.cs @@ -253,4 +253,24 @@ namespace Game.DataStorage public byte DepositRate; public byte ConsignmentRate; } + + public sealed class AzeriteItemRecord + { + public uint ID; + public uint ItemID; + } + + public sealed class AzeriteKnowledgeMultiplierRecord + { + public uint ID; + public float Multiplier; + } + + public sealed class AzeriteLevelInfoRecord + { + public uint ID; + public ulong BaseExperienceToNextLevel; + public ulong MinimumExperienceToNextLevel; + public uint ItemLevel; + } } diff --git a/Source/Game/Entities/Item/AzeriteItem.cs b/Source/Game/Entities/Item/AzeriteItem.cs new file mode 100644 index 000000000..d412ee122 --- /dev/null +++ b/Source/Game/Entities/Item/AzeriteItem.cs @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2012-2019 CypherCore + * + * 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 3 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 . + */ + +using System; +using System.Collections.Generic; +using System.Text; +using Game.Network; +using Framework.Constants; +using Framework.Database; +using Game.Network.Packets; +using Game.DataStorage; + +namespace Game.Entities +{ + public class AzeriteItem : Item + { + AzeriteItemData m_azeriteItemData; + + public AzeriteItem() + { + m_azeriteItemData = new AzeriteItemData(); + + ObjectTypeMask |= TypeMask.AzeriteItem; + ObjectTypeId = TypeId.AzeriteItem; + + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData.DEBUGknowledgeWeek), -1); + } + + public override bool Create(ulong guidlow, uint itemId, Player owner) + { + if (!base.Create(guidlow, itemId, owner)) + return false; + + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData.Level), 1u); + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData.KnowledgeLevel), GetCurrentKnowledgeLevel()); + return true; + } + + public override void SaveToDB(SQLTransaction trans) + { + base.SaveToDB(trans); + + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEM_INSTANCE_AZERITE); + stmt.AddValue(0, GetGUID().GetCounter()); + trans.Append(stmt); + + stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_ITEM_INSTANCE_AZERITE); + stmt.AddValue(0, GetGUID().GetCounter()); + stmt.AddValue(1, m_azeriteItemData.Xp); + stmt.AddValue(2, m_azeriteItemData.Level); + stmt.AddValue(3, m_azeriteItemData.KnowledgeLevel); + trans.Append(stmt); + } + + public override bool LoadFromDB(ulong guid, ObjectGuid ownerGuid, SQLFields fields, uint entry) + { + if (!base.LoadFromDB(guid, ownerGuid, fields, entry)) + return false; + + bool needSave = false; + + ulong xp = fields.Read(43); + uint level = fields.Read(44); + uint knowledgeLevel = fields.Read(45); + + if (!CliDB.AzeriteLevelInfoStorage.ContainsKey(level)) + { + xp = 0; + level = 1; + knowledgeLevel = GetCurrentKnowledgeLevel(); + needSave = true; + } + else if (level > PlayerConst.MaxAzeriteItemLevel) + { + xp = 0; + level = PlayerConst.MaxAzeriteItemLevel; + needSave = true; + } + + if (knowledgeLevel != GetCurrentKnowledgeLevel()) + { + // rescale XP to maintain same progress % + ulong oldMax = CalcTotalXPToNextLevel(level, knowledgeLevel); + knowledgeLevel = GetCurrentKnowledgeLevel(); + ulong newMax = CalcTotalXPToNextLevel(level, knowledgeLevel); + xp = (ulong)(xp / (double)oldMax * newMax); + needSave = true; + } + else if (knowledgeLevel > PlayerConst.MaxAzeriteItemKnowledgeLevel) + { + knowledgeLevel = PlayerConst.MaxAzeriteItemKnowledgeLevel; + needSave = true; + } + + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData.Xp), xp); + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData.Level), level); + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData.KnowledgeLevel), knowledgeLevel); + + if (needSave) + { + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ITEM_INSTANCE_AZERITE_ON_LOAD); + stmt.AddValue(0, xp); + stmt.AddValue(1, knowledgeLevel); + stmt.AddValue(2, guid); + DB.Characters.Execute(stmt); + } + + return true; + } + + public override void DeleteFromDB(SQLTransaction trans) + { + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEM_INSTANCE_AZERITE); + stmt.AddValue(0, GetGUID().GetCounter()); + trans.Append(stmt); + + base.DeleteFromDB(trans); + } + + public override uint GetItemLevel(Player owner) + { + return CliDB.AzeriteLevelInfoStorage.LookupByKey(m_azeriteItemData.Level).ItemLevel; + } + + uint GetCurrentKnowledgeLevel() + { + // count weeks from 26.06.2019 + DateTime now = GameTime.GetDateAndTime(); + DateTime beginDate = new DateTime(2019, 6, 26); + uint knowledge = 0; + while (beginDate < now && knowledge < PlayerConst.MaxAzeriteItemKnowledgeLevel) + { + ++knowledge; + beginDate.AddDays(7); + } + return knowledge; + } + + ulong CalcTotalXPToNextLevel(uint level, uint knowledgeLevel) + { + AzeriteLevelInfoRecord levelInfo = CliDB.AzeriteLevelInfoStorage.LookupByKey(level); + ulong totalXp = levelInfo.BaseExperienceToNextLevel * (ulong)CliDB.AzeriteKnowledgeMultiplierStorage.LookupByKey(knowledgeLevel).Multiplier; + return Math.Max(totalXp, levelInfo.MinimumExperienceToNextLevel); + } + + public void GiveXP(ulong xp) + { + Player owner = GetOwner(); + uint level = m_azeriteItemData.Level; + if (level < PlayerConst.MaxAzeriteItemLevel) + { + ulong currentXP = m_azeriteItemData.Xp; + ulong remainingXP = xp; + do + { + ulong totalXp = CalcTotalXPToNextLevel(level, m_azeriteItemData.KnowledgeLevel); + if (currentXP + remainingXP >= totalXp) + { + // advance to next level + ++level; + remainingXP -= totalXp - currentXP; + currentXP = 0; + } + else + { + currentXP += remainingXP; + remainingXP = 0; + } + } while (remainingXP > 0 && level < PlayerConst.MaxAzeriteItemLevel); + + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData.Xp), currentXP); + + owner.UpdateCriteria(CriteriaTypes.HeartOfAzerothArtifactPowerEarned, xp); + + // changing azerite level changes item level, need to update stats + if (m_azeriteItemData.Level != level) + { + if (IsEquipped()) + owner._ApplyItemBonuses(this, GetSlot(), false); + + SetUpdateFieldValue(m_values.ModifyValue(m_azeriteItemData).ModifyValue(m_azeriteItemData. Level), level); + owner.UpdateCriteria(CriteriaTypes.HeartOfAzerothLevelReached, level); + + if (IsEquipped()) + owner._ApplyItemBonuses(this, GetSlot(), true); + } + + SetState(ItemUpdateState.Changed, owner); + } + + AzeriteXpGain xpGain = new AzeriteXpGain(); + xpGain.ItemGUID = GetGUID(); + xpGain.XP = xp; + owner.SendPacket(xpGain); + } + + public override void BuildValuesCreate(WorldPacket data, Player target) + { + UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target); + WorldPacket buffer = new WorldPacket(); + + buffer.WriteUInt8((byte)flags); + m_objectData.WriteCreate(buffer, flags, this, target); + m_itemData.WriteCreate(buffer, flags, this, target); + m_azeriteItemData.WriteCreate(buffer, flags, this, target); + + data.WriteUInt32(buffer.GetSize()); + data.WriteBytes(buffer); + } + + public override void BuildValuesUpdate(WorldPacket data, Player target) + { + UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target); + WorldPacket buffer = new WorldPacket(); + + if (m_values.HasChanged(TypeId.Object)) + m_objectData.WriteUpdate(buffer, flags, this, target); + + if (m_values.HasChanged(TypeId.Item)) + m_itemData.WriteUpdate(buffer, flags, this, target); + + if (m_values.HasChanged(TypeId.AzeriteItem)) + m_azeriteItemData.WriteUpdate(buffer, flags, this, target); + + data.WriteUInt32(buffer.GetSize()); + data.WriteUInt32(m_values.GetChangedObjectTypeMask()); + data.WriteBytes(buffer); + } + + public override void BuildValuesUpdateWithFlag(WorldPacket data, UpdateFieldFlag flags, Player target) + { + UpdateMask valuesMask = new UpdateMask(14); + valuesMask.Set((int)TypeId.Item); + valuesMask.Set((int)TypeId.AzeriteItem); + + WorldPacket buffer = new WorldPacket(); + buffer.WriteUInt32(valuesMask.GetBlock(0)); + + UpdateMask mask = new UpdateMask(40); + m_itemData.AppendAllowedFieldsMaskForFlag(mask, flags); + m_itemData.WriteUpdate(buffer, mask, flags, this, target); + + UpdateMask mask2 = new UpdateMask(9); + m_azeriteItemData.AppendAllowedFieldsMaskForFlag(mask2, flags); + m_azeriteItemData.WriteUpdate(buffer, mask2, flags, this, target); + + data.WriteUInt32(buffer.GetSize()); + data.WriteBytes(buffer); + } + + public override void ClearUpdateMask(bool remove) + { + m_values.ClearChangesMask(m_azeriteItemData); + base.ClearUpdateMask(remove); + } + } +} diff --git a/Source/Game/Entities/Item/Bag.cs b/Source/Game/Entities/Item/Bag.cs index 7e54d885c..10f14283d 100644 --- a/Source/Game/Entities/Item/Bag.cs +++ b/Source/Game/Entities/Item/Bag.cs @@ -287,11 +287,6 @@ namespace Game.Entities void SetSlot(int slot, ObjectGuid guid) { SetUpdateFieldValue(ref m_values.ModifyValue(m_containerData).ModifyValue(m_containerData.Slots, slot), guid); } - public static Item NewItemOrBag(ItemTemplate proto) - { - return (proto.GetInventoryType() == InventoryType.Bag) ? new Bag() : new Item(); - } - ContainerData m_containerData; Item[] m_bagslot = new Item[36]; } diff --git a/Source/Game/Entities/Item/Item.cs b/Source/Game/Entities/Item/Item.cs index 001be4919..314bf5597 100644 --- a/Source/Game/Entities/Item/Item.cs +++ b/Source/Game/Entities/Item/Item.cs @@ -1869,7 +1869,7 @@ namespace Game.Entities ItemContainerDeleteLootItemsFromDB(); } - public uint GetItemLevel(Player owner) + public virtual uint GetItemLevel(Player owner) { uint minItemLevel = owner.m_unitData.MinItemLevel; uint minItemLevelCutoff = owner.m_unitData.MinItemLevelCutoff; @@ -2386,6 +2386,17 @@ namespace Game.Entities return _bonusData.RequiredLevel; } + public static Item NewItemOrBag(ItemTemplate proto) + { + if (proto.GetInventoryType() == InventoryType.Bag) + return new Bag(); + + if (Global.DB2Mgr.IsAzeriteItem(proto.GetId())) + return new AzeriteItem(); + + return new Item(); + } + public static void AddItemsSetItem(Player player, Item item) { ItemTemplate proto = item.GetTemplate(); @@ -2535,17 +2546,17 @@ namespace Game.Entities public void AddItemFlag(ItemFieldFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.DynamicFlags), (uint)flags); } public void RemoveItemFlag(ItemFieldFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.DynamicFlags), (uint)flags); } public void SetItemFlags(ItemFieldFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.DynamicFlags), (uint)flags); } + bool HasItemFlag2(ItemFieldFlags2 flag) { return (m_itemData.DynamicFlags2 & (uint)flag) != 0; } + void AddItemFlag2(ItemFieldFlags2 flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.DynamicFlags2), (uint)flags); } + void RemoveItemFlag2(ItemFieldFlags2 flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.DynamicFlags2), (uint)flags); } + void SetItemFlags2(ItemFieldFlags2 flags) { SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.DynamicFlags2), (uint)flags); } - public Bag ToBag() - { - if (IsBag()) - return (this as Bag); - else - return null; - } + public Bag ToBag() { return IsBag() ? this as Bag : null; } + public AzeriteItem ToAzeriteItem() { return IsAzeriteItem() ? this as AzeriteItem : null; } public bool IsLocked() { return !HasItemFlag(ItemFieldFlags.Unlocked); } public bool IsBag() { return GetTemplate().GetInventoryType() == InventoryType.Bag; } + bool IsAzeriteItem() { return GetTypeId() == TypeId.AzeriteItem; } public bool IsCurrencyToken() { return GetTemplate().IsCurrencyToken(); } public bool IsBroken() { return m_itemData.MaxDurability > 0 && m_itemData.Durability == 0; } public void SetDurability(uint durability) { SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.Durability), durability); } @@ -2948,7 +2959,5 @@ namespace Game.Entities [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public ushort[] BonusListIDs = new ushort[16]; public byte Context; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] Padding = new byte[3]; } } diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index e7d96ac94..1a15aadc5 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -291,7 +291,7 @@ namespace Game.Entities public UpdateField Context = new UpdateField(0, 16); public UpdateField ArtifactXP = new UpdateField(0, 17); public UpdateField ItemAppearanceModID = new UpdateField(0, 18); - public UpdateField Field_130 = new UpdateField(0, 19); + public UpdateField DynamicFlags2 = new UpdateField(0, 19); public UpdateFieldArray SpellCharges = new UpdateFieldArray(5, 20, 21); public UpdateFieldArray Enchantment = new UpdateFieldArray(13, 26, 27); @@ -343,7 +343,7 @@ namespace Game.Entities data.WriteInt32(Gems.Size()); if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.Owner)) { - data.WriteUInt32(Field_130); + data.WriteUInt32(DynamicFlags2); } for (int i = 0; i < Modifiers.Size(); ++i) { @@ -496,7 +496,7 @@ namespace Game.Entities } if (changesMask[19]) { - data.WriteUInt32(Field_130); + data.WriteUInt32(DynamicFlags2); } } if (changesMask[20]) @@ -541,7 +541,7 @@ namespace Game.Entities ClearChangesMask(Context); ClearChangesMask(ArtifactXP); ClearChangesMask(ItemAppearanceModID); - ClearChangesMask(Field_130); + ClearChangesMask(DynamicFlags2); ClearChangesMask(SpellCharges); ClearChangesMask(Enchantment); _changesMask.ResetAll(); @@ -642,19 +642,19 @@ namespace Game.Entities public uint AzeriteEssenceID; public uint Rank; - public void WriteCreate(WorldPacket data, Item owner, Player receiver) + public void WriteCreate(WorldPacket data, AzeriteItem owner, Player receiver) { data.WriteUInt32(AzeriteEssenceID); data.WriteUInt32(Rank); } - public void WriteUpdate(WorldPacket data, Item owner, Player receiver) + public void WriteUpdate(WorldPacket data, AzeriteItem owner, Player receiver) { data.WriteUInt32(AzeriteEssenceID); data.WriteUInt32(Rank); } } - public class SelectedAzeriteEssences : BaseUpdateData + public class SelectedAzeriteEssences : BaseUpdateData { UpdateField SpecializationID = new UpdateField(0, 1); UpdateField Enabled = new UpdateField(0, 2); @@ -662,7 +662,7 @@ namespace Game.Entities public SelectedAzeriteEssences() : base(7) { } - public override void WriteCreate(WorldPacket data, Item owner, Player receiver) + public override void WriteCreate(WorldPacket data, AzeriteItem owner, Player receiver) { for (int i = 0; i < 3; ++i) { @@ -672,7 +672,7 @@ namespace Game.Entities data.WriteBits(Enabled, 1); data.FlushBits(); } - public override void WriteUpdate(WorldPacket data, Item owner, Player receiver) + public override void WriteUpdate(WorldPacket data, AzeriteItem owner, Player receiver) { UpdateMask changesMask = _changesMask; data.WriteBits(changesMask.GetBlocksMask(0), 1); @@ -713,7 +713,7 @@ namespace Game.Entities } } - public class AzeriteItemData : BaseUpdateData + public class AzeriteItemData : BaseUpdateData { public DynamicUpdateField UnlockedEssences = new DynamicUpdateField(0, 1); public DynamicUpdateField SelectedEssences = new DynamicUpdateField(0, 2); @@ -726,7 +726,7 @@ namespace Game.Entities public AzeriteItemData() : base(9) { } - public override void WriteCreate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Item owner, Player receiver) + public override void WriteCreate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, AzeriteItem owner, Player receiver) { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.Owner)) { @@ -752,18 +752,18 @@ namespace Game.Entities SelectedEssences[i].WriteCreate(data, owner, receiver); } } - public override void WriteUpdate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Item owner, Player receiver) + public override void WriteUpdate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, AzeriteItem owner, Player receiver) { UpdateMask allowedMaskForTarget = new UpdateMask(9, new[] { 0x0000000Fu }); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); WriteUpdate(data, _changesMask & allowedMaskForTarget, fieldVisibilityFlags, owner, receiver); } - void AppendAllowedFieldsMaskForFlag(UpdateMask allowedMaskForTarget, UpdateFieldFlag fieldVisibilityFlags) + public void AppendAllowedFieldsMaskForFlag(UpdateMask allowedMaskForTarget, UpdateFieldFlag fieldVisibilityFlags) { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.Owner)) allowedMaskForTarget |= new UpdateMask(9, new[] { 0x000001F0u }); } - public void WriteUpdate(WorldPacket data, UpdateMask changesMask, UpdateFieldFlag fieldVisibilityFlags, Item owner, Player receiver) + public void WriteUpdate(WorldPacket data, UpdateMask changesMask, UpdateFieldFlag fieldVisibilityFlags, AzeriteItem owner, Player receiver) { data.WriteBits(changesMask.GetBlock(0), 9); diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index f467b5723..aa6b1c183 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -92,9 +92,9 @@ namespace Game.Entities if (item.GetTemplate().GetArtifactID() != 0 && artifactDataPair != null) item.LoadArtifactData(this, artifactDataPair.Item1, artifactDataPair.Item2, artifactDataPair.Item3, artifactDataPair.Item4); - ulong counter = result.Read(43); + ulong counter = result.Read(46); ObjectGuid bagGuid = counter != 0 ? ObjectGuid.Create(HighGuid.Item, counter) : ObjectGuid.Empty; - byte slot = result.Read(44); + byte slot = result.Read(47); GetSession().GetCollectionMgr().CheckHeirloomUpgrades(item); GetSession().GetCollectionMgr().AddItemAppearance(item); @@ -1228,7 +1228,7 @@ namespace Game.Entities } Item item = Bag.NewItemOrBag(proto); - ObjectGuid ownerGuid = result.Read(43) != 0 ? ObjectGuid.Create(HighGuid.Player, result.Read(43)) : ObjectGuid.Empty; + ObjectGuid ownerGuid = result.Read(46) != 0 ? ObjectGuid.Create(HighGuid.Player, result.Read(46)) : ObjectGuid.Empty; if (!item.LoadFromDB(itemGuid, ownerGuid, result.GetFields(), itemEntry)) { Log.outError(LogFilter.Player, "Player:_LoadMailedItems - Item in mail ({0}) doesn't exist !!!! - item guid: {1}, deleted from mail", mail.messageID, itemGuid); @@ -3833,6 +3833,10 @@ namespace Game.Entities stmt.AddValue(0, guid); trans.Append(stmt); + stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEM_INSTANCE_AZERITE_BY_OWNER); + stmt.AddValue(0, guid); + trans.Append(stmt); + stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_ITEM_INSTANCE_BY_OWNER); stmt.AddValue(0, guid); trans.Append(stmt); diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 82f911181..aab9d84eb 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -584,6 +584,7 @@ namespace Game.Entities break; case TypeId.Item: case TypeId.Container: + case TypeId.AzeriteItem: { Item item = (Item)questGiver; Global.ScriptMgr.OnQuestAccept(this, item, quest); diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index dedc1a9bb..b8b114118 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -1244,6 +1244,17 @@ namespace Game.Entities return; } + if (id == CurrencyTypes.Azerite) + { + if (count > 0) + { + Item heartOfAzeroth = GetItemByEntry(PlayerConst.ItemIdHeartOfAzeroth); + if (heartOfAzeroth != null) + heartOfAzeroth.ToAzeriteItem().GiveXP((ulong)count); + } + return; + } + uint oldTotalCount = 0; uint oldWeekCount = 0; uint oldTrackedCount = 0; diff --git a/Source/Game/Guilds/Guild.cs b/Source/Game/Guilds/Guild.cs index 742ebc96e..f53a12f30 100644 --- a/Source/Game/Guilds/Guild.cs +++ b/Source/Game/Guilds/Guild.cs @@ -1338,7 +1338,7 @@ namespace Game.Guilds public bool LoadBankItemFromDB(SQLFields field) { - byte tabId = field.Read(44); + byte tabId = field.Read(47); if (tabId >= _GetPurchasedTabsSize()) { Log.outError(LogFilter.Guild, "Invalid tab for item (GUID: {0}, id: {1}) in guild bank, skipped.", @@ -3241,7 +3241,7 @@ namespace Game.Guilds public bool LoadItemFromDB(SQLFields field) { - byte slotId = field.Read(45); + byte slotId = field.Read(48); uint itemGuid = field.Read(0); uint itemEntry = field.Read(1); if (slotId >= GuildConst.MaxBankSlots) diff --git a/Source/Game/Guilds/GuildManager.cs b/Source/Game/Guilds/GuildManager.cs index 62cab0177..fe30c9b8d 100644 --- a/Source/Game/Guilds/GuildManager.cs +++ b/Source/Game/Guilds/GuildManager.cs @@ -382,7 +382,7 @@ namespace Game uint count = 0; do { - ulong guildId = result.Read(43); + ulong guildId = result.Read(46); Guild guild = GetGuildById(guildId); if (guild) guild.LoadBankItemFromDB(result.GetFields()); diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index e8b2dd981..936e931fd 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -3434,7 +3434,7 @@ namespace Game.Maps // prepare static data ObjectGuid sourceGUID = source != null ? source.GetGUID() : ObjectGuid.Empty; //some script commands doesn't have source ObjectGuid targetGUID = target != null ? target.GetGUID() : ObjectGuid.Empty; - ObjectGuid ownerGUID = (source != null && source.GetTypeId() == TypeId.Item) ? ((Item)source).GetOwnerGUID() : ObjectGuid.Empty; + ObjectGuid ownerGUID = (source != null && source.IsTypeMask(TypeMask.Item)) ? ((Item)source).GetOwnerGUID() : ObjectGuid.Empty; // Schedule script execution for all scripts in the script map bool immedScript = false; @@ -3468,7 +3468,7 @@ namespace Game.Maps // prepare static data ObjectGuid sourceGUID = source != null ? source.GetGUID() : ObjectGuid.Empty; ObjectGuid targetGUID = target != null ? target.GetGUID() : ObjectGuid.Empty; - ObjectGuid ownerGUID = (source != null && source.GetTypeId() == TypeId.Item) ? ((Item)source).GetOwnerGUID() : ObjectGuid.Empty; + ObjectGuid ownerGUID = (source != null && source.IsTypeMask(TypeMask.Item)) ? ((Item)source).GetOwnerGUID() : ObjectGuid.Empty; var sa = new ScriptAction(); sa.sourceGUID = sourceGUID; diff --git a/Source/Game/Network/Packets/AzeriteItemPackets.cs b/Source/Game/Network/Packets/AzeriteItemPackets.cs new file mode 100644 index 000000000..d2b22039d --- /dev/null +++ b/Source/Game/Network/Packets/AzeriteItemPackets.cs @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012-2019 CypherCore + * + * 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 3 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 . + */ + +using Framework.Constants; +using Game.Entities; + +namespace Game.Network.Packets +{ + class AzeriteXpGain : ServerPacket + { + public AzeriteXpGain() : base(ServerOpcodes.AzeriteXpGain) { } + + public override void Write() + { + _worldPacket.WritePackedGuid(ItemGUID); + _worldPacket.WriteUInt64(XP); + } + + public ObjectGuid ItemGUID; + public ulong XP; + } +} diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index eff92f48b..6058fffde 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -2855,6 +2855,31 @@ LOCK TABLES `item_instance_artifact_powers` WRITE; /*!40000 ALTER TABLE `item_instance_artifact_powers` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `item_instance_azerite` +-- + +DROP TABLE IF EXISTS `item_instance_azerite`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `item_instance_azerite` ( + `itemGuid` bigint(20) unsigned NOT NULL, + `xp` bigint(20) unsigned NOT NULL DEFAULT '0', + `level` int(10) unsigned NOT NULL DEFAULT '1', + `knowledgeLevel` int(10) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`itemGuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `item_instance_azerite` +-- + +LOCK TABLES `item_instance_azerite` WRITE; +/*!40000 ALTER TABLE `item_instance_azerite` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_instance_azerite` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `item_instance_gems` -- @@ -3570,7 +3595,8 @@ INSERT INTO `updates` VALUES ('2019_07_15_00_characters.sql','E1C77F604FB2A2FE8B32258CD0C9EC71BEA4F0FF','RELEASED','2019-06-25 22:40:37',0), ('2019_10_26_00_characters.sql','F1090ACDEB876A7BB5ED8829373F6305A217949A','RELEASED','2019-10-25 23:04:42',0), ('2019_10_26_01_characters.sql','59D5860930D02AB77D2AAA704C564957A9143760','RELEASED','2019-10-26 22:04:46',0), -('2019_11_03_00_characters.sql','DC789597F85B890E9A7901B4443DAD9CAEE2A02A','RELEASED','2019-11-03 14:13:27',0); +('2019_11_03_00_characters.sql','DC789597F85B890E9A7901B4443DAD9CAEE2A02A','RELEASED','2019-11-03 14:13:27',0), +('2019_11_12_00_characters.sql','D4C642B4D48DAE9F56329BDE51C258323A132A91','RELEASED','2019-11-12 16:31:29',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/characters/master/2019_11_12_00_characters.sql b/sql/updates/characters/master/2019_11_12_00_characters.sql new file mode 100644 index 000000000..010e16932 --- /dev/null +++ b/sql/updates/characters/master/2019_11_12_00_characters.sql @@ -0,0 +1,11 @@ +-- +-- Table structure for table `item_instance_azerite` +-- +DROP TABLE IF EXISTS `item_instance_azerite`; +CREATE TABLE `item_instance_azerite` ( + `itemGuid` bigint(20) unsigned NOT NULL, + `xp` bigint(20) unsigned NOT NULL DEFAULT '0', + `level` int(10) unsigned NOT NULL DEFAULT '1', + `knowledgeLevel` int(10) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`itemGuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/sql/updates/hotfixes/master/2019_11_12_00_hotfixes.sql b/sql/updates/hotfixes/master/2019_11_12_00_hotfixes.sql new file mode 100644 index 000000000..a7c36362c --- /dev/null +++ b/sql/updates/hotfixes/master/2019_11_12_00_hotfixes.sql @@ -0,0 +1,34 @@ +-- +-- Table structure for table `azerite_item` +-- +DROP TABLE IF EXISTS `azerite_item`; +CREATE TABLE `azerite_item` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `ItemID` int(11) NOT NULL DEFAULT '0', + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `azerite_knowledge_multiplier` +-- +DROP TABLE IF EXISTS `azerite_knowledge_multiplier`; +CREATE TABLE `azerite_knowledge_multiplier` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `Multiplier` float NOT NULL DEFAULT '0', + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `azerite_level_info` +-- +DROP TABLE IF EXISTS `azerite_level_info`; +CREATE TABLE `azerite_level_info` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `BaseExperienceToNextLevel` bigint(20) unsigned NOT NULL DEFAULT '0', + `MinimumExperienceToNextLevel` bigint(20) unsigned NOT NULL DEFAULT '0', + `ItemLevel` int(11) NOT NULL DEFAULT '0', + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/world/master/2019_11_12_00_world.sql b/sql/updates/world/master/2019_11_12_00_world.sql new file mode 100644 index 000000000..d4392a7a9 --- /dev/null +++ b/sql/updates/world/master/2019_11_12_00_world.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_item_heart_of_azeroth'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(277253,'spell_item_heart_of_azeroth');