TrinityCore
CharmInfo.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 "CharmInfo.h"
19#include "Creature.h"
20#include "Map.h"
21#include "SpellInfo.h"
22#include "SpellMgr.h"
23#include "StringConvert.h"
24#include "Unit.h"
25
27: _unit(unit), _CommandState(COMMAND_FOLLOW), _petnumber(0), _oldReactState(REACT_PASSIVE),
28 _isCommandAttack(false), _isCommandFollow(false), _isAtStay(false), _isFollowing(false), _isReturning(false),
29 _stayX(0.0f), _stayY(0.0f), _stayZ(0.0f)
30{
31 for (uint8 i = 0; i < MAX_SPELL_CHARM; ++i)
32 _charmspells[i].SetActionAndType(0, ACT_DISABLED);
33
34 if (Creature* creature = _unit->ToCreature())
35 {
36 _oldReactState = creature->GetReactState();
37 creature->SetReactState(REACT_PASSIVE);
38 }
39}
40
42
44{
45 if (Creature* creature = _unit->ToCreature())
46 creature->SetReactState(_oldReactState);
47}
48
50{
51 // the first 3 SpellOrActions are attack, follow and stay
54
55 // middle 4 SpellOrActions are spells/special attacks/abilities
58
59 // last 3 SpellOrActions are reactions
62}
63
64void CharmInfo::InitEmptyActionBar(bool withAttack)
65{
66 if (withAttack)
68 else
72}
73
75{
76 if (_unit->GetTypeId() == TYPEID_UNIT)
77 {
78 // Adding switch until better way is found. Malcrom
79 // Adding entrys to this switch will prevent COMMAND_ATTACK being added to pet bar.
80 switch (_unit->GetEntry())
81 {
82 case 23575: // Mindless Abomination
83 case 24783: // Trained Rock Falcon
84 case 27664: // Crashin' Thrashin' Racer
85 case 40281: // Crashin' Thrashin' Racer
86 case 28511: // Eye of Acherus
87 break;
88 default:
90 break;
91 }
92
93 for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
94 {
95 uint32 spellId = _unit->ToCreature()->m_spells[i];
96 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _unit->GetMap()->GetDifficultyID());
97 if (spellInfo)
98 {
100 continue;
101
102 if (spellInfo->IsPassive())
103 _unit->CastSpell(_unit, spellInfo->Id, true);
104 else
106 }
107 }
108 }
109 else
111}
112
114{
115 if (_unit->GetTypeId() == TYPEID_PLAYER) // charmed players don't have spells
116 {
118 return;
119 }
120
122
123 for (uint32 x = 0; x < MAX_SPELL_CHARM; ++x)
124 {
125 uint32 spellId = _unit->ToCreature()->m_spells[x];
126 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _unit->GetMap()->GetDifficultyID());
127
128 if (!spellInfo)
129 {
131 continue;
132 }
133
135 continue;
136
137 if (spellInfo->IsPassive())
138 {
139 _unit->CastSpell(_unit, spellInfo->Id, true);
141 }
142 else
143 {
145
146 ActiveStates newstate = ACT_PASSIVE;
147
148 if (!spellInfo->IsAutocastable())
149 newstate = ACT_PASSIVE;
150 else
151 {
152 if (spellInfo->NeedsExplicitUnitTarget())
153 {
154 newstate = ACT_ENABLED;
155 ToggleCreatureAutocast(spellInfo, true);
156 }
157 else
158 newstate = ACT_DISABLED;
159 }
160
161 AddSpellToActionBar(spellInfo, newstate);
162 }
163 }
164}
165
166bool CharmInfo::AddSpellToActionBar(SpellInfo const* spellInfo, ActiveStates newstate, uint8 preferredSlot)
167{
168 uint32 spell_id = spellInfo->Id;
169 uint32 first_id = spellInfo->GetFirstRankSpell()->Id;
170
171 ASSERT(preferredSlot < MAX_UNIT_ACTION_BAR_INDEX);
172 // new spell rank can be already listed
173 for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
174 {
175 if (uint32 action = PetActionBar[i].GetAction())
176 {
177 if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id)
178 {
179 PetActionBar[i].SetAction(spell_id);
180 return true;
181 }
182 }
183 }
184
185 // or use empty slot in other case
186 for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
187 {
188 uint8 j = (preferredSlot + i) % MAX_UNIT_ACTION_BAR_INDEX;
189 if (!PetActionBar[j].GetAction() && PetActionBar[j].IsActionBarForSpell())
190 {
191 SetActionBar(j, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate);
192 return true;
193 }
194 }
195 return false;
196}
197
199{
200 uint32 first_id = sSpellMgr->GetFirstSpellInChain(spell_id);
201
202 for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
203 {
204 if (uint32 action = PetActionBar[i].GetAction())
205 {
206 if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id)
207 {
209 return true;
210 }
211 }
212 }
213
214 return false;
215}
216
218{
219 if (spellInfo->IsPassive())
220 return;
221
222 for (uint32 x = 0; x < MAX_SPELL_CHARM; ++x)
223 if (spellInfo->Id == _charmspells[x].GetAction())
225}
226
227void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow)
228{
229 _petnumber = petnumber;
230 if (statwindow)
232 else
234}
235
236void CharmInfo::LoadPetActionBar(const std::string& data)
237{
239
240 std::vector<std::string_view> tokens = Trinity::Tokenize(data, ' ', false);
241 if (tokens.size() != (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START) * 2)
242 return; // non critical, will reset to default
243
244 auto iter = tokens.begin();
245 for (uint8 index = ACTION_BAR_INDEX_START; index < ACTION_BAR_INDEX_END; ++index)
246 {
247 Optional<uint8> type = Trinity::StringTo<uint8>(*(iter++));
248 Optional<uint32> action = Trinity::StringTo<uint32>(*(iter++));
249
250 if (!type || !action)
251 continue;
252
253 PetActionBar[index].SetActionAndType(*action, static_cast<ActiveStates>(*type));
254
255 // check correctness
256 if (PetActionBar[index].IsActionBarForSpell())
257 {
258 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction(), _unit->GetMap()->GetDifficultyID());
259 if (!spellInfo)
260 SetActionBar(index, 0, ACT_PASSIVE);
261 else if (!spellInfo->IsAutocastable())
262 SetActionBar(index, PetActionBar[index].GetAction(), ACT_PASSIVE);
263 }
264 }
265}
266
268{
269 for (uint32 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
270 *data << uint32(PetActionBar[i].packedData);
271}
272
273void CharmInfo::SetSpellAutocast(SpellInfo const* spellInfo, bool state)
274{
275 for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
276 {
277 if (spellInfo->Id == PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell())
278 {
280 break;
281 }
282 }
283}
#define MAX_UNIT_ACTION_BAR_INDEX
Definition: CharmInfo.h:86
@ ACTION_BAR_INDEX_PET_SPELL_START
Definition: CharmInfo.h:81
@ ACTION_BAR_INDEX_PET_SPELL_END
Definition: CharmInfo.h:82
@ ACTION_BAR_INDEX_END
Definition: CharmInfo.h:83
@ ACTION_BAR_INDEX_START
Definition: CharmInfo.h:80
constexpr uint8 MAX_SPELL_CHARM
Definition: CharmInfo.h:28
const uint32 MAX_CREATURE_SPELLS
Definition: CreatureData.h:419
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ SPELL_ATTR5_NOT_AVAILABLE_WHILE_CHARMED
#define sSpellMgr
Definition: SpellMgr.h:849
@ REACT_PASSIVE
Definition: UnitDefines.h:506
ActiveStates
Definition: UnitDefines.h:495
@ ACT_REACTION
Definition: UnitDefines.h:500
@ ACT_DECIDE
Definition: UnitDefines.h:501
@ ACT_COMMAND
Definition: UnitDefines.h:499
@ ACT_ENABLED
Definition: UnitDefines.h:498
@ ACT_PASSIVE
Definition: UnitDefines.h:496
@ ACT_DISABLED
Definition: UnitDefines.h:497
@ COMMAND_ATTACK
Definition: UnitDefines.h:528
@ COMMAND_FOLLOW
Definition: UnitDefines.h:527
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition: Creature.h:302
Difficulty GetDifficultyID() const
Definition: Map.h:324
static Creature * ToCreature(Object *o)
Definition: Object.h:219
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
SpellInfo const * GetFirstRankSpell() const
Definition: SpellInfo.cpp:4272
bool IsAutocastable() const
Definition: SpellInfo.cpp:1597
uint32 const Id
Definition: SpellInfo.h:325
bool IsPassive() const
Definition: SpellInfo.cpp:1592
bool HasAttribute(SpellAttr0 attribute) const
Definition: SpellInfo.h:449
bool NeedsExplicitUnitTarget() const
Definition: SpellInfo.cpp:1551
Definition: Unit.h:627
void SetPetNumberForClient(uint32 petNumber)
Definition: Unit.h:1224
Map * GetMap() const
Definition: Object.h:624
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
void apply(T *val)
Definition: ByteConverter.h:41
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition: Util.cpp:56
void RestoreState()
Definition: CharmInfo.cpp:43
CharmInfo(Unit *unit)
Definition: CharmInfo.cpp:26
void LoadPetActionBar(const std::string &data)
Definition: CharmInfo.cpp:236
void SetActionBar(uint8 index, uint32 spellOrAction, ActiveStates type)
Definition: CharmInfo.h:112
bool AddSpellToActionBar(SpellInfo const *spellInfo, ActiveStates newstate=ACT_DECIDE, uint8 preferredSlot=0)
Definition: CharmInfo.cpp:166
void InitPossessCreateSpells()
Definition: CharmInfo.cpp:74
void SetPetNumber(uint32 petnumber, bool statwindow)
Definition: CharmInfo.cpp:227
void InitPetActionBar()
Definition: CharmInfo.cpp:49
UnitActionBarEntry PetActionBar[MAX_UNIT_ACTION_BAR_INDEX]
Definition: CharmInfo.h:139
void InitCharmCreateSpells()
Definition: CharmInfo.cpp:113
void BuildActionBar(WorldPacket *data)
Definition: CharmInfo.cpp:267
bool RemoveSpellFromActionBar(uint32 spell_id)
Definition: CharmInfo.cpp:198
void SetSpellAutocast(SpellInfo const *spellInfo, bool state)
Definition: CharmInfo.cpp:273
ReactStates _oldReactState
Definition: CharmInfo.h:145
void ToggleCreatureAutocast(SpellInfo const *spellInfo, bool apply)
Definition: CharmInfo.cpp:217
void InitEmptyActionBar(bool withAttack=true)
Definition: CharmInfo.cpp:64
Unit * _unit
Definition: CharmInfo.h:138
uint32 _petnumber
Definition: CharmInfo.h:142
CharmSpellInfo _charmspells[4]
Definition: CharmInfo.h:140
void SetActionAndType(uint32 action, ActiveStates type)
Definition: CharmInfo.h:52
bool IsActionBarForSpell() const
Definition: CharmInfo.h:46
void SetType(ActiveStates type)
Definition: CharmInfo.h:57
void SetAction(uint32 action)
Definition: CharmInfo.h:62
uint32 GetAction() const
Definition: CharmInfo.h:45