TrinityCore
AzeriteHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
20#include "AzeriteItem.h"
21#include "AzeritePackets.h"
22#include "DB2Stores.h"
23#include "NPCPackets.h"
24#include "Player.h"
25#include "SpellHistory.h"
26
28{
30 return;
31
33 if (!item)
34 return;
35
36 AzeriteItem* azeriteItem = item->ToAzeriteItem();
37 if (!azeriteItem || !azeriteItem->CanUseEssences())
38 return;
39
40 AzeriteItemMilestonePowerEntry const* milestonePower = sAzeriteItemMilestonePowerStore.LookupEntry(azeriteEssenceUnlockMilestone.AzeriteItemMilestonePowerID);
41 if (!milestonePower || milestonePower->RequiredLevel > int32(azeriteItem->GetLevel()))
42 return;
43
44 // check that all previous milestones are unlocked
45 for (AzeriteItemMilestonePowerEntry const* previousMilestone : sDB2Manager.GetAzeriteItemMilestonePowers())
46 {
47 if (previousMilestone == milestonePower)
48 break;
49
50 if (!azeriteItem->HasUnlockedEssenceMilestone(previousMilestone->ID))
51 return;
52 }
53
54 azeriteItem->AddUnlockedEssenceMilestone(milestonePower->ID);
55 _player->ApplyAzeriteItemMilestonePower(azeriteItem, milestonePower, true);
56 azeriteItem->SetState(ITEM_CHANGED, _player);
57}
58
60{
62 activateEssenceResult.AzeriteEssenceID = azeriteEssenceActivateEssence.AzeriteEssenceID;
64 if (!item)
65 {
67 activateEssenceResult.Slot = azeriteEssenceActivateEssence.Slot;
68 SendPacket(activateEssenceResult.Write());
69 return;
70 }
71
72 AzeriteItem* azeriteItem = item->ToAzeriteItem();
73 if (!azeriteItem || !azeriteItem->CanUseEssences())
74 {
76 SendPacket(activateEssenceResult.Write());
77 return;
78 }
79
80 if (azeriteEssenceActivateEssence.Slot >= MAX_AZERITE_ESSENCE_SLOT || !azeriteItem->HasUnlockedEssenceSlot(azeriteEssenceActivateEssence.Slot))
81 {
83 SendPacket(activateEssenceResult.Write());
84 return;
85 }
86
87 UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences();
88 // essence is already in that slot, nothing to do
89 if (selectedEssences && selectedEssences->AzeriteEssenceID[azeriteEssenceActivateEssence.Slot] == uint32(azeriteEssenceActivateEssence.AzeriteEssenceID))
90 return;
91
92 uint32 rank = azeriteItem->GetEssenceRank(azeriteEssenceActivateEssence.AzeriteEssenceID);
93 if (!rank)
94 {
96 activateEssenceResult.Arg = azeriteEssenceActivateEssence.AzeriteEssenceID;
97 SendPacket(activateEssenceResult.Write());
98 return;
99 }
100
101 if (_player->IsInCombat())
102 {
104 activateEssenceResult.Slot = azeriteEssenceActivateEssence.Slot;
105 SendPacket(activateEssenceResult.Write());
106 return;
107 }
108
109 if (_player->isDead())
110 {
112 activateEssenceResult.Slot = azeriteEssenceActivateEssence.Slot;
113 SendPacket(activateEssenceResult.Write());
114 return;
115 }
116
118 {
120 activateEssenceResult.Slot = azeriteEssenceActivateEssence.Slot;
121 SendPacket(activateEssenceResult.Write());
122 return;
123 }
124
125 if (selectedEssences)
126 {
127 // need to remove selected essence from another slot if selected
128 int32 removeEssenceFromSlot = -1;
129 for (int32 slot = 0; slot < MAX_AZERITE_ESSENCE_SLOT; ++slot)
130 if (azeriteEssenceActivateEssence.Slot != uint8(slot) && selectedEssences->AzeriteEssenceID[slot] == uint32(azeriteEssenceActivateEssence.AzeriteEssenceID))
131 removeEssenceFromSlot = slot;
132
133 // check cooldown of major essence slot
134 if (selectedEssences->AzeriteEssenceID[0] && (azeriteEssenceActivateEssence.Slot == 0 || removeEssenceFromSlot == 0))
135 {
136 for (uint32 essenceRank = 1; essenceRank <= rank; ++essenceRank)
137 {
138 AzeriteEssencePowerEntry const* azeriteEssencePower = ASSERT_NOTNULL(sDB2Manager.GetAzeriteEssencePower(selectedEssences->AzeriteEssenceID[0], essenceRank));
139 if (_player->GetSpellHistory()->HasCooldown(azeriteEssencePower->MajorPowerDescription))
140 {
142 activateEssenceResult.Arg = azeriteEssencePower->MajorPowerDescription;
143 activateEssenceResult.Slot = azeriteEssenceActivateEssence.Slot;
144 SendPacket(activateEssenceResult.Write());
145 return;
146 }
147 }
148 }
149
150 if (removeEssenceFromSlot != -1)
151 {
152 _player->ApplyAzeriteEssence(azeriteItem, selectedEssences->AzeriteEssenceID[removeEssenceFromSlot], MAX_AZERITE_ESSENCE_RANK,
153 AzeriteItemMilestoneType(sDB2Manager.GetAzeriteItemMilestonePower(removeEssenceFromSlot)->Type) == AzeriteItemMilestoneType::MajorEssence, false);
154 azeriteItem->SetSelectedAzeriteEssence(removeEssenceFromSlot, 0);
155 }
156
157 if (selectedEssences->AzeriteEssenceID[azeriteEssenceActivateEssence.Slot])
158 {
159 _player->ApplyAzeriteEssence(azeriteItem, selectedEssences->AzeriteEssenceID[azeriteEssenceActivateEssence.Slot], MAX_AZERITE_ESSENCE_RANK,
160 AzeriteItemMilestoneType(sDB2Manager.GetAzeriteItemMilestonePower(azeriteEssenceActivateEssence.Slot)->Type) == AzeriteItemMilestoneType::MajorEssence, false);
161 }
162 }
163 else
165
166 azeriteItem->SetSelectedAzeriteEssence(azeriteEssenceActivateEssence.Slot, azeriteEssenceActivateEssence.AzeriteEssenceID);
167
168 _player->ApplyAzeriteEssence(azeriteItem, azeriteEssenceActivateEssence.AzeriteEssenceID, rank,
169 AzeriteItemMilestoneType(sDB2Manager.GetAzeriteItemMilestonePower(azeriteEssenceActivateEssence.Slot)->Type) == AzeriteItemMilestoneType::MajorEssence, true);
170
171 azeriteItem->SetState(ITEM_CHANGED, _player);
172}
173
175{
176 Item* item = _player->GetItemByGuid(azeriteEmpoweredItemViewed.ItemGUID);
177 if (!item || !item->IsAzeriteEmpoweredItem())
178 return;
179
182}
183
185{
186 Item* item = _player->GetItemByPos(azeriteEmpoweredItemSelectPower.ContainerSlot, azeriteEmpoweredItemSelectPower.Slot);
187 if (!item)
188 return;
189
190 AzeritePowerEntry const* azeritePower = sAzeritePowerStore.LookupEntry(azeriteEmpoweredItemSelectPower.AzeritePowerID);
191 if (!azeritePower)
192 return;
193
194 AzeriteEmpoweredItem* azeriteEmpoweredItem = item->ToAzeriteEmpoweredItem();
195 if (!azeriteEmpoweredItem)
196 return;
197
198 // Validate tier
199 int32 actualTier = azeriteEmpoweredItem->GetTierForAzeritePower(Classes(_player->GetClass()), azeriteEmpoweredItemSelectPower.AzeritePowerID);
200 if (azeriteEmpoweredItemSelectPower.Tier > MAX_AZERITE_EMPOWERED_TIER || azeriteEmpoweredItemSelectPower.Tier != actualTier)
201 return;
202
203 uint32 azeriteLevel = 0;
205 if (!heartOfAzeroth)
206 return;
207
208 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
209 azeriteLevel = azeriteItem->GetEffectiveLevel();
210
211 // Check required heart of azeroth level
212 if (azeriteLevel < azeriteEmpoweredItem->GetRequiredAzeriteLevelForTier(uint32(actualTier)))
213 return;
214
215 // tiers are ordered backwards, you first select the highest one
216 for (int32 i = actualTier + 1; i < azeriteEmpoweredItem->GetMaxAzeritePowerTier(); ++i)
217 if (!azeriteEmpoweredItem->GetSelectedAzeritePower(i))
218 return;
219
220 bool activateAzeritePower = azeriteEmpoweredItem->IsEquipped() && heartOfAzeroth->IsEquipped();
221 if (azeritePower->ItemBonusListID && activateAzeritePower)
222 _player->_ApplyItemMods(azeriteEmpoweredItem, azeriteEmpoweredItem->GetSlot(), false);
223
224 azeriteEmpoweredItem->SetSelectedAzeritePower(actualTier, azeriteEmpoweredItemSelectPower.AzeritePowerID);
225
226 if (activateAzeritePower)
227 {
228 // apply all item mods when azerite power grants a bonus, item level changes and that affects stats and auras that scale with item level
229 if (azeritePower->ItemBonusListID)
230 _player->_ApplyItemMods(azeriteEmpoweredItem, azeriteEmpoweredItem->GetSlot(), true);
231 else
232 _player->ApplyAzeritePower(azeriteEmpoweredItem, azeritePower, true);
233 }
234
235 azeriteEmpoweredItem->SetState(ITEM_CHANGED, _player);
236}
237
239{
241 npcInteraction.Npc = npc;
243 npcInteraction.Success = true;
244 SendPacket(npcInteraction.Write());
245}
constexpr uint32 ITEM_ID_HEART_OF_AZEROTH
Definition: AzeriteItem.h:23
DB2Storage< AzeriteItemMilestonePowerEntry > sAzeriteItemMilestonePowerStore("AzeriteItemMilestonePower.db2", &AzeriteItemMilestonePowerLoadInfo::Instance)
DB2Storage< AzeritePowerEntry > sAzeritePowerStore("AzeritePower.db2", &AzeritePowerLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
#define MAX_AZERITE_EMPOWERED_TIER
Definition: DBCEnums.h:200
AzeriteItemMilestoneType
Definition: DBCEnums.h:206
#define MAX_AZERITE_ESSENCE_RANK
Definition: DBCEnums.h:203
#define MAX_AZERITE_ESSENCE_SLOT
Definition: DBCEnums.h:202
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
@ ITEM_FIELD_FLAG_AZERITE_EMPOWERED_ITEM_VIEWED
Definition: ItemTemplate.h:153
@ ITEM_CHANGED
Definition: Item.h:55
@ PLAYER_FLAGS_RESTING
Definition: Player.h:433
Classes
@ UNIT_FLAG2_ALLOW_CHANGING_TALENTS
Definition: UnitDefines.h:203
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
int32 GetTierForAzeritePower(Classes playerClass, int32 azeritePowerId) const
int32 GetMaxAzeritePowerTier() const
uint32 GetSelectedAzeritePower(int32 tier) const
void SetSelectedAzeritePower(int32 tier, int32 azeritePowerId)
UF::SelectedAzeriteEssences const * GetSelectedAzeriteEssences() const
void SetSelectedAzeriteEssence(uint8 slot, uint32 azeriteEssenceId)
bool HasUnlockedEssenceSlot(uint8 slot) const
static GameObject const * FindHeartForge(Player const *owner)
bool HasUnlockedEssenceMilestone(uint32 azeriteItemMilestonePowerId) const
Definition: AzeriteItem.h:61
bool CanUseEssences() const
void AddUnlockedEssenceMilestone(uint32 azeriteItemMilestonePowerId)
Definition: AzeriteItem.h:62
void CreateSelectedAzeriteEssences(uint32 specializationId)
uint32 GetLevel() const
Definition: AzeriteItem.h:41
uint32 GetEssenceRank(uint32 azeriteEssenceId) const
Definition: Item.h:170
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition: Item.cpp:1166
uint8 GetSlot() const
Definition: Item.h:280
void SetItemFlag(ItemFieldFlags flags)
Definition: Item.h:209
bool IsAzeriteEmpoweredItem() const
Definition: Item.h:254
AzeriteItem * ToAzeriteItem()
Definition: Item.h:243
bool IsEquipped() const
Definition: Item.cpp:1244
AzeriteEmpoweredItem * ToAzeriteEmpoweredItem()
Definition: Item.h:245
ChrSpecialization GetPrimarySpecialization() const
Definition: Player.h:1841
void ApplyAzeriteEssence(AzeriteItem *item, uint32 azeriteEssenceId, uint32 rank, bool major, bool apply)
Definition: Player.cpp:8557
void _ApplyItemMods(Item *item, uint8 slot, bool apply, bool updateItemAuras=true)
Definition: Player.cpp:7865
Item * GetItemByEntry(uint32 entry, ItemSearchLocation where=ItemSearchLocation::Default) const
Definition: Player.cpp:12589
void ApplyAzeritePower(AzeriteEmpoweredItem *item, AzeritePowerEntry const *azeritePower, bool apply)
Definition: Player.cpp:8611
Item * GetItemByPos(uint16 pos) const
Definition: Player.cpp:9582
void ApplyAzeriteItemMilestonePower(AzeriteItem *item, AzeriteItemMilestonePowerEntry const *azeriteItemMilestonePower, bool apply)
Definition: Player.cpp:8542
bool HasPlayerFlag(PlayerFlags flags) const
Definition: Player.h:2737
Item * GetItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9566
bool HasCooldown(SpellInfo const *spellInfo, uint32 itemId=0) const
uint8 GetClass() const
Definition: Unit.h:752
bool HasUnitFlag2(UnitFlags2 flags) const
Definition: Unit.h:837
SpellHistory * GetSpellHistory()
Definition: Unit.h:1457
bool IsInCombat() const
Definition: Unit.h:1043
bool isDead() const
Definition: Unit.h:1166
WorldPacket const * Write() override
WorldPacket const * Write() override
Definition: NPCPackets.cpp:94
void HandleAzeriteEssenceUnlockMilestone(WorldPackets::Azerite::AzeriteEssenceUnlockMilestone &azeriteEssenceUnlockMilestone)
void SendAzeriteRespecNPC(ObjectGuid npc)
void HandleAzeriteEssenceActivateEssence(WorldPackets::Azerite::AzeriteEssenceActivateEssence &azeriteEssenceActivateEssence)
void HandleAzeriteEmpoweredItemSelectPower(WorldPackets::Azerite::AzeriteEmpoweredItemSelectPower &azeriteEmpoweredItemSelectPower)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
Player * _player
void HandleAzeriteEmpoweredItemViewed(WorldPackets::Azerite::AzeriteEmpoweredItemViewed &azeriteEmpoweredItemViewed)
UpdateFieldArray< uint32, 4, 3, 4 > AzeriteEssenceID
Definition: UpdateFields.h:187