TrinityCore
ArtifactHandler.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"
19#include "ArtifactPackets.h"
20#include "ConditionMgr.h"
21#include "DB2Stores.h"
22#include "GameTables.h"
23#include "Item.h"
24#include "Player.h"
25#include "SpellAuraEffects.h"
26#include "SpellInfo.h"
27#include "SpellPackets.h"
28
30{
32 return;
33
34 Item* artifact = _player->GetItemByGuid(artifactAddPower.ArtifactGUID);
35 if (!artifact || artifact->IsArtifactDisabled())
36 return;
37
38 uint32 currentArtifactTier = artifact->GetModifier(ITEM_MODIFIER_ARTIFACT_TIER);
39
40 uint64 xpCost = 0;
42 xpCost = uint64(currentArtifactTier == MAX_ARTIFACT_TIER ? cost->XP2 : cost->XP);
43
44 if (xpCost > artifact->m_itemData->ArtifactXP)
45 return;
46
47 if (artifactAddPower.PowerChoices.empty())
48 return;
49
50 UF::ArtifactPower const* artifactPower = artifact->GetArtifactPower(artifactAddPower.PowerChoices[0].ArtifactPowerID);
51 if (!artifactPower)
52 return;
53
54 ArtifactPowerEntry const* artifactPowerEntry = sArtifactPowerStore.LookupEntry(artifactPower->ArtifactPowerID);
55 if (!artifactPowerEntry)
56 return;
57
58 if (artifactPowerEntry->Tier > currentArtifactTier)
59 return;
60
61 uint32 maxRank = artifactPowerEntry->MaxPurchasableRank;
62 if (artifactPowerEntry->Tier < currentArtifactTier)
63 {
64 if (artifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_FINAL)
65 maxRank = 1;
66 else if (artifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER)
67 maxRank += currentArtifactTier - artifactPowerEntry->Tier;
68 }
69
70 if (artifactAddPower.PowerChoices[0].Rank != artifactPower->PurchasedRank + 1 ||
71 artifactAddPower.PowerChoices[0].Rank > maxRank)
72 return;
73
74 if (!(artifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_NO_LINK_REQUIRED))
75 {
76 if (std::vector<uint32> const* artifactPowerLinks = sDB2Manager.GetArtifactPowerLinks(artifactPower->ArtifactPowerID))
77 {
78 bool hasAnyLink = false;
79 for (uint32 artifactPowerLinkId : *artifactPowerLinks)
80 {
81 ArtifactPowerEntry const* artifactPowerLink = sArtifactPowerStore.LookupEntry(artifactPowerLinkId);
82 if (!artifactPowerLink)
83 continue;
84
85 UF::ArtifactPower const* artifactPowerLinkLearned = artifact->GetArtifactPower(artifactPowerLinkId);
86 if (!artifactPowerLinkLearned)
87 continue;
88
89 if (artifactPowerLinkLearned->PurchasedRank >= artifactPowerLink->MaxPurchasableRank)
90 {
91 hasAnyLink = true;
92 break;
93 }
94 }
95
96 if (!hasAnyLink)
97 return;
98 }
99 }
100
101 ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(artifactPower->ArtifactPowerID, artifactPower->CurrentRankWithBonus + 1 - 1); // need data for next rank, but -1 because of how db2 data is structured
102 if (!artifactPowerRank)
103 return;
104
105 artifact->SetArtifactPower(artifactPower->ArtifactPowerID, artifactPower->PurchasedRank + 1, artifactPower->CurrentRankWithBonus + 1);
106
107 if (artifact->IsEquipped())
108 {
109 _player->ApplyArtifactPowerRank(artifact, artifactPowerRank, true);
110
111 for (UF::ArtifactPower const& power : artifact->m_itemData->ArtifactPowers)
112 {
113 ArtifactPowerEntry const* scaledArtifactPowerEntry = sArtifactPowerStore.AssertEntry(power.ArtifactPowerID);
114 if (!(scaledArtifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS))
115 continue;
116
117 ArtifactPowerRankEntry const* scaledArtifactPowerRank = sDB2Manager.GetArtifactPowerRank(scaledArtifactPowerEntry->ID, 0);
118 if (!scaledArtifactPowerRank)
119 continue;
120
121 artifact->SetArtifactPower(power.ArtifactPowerID, power.PurchasedRank, power.CurrentRankWithBonus + 1);
122
123 _player->ApplyArtifactPowerRank(artifact, scaledArtifactPowerRank, false);
124 _player->ApplyArtifactPowerRank(artifact, scaledArtifactPowerRank, true);
125 }
126 }
127
128 artifact->SetArtifactXP(artifact->m_itemData->ArtifactXP - xpCost);
129 artifact->SetState(ITEM_CHANGED, _player);
130
131 uint32 totalPurchasedArtifactPower = artifact->GetTotalPurchasedArtifactPowers();
132 uint32 artifactTier = 0;
133
134 for (ArtifactTierEntry const* tier : sArtifactTierStore)
135 {
136 if (artifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_FINAL && artifactPowerEntry->Tier < MAX_ARTIFACT_TIER)
137 {
138 artifactTier = artifactPowerEntry->Tier + 1;
139 break;
140 }
141
142 if (totalPurchasedArtifactPower < tier->MaxNumTraits)
143 {
144 artifactTier = tier->ArtifactTier;
145 break;
146 }
147 }
148
149 artifactTier = std::max(artifactTier, currentArtifactTier);
150
151 for (uint32 i = currentArtifactTier; i <= artifactTier; ++i)
152 artifact->InitArtifactPowers(artifact->GetTemplate()->GetArtifactID(), uint8(i));
153
154 artifact->SetModifier(ITEM_MODIFIER_ARTIFACT_TIER, artifactTier);
155}
156
158{
160 return;
161
162 ArtifactAppearanceEntry const* artifactAppearance = sArtifactAppearanceStore.LookupEntry(artifactSetAppearance.ArtifactAppearanceID);
163 if (!artifactAppearance)
164 return;
165
166 Item* artifact = _player->GetItemByGuid(artifactSetAppearance.ArtifactGUID);
167 if (!artifact)
168 return;
169
170 ArtifactAppearanceSetEntry const* artifactAppearanceSet = sArtifactAppearanceSetStore.LookupEntry(artifactAppearance->ArtifactAppearanceSetID);
171 if (!artifactAppearanceSet || artifactAppearanceSet->ArtifactID != artifact->GetTemplate()->GetArtifactID())
172 return;
173
174 if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(artifactAppearance->UnlockPlayerConditionID))
175 if (!sConditionMgr->IsPlayerMeetingCondition(_player, playerCondition))
176 return;
177
178 artifact->SetAppearanceModId(artifactAppearance->ItemAppearanceModifierID);
179 artifact->SetModifier(ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID, artifactAppearance->ID);
180 artifact->SetState(ITEM_CHANGED, _player);
181 Item* childItem = _player->GetChildItemByGuid(artifact->GetChildItem());
182 if (childItem)
183 {
184 childItem->SetAppearanceModId(artifactAppearance->ItemAppearanceModifierID);
185 childItem->SetState(ITEM_CHANGED, _player);
186 }
187
188 if (artifact->IsEquipped())
189 {
190 // change weapon appearance
191 _player->SetVisibleItemSlot(artifact->GetSlot(), artifact);
192 if (childItem)
193 _player->SetVisibleItemSlot(childItem->GetSlot(), childItem);
194
195 // change druid form appearance
196 if (artifactAppearance->OverrideShapeshiftDisplayID && artifactAppearance->OverrideShapeshiftFormID && _player->GetShapeshiftForm() == ShapeshiftForm(artifactAppearance->OverrideShapeshiftFormID))
198 }
199}
200
202{
204 return;
205
206 Item* artifact = _player->GetItemByGuid(confirmArtifactRespec.ArtifactGUID);
207 if (!artifact || artifact->IsArtifactDisabled())
208 return;
209
210 uint64 xpCost = 0;
212 xpCost = uint64(artifact->GetModifier(ITEM_MODIFIER_ARTIFACT_TIER) == 1 ? cost->XP2 : cost->XP);
213
214 if (xpCost > artifact->m_itemData->ArtifactXP)
215 return;
216
217 uint64 newAmount = artifact->m_itemData->ArtifactXP - xpCost;
218 for (uint32 i = 0; i <= artifact->GetTotalPurchasedArtifactPowers(); ++i)
219 if (GtArtifactLevelXPEntry const* cost = sArtifactLevelXPGameTable.GetRow(i))
220 newAmount += uint64(artifact->GetModifier(ITEM_MODIFIER_ARTIFACT_TIER) == 1 ? cost->XP2 : cost->XP);
221
222 for (UF::ArtifactPower const& artifactPower : artifact->m_itemData->ArtifactPowers)
223 {
224 uint8 oldPurchasedRank = artifactPower.PurchasedRank;
225 if (!oldPurchasedRank)
226 continue;
227
228 artifact->SetArtifactPower(artifactPower.ArtifactPowerID, artifactPower.PurchasedRank - oldPurchasedRank, artifactPower.CurrentRankWithBonus - oldPurchasedRank);
229
230 if (artifact->IsEquipped())
231 if (ArtifactPowerRankEntry const* artifactPowerRank = sDB2Manager.GetArtifactPowerRank(artifactPower.ArtifactPowerID, 0))
232 _player->ApplyArtifactPowerRank(artifact, artifactPowerRank, false);
233 }
234
235 for (UF::ArtifactPower const& power : artifact->m_itemData->ArtifactPowers)
236 {
237 ArtifactPowerEntry const* scaledArtifactPowerEntry = sArtifactPowerStore.AssertEntry(power.ArtifactPowerID);
238 if (!(scaledArtifactPowerEntry->Flags & ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS))
239 continue;
240
241 ArtifactPowerRankEntry const* scaledArtifactPowerRank = sDB2Manager.GetArtifactPowerRank(scaledArtifactPowerEntry->ID, 0);
242 if (!scaledArtifactPowerRank)
243 continue;
244
245 artifact->SetArtifactPower(power.ArtifactPowerID, power.PurchasedRank, 0);
246
247 _player->ApplyArtifactPowerRank(artifact, scaledArtifactPowerRank, false);
248 }
249
250 artifact->SetArtifactXP(newAmount);
251 artifact->SetState(ITEM_CHANGED, _player);
252}
#define sConditionMgr
Definition: ConditionMgr.h:365
DB2Storage< ArtifactAppearanceEntry > sArtifactAppearanceStore("ArtifactAppearance.db2", &ArtifactAppearanceLoadInfo::Instance)
DB2Storage< ArtifactPowerEntry > sArtifactPowerStore("ArtifactPower.db2", &ArtifactPowerLoadInfo::Instance)
DB2Storage< ArtifactTierEntry > sArtifactTierStore("ArtifactTier.db2", &ArtifactTierLoadInfo::Instance)
DB2Storage< PlayerConditionEntry > sPlayerConditionStore("PlayerCondition.db2", &PlayerConditionLoadInfo::Instance)
DB2Storage< ArtifactAppearanceSetEntry > sArtifactAppearanceSetStore("ArtifactAppearanceSet.db2", &ArtifactAppearanceSetLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
@ ARTIFACT_POWER_FLAG_SCALES_WITH_NUM_POWERS
Definition: DBCEnums.h:191
@ ARTIFACT_POWER_FLAG_MAX_RANK_WITH_TIER
Definition: DBCEnums.h:193
@ ARTIFACT_POWER_FLAG_NO_LINK_REQUIRED
Definition: DBCEnums.h:189
@ ARTIFACT_POWER_FLAG_FINAL
Definition: DBCEnums.h:190
#define MAX_ARTIFACT_TIER
Definition: DBCEnums.h:198
uint8_t uint8
Definition: Define.h:144
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
GameTable< GtArtifactLevelXPEntry > sArtifactLevelXPGameTable
Definition: GameTables.cpp:29
@ ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID
Definition: ItemDefines.h:219
@ ITEM_MODIFIER_ARTIFACT_TIER
Definition: ItemDefines.h:235
@ ITEM_CHANGED
Definition: Item.h:55
@ GAMEOBJECT_TYPE_ITEM_FORGE
ShapeshiftForm
@ UNIT_NPC_FLAG_ARTIFACT_POWER_RESPEC
Definition: UnitDefines.h:324
@ UNIT_NPC_FLAG_2_NONE
Definition: UnitDefines.h:336
Definition: Item.h:170
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
Definition: Item.cpp:1166
uint8 GetSlot() const
Definition: Item.h:280
void SetArtifactPower(uint16 artifactPowerId, uint8 purchasedRank, uint8 currentRankWithBonus)
Definition: Item.cpp:2599
void InitArtifactPowers(uint8 artifactId, uint8 artifactTier)
Definition: Item.cpp:2614
void SetModifier(ItemModifier modifier, uint32 value)
Definition: Item.cpp:2436
ItemTemplate const * GetTemplate() const
Definition: Item.cpp:1141
bool IsEquipped() const
Definition: Item.cpp:1244
UF::ArtifactPower const * GetArtifactPower(uint32 artifactPowerId) const
Definition: Item.cpp:2579
bool IsArtifactDisabled() const
Definition: Item.cpp:2571
void SetArtifactXP(uint64 xp)
Definition: Item.h:438
void SetAppearanceModId(uint32 appearanceModId)
Definition: Item.h:346
ObjectGuid GetChildItem() const
Definition: Item.h:423
uint32 GetModifier(ItemModifier modifier) const
Definition: Item.cpp:2423
uint32 GetTotalPurchasedArtifactPowers() const
Definition: Item.cpp:2655
UF::UpdateField< UF::ItemData, 0, TYPEID_ITEM > m_itemData
Definition: Item.h:449
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
Definition: Player.cpp:1947
Item * GetChildItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9695
GameObject * GetGameObjectIfCanInteractWith(ObjectGuid const &guid) const
Definition: Player.cpp:2004
void SetVisibleItemSlot(uint8 slot, Item *pItem)
Definition: Player.cpp:11995
Item * GetItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9566
void ApplyArtifactPowerRank(Item *artifact, ArtifactPowerRankEntry const *artifactPowerRank, bool apply)
Definition: Player.cpp:8458
void RestoreDisplayId(bool ignorePositiveAurasPreventingMounting=false)
Definition: Unit.cpp:10172
ShapeshiftForm GetShapeshiftForm() const
Definition: Unit.h:1463
bool IsMounted() const
Definition: Unit.h:898
Array< ArtifactPowerChoice, 1 > PowerChoices
void HandleConfirmArtifactRespec(WorldPackets::Artifact::ConfirmArtifactRespec &confirmArtifactRespec)
void HandleArtifactSetAppearance(WorldPackets::Artifact::ArtifactSetAppearance &artifactSetAppearance)
void HandleArtifactAddPower(WorldPackets::Artifact::ArtifactAddPower &artifactAddPower)
Player * _player
uint8 GetArtifactID() const
Definition: ItemTemplate.h:824
uint8 CurrentRankWithBonus
Definition: UpdateFields.h:99