Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
BattlePetPackets.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "BattlePetPackets.h"
7
8#include "BattlePet.h"
10#include "DB2Stores.h"
11
12#include <algorithm>
13#include <cmath>
14
16{
17 namespace
18 {
19 uint8 constexpr PetBattleEffectTargetStatChange = 0;
20 uint8 constexpr PetBattleEffectTargetState = 1;
21 uint8 constexpr PetBattleEffectTargetAbilityChange = 2;
22 uint8 constexpr PetBattleEffectTargetPet = 3;
23 uint8 constexpr PetBattleEffectTargetNone = 4;
24 uint8 constexpr PetBattleEffectTargetTriggerAbility = 5;
25 uint8 constexpr PetBattleEffectTargetNpcEmote = 6;
26 uint8 constexpr PetBattleEffectTargetAura = 7;
27 uint8 constexpr PetBattleEffectActivePet = 4;
28 uint8 constexpr PetBattleEffectCatch = 5;
29 uint16 constexpr PetBattleEffectFlagMiss = 0x0002;
30 uint8 constexpr PetBattleRoundResultNormal = 2;
31 uint8 constexpr PetBattleRoundResultCatchOrKill = 3;
32
33 void WriteRoundEffectBits(WorldPacket& data, BattlePetRoundEffect const& effect)
34 {
35 data.WriteBit(!effect.AbilityEffectID);
36 data.WriteBit(!effect.PetBattleEffectType);
37 data.WriteBits(effect.Targets.size(), 25);
38 data.WriteBit(1);
39
40 for (BattlePetRoundEffectTarget const& target : effect.Targets)
41 {
42 data.WriteBits(target.Type, 3);
43
44 if (target.Type == PetBattleEffectTargetStatChange)
45 data.WriteBit(!target.HasStatus);
46
47 if (target.Type == PetBattleEffectTargetAura)
48 {
49 data.WriteBit(1);
50 data.WriteBit(1);
51 data.WriteBit(1);
52 data.WriteBit(1);
53 }
54
55 if (target.Type == PetBattleEffectTargetNpcEmote)
56 data.WriteBit(1);
57
58 if (target.Type == PetBattleEffectTargetAbilityChange)
59 {
60 data.WriteBit(1);
61 data.WriteBit(1);
62 data.WriteBit(1);
63 }
64
65 if (target.Type == PetBattleEffectTargetTriggerAbility)
66 data.WriteBit(1);
67
68 if (target.Type == PetBattleEffectTargetState)
69 {
70 data.WriteBit(!target.HasStateValue);
71 data.WriteBit(!target.HasStateID);
72 }
73
74 data.WriteBit(target.PetX == -1);
75
76 if (target.Type == PetBattleEffectTargetPet)
77 data.WriteBit(!target.HasRemainingHealth);
78 }
79
80 data.WriteBit(effect.CasterPBOID == -1);
81 data.WriteBit(!effect.TurnInstanceID);
82 data.WriteBit(!effect.StackDepth);
83 data.WriteBit(!effect.Flags);
84 }
85
86 void WriteRoundEffectBytes(WorldPacket& data, BattlePetRoundEffect const& effect)
87 {
88 if (effect.Flags)
89 data << uint16(effect.Flags);
90
91 if (effect.AbilityEffectID)
92 data << uint32(effect.AbilityEffectID);
93
94 for (BattlePetRoundEffectTarget const& target : effect.Targets)
95 {
96 if (target.PetX != -1)
97 data << uint8(target.PetX);
98
99 if (target.Type == PetBattleEffectTargetStatChange && target.HasStatus)
100 data << uint32(target.Status);
101
102 if (target.Type == PetBattleEffectTargetState)
103 {
104 if (target.HasStateID)
105 data << uint32(target.StateID);
106
107 if (target.HasStateValue)
108 data << uint32(target.StateValue);
109 }
110
111 if (target.Type == PetBattleEffectTargetAbilityChange)
112 {
113 data << uint32(0);
114 data << uint32(0);
115 data << uint32(0);
116 }
117
118 if (target.Type == PetBattleEffectTargetPet && target.HasRemainingHealth)
119 data << int32(target.RemainingHealth);
120
121 if (target.Type == PetBattleEffectTargetTriggerAbility)
122 data << uint32(0);
123
124 if (target.Type == PetBattleEffectTargetNpcEmote)
125 data << uint32(0);
126 }
127
128 if (effect.PetBattleEffectType)
129 data << uint8(effect.PetBattleEffectType);
130
131 if (effect.TurnInstanceID)
132 data << uint16(effect.TurnInstanceID);
133
134 if (effect.CasterPBOID != -1)
135 data << uint8(effect.CasterPBOID);
136
137 if (effect.StackDepth)
138 data << uint8(effect.StackDepth);
139
140 }
141 }
142
144 {
146 data.Id = battlePet.GetId();
147 data.Level = battlePet.GetLevel();
148 data.Quality = battlePet.GetQuality();
149 data.Power = battlePet.GetPower();
150 data.MaxHealth = battlePet.GetMaxHealth();
151 data.Speed = battlePet.GetSpeed();
152 data.CurrentHealth = battlePet.GetCurrentHealth();
153 data.Xp = battlePet.GetXp();
154 data.Flags = battlePet.GetFlags();
155 data.Nickname = battlePet.GetNickname();
156 data.Species = battlePet.GetSpecies();
157 for (uint8 i = 0; i < 3; ++i)
158 data.Abilities[i] = BattlePetGetSpeciesAbility(data.Species, i, data.Flags, data.Level);
159
160 return data;
161 }
162
164 {
165 BattlePet battlePet(id, speciesId, level, quality, breed);
166 return BuildInitialUpdatePetData(battlePet);
167 }
168
170 {
171 BattlePetInput input;
172
173 input.HasAbilityID = !data.ReadBit();
174 input.HasNewFrontPet = !data.ReadBit();
175 input.HasDebugFlags = !data.ReadBit();
176 input.IgnoreAbandonPenalty = data.ReadBit();
177 input.HasBattleInterrupted = !data.ReadBit();
178 input.HasRoundID = !data.ReadBit();
179 input.HasMoveType = !data.ReadBit();
180
181 if (input.HasMoveType)
182 data >> input.MoveType;
183
184 if (input.HasDebugFlags)
185 data >> input.DebugFlags;
186
187 if (input.HasRoundID)
188 data >> input.RoundID;
189
190 if (input.HasBattleInterrupted)
191 data >> input.BattleInterrupted;
192
193 if (input.HasAbilityID)
194 data >> input.AbilityID;
195
196 if (input.HasNewFrontPet)
197 data >> input.NewFrontPet;
198
199 return input;
200 }
201
203 {
204 BattlePetInputCommand command;
205 command.HasRoundID = input.HasRoundID;
206 command.RoundID = input.RoundID;
207 command.AbilityID = input.AbilityID;
208 command.MoveType = input.MoveType;
209 command.NewFrontPet = input.NewFrontPet;
211 command.BattleInterrupted = input.BattleInterrupted;
212
213 if (!input.HasRoundID)
214 return command;
215
216 if (input.HasMoveType)
217 {
218 switch (input.MoveType)
219 {
221 if (input.HasAbilityID)
223 break;
225 if (input.HasNewFrontPet)
227 break;
230 break;
233 break;
234 default:
235 break;
236 }
237 }
238 else if (input.HasNewFrontPet)
240 else if (input.HasAbilityID)
242
245
246 return command;
247 }
248
250 {
252 data >> selection.PetID;
253 return selection;
254 }
255
257 {
259
260 if (data.rpos() + 2 > data.size())
261 return request;
262
263 data.ReadGuidMask(request.Guid, 6, 2, 3, 7, 0, 4);
264 request.Cancelled = data.ReadBit();
265 data.ReadGuidMask(request.Guid, 5, 1);
266
267 uint8 guidByteCount = 0;
268 for (uint8 i = 0; i < 8; ++i)
269 if (request.Guid[i])
270 ++guidByteCount;
271
272 if (data.rpos() + guidByteCount > data.size())
273 return BattlePetRequestUpdate();
274
275 data.ReadGuidBytes(request.Guid, 3, 5, 6, 7, 1, 0, 2, 4);
276
277 return request;
278 }
279
281 {
283 target.PetX = targetPet;
284 target.Type = PetBattleEffectTargetNone;
285
287 effect.CasterPBOID = casterPet;
288 effect.PetBattleEffectType = PetBattleEffectActivePet;
289 effect.Targets.push_back(target);
290
291 return effect;
292 }
293
294 BattlePetRoundEffect BuildDamageEffect(uint8 casterPet, uint8 targetPet, int32 remainingHealth,
295 uint32 abilityEffectId, uint16 turnInstanceId)
296 {
298 target.PetX = targetPet;
299 target.Type = PetBattleEffectTargetPet;
300 target.HasRemainingHealth = true;
301 target.RemainingHealth = remainingHealth;
302
304 effect.CasterPBOID = casterPet;
305 effect.TurnInstanceID = turnInstanceId;
306 effect.StackDepth = 1;
307 effect.AbilityEffectID = abilityEffectId;
308 effect.Targets.push_back(target);
309
310 return effect;
311 }
312
313 BattlePetRoundEffect BuildCatchEffect(uint8 casterPet, uint8 targetPet, uint32 abilityEffectId,
314 bool captured, uint16 turnInstanceId)
315 {
317 target.PetX = targetPet;
318 target.Type = PetBattleEffectTargetStatChange;
319 target.HasStatus = true;
320 target.Status = captured ? 1 : 0;
321
323 effect.CasterPBOID = casterPet;
324 effect.PetBattleEffectType = PetBattleEffectCatch;
325 effect.Flags = captured ? PetBattleEffectFlagMiss : 0;
326 effect.TurnInstanceID = turnInstanceId;
327 effect.StackDepth = 1;
328 effect.AbilityEffectID = abilityEffectId;
329 effect.Targets.push_back(target);
330
331 return effect;
332 }
333
334 void AppendDamageRoundEffect(BattlePetRoundResult& round, uint8 casterPet, uint8 targetPet,
335 int32 remainingHealth, uint32 abilityEffectId, bool targetDied)
336 {
337 round.Effects.push_back(BuildDamageEffect(casterPet, targetPet, remainingHealth, abilityEffectId));
338
339 if (targetDied)
340 round.DeadPets.push_back(targetPet);
341 }
342
344 int32 remainingHealth, uint32 abilityEffectId, bool targetDied)
345 {
347 round.RoundID = roundId;
348 AppendDamageRoundEffect(round, casterPet, targetPet, remainingHealth, abilityEffectId, targetDied);
349
350 return round;
351 }
352
354 {
356 round.RoundID = turn.RoundID;
357
358 if (!turn.Accepted || !turn.HasRoundResult)
359 return round;
360
361 AppendRoundCooldowns(round, turn);
362
363 switch (turn.EffectKind)
364 {
367 abilityEffectId, turn.TargetDied);
368
369 if (turn.RequiresFrontPet)
371 break;
373 round.Effects.push_back(BuildPetSwapEffect(turn.CasterPet, turn.TargetPet));
374 break;
375 default:
376 break;
377 }
378
379 return round;
380 }
381
383 {
384 for (ActivePetBattleCooldown const& source : turn.Cooldowns)
385 {
386 BattlePetRoundCooldown cooldown;
387 cooldown.AbilityID = source.AbilityID;
388 cooldown.Cooldown = source.Cooldown;
389 cooldown.Lockdown = source.Lockdown;
390 cooldown.AbilitySlot = source.AbilitySlot;
391 cooldown.PetPBOID = source.PetPBOID;
392 cooldown.HasPetPBOID = true;
393 round.Cooldowns.push_back(cooldown);
394 }
395 }
396
398 {
399 round.NextPetBattleState = PetBattleRoundResultCatchOrKill;
400 }
401
402 BattlePetFinalRound BuildFinalRoundState(bool allyWon, bool abandoned,
403 std::vector<BattlePetFinalRoundPet> const& pets)
404 {
405 BattlePetFinalRound finalRound;
406 finalRound.Winners[0] = allyWon;
407 finalRound.Winners[1] = !allyWon;
408 finalRound.Abandoned = abandoned;
409 finalRound.Pets = pets;
410
411 return finalRound;
412 }
413
414 BattlePetFinalRound BuildFinalRoundState(bool allyWon, bool abandoned,
415 BattlePetFinalRoundPet const& allyPet, BattlePetFinalRoundPet const& enemyPet)
416 {
417 std::vector<BattlePetFinalRoundPet> pets;
418 pets.push_back(allyPet);
419 pets.push_back(enemyPet);
420 return BuildFinalRoundState(allyWon, abandoned, pets);
421 }
422
424 uint8 teamCount, bool isPvP)
425 {
427
428 bool const hasWaitingForFrontPetsMaxSecs = true;
429 bool const hasPvPMaxRoundTime = true;
430 bool const hasForfeitPenalty = true;
431 bool const hasCreatureId = false;
432 bool const hasDisplayId = false;
433 ObjectGuid battlePetGuid = isPvP ? ObjectGuid(0) : wildBattlePetGuid;
434
435 for (uint8 i = 0; i < 3; i++)
436 {
437 data.WriteBits(0, 21);
438 data.WriteBits(0, 21);
439 }
440
441 for (uint8 i = 0; i < 2; i++)
442 {
443 InitialUpdateTeamData const* team = teams && i < teamCount ? &teams[i] : NULL;
444 uint8 const battlePetCount = team
445 ? std::min<uint8>(team->PetCount, INITIAL_UPDATE_MAX_TEAM_PETS)
446 : 0;
447 bool const hasRoundTimeSec = false;
448 bool const hasFrontPet = battlePetCount != 0;
449 bool const trapStatus = team && team->TrapStatus != 0;
450
451 ObjectGuid characterGuid = team ? team->OwnerGuid : 0;
452
453 data.WriteBit(!trapStatus);
454 data.WriteBits(battlePetCount, 2);
455 data.WriteBit(characterGuid[2]);
456
457 for (uint8 j = 0; j < battlePetCount; j++)
458 {
459 InitialUpdatePetData const& activePet = team->Pets[j];
460 ObjectGuid petEntry = activePet.Id;
461
462 data.WriteBits(0, 21);
463 data.WriteBit(petEntry[3]);
464 data.WriteBits(0, 21);
465
466 uint8 abilityCount = 0;
467 for (uint8 k = 0; k < 3; k++)
468 if (activePet.Abilities[k])
469 abilityCount++;
470
471 data.WriteBit(petEntry[0]);
472 data.WriteBit(!activePet.Flags);
473 data.WriteGuidMask(petEntry, 5, 1);
474
475 data.WriteBits(abilityCount, 20);
476 data.WriteBit(0);
477 data.WriteBits(activePet.Nickname.size(), 7);
478 data.WriteGuidMask(petEntry, 2, 4);
479
480 for (uint8 l = 0; l < 3; l++)
481 if (activePet.Abilities[l])
482 data.WriteBit(0);
483
484 data.WriteGuidMask(petEntry, 6, 7);
485 }
486
487 data.WriteBit(!hasFrontPet);
488 data.WriteBit(!hasRoundTimeSec);
489 data.WriteGuidMask(characterGuid, 5, 3, 4, 6, 7, 0, 1);
490 }
491
492 data.WriteBit(!hasForfeitPenalty);
493
494 data.WriteBit(0);
495 data.WriteBit(isPvP);
496
497 data.WriteBit(!hasDisplayId);
498 data.WriteBit(!hasCreatureId);
499 data.WriteBit(!hasWaitingForFrontPetsMaxSecs);
500 data.WriteBit(uint64(battlePetGuid) == 0);
501
502 data.WriteGuidMask(battlePetGuid, 2, 4, 5, 1, 3, 6, 7, 0);
503
504 data.WriteBit(!hasPvPMaxRoundTime);
505 data.WriteBit(0);
506
507 data.FlushBits();
508
509 for (uint8 i = 0; i < 2; i++)
510 {
511 InitialUpdateTeamData const* team = teams && i < teamCount ? &teams[i] : NULL;
512 uint8 const battlePetCount = team ? std::min<uint8>(team->PetCount, INITIAL_UPDATE_MAX_TEAM_PETS) : 0;
513 ObjectGuid characterGuid = team ? team->OwnerGuid : 0;
514
515 bool const hasRoundTimeSec = false;
516 bool const hasFrontPet = battlePetCount != 0;
517 bool const trapStatus = team && team->TrapStatus != 0;
518
519 uint8 battlePetTeamIndex = 0;
520 for (uint8 j = 0; j < battlePetCount; j++)
521 {
522 data << battlePetTeamIndex;
523 battlePetTeamIndex++;
524
525 InitialUpdatePetData const& activePet = team->Pets[j];
526 ObjectGuid petEntry = activePet.Id;
527 uint8 const petBattleObjectId = i == 0 ? j : uint8(3 + j);
528
529 for (uint8 k = 0; k < 3; k++)
530 {
531 if (!activePet.Abilities[k])
532 continue;
533
534 data << uint32(activePet.Abilities[k]);
535 data << uint8(k);
536 data << uint8(petBattleObjectId);
537 data << uint16(0);
538 data << uint16(0);
539 }
540
541 data << uint32(0);
542 data.WriteByteSeq(petEntry[4]);
543 data << uint16(activePet.Level);
544 data.WriteByteSeq(petEntry[7]);
545 data << uint16(activePet.Quality);
546 data.WriteByteSeq(petEntry[6]);
547 data << uint32(activePet.Power);
548 data.WriteByteSeq(petEntry[0]);
549 data << uint32(activePet.MaxHealth);
550 data.WriteByteSeq(petEntry[5]);
551 data.WriteByteSeq(petEntry[2]);
552 data << uint32(activePet.Speed);
553 data << uint32(activePet.CurrentHealth);
554 data.WriteByteSeq(petEntry[3]);
555 data << uint32(0);
556 data.WriteByteSeq(petEntry[1]);
557 data << uint32(0);
558 data << uint16(activePet.Xp);
559 if (activePet.Flags)
560 data << uint16(activePet.Flags);
561
562 data.WriteString(activePet.Nickname);
563 data << uint32(activePet.Species);
564 }
565
566 if (trapStatus)
567 data << uint32(team->TrapStatus);
568
569 data << uint32(team ? team->TrapAbility : 0);
570 data.WriteGuidBytes(characterGuid, 5, 7, 6, 1, 4, 0);
571
572 if (hasFrontPet)
573 data << uint8(team ? team->FrontPet : 0);
574
575 data << uint8(6);
576
577 if (hasRoundTimeSec)
578 data << uint16(0);
579
580 data.WriteGuidBytes(characterGuid, 3, 2);
581 }
582
583 if (hasForfeitPenalty)
584 data << uint8(10);
585
586 data << uint8(1);
587
588 data.WriteGuidBytes(battlePetGuid, 5, 4, 3, 2, 7, 0, 1, 6);
589
590 if (hasDisplayId)
591 data << uint32(0);
592
593 if (hasPvPMaxRoundTime)
594 data << uint16(30);
595
596 data << uint32(0);
597
598 if (hasWaitingForFrontPetsMaxSecs)
599 data << uint16(30);
600
601 if (hasCreatureId)
602 data << uint32(0);
603
604 return data;
605 }
606
608 uint8 teamPetCount, bool isPvP)
609 {
610 InitialUpdateTeamData teams[2];
611 for (uint8 i = 0; teamPets && i < 2 && i < teamPetCount; i++)
612 {
613 teams[i].Pets[0] = teamPets[i];
614 teams[i].PetCount = 1;
615 }
616
617 return BuildInitialUpdatePacket(wildBattlePetGuid, teams, 2, isPvP);
618 }
619
621 bool isPvP)
622 {
623 InitialUpdatePetData teamPets[2] = { activePet, activePet };
624 return BuildInitialUpdatePacket(wildBattlePetGuid, teamPets, 2, isPvP);
625 }
626
627 WorldPacket BuildFirstRoundPacket(uint32 roundId, uint8 allyFrontPet, uint8 enemyFrontPet,
628 uint8 allyTrapStatus, uint8 enemyTrapStatus)
629 {
630 uint8 const frontPets[2] = { allyFrontPet, enemyFrontPet };
631 uint8 const trapStatuses[2] = { allyTrapStatus, enemyTrapStatus };
632
634 for (uint8 i = 0; i < 2; ++i)
635 {
636 data << uint16(0); // RoundTimeSecs
637 data << uint8(trapStatuses[i]); // NextTrapStatus
638 data << uint8(0); // NextInputFlags
639 }
640
641 data << uint32(roundId);
642
643 data.WriteBit(0); // has NextPetBattleState
644 data.WriteBits(0, 3); // PetX died count
645 data.WriteBits(0, 20); // Cooldown count
646 data.WriteBits(2, 22); // Front pet effects
647
648 for (uint8 i = 0; i < 2; ++i)
649 {
650 data.WriteBit(1); // no SourceAuraInstanceID
651 data.WriteBit(1); // no AbilityEffectID
652 data.WriteBit(1); // no TurnInstanceID
653 data.WriteBit(1); // no StackDepth
654 data.WriteBit(0); // has CasterPBOID
655 data.WriteBits(1, 25); // Target count
656 data.WriteBit(0); // has target PetX
657 data.WriteBits(PetBattleEffectTargetNone, 3);
658 data.WriteBit(1); // no Flags
659 data.WriteBit(0); // has PetBattleEffectType
660 }
661
662 data.FlushBits();
663
664 for (uint8 i = 0; i < 2; ++i)
665 {
666 data << uint8(frontPets[i]); // CasterPBOID
667 data << uint8(frontPets[i]); // Target PetX
668 data << uint8(PetBattleEffectActivePet);
669 }
670
671 data << uint8(PetBattleRoundResultNormal);
672 return data;
673 }
674
679
680 float CalculateBattlePetFacing(G3D::Vector3 const& origin, G3D::Vector3 const* positions)
681 {
682 float const centerX = (positions[0].x + positions[1].x) * 0.5f;
683 float const centerY = (positions[0].y + positions[1].y) * 0.5f;
684 float facing = std::atan2(centerY - origin.y, centerX - origin.x);
685 if (facing < 0.0f)
686 facing += 6.28318530717958647692f;
687
688 return facing;
689 }
690
691 float ResolveBattlePetFacing(bool hasClientOrientation, float clientOrientation,
692 G3D::Vector3 const& origin, G3D::Vector3 const* positions)
693 {
694 if (hasClientOrientation)
695 return clientOrientation;
696
697 return CalculateBattlePetFacing(origin, positions);
698 }
699
701 {
703
704 for (uint8 i = 0; i < 2; ++i)
705 {
706 data << uint8(round.TrapStatus[i]);
707 data << uint8(round.InputFlags[i]);
708 data << uint16(0); // round time seconds
709 }
710
711 data << uint32(round.RoundID);
712 data.WriteBits(round.Effects.size(), 22);
713
714 for (BattlePetRoundEffect const& effect : round.Effects)
715 WriteRoundEffectBits(data, effect);
716
717 data.WriteBit(!round.NextPetBattleState);
718 data.WriteBits(round.DeadPets.size(), 3);
719 data.WriteBits(round.Cooldowns.size(), 20);
720
721 for (BattlePetRoundCooldown const& cooldown : round.Cooldowns)
722 data.WriteBit(!cooldown.HasPetPBOID);
723
724 data.FlushBits();
725
726 for (BattlePetRoundCooldown const& cooldown : round.Cooldowns)
727 {
728 data << uint16(cooldown.Cooldown);
729 data << uint16(cooldown.Lockdown);
730 data << uint32(cooldown.AbilityID);
731 data << uint8(cooldown.AbilitySlot);
732
733 if (cooldown.HasPetPBOID)
734 data << uint8(cooldown.PetPBOID);
735 }
736
737 for (BattlePetRoundEffect const& effect : round.Effects)
738 WriteRoundEffectBytes(data, effect);
739
740 if (round.NextPetBattleState)
741 data << uint8(round.NextPetBattleState);
742
743 return data;
744 }
745
747 {
749
750 data.WriteBit(finalRound.PvPBattle);
751 data.WriteBit(finalRound.Winners[0]);
752 data.WriteBit(finalRound.Winners[1]);
753 data.WriteBits(finalRound.Pets.size(), 20);
754
755 for (BattlePetFinalRoundPet const& pet : finalRound.Pets)
756 {
757 data.WriteBit(0); // has new level
758 data.WriteBit(pet.Caged);
759 data.WriteBit(pet.SeenAction);
760 data.WriteBit(0); // has xp
761 data.WriteBit(pet.Captured);
762 data.WriteBit(0); // has initial level
763 data.WriteBit(pet.AwardedXP);
764 }
765
766 data.WriteBit(1); // abandoned/result ack
767
768 for (BattlePetFinalRoundPet const& pet : finalRound.Pets)
769 {
770 data << uint32(pet.RemainingHealth);
771 data << uint16(pet.InitialLevel);
772 data << uint16(pet.Xp);
773 data << uint8(pet.Pboid);
774 data << uint16(pet.NewLevel);
775 data << uint32(pet.MaxHealth);
776 }
777
778 for (uint8 i = 0; i < 2; ++i)
779 data << uint32(finalRound.NpcCreatureID[i]);
780
781 return data;
782 }
783
784 WorldPacket BuildFinalizeLocationPacket(G3D::Vector3 const& origin, G3D::Vector3 const* positions,
785 bool hasOrientation, float orientation, bool hasLocationResult, uint32 locationResult)
786 {
788 data << origin.x;
789 data << origin.y;
790
791 for (uint8 i = 0; i < 2; i++)
792 {
793 data << positions[i].y;
794 data << positions[i].x;
795 data << positions[i].z;
796 }
797
798 data << origin.z;
799
800 data.WriteBit(!hasOrientation);
801 data.WriteBit(!hasLocationResult);
802
803 if (hasLocationResult)
804 data << uint32(locationResult);
805
806 if (hasOrientation)
807 data << float(orientation);
808
809 return data;
810 }
811
812 WorldPacket BuildPvpChallengePacket(ObjectGuid challengerGuid, G3D::Vector3 const& origin, G3D::Vector3 const* positions,
813 bool hasOrientation, float orientation, bool hasLocationResult, uint32 locationResult)
814 {
816
817 data.WriteGuidMask(challengerGuid, 4);
818 data.WriteBit(!hasOrientation);
819 data.WriteGuidMask(challengerGuid, 2, 5, 7, 3, 6, 0, 1);
820 data.WriteBit(!hasLocationResult);
821 data.FlushBits();
822
823 if (hasOrientation)
824 data << float(orientation);
825
826 data.WriteGuidBytes(challengerGuid, 1);
827 data << origin.x;
828 data.WriteGuidBytes(challengerGuid, 0, 5);
829 data << origin.y;
830
831 if (hasLocationResult)
832 data << uint32(locationResult);
833
834 data.WriteGuidBytes(challengerGuid, 2);
835
836 for (uint8 i = 0; i < 2; ++i)
837 {
838 data << positions[i].y;
839 data << positions[i].x;
840 data << positions[i].z;
841 }
842
843 data << origin.z;
844 data.WriteGuidBytes(challengerGuid, 7, 3, 4, 6);
845
846 return data;
847 }
848
849 WorldPacket BuildQueueStatusPacket(ObjectGuid requesterGuid, uint32 status, uint32 const* slotResults)
850 {
851 WorldPacket data(SMSG_PET_BATTLE_QUEUE_STATUS, 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 8 + 1);
852
853 data.WriteGuidMask(requesterGuid, 7, 2, 6, 1);
854 data.WriteBit(0); // hasAverageWaitTime
855 data.WriteGuidMask(requesterGuid, 4);
856 data.WriteBits(0, 22);
857 data.WriteGuidMask(requesterGuid, 0);
858 data.WriteBit(0); // hasClientWaitTime
859 data.WriteGuidMask(requesterGuid, 3, 5);
860
861 data.FlushBits();
862 data.WriteGuidBytes(requesterGuid, 2, 4);
863 data << uint32(0); // CliRideTicket.Time
864 data.WriteGuidBytes(requesterGuid, 3);
865 data << uint32(status);
866 data.WriteGuidBytes(requesterGuid, 6);
867 data.WriteGuidBytes(requesterGuid, 1);
868 data << uint32(0); // CliRideTicket.Type
869 data.WriteGuidBytes(requesterGuid, 5, 7);
870 data << uint32(0); // CliRideTicket.Id
871 data.WriteGuidBytes(requesterGuid, 0);
872
873 for (uint8 i = 0; i < PET_BATTLE_QUEUE_SLOT_COUNT; i++)
874 data << uint32(slotResults ? slotResults[i] : PET_BATTLE_QUEUE_STATUS_QUEUED);
875
876 return data;
877 }
878
883
885 {
887 data.WriteBit(0);
888 data.FlushBits();
889 data << uint8(reason);
890
891 return data;
892 }
893}
@ ACTIVE_PET_BATTLE_TURN_EFFECT_DAMAGE
@ ACTIVE_PET_BATTLE_TURN_EFFECT_SWAP
uint32 BattlePetGetSpeciesAbility(uint16 speciesId, uint8 abilitySlot, uint16 flags, uint8 level)
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::uint16_t uint16
Definition Define.h:78
uint16 GetXp() const
Definition BattlePet.h:220
uint16 GetSpeed() const
Definition BattlePet.h:224
uint8 GetLevel() const
Definition BattlePet.h:219
uint8 GetQuality() const
Definition BattlePet.h:225
uint64 GetId() const
Definition BattlePet.h:215
uint16 GetCurrentHealth() const
Definition BattlePet.h:221
uint16 GetSpecies() const
Definition BattlePet.h:216
uint16 GetMaxHealth() const
Definition BattlePet.h:222
uint16 GetPower() const
Definition BattlePet.h:223
std::string GetNickname() const
Definition BattlePet.h:217
uint16 GetFlags() const
Definition BattlePet.h:237
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
size_t rpos() const
Definition ByteBuffer.h:470
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
void WriteString(std::string const &str)
Definition ByteBuffer.h:578
void ReadGuidBytes(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:256
void ReadGuidMask(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:240
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
size_t size() const
Definition ByteBuffer.h:609
void WriteByteSeq(uint8 b)
Definition ByteBuffer.h:227
void FlushBits()
Definition ByteBuffer.h:154
bool ReadBit()
Definition ByteBuffer.h:180
@ SMSG_PET_BATTLE_FIRST_ROUND
Definition Opcodes.h:859
@ SMSG_PET_BATTLE_ROUND_RESULT
Definition Opcodes.h:866
@ SMSG_PET_BATTLE_PVP_CHALLENGE
Definition Opcodes.h:862
@ SMSG_PET_BATTLE_INITIAL_UPDATE
Definition Opcodes.h:860
@ SMSG_PET_BATTLE_QUEUE_PROPOSE_MATCH
Definition Opcodes.h:863
@ SMSG_PET_BATTLE_FINALIZE_LOCATION
Definition Opcodes.h:856
@ SMSG_PET_BATTLE_REQUEST_FAILED
Definition Opcodes.h:865
@ SMSG_PET_BATTLE_QUEUE_STATUS
Definition Opcodes.h:864
@ SMSG_PET_BATTLE_FINAL_ROUND
Definition Opcodes.h:857
@ SMSG_PET_BATTLE_FINISHED
Definition Opcodes.h:858
BattlePetRoundEffect BuildPetSwapEffect(uint8 casterPet, uint8 targetPet)
WorldPacket BuildQueueStatusPacket(ObjectGuid requesterGuid, uint32 status, uint32 const *slotResults)
WorldPacket BuildRequestFailedPacket(uint8 reason)
BattlePetInput ReadBattlePetInput(WorldPacket &data)
InitialUpdatePetData BuildInitialUpdatePetData(BattlePet const &battlePet)
BattlePetRoundResult BuildRoundResultFromTurn(ActivePetBattleTurn const &turn, uint32 abilityEffectId)
BattlePetFirstPetSelection ReadBattlePetFirstPetSelection(WorldPacket &data)
void AppendDamageRoundEffect(BattlePetRoundResult &round, uint8 casterPet, uint8 targetPet, int32 remainingHealth, uint32 abilityEffectId, bool targetDied)
BattlePetInputCommand BuildBattlePetInputCommand(BattlePetInput const &input)
WorldPacket BuildFinalizeLocationPacket(G3D::Vector3 const &origin, G3D::Vector3 const *positions, bool hasOrientation, float orientation, bool hasLocationResult, uint32 locationResult)
BattlePetRequestUpdate ReadBattlePetRequestUpdate(WorldPacket &data)
WorldPacket BuildInitialUpdatePacket(ObjectGuid wildBattlePetGuid, InitialUpdateTeamData const *teams, uint8 teamCount, bool isPvP)
BattlePetRoundEffect BuildCatchEffect(uint8 casterPet, uint8 targetPet, uint32 abilityEffectId, bool captured, uint16 turnInstanceId)
WorldPacket BuildFinalRoundPacket(BattlePetFinalRound const &finalRound)
WorldPacket BuildPvpChallengePacket(ObjectGuid challengerGuid, G3D::Vector3 const &origin, G3D::Vector3 const *positions, bool hasOrientation, float orientation, bool hasLocationResult, uint32 locationResult)
WorldPacket BuildFirstRoundPacket(uint32 roundId, uint8 allyFrontPet, uint8 enemyFrontPet, uint8 allyTrapStatus, uint8 enemyTrapStatus)
InitialUpdatePetData BuildWildInitialUpdatePetData(uint64 id, uint16 speciesId, uint8 level, uint8 quality, uint8 breed)
BattlePetRoundEffect BuildDamageEffect(uint8 casterPet, uint8 targetPet, int32 remainingHealth, uint32 abilityEffectId, uint16 turnInstanceId)
WorldPacket BuildRoundResultPacket(BattlePetRoundResult const &round)
void AppendRoundCooldowns(BattlePetRoundResult &round, ActivePetBattleTurn const &turn)
float CalculateBattlePetFacing(G3D::Vector3 const &origin, G3D::Vector3 const *positions)
uint8 const INITIAL_UPDATE_MAX_TEAM_PETS
WorldPacket BuildQueueProposeMatchPacket()
BattlePetRoundResult BuildDamageRoundResult(uint32 roundId, uint8 casterPet, uint8 targetPet, int32 remainingHealth, uint32 abilityEffectId, bool targetDied)
BattlePetFinalRound BuildFinalRoundState(bool allyWon, bool abandoned, std::vector< BattlePetFinalRoundPet > const &pets)
void MarkRoundResultAsCatchOrKill(BattlePetRoundResult &round)
float ResolveBattlePetFacing(bool hasClientOrientation, float clientOrientation, G3D::Vector3 const &origin, G3D::Vector3 const *positions)
std::vector< ActivePetBattleCooldown > Cooldowns
std::vector< BattlePetFinalRoundPet > Pets
std::vector< BattlePetRoundEffectTarget > Targets
std::vector< BattlePetRoundCooldown > Cooldowns
std::vector< BattlePetRoundEffect > Effects
InitialUpdatePetData Pets[INITIAL_UPDATE_MAX_TEAM_PETS]