AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
Trainer::Trainer Class Reference

#include "Trainer.h"

Public Member Functions

 Trainer (uint32 trainerId, Type type, uint32 requirement, std::string greeting, std::vector< Spell > spells)
 
Spell const * GetSpell (uint32 spellId) const
 
std::vector< Spell > const & GetSpells () const
 
void SendSpells (Creature *npc, Player *player, LocaleConstant locale) const
 
bool CanTeachSpell (Player const *player, Spell const *trainerSpell) const
 
void TeachSpell (Creature *npc, Player *player, uint32 spellId)
 
Type GetTrainerType () const
 
uint32 GetTrainerRequirement () const
 
bool IsTrainerValidForPlayer (Player const *player) const
 

Private Member Functions

SpellState GetSpellState (Player const *player, Spell const *trainerSpell) const
 
SpellState GetDefaultSpellState (Player const *player, Spell const *trainerSpell) const
 
void SendTeachFailure (Creature const *npc, Player const *player, uint32 spellId, FailReason reason) const
 
void SendTeachSucceeded (Creature const *npc, Player const *player, uint32 spellId) const
 
std::string const & GetGreeting (LocaleConstant locale) const
 
void AddGreetingLocale (LocaleConstant locale, std::string greeting)
 

Private Attributes

friend ObjectMgr
 
uint32 _trainerId
 
Type _type
 
uint32 _requirement
 
std::vector< Spell_spells
 
std::array< std::string, TOTAL_LOCALES_greeting
 

Detailed Description

Constructor & Destructor Documentation

◆ Trainer()

Trainer::Trainer::Trainer ( uint32  trainerId,
Type  type,
uint32  requirement,
std::string  greeting,
std::vector< Spell spells 
)
33 : _trainerId(trainerId), _type(type), _requirement(requirement), _spells(std::move(spells))
34 {
35 _greeting[DEFAULT_LOCALE] = std::move(greeting);
36 }
#define DEFAULT_LOCALE
Definition Common.h:139
spells
Definition boss_krystallus.cpp:26
uint32 _trainerId
Definition Trainer.h:90
std::vector< Spell > _spells
Definition Trainer.h:93
Type _type
Definition Trainer.h:91
std::array< std::string, TOTAL_LOCALES > _greeting
Definition Trainer.h:94
uint32 _requirement
Definition Trainer.h:92

References DEFAULT_LOCALE.

Member Function Documentation

◆ AddGreetingLocale()

void Trainer::Trainer::AddGreetingLocale ( LocaleConstant  locale,
std::string  greeting 
)
private
273 {
274 _greeting[locale] = std::move(greeting);
275 }

◆ CanTeachSpell()

bool Trainer::Trainer::CanTeachSpell ( Player const *  player,
Spell const *  trainerSpell 
) const
141 {
142 SpellState state = GetSpellState(player, trainerSpell);
143 if (state != SpellState::Available)
144 return false;
145
146 SpellInfo const* trainerSpellInfo = sSpellMgr->AssertSpellInfo(trainerSpell->SpellId);
147
148 for (SpellEffectInfo const& spellEffectInfo : trainerSpellInfo->GetEffects())
149 {
150 if (!spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL))
151 continue;
152
153 SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell);
154 if (learnedSpellInfo && learnedSpellInfo->IsPrimaryProfessionFirstRank() && !player->GetFreePrimaryProfessionPoints())
155 return false;
156 }
157
158 return true;
159 }
@ SPELL_EFFECT_LEARN_SPELL
Definition SharedDefines.h:802
#define sSpellMgr
Definition SpellMgr.h:847
SpellState
Definition Spell.h:235
Definition SpellInfo.h:270
Definition SpellInfo.h:340
bool IsPrimaryProfessionFirstRank() const
Definition SpellInfo.cpp:1019
SpellState GetSpellState(Player const *player, Spell const *trainerSpell) const
Definition Trainer.cpp:161

References Trainer::Available, SpellInfo::GetEffects(), Player::GetFreePrimaryProfessionPoints(), SpellInfo::IsPrimaryProfessionFirstRank(), SPELL_EFFECT_LEARN_SPELL, Trainer::Spell::SpellId, and sSpellMgr.

◆ GetDefaultSpellState()

SpellState Trainer::Trainer::GetDefaultSpellState ( Player const *  player,
Spell const *  trainerSpell 
) const
private
169 {
170 if (player->HasSpell(trainerSpell->SpellId))
171 return SpellState::Known;
172
173 // check race/class requirement
174 if (!player->IsSpellFitByClassAndRace(trainerSpell->SpellId))
176
177 // check skill requirement
178 if (trainerSpell->ReqSkillLine && player->GetBaseSkillValue(trainerSpell->ReqSkillLine) < trainerSpell->ReqSkillRank)
180
181 for (int32 reqAbility : trainerSpell->ReqAbility)
182 if (reqAbility && !player->HasSpell(reqAbility))
183 return SpellState::Unavailable;
184
185 // check level requirement
186 if (player->GetLevel() < trainerSpell->ReqLevel)
188
189 // check ranks
190 bool hasLearnSpellEffect = false;
191 bool knowsAllLearnedSpells = true;
192 for (SpellEffectInfo const& spellEffectInfo : sSpellMgr->AssertSpellInfo(trainerSpell->SpellId)->GetEffects())
193 {
194 if (!spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL))
195 continue;
196
197 hasLearnSpellEffect = true;
198 if (!player->HasSpell(spellEffectInfo.TriggerSpell))
199 knowsAllLearnedSpells = false;
200
201 if (uint32 previousRankSpellId = sSpellMgr->GetPrevSpellInChain(spellEffectInfo.TriggerSpell))
202 if (!player->HasSpell(previousRankSpellId))
204 }
205
206 if (!hasLearnSpellEffect)
207 {
208 if (uint32 previousRankSpellId = sSpellMgr->GetPrevSpellInChain(trainerSpell->SpellId))
209 if (!player->HasSpell(previousRankSpellId))
211 }
212 else if (knowsAllLearnedSpells)
213 return SpellState::Known;
214
215 // check additional spell requirement
216 for (auto const& requirePair : sSpellMgr->GetSpellsRequiredForSpellBounds(trainerSpell->SpellId))
217 if (!player->HasSpell(requirePair.second))
218 return SpellState::Unavailable;
219
221 }
std::int32_t int32
Definition Define.h:103
std::uint32_t uint32
Definition Define.h:107

References Trainer::Available, Player::GetBaseSkillValue(), Unit::GetLevel(), Player::HasSpell(), Player::IsSpellFitByClassAndRace(), Trainer::Known, Trainer::Spell::ReqAbility, Trainer::Spell::ReqLevel, Trainer::Spell::ReqSkillLine, Trainer::Spell::ReqSkillRank, SPELL_EFFECT_LEARN_SPELL, Trainer::Spell::SpellId, sSpellMgr, and Trainer::Unavailable.

◆ GetGreeting()

std::string const & Trainer::Trainer::GetGreeting ( LocaleConstant  locale) const
private
265 {
266 if (_greeting[locale].empty())
268
269 return _greeting[locale];
270 }

References DEFAULT_LOCALE.

◆ GetSpell()

Spell const * Trainer::Trainer::GetSpell ( uint32  spellId) const
128 {
129 auto itr = std::find_if(_spells.begin(), _spells.end(), [spellId](Spell const& trainerSpell)
130 {
131 return trainerSpell.SpellId == spellId;
132 });
133
134 if (itr != _spells.end())
135 return &(*itr);
136
137 return nullptr;
138 }
Definition Spell.h:298

◆ GetSpells()

std::vector< Spell > const & Trainer::Trainer::GetSpells ( ) const
inline
71{ return _spells; }

◆ GetSpellState()

SpellState Trainer::Trainer::GetSpellState ( Player const *  player,
Spell const *  trainerSpell 
) const
private
162 {
163 SpellState state = GetDefaultSpellState(player, trainerSpell);
164 sScriptMgr->OnPlayerGetTrainerSpellState(player, _trainerId, trainerSpell->SpellId, state);
165 return state;
166 }
#define sScriptMgr
Definition ScriptMgr.h:765
SpellState GetDefaultSpellState(Player const *player, Spell const *trainerSpell) const
Definition Trainer.cpp:168

References Trainer::Spell::SpellId, and sScriptMgr.

◆ GetTrainerRequirement()

uint32 Trainer::Trainer::GetTrainerRequirement ( ) const
inline
77{ return _requirement; }

◆ GetTrainerType()

Type Trainer::Trainer::GetTrainerType ( ) const
inline
76{ return _type; }

◆ IsTrainerValidForPlayer()

bool Trainer::Trainer::IsTrainerValidForPlayer ( Player const *  player) const
224 {
226 return true;
227
228 switch (GetTrainerType())
229 {
230 case Type::Class:
231 case Type::Pet:
232 // check class for class trainers
233 return player->getClass() == GetTrainerRequirement();
234 case Type::Mount:
235 // check race for mount trainers
236 return player->getRace() == GetTrainerRequirement();
237 case Type::Tradeskill:
238 // check spell for profession trainers
239 return player->HasSpell(GetTrainerRequirement());
240 default:
241 break;
242 }
243
244 return true;
245 }
uint32 GetTrainerRequirement() const
Definition Trainer.h:77
Type GetTrainerType() const
Definition Trainer.h:76

References Trainer::Class, Unit::getClass(), Unit::getRace(), Player::HasSpell(), Trainer::Mount, Trainer::Pet, and Trainer::Tradeskill.

Referenced by Creature::CanResetTalents(), Player::PrepareGossipMenu(), and WorldSession::SendTrainerList().

◆ SendSpells()

void Trainer::Trainer::SendSpells ( Creature npc,
Player player,
LocaleConstant  locale 
) const
39 {
40 float reputationDiscount = player->GetReputationPriceDiscount(npc);
41
43 trainerList.TrainerGUID = npc->GetGUID();
44 trainerList.TrainerType = AsUnderlyingType(_type);
45 trainerList.Greeting = GetGreeting(locale);
46 trainerList.Spells.reserve(_spells.size());
47 for (Spell const& trainerSpell : _spells)
48 {
49 if (!player->IsSpellFitByClassAndRace(trainerSpell.SpellId))
50 continue;
51
52 SpellInfo const* trainerSpellInfo = sSpellMgr->AssertSpellInfo(trainerSpell.SpellId);
53
54 bool primaryProfessionFirstRank = false;
55 for (SpellEffectInfo const& spellEffectInfo : trainerSpellInfo->GetEffects())
56 {
57 if (!spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL))
58 continue;
59
60 SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(spellEffectInfo.TriggerSpell);
61 if (learnedSpellInfo && learnedSpellInfo->IsPrimaryProfessionFirstRank())
62 primaryProfessionFirstRank = true;
63 }
64
65 trainerList.Spells.emplace_back();
66 WorldPackets::NPC::TrainerListSpell& trainerListSpell = trainerList.Spells.back();
67 trainerListSpell.SpellID = trainerSpell.SpellId;
68 trainerListSpell.Usable = AsUnderlyingType(GetSpellState(player, &trainerSpell));
69 trainerListSpell.MoneyCost = int32(trainerSpell.MoneyCost * reputationDiscount);
70 trainerListSpell.PointCost[0] = 0; // spells don't cost talent points
71 trainerListSpell.PointCost[1] = (primaryProfessionFirstRank ? 1 : 0);
72 trainerListSpell.ReqLevel = trainerSpell.ReqLevel;
73 trainerListSpell.ReqSkillLine = trainerSpell.ReqSkillLine;
74 trainerListSpell.ReqSkillRank = trainerSpell.ReqSkillRank;
75 std::copy(trainerSpell.ReqAbility.begin(), trainerSpell.ReqAbility.end(), trainerListSpell.ReqAbility.begin());
76 }
77
78 sScriptMgr->OnPlayerBeforeReceiveSpellListFromTrainer(player, npc, trainerList);
79
80 player->SendDirectMessage(trainerList.Write());
81 }
npc
Definition BattlegroundSA.h:47
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:610
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:5864
bool IsSpellFitByClassAndRace(uint32 spell_id) const
Definition Player.cpp:12633
float GetReputationPriceDiscount(Creature const *creature) const
Definition Player.cpp:12602
std::string const & GetGreeting(LocaleConstant locale) const
Definition Trainer.cpp:264
Definition NPCPackets.h:56
WorldPacket const * Write() override
Definition NPCPackets.cpp:25
int32 TrainerType
Definition NPCPackets.h:63
std::vector< TrainerListSpell > Spells
Definition NPCPackets.h:64
ObjectGuid TrainerGUID
Definition NPCPackets.h:62
std::string Greeting
Definition NPCPackets.h:65
Definition NPCPackets.h:44
uint8 Usable
Definition NPCPackets.h:46
int32 ReqSkillLine
Definition NPCPackets.h:50
int32 MoneyCost
Definition NPCPackets.h:47
uint8 ReqLevel
Definition NPCPackets.h:49
std::array< int32, 3 > ReqAbility
Definition NPCPackets.h:52
int32 SpellID
Definition NPCPackets.h:45
int32 ReqSkillRank
Definition NPCPackets.h:51
std::array< int32, 2 > PointCost
Definition NPCPackets.h:48

References AsUnderlyingType(), SpellInfo::GetEffects(), Player::GetReputationPriceDiscount(), WorldPackets::NPC::TrainerList::Greeting, SpellInfo::IsPrimaryProfessionFirstRank(), Player::IsSpellFitByClassAndRace(), WorldPackets::NPC::TrainerListSpell::MoneyCost, WorldPackets::NPC::TrainerListSpell::PointCost, WorldPackets::NPC::TrainerListSpell::ReqAbility, WorldPackets::NPC::TrainerListSpell::ReqLevel, WorldPackets::NPC::TrainerListSpell::ReqSkillLine, WorldPackets::NPC::TrainerListSpell::ReqSkillRank, Player::SendDirectMessage(), SPELL_EFFECT_LEARN_SPELL, WorldPackets::NPC::TrainerListSpell::SpellID, WorldPackets::NPC::TrainerList::Spells, sScriptMgr, sSpellMgr, WorldPackets::NPC::TrainerList::TrainerGUID, WorldPackets::NPC::TrainerList::TrainerType, WorldPackets::NPC::TrainerListSpell::Usable, and WorldPackets::NPC::TrainerList::Write().

Referenced by WorldSession::SendTrainerList().

◆ SendTeachFailure()

void Trainer::Trainer::SendTeachFailure ( Creature const *  npc,
Player const *  player,
uint32  spellId,
FailReason  reason 
) const
private
248 {
250 trainerBuyFailed.TrainerGUID = npc->GetGUID();
251 trainerBuyFailed.SpellID = spellId;
252 trainerBuyFailed.TrainerFailedReason = AsUnderlyingType(reason);
253 player->SendDirectMessage(trainerBuyFailed.Write());
254 }
Definition NPCPackets.h:80
int32 TrainerFailedReason
Definition NPCPackets.h:88
WorldPacket const * Write() override
Definition NPCPackets.cpp:54
int32 SpellID
Definition NPCPackets.h:87
ObjectGuid TrainerGUID
Definition NPCPackets.h:86

References AsUnderlyingType(), Player::SendDirectMessage(), WorldPackets::NPC::TrainerBuyFailed::SpellID, WorldPackets::NPC::TrainerBuyFailed::TrainerFailedReason, WorldPackets::NPC::TrainerBuyFailed::TrainerGUID, and WorldPackets::NPC::TrainerBuyFailed::Write().

◆ SendTeachSucceeded()

void Trainer::Trainer::SendTeachSucceeded ( Creature const *  npc,
Player const *  player,
uint32  spellId 
) const
private
257 {
258 WorldPackets::NPC::TrainerBuySucceeded trainerBuySucceeded;
259 trainerBuySucceeded.TrainerGUID = npc->GetGUID();
260 trainerBuySucceeded.SpellID = spellId;
261 player->SendDirectMessage(trainerBuySucceeded.Write());
262 }
Definition NPCPackets.h:92
ObjectGuid TrainerGUID
Definition NPCPackets.h:98
WorldPacket const * Write() override
Definition NPCPackets.cpp:63
int32 SpellID
Definition NPCPackets.h:99

References Player::SendDirectMessage(), WorldPackets::NPC::TrainerBuySucceeded::SpellID, WorldPackets::NPC::TrainerBuySucceeded::TrainerGUID, and WorldPackets::NPC::TrainerBuySucceeded::Write().

◆ TeachSpell()

void Trainer::Trainer::TeachSpell ( Creature npc,
Player player,
uint32  spellId 
)
84 {
85 if (!IsTrainerValidForPlayer(player))
86 return;
87
88 Spell const* trainerSpell = GetSpell(spellId);
89 if (!trainerSpell)
90 {
92 return;
93 }
94
95 if (!CanTeachSpell(player, trainerSpell))
96 {
98 return;
99 }
100
101 float reputationDiscount = player->GetReputationPriceDiscount(npc);
102 int32 moneyCost = int32(trainerSpell->MoneyCost * reputationDiscount);
103 if (!player->HasEnoughMoney(moneyCost))
104 {
106 return;
107 }
108
109 player->ModifyMoney(-moneyCost);
110
111 npc->SendPlaySpellVisual(179); // 53 SpellCastDirected
112 npc->SendPlaySpellImpact(player->GetGUID(), 362); // 113 EmoteSalute
113
114 // learn explicitly or cast explicitly. A cast puts each wrapped spell through learnSpell and
115 // its hook, but also runs whatever else the entry does (a class mount steps the Riding skill),
116 // so the entry itself is put to the hook first and a refusal skips the cast as a whole
117 if (!trainerSpell->IsCastable())
118 player->learnSpell(trainerSpell->SpellId, false);
119 else if (sScriptMgr->OnPlayerCanLearnSpell(player, trainerSpell->SpellId))
120 player->CastSpell(player, trainerSpell->SpellId, true);
121
122 SendTeachSucceeded(npc, player, spellId);
123
124 sScriptMgr->OnPlayerAfterTrainSpell(player, npc, spellId);
125 }
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:120
void learnSpell(uint32 spellId, bool temporary=false, bool learnFromSkill=false)
Definition Player.cpp:3419
bool ModifyMoney(int32 amount, bool sendError=true)
Definition Player.cpp:11684
bool HasEnoughMoney(uint32 amount) const
Definition Player.h:1633
bool IsTrainerValidForPlayer(Player const *player) const
Definition Trainer.cpp:223
Spell const * GetSpell(uint32 spellId) const
Definition Trainer.cpp:127
bool CanTeachSpell(Player const *player, Spell const *trainerSpell) const
Definition Trainer.cpp:140
void SendTeachFailure(Creature const *npc, Player const *player, uint32 spellId, FailReason reason) const
Definition Trainer.cpp:247
void SendTeachSucceeded(Creature const *npc, Player const *player, uint32 spellId) const
Definition Trainer.cpp:256
SpellCastResult CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=nullptr, AuraEffect const *triggeredByAura=nullptr, ObjectGuid originalCaster=ObjectGuid::Empty)
Definition Unit.cpp:1367

References Unit::CastSpell(), Object::GetGUID(), Player::GetReputationPriceDiscount(), Player::HasEnoughMoney(), Trainer::Spell::IsCastable(), Player::learnSpell(), Player::ModifyMoney(), Trainer::Spell::MoneyCost, Trainer::NotEnoughMoney, Trainer::NotEnoughSkill, Trainer::Spell::SpellId, sScriptMgr, and Trainer::Unavailable.

Referenced by WorldSession::HandleTrainerBuySpellOpcode().

Member Data Documentation

◆ _greeting

std::array<std::string, TOTAL_LOCALES> Trainer::Trainer::_greeting
private

◆ _requirement

uint32 Trainer::Trainer::_requirement
private

◆ _spells

std::vector<Spell> Trainer::Trainer::_spells
private

◆ _trainerId

uint32 Trainer::Trainer::_trainerId
private

◆ _type

Type Trainer::Trainer::_type
private

◆ ObjectMgr

friend Trainer::Trainer::ObjectMgr
private

The documentation for this class was generated from the following files: