TrinityCore
Loading...
Searching...
No Matches
SpellPackets.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 "SpellPackets.h"
19#include "MovementPackets.h"
20#include "SharedDefines.h"
21#include "Spell.h"
22#include "SpellAuraDefines.h"
23#include "SpellInfo.h"
24#include <span>
25
27{
32
37
43
45{
47 if (Reason == 0 || Reason == 1)
49
50 return &_worldPacket;
51}
52
58
60{
61 _worldPacket << uint32(Spells.size());
62 for (uint32 spellId : Spells)
63 _worldPacket << uint32(spellId);
64
65 return &_worldPacket;
66}
67
69{
70 data << int32(auraData.SpellID);
71 data << uint8(auraData.Flags);
72 data << uint8(auraData.CastLevel);
73 data << uint8(auraData.Applications);
74 if (!(auraData.Flags & AFLAG_SELF_CAST))
75 data << auraData.CastUnit.WriteAsPacked();
76
77 if (auraData.Flags & AFLAG_DURATION)
78 {
79 data << int32(auraData.Duration);
80 data << int32(auraData.Remaining);
81 }
82
83 return data;
84}
85
87{
88 data << uint8(aura.Slot);
89
90 if (aura.AuraData)
91 data << *aura.AuraData;
92 else
93 data << int32(0); // SpellID
94
95 return data;
96}
97
99{
101 _worldPacket << Aura; // this packet can carry multiple auras, just like SMSG_AURA_UPDATE_ALL but we don't use this, skip putting it in a vector
102
103 return &_worldPacket;
104}
105
107{
109 for (AuraInfo const& aura : Auras)
110 _worldPacket << aura;
111
112 return &_worldPacket;
113}
114
116{
117 buffer >> location.Transport.ReadAsPacked();
118 buffer >> location.Location;
119
120 return buffer;
121}
122
124{
125 buffer >> targetData.Flags;
126
128 buffer >> targetData.Unit.emplace().ReadAsPacked();
129
131 buffer >> targetData.Item.emplace().ReadAsPacked();
132
134 buffer >> targetData.SrcLocation.emplace();
135
137 buffer >> targetData.DstLocation.emplace();
138
139 if (targetData.Flags & TARGET_FLAG_STRING)
140 {
141 std::array<char, 128>& name = targetData.Name.emplace();
142 buffer.read(reinterpret_cast<uint8*>(name.data()), name.size());
143 }
144
145 return buffer;
146}
147
149{
150 buffer >> trajectory.Pitch;
151 buffer >> trajectory.Speed;
152
153 if (buffer.read<uint8>()) // has movement update
154 {
155 MovementInfo& moveUpdate = trajectory.MoveUpdate.emplace();
156 buffer.read_skip<uint32>(); // opcode, always MSG_MOVE_STOP
157 buffer >> moveUpdate.guid.ReadAsPacked();
158 buffer >> moveUpdate;
159 }
160
161 return buffer;
162}
163
165{
166 buffer >> request.CastID;
167 buffer >> request.SpellID;
168 buffer >> request.SendCastFlags;
169
170 buffer >> request.Target;
171
172 if (request.SendCastFlags & 0x2)
173 buffer >> request.MissileTrajectory.emplace();
174
175 return buffer;
176}
177
179{
181}
182
184{
187}
188
190{
191 data << uint32(initialSpell.SpellID);
192 data << uint16(initialSpell.ActionBarSlot);
193
194 return data;
195}
196
198{
199 data << uint32(historyEntry.SpellID);
200 data << uint16(historyEntry.ItemID);
201 data << uint16(historyEntry.Category);
202
203 // send infinity cooldown in special format
204 if (historyEntry.OnHold)
205 {
206 data << uint32(1);
207 data << uint32(0x80000000);
208 }
209 else
210 {
211 data << int32(historyEntry.RecoveryTime);
212 data << int32(historyEntry.CategoryRecoveryTime);
213 }
214
215 return data;
216}
217
219{
221 _worldPacket << uint16(Spells.size());
222 for (InitialSpell const& spell : Spells)
223 _worldPacket << spell;
224
228
229 return &_worldPacket;
230}
231
233{
234 data << targetLocation.Transport.WriteAsPacked(); // relative position guid here - transport for example
235 data << targetLocation.Location;
236 return data;
237}
238
240{
241 data << uint32(spellTargetData.Flags);
242
243 if (spellTargetData.Unit)
244 data << spellTargetData.Unit->WriteAsPacked();
245
246 if (spellTargetData.Item)
247 data << spellTargetData.Item->WriteAsPacked();
248
249 if (spellTargetData.SrcLocation)
250 data << *spellTargetData.SrcLocation;
251
252 if (spellTargetData.DstLocation)
253 data << *spellTargetData.DstLocation;
254
255 if (spellTargetData.Name)
256 data.append(spellTargetData.Name->data(), spellTargetData.Name->size());
257
258 return data;
259}
260
262{
263 data << spellMissStatus.TargetGUID;
264 data << uint8(spellMissStatus.Reason);
266 data << uint8(spellMissStatus.ReflectStatus);
267
268 return data;
269}
270
272{
273 data << uint8(runeData.Start);
274 data << uint8(runeData.Count);
275 for (uint8 cooldown : runeData.Cooldowns)
276 data << uint8(cooldown);
277
278 return data;
279}
280
282{
283 data << float(traj.Pitch);
284 data << uint32(traj.TravelTime);
285 return data;
286}
287
289{
290 data << uint32(spellAmmo.DisplayID);
291 data << uint32(spellAmmo.InventoryType);
292 return data;
293}
294
296{
297 data << uint32(immunities.School);
298 data << uint32(immunities.Value);
299 return data;
300}
301
303{
304 data << spellCastData.CasterGUID.WriteAsPacked();
305 data << spellCastData.CasterUnit.WriteAsPacked();
306 data << uint8(spellCastData.CastID); // pending spell cast?
307 data << uint32(spellCastData.SpellID); // spellId
308 data << uint32(spellCastData.CastFlags); // cast flags
309 data << uint32(spellCastData.CastTime); // timestamp
310
311 if (spellCastData.HitTargets && spellCastData.MissStatus)
312 {
313 // Hit and miss target counts are both uint8, that limits us to 255 targets for each
314 // sending more than 255 targets crashes the client (since count sent would be wrong)
315 // Spells like 40647 (with a huge radius) can easily reach this limit (spell might need
316 // target conditions but we still need to limit the number of targets sent and keeping
317 // correct count for both hit and miss).
318 static constexpr std::size_t PACKET_TARGET_LIMIT = std::numeric_limits<uint8>::max();
319
320 std::span<ObjectGuid const> hitTargets(spellCastData.HitTargets->data(), std::min(spellCastData.HitTargets->size(), PACKET_TARGET_LIMIT));
321 data << uint8(hitTargets.size());
322 for (ObjectGuid const& target : hitTargets)
323 data << target;
324
325 std::span<SpellMissStatus const> missTargets(spellCastData.MissStatus->data(), std::min(spellCastData.MissStatus->size(), PACKET_TARGET_LIMIT));
326 data << uint8(missTargets.size());
327 for (SpellMissStatus const& status : missTargets)
328 data << status;
329 }
330
331 data << spellCastData.Target;
332
333 if (spellCastData.RemainingPower)
334 data << uint32(*spellCastData.RemainingPower);
335
336 if (spellCastData.RemainingRunes)
337 data << *spellCastData.RemainingRunes;
338
339 if (spellCastData.MissileTrajectory)
340 data << *spellCastData.MissileTrajectory;
341
342 if (spellCastData.Ammo)
343 data << *spellCastData.Ammo;
344
345 if (spellCastData.Immunities)
346 data << *spellCastData.Immunities;
347
349 {
350 data << uint32(0);
351 data << uint32(0);
352 }
353
354 if (spellCastData.DestLocSpellCastIndex)
355 data << uint8(*spellCastData.DestLocSpellCastIndex);
356
357 if (spellCastData.TargetPoints)
358 {
359 data << int32(spellCastData.TargetPoints->size());
360 for (TargetLocation const& targetPoint : *spellCastData.TargetPoints)
361 {
362 data << targetPoint.Location;
363 data << targetPoint.Transport;
364 }
365 }
366
367 return data;
368}
369
371{
373
374 return &_worldPacket;
375}
376
378{
380
381 return &_worldPacket;
382}
383
391
401
411
413{
417
418 if (FailedArg1 || FailedArg2)
419 _worldPacket << int32(FailedArg1.value_or(0));
420
421 if (FailedArg2)
423
424 return &_worldPacket;
425}
426
428{
432
433 if (FailedArg1 || FailedArg2)
434 _worldPacket << int32(FailedArg1.value_or(0));
435
436 if (FailedArg2)
438
439 return &_worldPacket;
440}
441
443{
444 data << uint8(spellModifier.ClassIndex);
445 data << uint8(spellModifier.ModIndex);
446 data << int32(spellModifier.ModifierValue);
447
448 return data;
449}
450
452{
454
455 return &_worldPacket;
456}
457
459{
461
462 return &_worldPacket;
463}
464
472
474{
477}
478
480{
482 for (ResyncRune const& rune : Runes)
483 {
484 _worldPacket << rune.RuneType;
485 _worldPacket << rune.Cooldown;
486 }
487
488 return &_worldPacket;
489}
490
492{
494
495 return &_worldPacket;
496}
497}
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
Spells
Definition PlayerAI.cpp:32
@ SPELL_MISS_REFLECT
@ AFLAG_SELF_CAST
@ AFLAG_DURATION
@ TARGET_FLAG_TRADE_ITEM
@ TARGET_FLAG_GAMEOBJECT
@ TARGET_FLAG_STRING
@ TARGET_FLAG_CORPSE_ALLY
@ TARGET_FLAG_ITEM
@ TARGET_FLAG_UNIT_MINIPET
@ TARGET_FLAG_DEST_LOCATION
@ TARGET_FLAG_SOURCE_LOCATION
@ TARGET_FLAG_UNIT
@ TARGET_FLAG_CORPSE_ENEMY
@ CAST_FLAG_VISUAL_CHAIN
Definition Spell.h:97
void read_skip()
Definition ByteBuffer.h:334
void append(T value)
Definition ByteBuffer.h:133
PackedGuidWriter WriteAsPacked() const
Definition ObjectGuid.h:152
size_type size() const
WorldPacket _worldPacket
Definition Packet.h:42
std::vector< AuraInfo > Auras
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::vector< InitialSpell > Spells
std::vector< SpellHistoryEntry > SpellHistory
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::vector< ResyncRune > Runes
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
std::array< uint32, NumActionButtons > ActionButtons
ByteBuffer & operator>>(ByteBuffer &buffer, TargetLocation &location)
ByteBuffer & operator<<(ByteBuffer &data, AuraDataInfo const &auraData)
Optional< AuraDataInfo > AuraData