Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
BattlePetHandler.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 "BattlePet.h"
7#include "BattlePetMgr.h"
8#include "BattlePetPackets.h"
9#include "BattlePetPvpState.h"
10#include "Common.h"
11#include "Creature.h"
12#include "DB2Enums.h"
13#include "DB2Stores.h"
14#include "Item.h"
15#include "Log.h"
16#include "ObjectAccessor.h"
17#include "ObjectMgr.h"
18#include "Player.h"
19#include "TemporarySummon.h"
20#include "WorldPacket.h"
21#include "WorldSession.h"
22
23#include <cmath>
24#include <ctime>
25
26namespace
27{
28 uint32 const PetBattlePvpProposalTimeout = 60;
29 uint32 const PetBattlePvpChallengeTimeout = 60;
31
32 bool ValidatePetBattleQueueRequest(Player& player);
33 bool ValidatePetBattlePvpDuelTarget(Player& challenger, Player* target);
34
35 void SendPetBattleDuelPopup(Player& challenger, Player& target)
36 {
37 ObjectGuid arbiterGuid = challenger.GetGUID();
38 ObjectGuid casterGuid = challenger.GetGUID();
39
41 data.WriteGuidMask(arbiterGuid, 5);
42 data.WriteGuidMask(casterGuid, 4, 2, 7);
43 data.WriteGuidMask(arbiterGuid, 0);
44 data.WriteGuidMask(casterGuid, 5);
45 data.WriteGuidMask(arbiterGuid, 4, 6);
46 data.WriteGuidMask(casterGuid, 1, 3, 6);
47 data.WriteGuidMask(arbiterGuid, 7, 3, 2, 1);
48 data.WriteGuidMask(casterGuid, 0);
49
50 data.WriteGuidBytes(arbiterGuid, 5, 3);
51 data.WriteGuidBytes(casterGuid, 7, 4);
52 data.WriteGuidBytes(arbiterGuid, 7);
53 data.WriteGuidBytes(casterGuid, 3, 6, 0);
54 data.WriteGuidBytes(arbiterGuid, 4);
55 data.WriteGuidBytes(casterGuid, 2, 1);
56 data.WriteGuidBytes(arbiterGuid, 0, 2, 6, 1);
57 data.WriteGuidBytes(casterGuid, 5);
58
59 target.SendDirectMessage(&data);
60 }
61
62 bool BuildWildInitialUpdatePetData(Creature const& wildBattlePet,
64 {
65 uint16 const speciesId = BattlePetSpeciesIdByNpcId(wildBattlePet.GetEntry());
66 if (!speciesId)
67 return false;
68
69 wildPetBreed = sObjectMgr->BattlePetGetRandomBreed(speciesId);
71 uint64(wildBattlePet.GetGUID()), speciesId, BattlePetNormalizeWildLevel(wildBattlePet.getLevel()),
72 sObjectMgr->BattlePetGetRandomQuality(speciesId), wildPetBreed);
73 return true;
74 }
75
76 uint32 BattlePetInputDamageForEnemyAbility(uint32 abilityId, ActivePetBattle const& activeBattle)
77 {
78 if (!abilityId)
79 return 0;
80
81 uint16 const power = BattlePetPowerFromBattleState(activeBattle.EnemySpecies,
82 activeBattle.EnemyLevel, activeBattle.EnemyQuality, activeBattle.EnemyBreed);
83 return BattlePetDamageFromStats(abilityId, power, activeBattle.EnemyLevel);
84 }
85
86 uint32 BattlePetInputIncomingDamageReductionForEnemyAbility(uint32 abilityId, ActivePetBattle const& activeBattle)
87 {
88 if (!abilityId)
89 return 0;
90
91 uint16 const power = BattlePetPowerFromBattleState(activeBattle.EnemySpecies,
92 activeBattle.EnemyLevel, activeBattle.EnemyQuality, activeBattle.EnemyBreed);
93 return BattlePetIncomingDamageReductionFromStats(abilityId, power, activeBattle.EnemyLevel);
94 }
95
96 BattlePet const* GetActiveBattlePet(BattlePetMgr const& battlePetMgr)
97 {
98 ActivePetBattle const& activeBattle = battlePetMgr.GetActivePetBattle();
99 return battlePetMgr.GetBattlePet(activeBattle.AllyPetID);
100 }
101
102 BattlePet const* GetPvpOpponentActiveBattlePet(Player const& player, ActivePetBattle const& activeBattle)
103 {
104 if (!activeBattle.IsPvP())
105 return NULL;
106
107 Player* opponent = ObjectAccessor::FindPlayer(activeBattle.EnemyGUID);
108 if (!opponent)
109 return NULL;
110
111 BattlePetMgr* opponentBattlePetMgr = opponent->GetBattlePetMgr();
112 if (!opponentBattlePetMgr || !opponentBattlePetMgr->HasActivePetBattle())
113 return NULL;
114
115 ActivePetBattle const& opponentBattle = opponentBattlePetMgr->GetActivePetBattle();
116 if (!opponentBattle.IsPvP() || opponentBattle.EnemyGUID != player.GetGUID())
117 return NULL;
118
119 return GetActiveBattlePet(*opponentBattlePetMgr);
120 }
121
122 uint8 BattlePetActiveAbilitySlot(BattlePet const* battlePet, uint32 abilityId)
123 {
124 if (!battlePet || !abilityId)
126
127 for (uint8 slot = 0; slot < BATTLE_PET_ABILITY_SLOT_COUNT; ++slot)
128 if (BattlePetGetSpeciesAbility(battlePet->GetSpecies(), slot, battlePet->GetFlags(), battlePet->GetLevel()) == abilityId)
129 return slot;
130
132 }
133
134 void SendBattlePetRoundResult(Player& player, Skyfire::BattlePetPackets::BattlePetRoundResult const& round)
135 {
137 player.SendDirectMessage(&packet);
138 }
139
140 void SendBattlePetFinalRound(Player& player, Skyfire::BattlePetPackets::BattlePetFinalRound const& finalRound)
141 {
143 player.SendDirectMessage(&finalRoundPacket);
144 }
145
146 void SendBattlePetFinished(Player& player)
147 {
149 player.SendDirectMessage(&finishedPacket);
150 }
151
152 void ClearActivePetBattleAndSave(Player& player)
153 {
154 BattlePetMgr* battlePetMgr = player.GetBattlePetMgr();
155 battlePetMgr->ClearActivePetBattle();
156 battlePetMgr->SaveToDb();
157 }
158
159 uint8 OpponentWinnerForFinalRound(Skyfire::BattlePetPackets::BattlePetFinalRound const& finalRound)
160 {
161 if (finalRound.Winners[0])
163
164 if (finalRound.Winners[1])
166
168 }
169
170 void FinishActivePvpPetBattleForOpponent(Player& player, uint64 opponentGuid, uint8 opponentWinner, bool abandoned)
171 {
172 if (!opponentGuid)
173 return;
174
175 Player* opponent = ObjectAccessor::FindPlayer(opponentGuid);
176 if (!opponent)
177 return;
178
179 BattlePetMgr* opponentBattlePetMgr = opponent->GetBattlePetMgr();
180 if (!opponentBattlePetMgr->HasActivePetBattle())
181 return;
182
183 ActivePetBattle const& opponentBattle = opponentBattlePetMgr->GetActivePetBattle();
184 if (!opponentBattle.IsPvP() || opponentBattle.EnemyGUID != player.GetGUID())
185 return;
186
187 if (opponentWinner)
188 opponentBattlePetMgr->FinishActivePetBattle(opponentWinner);
189
191 if (opponentBattlePetMgr->BuildActivePetBattleFinalRound(abandoned, opponentFinalRound))
192 SendBattlePetFinalRound(*opponent, opponentFinalRound);
193
194 ClearActivePetBattleAndSave(*opponent);
195 }
196
197 void FinishActivePvpPetBattle(Player& player, uint64 opponentGuid,
199 uint8 opponentWinner, bool opponentAbandoned)
200 {
201 SendBattlePetFinalRound(player, playerFinalRound);
202 FinishActivePvpPetBattleForOpponent(player, opponentGuid, opponentWinner, opponentAbandoned);
203 ClearActivePetBattleAndSave(player);
204 }
205
206 void FinishActivePvpPetBattleAfterForfeit(Player& loser, uint64 opponentGuid,
208 {
209 FinishActivePvpPetBattle(loser, opponentGuid, loserFinalRound, PET_BATTLE_WINNER_ALLY, true);
210 }
211
212 uint32 PetBattleQueueSlotResult(Player& player, uint8 slot)
213 {
214 BattlePetMgr* battlePetMgr = player.GetBattlePetMgr();
215 if (!battlePetMgr->HasLoadoutSlot(slot))
217
218 uint64 const petId = battlePetMgr->GetLoadoutSlot(slot);
219 if (!petId)
221
222 BattlePet* battlePet = battlePetMgr->GetBattlePet(petId);
223 if (!battlePet)
225
226 if (!battlePet->GetSpecies())
228
229 if (!battlePet->GetCurrentHealth())
231
233 }
234
235 void BuildPetBattleQueueSlotResults(Player& player,
237 {
239 slotResults[slot] = PetBattleQueueSlotResult(player, slot);
240 }
241
242 void SendPetBattleQueueStatus(WorldSession& session, Player& player, uint32 status)
243 {
245 BuildPetBattleQueueSlotResults(player, slotResults);
246
247 WorldPacket data = Skyfire::BattlePetPackets::BuildQueueStatusPacket(player.GetGUID(), status, slotResults);
248 session.SendPacket(&data);
249 }
250
251 void SendPetBattleQueueStatus(Player& player, uint32 status)
252 {
253 if (WorldSession* session = player.GetSession())
254 SendPetBattleQueueStatus(*session, player, status);
255 }
256
257 void SendPetBattleQueueProposeMatch(Player& player)
258 {
259 if (WorldSession* session = player.GetSession())
260 {
262 session->SendPacket(&data);
263 }
264 }
265
266 void SendPetBattlePvpChallengeFailed(uint64 playerGuid)
267 {
268 if (Player* player = ObjectAccessor::FindPlayer(playerGuid))
270 }
271
272 bool IsPetBattlePvpChallengeExpired(PetBattlePvpChallenge const& challenge)
273 {
274 return challenge.CreatedAt && time(NULL) - challenge.CreatedAt >= PetBattlePvpChallengeTimeout;
275 }
276
277 void ClearPetBattlePvpChallengeForTarget(uint64 targetGuid, bool notifyPlayers = false,
278 uint64 exceptGuid = 0)
279 {
280 PetBattlePvpStateStore::ChallengeMap::iterator challengeItr =
281 PetBattlePvpState.ChallengesByTarget().find(targetGuid);
282 if (challengeItr == PetBattlePvpState.ChallengesByTarget().end())
283 return;
284
285 PetBattlePvpChallenge const challenge = challengeItr->second;
286 PetBattlePvpState.EraseChallengeForTarget(targetGuid);
287
288 if (!notifyPlayers)
289 return;
290
291 if (challenge.ChallengerGuid != exceptGuid)
292 SendPetBattlePvpChallengeFailed(challenge.ChallengerGuid);
293
294 if (challenge.TargetGuid != exceptGuid)
295 SendPetBattlePvpChallengeFailed(challenge.TargetGuid);
296 }
297
298 void ClearPetBattlePvpChallengesFor(uint64 playerGuid, bool notifyPlayers = false,
299 uint64 exceptGuid = 0)
300 {
301 ClearPetBattlePvpChallengeForTarget(playerGuid, notifyPlayers, exceptGuid);
302
303 PetBattlePvpStateStore::ChallengeTargetMap::iterator targetItr =
304 PetBattlePvpState.ChallengeTargetByChallenger().find(playerGuid);
305 if (targetItr == PetBattlePvpState.ChallengeTargetByChallenger().end())
306 return;
307
308 ClearPetBattlePvpChallengeForTarget(targetItr->second, notifyPlayers, exceptGuid);
309 }
310
311 PetBattlePvpStateStore::ChallengeMap::iterator FindPetBattlePvpChallengeForPlayer(uint64 playerGuid)
312 {
313 return PetBattlePvpState.FindChallengeForPlayer(playerGuid);
314 }
315
316 bool ExpirePetBattlePvpChallenge(Player& player)
317 {
318 PetBattlePvpStateStore::ChallengeMap::iterator challengeItr =
319 FindPetBattlePvpChallengeForPlayer(player.GetGUID());
320 if (challengeItr == PetBattlePvpState.ChallengesByTarget().end()
321 || !IsPetBattlePvpChallengeExpired(challengeItr->second))
322 return false;
323
324 ClearPetBattlePvpChallengeForTarget(challengeItr->first, true);
325 return true;
326 }
327
328 bool BuildPlayerPetBattleTeam(Player& player, Skyfire::BattlePetPackets::InitialUpdateTeamData& team)
329 {
331
332 BattlePetMgr* battlePetMgr = player.GetBattlePetMgr();
333 BattlePet* activeBattlePet = battlePetMgr->GetFirstAliveLoadoutBattlePet();
334 if (!activeBattlePet)
335 return false;
336
337 for (uint8 slot = 0; slot < BATTLE_PET_MAX_LOADOUT_SLOTS
339 {
340 BattlePet* loadoutBattlePet = battlePetMgr->GetBattlePet(battlePetMgr->GetLoadoutSlot(slot));
341 if (!loadoutBattlePet)
342 continue;
343
344 uint8 const petIndex = team.PetCount;
345 team.Pets[petIndex] = Skyfire::BattlePetPackets::BuildInitialUpdatePetData(*loadoutBattlePet);
346 team.PetCount++;
347
348 if (loadoutBattlePet == activeBattlePet)
349 team.FrontPet = petIndex;
350 }
351
352 if (!team.PetCount)
353 return false;
354
355 team.OwnerGuid = player.GetGUID();
357 return true;
358 }
359
360 void SetActivePetBattleTeam(BattlePetMgr& battlePetMgr,
362 {
363 for (uint8 petIndex = 0; petIndex < team.PetCount; petIndex++)
364 battlePetMgr.SetActivePetBattleAllyPet(petIndex, team.Pets[petIndex].Id,
365 team.Pets[petIndex].MaxHealth, team.Pets[petIndex].CurrentHealth);
366 }
367
368 G3D::Vector3 CalculatePetBattlePlayerPosition(Player const& player,
369 G3D::Vector3 const& ownPetPosition, G3D::Vector3 const& opponentPetPosition)
370 {
371 float dx = opponentPetPosition.x - ownPetPosition.x;
372 float dy = opponentPetPosition.y - ownPetPosition.y;
373 float length = std::sqrt(dx * dx + dy * dy);
374 if (length < 0.1f)
375 {
376 dx = std::cos(player.GetOrientation());
377 dy = std::sin(player.GetOrientation());
378 length = 1.0f;
379 }
380
381 dx /= length;
382 dy /= length;
383
384 constexpr float playerPetBackstep = 2.5f;
385 return G3D::Vector3(ownPetPosition.x - dx * playerPetBackstep,
386 ownPetPosition.y - dy * playerPetBackstep, ownPetPosition.z);
387 }
388
389 void PlacePlayerForPetBattle(Player& player, G3D::Vector3 const& ownPetPosition,
390 G3D::Vector3 const& opponentPetPosition)
391 {
392 G3D::Vector3 const playerPosition =
393 CalculatePetBattlePlayerPosition(player, ownPetPosition, opponentPetPosition);
394 float const orientation = Position::NormalizeOrientation(
395 std::atan2(opponentPetPosition.y - playerPosition.y,
396 opponentPetPosition.x - playerPosition.x));
397
398 player.NearTeleportTo(playerPosition.x, playerPosition.y, playerPosition.z, orientation);
400 opponentPetPosition.x, opponentPetPosition.y);
401 }
402
403 bool StartPetBattlePvpForPlayer(Player& player, Player& opponent,
406 G3D::Vector3 const& origin, G3D::Vector3 const* positions,
407 float orientation, bool hasLocationResult, uint32 locationResult,
408 BattlePetAchievementSource battleSource)
409 {
410 if (!playerTeam.PetCount || !opponentTeam.PetCount)
411 return false;
412
413 BattlePetMgr* battlePetMgr = player.GetBattlePetMgr();
415 playerTeam.Pets[playerTeam.FrontPet];
417 opponentTeam.Pets[opponentTeam.FrontPet];
418 uint8 const enemyFrontPet = uint8(3 + opponentTeam.FrontPet);
419
420 PlacePlayerForPetBattle(player, positions[0], positions[1]);
421
423 origin, positions, true, orientation, hasLocationResult, locationResult);
424 player.SendDirectMessage(&finalizeLocation);
425
426 battlePetMgr->StartPvpPetBattle(opponent.GetGUID(),
427 activePet.Id, activePet.MaxHealth, activePet.CurrentHealth,
428 opponentPet.Id, opponentPet.MaxHealth, opponentPet.CurrentHealth,
429 uint16(opponentPet.Species), uint8(opponentPet.Level), uint8(opponentPet.Quality),
430 playerTeam.FrontPet, enemyFrontPet, battleSource);
431
432 SetActivePetBattleTeam(*battlePetMgr, playerTeam);
433 battlePetMgr->SelectActivePetBattleFrontPet(playerTeam.FrontPet);
434
436 teams[0] = playerTeam;
437 teams[1] = opponentTeam;
438 teams[0].TrapStatus = battlePetMgr->GetActivePetBattleTrapStatus();
440
442 ObjectGuid(0), teams, 2, true);
443 player.SendDirectMessage(&initialUpdate);
444 return true;
445 }
446
447 bool StartPetBattlePvp(Player& player, Player& opponent, G3D::Vector3 const& origin,
448 G3D::Vector3 const* positions, float orientation, bool hasLocationResult, uint32 locationResult,
450 {
451 if (!ValidatePetBattleQueueRequest(player) || !ValidatePetBattlePvpDuelTarget(player, &opponent))
452 return false;
453
456 if (!BuildPlayerPetBattleTeam(player, playerTeam) || !BuildPlayerPetBattleTeam(opponent, opponentTeam))
457 {
460 return false;
461 }
462
463 G3D::Vector3 opponentPositions[2] = { positions[1], positions[0] };
464 float const opponentOrientation = Position::NormalizeOrientation(orientation + 3.14159265358979323846f);
465
466 bool const playerStarted = StartPetBattlePvpForPlayer(player, opponent, playerTeam, opponentTeam,
467 origin, positions, orientation, hasLocationResult, locationResult, battleSource);
468 bool const opponentStarted = StartPetBattlePvpForPlayer(opponent, player, opponentTeam, playerTeam,
469 origin, opponentPositions, opponentOrientation, hasLocationResult, locationResult, battleSource);
470
471 if (!playerStarted || !opponentStarted)
472 {
475 return false;
476 }
477
478 return true;
479 }
480
481 void BuildPetBattleQueueLocation(Player const& player, Player const& opponent,
482 G3D::Vector3& origin, G3D::Vector3* positions, float& orientation)
483 {
484 origin = G3D::Vector3(player.GetPositionX(), player.GetPositionY(), player.GetPositionZ());
485
486 float dx = opponent.GetPositionX() - player.GetPositionX();
487 float dy = opponent.GetPositionY() - player.GetPositionY();
488 float length = std::sqrt(dx * dx + dy * dy);
489 if (length < 0.1f)
490 {
491 dx = std::cos(player.GetOrientation());
492 dy = std::sin(player.GetOrientation());
493 length = 1.0f;
494 }
495
496 dx /= length;
497 dy /= length;
498
499 float const centerX = (player.GetPositionX() + opponent.GetPositionX()) * 0.5f;
500 float const centerY = (player.GetPositionY() + opponent.GetPositionY()) * 0.5f;
501 float const centerZ = (player.GetPositionZ() + opponent.GetPositionZ()) * 0.5f;
502
503 positions[0] = G3D::Vector3(centerX - dx * 1.5f, centerY - dy * 1.5f, centerZ);
504 positions[1] = G3D::Vector3(centerX + dx * 1.5f, centerY + dy * 1.5f, centerZ);
505 orientation = Skyfire::BattlePetPackets::CalculateBattlePetFacing(origin, positions);
506 }
507
508 bool IsPetBattlePvpQueueCandidate(Player* player)
509 {
510 if (!player)
511 return false;
512
513 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
514 return battlePetMgr && battlePetMgr->IsPetBattlePvpQueued()
515 && !battlePetMgr->HasActivePetBattle()
516 && battlePetMgr->HasLoadoutBattlePet()
517 && battlePetMgr->GetFirstAliveLoadoutBattlePet();
518 }
519
520 void RemovePetBattlePvpQueueEntry(uint64 playerGuid)
521 {
522 PetBattlePvpState.RemoveQueueEntry(playerGuid);
523 }
524
525 void ClearPetBattlePvpProposal(uint64 playerGuid)
526 {
527 PetBattlePvpState.ClearProposal(playerGuid);
528 }
529
530 bool IsPetBattlePvpProposalExpired(PetBattlePvpProposal const& proposal)
531 {
532 return proposal.CreatedAt && time(NULL) - proposal.CreatedAt >= PetBattlePvpProposalTimeout;
533 }
534
535 void LeavePetBattlePvpQueue(Player& player, bool sendStatus,
538 bool sendOpponentStatus = true)
539 {
540 uint64 const playerGuid = player.GetGUID();
541 RemovePetBattlePvpQueueEntry(playerGuid);
542
543 PetBattlePvpStateStore::ProposalMap::iterator proposalItr = PetBattlePvpState.Proposals().find(playerGuid);
544 uint64 const opponentGuid = proposalItr != PetBattlePvpState.Proposals().end() ? proposalItr->second.OpponentGuid : 0;
545 ClearPetBattlePvpProposal(playerGuid);
546
547 player.GetBattlePetMgr()->SetPetBattlePvpQueued(false);
548 if (sendStatus)
549 SendPetBattleQueueStatus(player, playerStatus);
550
551 if (!opponentGuid)
552 return;
553
554 if (Player* opponent = ObjectAccessor::FindPlayer(opponentGuid))
555 {
556 opponent->GetBattlePetMgr()->SetPetBattlePvpQueued(false);
557 if (sendOpponentStatus)
558 SendPetBattleQueueStatus(*opponent, opponentStatus);
559 }
560 }
561
562 bool ExpirePetBattlePvpProposal(Player& player)
563 {
564 PetBattlePvpStateStore::ProposalMap::iterator proposalItr =
565 PetBattlePvpState.Proposals().find(player.GetGUID());
566 if (proposalItr == PetBattlePvpState.Proposals().end() || !IsPetBattlePvpProposalExpired(proposalItr->second))
567 return false;
568
569 LeavePetBattlePvpQueue(player, true,
572 return true;
573 }
574
575 uint64 TakePetBattlePvpQueueOpponent(Player& player)
576 {
577 uint64 const playerGuid = player.GetGUID();
578 RemovePetBattlePvpQueueEntry(playerGuid);
579
580 for (PetBattlePvpStateStore::QueueContainer::iterator itr = PetBattlePvpState.Queue().begin();
581 itr != PetBattlePvpState.Queue().end();)
582 {
583 Player* opponent = ObjectAccessor::FindPlayer(*itr);
584 if (!IsPetBattlePvpQueueCandidate(opponent))
585 {
586 if (opponent)
587 opponent->GetBattlePetMgr()->SetPetBattlePvpQueued(false);
588
589 itr = PetBattlePvpState.Queue().erase(itr);
590 continue;
591 }
592
593 uint64 const opponentGuid = *itr;
594 PetBattlePvpState.Queue().erase(itr);
595 return opponentGuid;
596 }
597
598 return 0;
599 }
600
601 void ProposePetBattlePvpMatch(Player& player, Player& opponent)
602 {
603 uint64 const playerGuid = player.GetGUID();
604 uint64 const opponentGuid = opponent.GetGUID();
605 time_t const createdAt = time(NULL);
606
607 PetBattlePvpState.AddProposalPair(playerGuid, opponentGuid, createdAt);
608
609 SendPetBattleQueueProposeMatch(player);
610 SendPetBattleQueueProposeMatch(opponent);
611 }
612
613 void JoinPetBattlePvpQueue(WorldSession& session, Player& player)
614 {
615 BattlePetMgr* battlePetMgr = player.GetBattlePetMgr();
616 uint64 const playerGuid = player.GetGUID();
617
618 if (battlePetMgr->IsPetBattlePvpQueued())
619 {
620 SendPetBattleQueueStatus(session, player, Skyfire::BattlePetPackets::PET_BATTLE_QUEUE_STATUS_ALREADY_QUEUED);
621 return;
622 }
623
624 ClearPetBattlePvpChallengesFor(playerGuid);
625 ClearPetBattlePvpProposal(playerGuid);
626 RemovePetBattlePvpQueueEntry(playerGuid);
627 battlePetMgr->SetPetBattlePvpQueued(true);
628 SendPetBattleQueueStatus(session, player, Skyfire::BattlePetPackets::PET_BATTLE_QUEUE_STATUS_QUEUED);
629
630 uint64 const opponentGuid = TakePetBattlePvpQueueOpponent(player);
631 if (Player* opponent = ObjectAccessor::FindPlayer(opponentGuid))
632 {
633 opponent->GetBattlePetMgr()->SetPetBattlePvpQueued(true);
634 ProposePetBattlePvpMatch(player, *opponent);
635 return;
636 }
637
638 PetBattlePvpState.AddQueueEntry(playerGuid);
639 }
640
641 void FailAcceptedPetBattlePvpQueueMatch(Player& player, Player* opponent)
642 {
643 LeavePetBattlePvpQueue(player, true,
646 opponent != nullptr);
647
648 if (opponent && opponent->GetBattlePetMgr()->IsPetBattlePvpQueued())
649 {
650 opponent->GetBattlePetMgr()->SetPetBattlePvpQueued(false);
651 SendPetBattleQueueStatus(*opponent,
653 }
654 }
655
656 bool ReadPetBattleQueueProposeAccepted(WorldPacket& recvData)
657 {
658 if (recvData.rpos() >= recvData.size())
659 return false;
660
661 return recvData.ReadBit();
662 }
663
664 void ReadPetBattlePvpDuelRequestLocation(WorldPacket& recvData, PetBattleRequest& petBattleRequest)
665 {
666 recvData >> petBattleRequest.Origin.z;
667
668 for (uint8 i = 0; i < 2; i++)
669 {
670 recvData >> petBattleRequest.Positions[i].x;
671 recvData >> petBattleRequest.Positions[i].z;
672 recvData >> petBattleRequest.Positions[i].y;
673 }
674
675 recvData >> petBattleRequest.Origin.y;
676 recvData >> petBattleRequest.Origin.x;
677
678 petBattleRequest.LocationResult = 21;
679 if (recvData.size() >= sizeof(uint32))
680 {
681 uint8 const* tail = recvData.contents() + recvData.size() - sizeof(uint32);
682 petBattleRequest.LocationResult = uint32(tail[0])
683 | (uint32(tail[1]) << 8)
684 | (uint32(tail[2]) << 16)
685 | (uint32(tail[3]) << 24);
686 }
687 }
688
689 bool ValidatePetBattleQueueRequest(Player& player)
690 {
691 BattlePetMgr* battlePetMgr = player.GetBattlePetMgr();
692 if (battlePetMgr->HasActivePetBattle())
693 {
695 return false;
696 }
697
698 if (player.IsInCombat())
699 {
701 return false;
702 }
703
704 if (!battlePetMgr->HasLoadoutBattlePet())
705 {
707 return false;
708 }
709
710 if (!battlePetMgr->GetFirstAliveLoadoutBattlePet())
711 {
713 return false;
714 }
715
716 return true;
717 }
718
719 bool ValidatePetBattlePvpDuelTarget(Player& challenger, Player* target)
720 {
721 BattlePetMgr* challengerBattlePetMgr = challenger.GetBattlePetMgr();
722 BattlePetMgr* targetBattlePetMgr = target ? target->GetBattlePetMgr() : nullptr;
723 if (!target || target == &challenger || !targetBattlePetMgr || targetBattlePetMgr->HasActivePetBattle()
724 || target->GetMapId() != challenger.GetMapId())
725 {
727 return false;
728 }
729
730 if (target->IsInCombat())
731 {
733 return false;
734 }
735
736 if (!targetBattlePetMgr->HasLoadoutBattlePet())
737 {
739 return false;
740 }
741
742 if (!targetBattlePetMgr->GetFirstAliveLoadoutBattlePet())
743 {
745 return false;
746 }
747
748 return true;
749 }
750
751 bool HandlePendingPetBattlePvpChallengeResponse(Player& target,
753 {
754 uint64 const targetGuid = target.GetGUID();
755 PetBattlePvpStateStore::ChallengeMap::iterator challengeItr =
756 PetBattlePvpState.ChallengesByTarget().find(targetGuid);
757 if (challengeItr == PetBattlePvpState.ChallengesByTarget().end())
758 return false;
759
760 if (IsPetBattlePvpChallengeExpired(challengeItr->second))
761 {
762 ClearPetBattlePvpChallengeForTarget(targetGuid, true);
763 return true;
764 }
765
766 PetBattlePvpChallenge challenge = challengeItr->second;
767 Player* challenger = ObjectAccessor::FindPlayer(challenge.ChallengerGuid);
768 if (!challenger)
769 {
770 ClearPetBattlePvpChallengeForTarget(targetGuid);
772 return true;
773 }
774
775 if (request.Cancelled)
776 {
777 ClearPetBattlePvpChallengeForTarget(targetGuid);
779 return true;
780 }
781
782 if (!challengeItr->second.PromptAcknowledged)
783 {
784 challengeItr->second.PromptAcknowledged = true;
785 return true;
786 }
787
788 challenge = challengeItr->second;
789 ClearPetBattlePvpChallengeForTarget(targetGuid);
790
791 LeavePetBattlePvpQueue(*challenger, false);
792 LeavePetBattlePvpQueue(target, false);
793
794 if (!StartPetBattlePvp(*challenger, target, challenge.Origin, challenge.Positions,
795 challenge.Orientation, challenge.HasLocationResult, challenge.LocationResult))
796 {
799 }
800
801 return true;
802 }
803
804 bool CompletePendingPetBattlePvpChallenge(Player& target, bool accepted)
805 {
806 uint64 const targetGuid = target.GetGUID();
807 PetBattlePvpStateStore::ChallengeMap::iterator challengeItr =
808 PetBattlePvpState.ChallengesByTarget().find(targetGuid);
809 if (challengeItr == PetBattlePvpState.ChallengesByTarget().end())
810 return false;
811
812 if (IsPetBattlePvpChallengeExpired(challengeItr->second))
813 {
814 ClearPetBattlePvpChallengeForTarget(targetGuid, true);
815 return true;
816 }
817
818 PetBattlePvpChallenge challenge = challengeItr->second;
819 Player* challenger = ObjectAccessor::FindPlayer(challenge.ChallengerGuid);
820 ClearPetBattlePvpChallengeForTarget(targetGuid);
821
822 if (!challenger)
823 {
825 return true;
826 }
827
828 if (!accepted)
829 {
831 return true;
832 }
833
834 LeavePetBattlePvpQueue(*challenger, false);
835 LeavePetBattlePvpQueue(target, false);
836
837 if (!StartPetBattlePvp(*challenger, target, challenge.Origin, challenge.Positions,
838 challenge.Orientation, challenge.HasLocationResult, challenge.LocationResult))
839 {
842 }
843
844 return true;
845 }
846}
847
849{
850 Player* player = GetPlayer();
851 if (!player)
852 return;
853
854 ExpirePetBattlePvpChallenge(*player);
855 ExpirePetBattlePvpProposal(*player);
856}
857
859{
860 Player* player = GetPlayer();
861 if (!player)
862 return;
863
864 ClearPetBattlePvpChallengesFor(player->GetGUID(), true, player->GetGUID());
865 LeavePetBattlePvpQueue(*player, false,
868}
869
871{
872 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_START_PVP_MATCHMAKING");
873
874 Player* player = GetPlayer();
875 if (!player || !ValidatePetBattleQueueRequest(*player))
876 return;
877
878 JoinPetBattlePvpQueue(*this, *player);
879}
880
882{
883 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_STOP_PVP_MATCHMAKING");
884
885 if (Player* player = GetPlayer())
886 LeavePetBattlePvpQueue(*player, true);
887}
888
890{
891 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_QUEUE_PROPOSE_MATCH_RESULT");
892
893 Player* player = GetPlayer();
894 if (!player)
895 return;
896
897 if (ExpirePetBattlePvpProposal(*player))
898 return;
899
900 uint64 const playerGuid = player->GetGUID();
901 PetBattlePvpStateStore::ProposalMap::iterator proposalItr = PetBattlePvpState.Proposals().find(playerGuid);
902 if (proposalItr == PetBattlePvpState.Proposals().end())
903 {
904 SendPetBattleQueueStatus(*this, *player, Skyfire::BattlePetPackets::PET_BATTLE_QUEUE_STATUS_NONE);
905 return;
906 }
907
908 if (!ReadPetBattleQueueProposeAccepted(recvData))
909 {
910 LeavePetBattlePvpQueue(*player, true,
913 return;
914 }
915
916 proposalItr->second.Accepted = true;
917
918 uint64 const opponentGuid = proposalItr->second.OpponentGuid;
919 PetBattlePvpStateStore::ProposalMap::iterator opponentProposalItr =
920 PetBattlePvpState.Proposals().find(opponentGuid);
921 if (opponentProposalItr == PetBattlePvpState.Proposals().end())
922 {
923 LeavePetBattlePvpQueue(*player, true);
924 return;
925 }
926
927 if (!opponentProposalItr->second.Accepted)
928 return;
929
930 Player* opponent = ObjectAccessor::FindPlayer(opponentGuid);
931 if (!opponent)
932 {
933 FailAcceptedPetBattlePvpQueueMatch(*player, nullptr);
934 return;
935 }
936
937 if (!ValidatePetBattleQueueRequest(*player) || !ValidatePetBattlePvpDuelTarget(*player, opponent))
938 {
939 FailAcceptedPetBattlePvpQueueMatch(*player, opponent);
940 return;
941 }
942
943 ClearPetBattlePvpProposal(playerGuid);
944 RemovePetBattlePvpQueueEntry(playerGuid);
945 RemovePetBattlePvpQueueEntry(opponentGuid);
946
947 player->GetBattlePetMgr()->SetPetBattlePvpQueued(false);
948 opponent->GetBattlePetMgr()->SetPetBattlePvpQueued(false);
949
950 SendPetBattleQueueStatus(*this, *player, Skyfire::BattlePetPackets::PET_BATTLE_QUEUE_STATUS_NONE);
951 SendPetBattleQueueStatus(*opponent, Skyfire::BattlePetPackets::PET_BATTLE_QUEUE_STATUS_NONE);
952
953 G3D::Vector3 origin;
954 G3D::Vector3 positions[2];
955 float orientation = 0.0f;
956 BuildPetBattleQueueLocation(*player, *opponent, origin, positions, orientation);
957 if (!StartPetBattlePvp(*player, *opponent, origin, positions, orientation, false, 0,
959 {
960 SendPetBattleQueueStatus(*this, *player,
962 SendPetBattleQueueStatus(*opponent,
964 }
965}
966
968{
969 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_REQUEST_PVP");
970
971 PetBattleRequest petBattleRequest = { };
972 ReadPetBattlePvpDuelRequestLocation(recvData, petBattleRequest);
973
974 Player* player = GetPlayer();
975 if (!player)
976 return;
977
978 if (!ValidatePetBattleQueueRequest(*player))
979 return;
980
981 Player* target = player->GetSelectedPlayer();
982 if (!ValidatePetBattlePvpDuelTarget(*player, target))
983 return;
984
985 LeavePetBattlePvpQueue(*player, false);
986 LeavePetBattlePvpQueue(*target, false);
987
988 uint64 const playerGuid = player->GetGUID();
989 uint64 const targetGuid = target->GetGUID();
990 ClearPetBattlePvpChallengesFor(playerGuid, true, playerGuid);
991 ClearPetBattlePvpChallengesFor(targetGuid, true, targetGuid);
992
994 false, petBattleRequest.Orientation, petBattleRequest.Origin, petBattleRequest.Positions);
995
996 PetBattlePvpChallenge challenge;
997 challenge.ChallengerGuid = playerGuid;
998 challenge.TargetGuid = targetGuid;
999 challenge.Origin = petBattleRequest.Origin;
1000 challenge.Positions[0] = petBattleRequest.Positions[0];
1001 challenge.Positions[1] = petBattleRequest.Positions[1];
1002 challenge.Orientation = petBattleRequest.Orientation;
1003 challenge.LocationResult = petBattleRequest.LocationResult;
1004 challenge.HasLocationResult = true;
1005 challenge.CreatedAt = time(NULL);
1006 PetBattlePvpState.AddChallenge(challenge);
1007
1009 player->GetGUID(), petBattleRequest.Origin, petBattleRequest.Positions,
1010 true, petBattleRequest.Orientation, true, petBattleRequest.LocationResult);
1011 target->SendDirectMessage(&data);
1012 SendPetBattleDuelPopup(*player, *target);
1013}
1014
1016{
1017 Player* player = GetPlayer();
1018 if (!player)
1019 return false;
1020
1021 return CompletePendingPetBattlePvpChallenge(*player, accepted);
1022}
1023
1025{
1026 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_DELETE");
1027
1028 ObjectGuid petEntry;
1029
1030 recvData.ReadGuidMask(petEntry, 3, 5, 6, 2, 4, 0, 7, 1);
1031 recvData.ReadGuidBytes(petEntry, 4, 1, 5, 0, 7, 2, 3, 6);
1032
1033 BattlePetMgr* battlePetMgr = GetPlayer()->GetBattlePetMgr();
1034
1035 BattlePet* battlePet = battlePetMgr->GetBattlePet(petEntry);
1036 if (!battlePet)
1037 {
1038 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_DELETE - Player %u tryed to release Battle Pet %lu which it doesn't own!",
1039 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1040 return;
1041 }
1042
1044 {
1045 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_DELETE - Player %u tryed to release Battle Pet %lu which isn't releasable!",
1046 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1047 return;
1048 }
1049
1050 if (battlePetMgr->GetLoadoutSlotForBattlePet(petEntry) != BATTLE_PET_LOADOUT_SLOT_NONE)
1051 {
1052 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_DELETE - Player %u tryed to release slotted Battle Pet %lu!",
1053 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1054 return;
1055 }
1056
1057 battlePetMgr->Delete(battlePet);
1058 battlePetMgr->SaveToDb();
1059}
1060
1061#define BATTLE_PET_MAX_DECLINED_NAMES 5
1062
1064{
1065 // TODO: finish this...
1066 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_MODIFY_NAME");
1067
1068 ObjectGuid petEntry;
1069 uint8 nicknameLen;
1070 std::string nickname;
1071 bool hasDeclinedNames;
1072 uint8 declinedNameLen[BATTLE_PET_MAX_DECLINED_NAMES];
1073
1074 petEntry[5] = recvData.ReadBit();
1075 petEntry[7] = recvData.ReadBit();
1076 petEntry[3] = recvData.ReadBit();
1077 petEntry[0] = recvData.ReadBit();
1078 petEntry[6] = recvData.ReadBit();
1079 nicknameLen = recvData.ReadBits(7);
1080 petEntry[2] = recvData.ReadBit();
1081 petEntry[1] = recvData.ReadBit();
1082 hasDeclinedNames = recvData.ReadBit();
1083 petEntry[4] = recvData.ReadBit();
1084
1085 if (hasDeclinedNames)
1086 for (uint8 i = 0; i < BATTLE_PET_MAX_DECLINED_NAMES; i++)
1087 declinedNameLen[i] = recvData.ReadBits(7);
1088
1089 recvData.ReadByteSeq(petEntry[3]);
1090 recvData.ReadByteSeq(petEntry[0]);
1091 recvData.ReadByteSeq(petEntry[6]);
1092 recvData.ReadByteSeq(petEntry[1]);
1093 recvData.ReadByteSeq(petEntry[5]);
1094 recvData.ReadByteSeq(petEntry[2]);
1095 recvData.ReadByteSeq(petEntry[4]);
1096 recvData.ReadByteSeq(petEntry[7]);
1097 nickname = recvData.ReadString(nicknameLen);
1098
1099 if (hasDeclinedNames)
1100 {
1101 std::string declinedNames[BATTLE_PET_MAX_DECLINED_NAMES];
1102 for (uint8 i = 0; i < BATTLE_PET_MAX_DECLINED_NAMES; i++)
1103 declinedNames[i] = recvData.ReadString(declinedNameLen[i]);
1104 }
1105
1106 BattlePetMgr* battlePetMgr = GetPlayer()->GetBattlePetMgr();
1107
1108 BattlePet* battlePet = battlePetMgr->GetBattlePet(petEntry);
1109 if (!battlePet)
1110 {
1111 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_MODIFY_NAME - Player %u tryed to set the name for Battle Pet %lu which it doesn't own!",
1112 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1113 return;
1114 }
1115
1116 if (nickname.size() > BATTLE_PET_MAX_NAME_LENGTH)
1117 {
1118 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_MODIFY_NAME - Player %u tryed to set the name for Battle Pet %lu with an invalid length!",
1119 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1120 return;
1121 }
1122
1123 // TODO: check for invalid characters, ect...
1124
1125 battlePet->SetNickname(nickname);
1126 battlePet->SetTimestamp((uint32)time(NULL));
1127
1128 if (battlePetMgr->GetCurrentSummonId())
1130
1131 battlePetMgr->SaveToDb();
1132}
1133
1135{
1136 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_QUERY_NAME");
1137
1138 ObjectGuid petEntry, petguid;
1139
1140 petguid[2] = recvData.ReadBit();
1141 petEntry[6] = recvData.ReadBit();
1142 petEntry[3] = recvData.ReadBit();
1143 petguid[3] = recvData.ReadBit();
1144 petEntry[7] = recvData.ReadBit();
1145 petguid[4] = recvData.ReadBit();
1146 petguid[1] = recvData.ReadBit();
1147 petguid[0] = recvData.ReadBit();
1148 petEntry[0] = recvData.ReadBit();
1149 petguid[7] = recvData.ReadBit();
1150 petguid[5] = recvData.ReadBit();
1151 petguid[6] = recvData.ReadBit();
1152 petEntry[1] = recvData.ReadBit();
1153 petEntry[2] = recvData.ReadBit();
1154 petEntry[5] = recvData.ReadBit();
1155 petEntry[4] = recvData.ReadBit();
1156
1157 recvData.ReadByteSeq(petguid[5]);
1158 recvData.ReadByteSeq(petEntry[1]);
1159 recvData.ReadByteSeq(petguid[0]);
1160 recvData.ReadByteSeq(petEntry[4]);
1161 recvData.ReadByteSeq(petguid[3]);
1162 recvData.ReadByteSeq(petEntry[3]);
1163 recvData.ReadByteSeq(petguid[1]);
1164 recvData.ReadByteSeq(petguid[6]);
1165 recvData.ReadByteSeq(petEntry[6]);
1166 recvData.ReadByteSeq(petEntry[0]);
1167 recvData.ReadByteSeq(petEntry[2]);
1168 recvData.ReadByteSeq(petguid[7]);
1169 recvData.ReadByteSeq(petguid[2]);
1170 recvData.ReadByteSeq(petEntry[7]);
1171 recvData.ReadByteSeq(petguid[4]);
1172 recvData.ReadByteSeq(petEntry[5]);
1173
1174 Unit* tempUnit = sObjectAccessor->FindUnit(petguid);
1175 if (!tempUnit)
1176 {
1177 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_QUERY_NAME - Player %u queried the name of Battle Pet %lu which doesnt't exist in world!",
1178 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1179 return;
1180 }
1181
1182 Unit* ownerUnit = tempUnit->ToTempSummon()->GetSummoner();
1183 if (!ownerUnit)
1184 return;
1185
1186 BattlePetMgr* battlePetMgr = ownerUnit->ToPlayer()->GetBattlePetMgr();
1187
1188 BattlePet* battlePet = battlePetMgr->GetBattlePet(battlePetMgr->GetCurrentSummonId());
1189 if (!battlePet)
1190 return;
1191
1192 BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(battlePet->GetSpecies());
1193 if (!speciesEntry)
1194 return;
1195
1196 WorldPacket data(SMSG_BATTLE_PET_QUERY_NAME_RESPONSE, 8 + 4 + 4 + 5 + battlePet->GetNickname().size());
1197 data << uint64(petEntry);
1198 data << uint32(battlePet->GetTimestamp());
1199 data << uint32(speciesEntry->NpcId);
1200 data.WriteBit(1); // has names
1201 data.WriteBits(battlePet->GetNickname().size(), 8);
1202
1203 // TODO: finish declined names
1204 for (uint8 i = 0; i < BATTLE_PET_MAX_DECLINED_NAMES; i++)
1205 data.WriteBits(0, 7);
1206
1207 data.WriteBit(0); // allowed?
1208 data.FlushBits();
1209
1210 data.WriteString(battlePet->GetNickname());
1211
1212 SendPacket(&data);
1213}
1214
1216{
1217 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_REQUEST_JOURNAL");
1218 BattlePetMgr* battlePetMgr = GetPlayer()->GetBattlePetMgr();
1219 battlePetMgr->SendBattlePetJournal();
1220 battlePetMgr->SendBattlePetJournalLock();
1221}
1222
1224{
1225 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_LEARN");
1226
1227 ObjectGuid itemGuid;
1228 recvData.ReadGuidMask(itemGuid, 7, 1, 0, 5, 4, 2, 3, 6);
1229 recvData.ReadGuidBytes(itemGuid, 2, 3, 4, 1, 5, 7, 0, 6);
1230
1231 Player* player = GetPlayer();
1232 Item* item = player->GetItemByGuid(itemGuid);
1233 if (!item)
1234 {
1235 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_LEARN - Player %u tried to learn a battle pet from missing item " UI64FMTD,
1236 player->GetGUIDLow(), uint64(itemGuid));
1237 return;
1238 }
1239
1240 BattlePetItemXSpeciesStore::const_iterator speciesItr = sBattlePetItemXSpeciesStore.find(item->GetEntry());
1241 if (speciesItr == sBattlePetItemXSpeciesStore.end() || !speciesItr->second)
1242 {
1243 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_LEARN - Player %u tried to learn a battle pet from non-pet item %u",
1244 player->GetGUIDLow(), item->GetEntry());
1245 return;
1246 }
1247
1248 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1249 if (!battlePetMgr->Create(speciesItr->second))
1250 return;
1251
1252 player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
1253 battlePetMgr->SaveToDb();
1254}
1255
1257{
1258 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_SET_BATTLE_SLOT");
1259
1260 uint8 slot;
1261 ObjectGuid petEntry;
1262
1263 recvData >> slot;
1264
1265 recvData.ReadGuidMask(petEntry, 4, 6, 5, 7, 3, 1, 0, 2);
1266 recvData.ReadGuidBytes(petEntry, 1, 3, 5, 0, 7, 6, 4, 2);
1267
1268 BattlePetMgr* battlePetMgr = GetPlayer()->GetBattlePetMgr();
1269
1270 BattlePet* battlePet = battlePetMgr->GetBattlePet(petEntry);
1271 if (!battlePet)
1272 {
1273 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_SET_BATTLE_SLOT - Player %u tryed to add Battle Pet %lu to loadout which it doesn't own!",
1274 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1275 return;
1276 }
1277
1278 if (!battlePetMgr->HasLoadoutSlot(slot))
1279 {
1280 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_SET_BATTLE_SLOT - Player %u tryed to add Battle Pet %lu into slot %u which is locked!",
1281 GetPlayer()->GetGUIDLow(), (uint64)petEntry, slot);
1282 return;
1283 }
1284
1285 // this check is also done clientside
1287 {
1288 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_SET_BATTLE_SLOT - Player %u tryed to add a compainion Battle Pet %lu into slot %u!",
1289 GetPlayer()->GetGUIDLow(), (uint64)petEntry, slot);
1290 return;
1291 }
1292
1293 // sever handles slot swapping, find source slot and replace it with the destination slot
1294 uint64 const dstPetEntry = battlePetMgr->GetLoadoutSlot(slot);
1295 uint8 srcSlot = battlePetMgr->GetLoadoutSlotForBattlePet(petEntry);
1296 if (srcSlot != BATTLE_PET_LOADOUT_SLOT_NONE && srcSlot != slot)
1297 {
1298 battlePetMgr->SetLoadoutSlot(srcSlot, dstPetEntry, true);
1299 battlePetMgr->SendBattlePetSlotUpdate(srcSlot, false, dstPetEntry);
1300 }
1301
1302 battlePetMgr->SetLoadoutSlot(slot, petEntry, true);
1303 battlePetMgr->SendBattlePetSlotUpdate(slot, false, petEntry);
1304 battlePetMgr->SaveToDb();
1305}
1306
1312
1314{
1315 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_SET_FLAGS");
1316
1317 ObjectGuid petEntry;
1318 uint32 flag;
1319
1320 recvData >> flag;
1321
1322 recvData.ReadGuidMask(petEntry, 5, 4);
1323 uint8 mode = recvData.ReadBits(2);
1324 recvData.ReadGuidMask(petEntry, 1, 4, 6, 3, 7, 0);
1325
1326 recvData.ReadGuidBytes(petEntry, 4, 0, 7, 3, 1, 6, 2, 5);
1327
1328 BattlePetMgr* battlePetMgr = GetPlayer()->GetBattlePetMgr();
1329 BattlePet* battlePet = battlePetMgr->GetBattlePet(petEntry);
1330 if (!battlePet)
1331 {
1332 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_SET_FLAGS - Player %u tryed to set the flags for Battle Pet %lu which it doesn't own!",
1333 GetPlayer()->GetGUIDLow(), (uint64)petEntry);
1334 return;
1335 }
1336
1337 // list of flags the client can currently change
1342 {
1343 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_SET_FLAGS - Player %u tryed to set an invalid Battle Pet flag %u!",
1344 GetPlayer()->GetGUIDLow(), flag);
1345 return;
1346 }
1347
1349 {
1350 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_SET_FLAGS - Player %u tryed to set Battle Pet flag %u with invalid mode %u!",
1351 GetPlayer()->GetGUIDLow(), flag, mode);
1352 return;
1353 }
1354
1355 uint8 const abilitySlot = BattlePetAbilitySlotForJournalFlag(flag);
1356 if (abilitySlot != BATTLE_PET_ABILITY_SLOT_INVALID)
1357 {
1358 bool const useAlternateAbility = mode == BATTLE_PET_FLAG_MODE_SET;
1359 if (!BattlePetHasSpeciesAbility(battlePet->GetSpecies(), abilitySlot, useAlternateAbility, battlePet->GetLevel()))
1360 {
1361 SF_LOG_DEBUG("network", "CMSG_BATTLE_PET_SET_FLAGS - Player %u tryed to select unavailable Battle Pet ability flag %u for pet %lu!",
1362 GetPlayer()->GetGUIDLow(), flag, (uint64)petEntry);
1363 return;
1364 }
1365 }
1366
1367 uint16 const oldFlags = battlePet->GetFlags();
1368 switch (mode)
1369 {
1371 battlePet->SetFlag(flag);
1372 break;
1374 battlePet->UnSetFlag(flag);
1375 break;
1376 }
1377
1378 if (oldFlags != battlePet->GetFlags())
1379 {
1380 battlePetMgr->SendBattlePetUpdate(battlePet, false);
1381 battlePetMgr->SaveToDb();
1382 }
1383}
1384
1386{
1387 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_SUMMON_COMPANION");
1388
1389 ObjectGuid petEntry;
1390
1391 recvData.ReadGuidMask(petEntry, 3, 2, 5, 0, 7, 1, 6, 4);
1392 recvData.ReadGuidBytes(petEntry, 6, 7, 3, 5, 0, 4, 1, 2);
1393
1394 Player* player = GetPlayer();
1395 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1396
1397 BattlePet* battlePet = battlePetMgr->GetBattlePet(petEntry);
1398 if (!battlePet)
1399 {
1400 SF_LOG_DEBUG("network", "CMSG_SUMMON_BATTLE_PET_COMPANION - Player %u tryed to summon battle pet companion %lu which it doesn't own!",
1401 player->GetGUIDLow(), (uint64)petEntry);
1402 return;
1403 }
1404
1405 if (!battlePet->GetCurrentHealth())
1406 {
1407 SF_LOG_DEBUG("network", "CMSG_SUMMON_BATTLE_PET_COMPANION - Player %u tryed to summon battle pet companion %lu which is dead!",
1408 player->GetGUIDLow(), (uint64)petEntry);
1409 return;
1410 }
1411
1412 if (battlePetMgr->GetCurrentSummonId() == petEntry)
1413 battlePetMgr->UnSummonCurrentBattlePet(false);
1414 else
1415 {
1416 if (uint32 summonSpell = BattlePetGetSummonSpell(battlePet->GetSpecies()))
1417 {
1418 battlePetMgr->SetCurrentSummonId(petEntry);
1419 player->CastSpell(player, summonSpell, true);
1420 }
1421 }
1422}
1423
1425{
1426 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_INPUT");
1427
1432 return;
1433
1434 Player* player = GetPlayer();
1435 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1436 if (!battlePetMgr->HasActivePetBattle())
1437 return;
1438
1439 bool handled = false;
1440 bool sendRound = false;
1441 bool sendFinal = false;
1442 uint64 pvpForfeitOpponentGuid = 0;
1443 uint64 pvpFinalOpponentGuid = 0;
1446
1447 switch (command.Action)
1448 {
1450 {
1451 ActivePetBattle const& activeBattle = battlePetMgr->GetActivePetBattle();
1452 uint32 const roundId = activeBattle.RoundID;
1453 uint32 const enemyAbilityId = BattlePetGetSpeciesAbility(
1454 activeBattle.EnemySpecies, 0, 0, activeBattle.EnemyLevel);
1455 BattlePet const* allyBattlePet = GetActiveBattlePet(*battlePetMgr);
1456 BattlePet const* enemyBattlePet = GetPvpOpponentActiveBattlePet(*player, activeBattle);
1457 uint32 const enemyDamage = enemyBattlePet
1458 ? BattlePetInputDamageForAbility(enemyAbilityId, enemyBattlePet)
1459 : BattlePetInputDamageForEnemyAbility(enemyAbilityId, activeBattle);
1460 uint8 const allyAbilitySlot = BattlePetActiveAbilitySlot(allyBattlePet, command.AbilityID);
1461 if (allyAbilitySlot == BATTLE_PET_ABILITY_SLOT_INVALID)
1462 return;
1463
1464 if (activeBattle.IsPvP())
1465 pvpFinalOpponentGuid = activeBattle.EnemyGUID;
1466
1467 handled = battlePetMgr->ApplyBattlePetAbilityExchangeInput(roundId,
1468 BattlePetInputDamageForAbility(command.AbilityID, allyBattlePet),
1470 allyAbilitySlot, command.AbilityID, BattlePetAbilityCooldown(command.AbilityID),
1471 enemyDamage,
1472 BattlePetInputEffectForAbility(enemyAbilityId),
1475 enemyBattlePet
1476 ? BattlePetInputIncomingDamageReductionForAbility(enemyAbilityId, enemyBattlePet)
1477 : BattlePetInputIncomingDamageReductionForEnemyAbility(enemyAbilityId, activeBattle),
1479 round, &finalRound);
1480 sendRound = handled;
1481 sendFinal = !finalRound.Pets.empty();
1482 break;
1483 }
1485 if (command.NewFrontPet < 0)
1486 return;
1487
1488 handled = battlePetMgr->ApplyBattlePetSwapInput(battlePetMgr->GetActivePetBattle().RoundID,
1489 uint8(command.NewFrontPet), round);
1490 sendRound = handled;
1491 break;
1493 {
1494 ActivePetBattle const& activeBattle = battlePetMgr->GetActivePetBattle();
1495 if (activeBattle.IsPvP())
1496 pvpForfeitOpponentGuid = activeBattle.EnemyGUID;
1497
1498 handled = battlePetMgr->ApplyBattlePetForfeitInput(battlePetMgr->GetActivePetBattle().RoundID, finalRound);
1499 sendFinal = handled;
1500 break;
1501 }
1503 {
1504 ActivePetBattle const& activeBattle = battlePetMgr->GetActivePetBattle();
1505 uint32 const enemyAbilityId = BattlePetGetSpeciesAbility(
1506 activeBattle.EnemySpecies, 0, 0, activeBattle.EnemyLevel);
1507 BattlePet const* enemyBattlePet = GetPvpOpponentActiveBattlePet(*player, activeBattle);
1508 uint32 const enemyDamage = enemyBattlePet
1509 ? BattlePetInputDamageForAbility(enemyAbilityId, enemyBattlePet)
1510 : BattlePetInputDamageForEnemyAbility(enemyAbilityId, activeBattle);
1511
1512 handled = battlePetMgr->ApplyBattlePetTrapInput(battlePetMgr->GetActivePetBattle().RoundID,
1513 BattlePetInputEffectForAbility(battlePetMgr->GetTrapAbility()), enemyDamage,
1514 BattlePetInputEffectForAbility(enemyAbilityId), round, finalRound);
1515 sendRound = handled;
1516 sendFinal = handled && !finalRound.Pets.empty();
1517 break;
1518 }
1519 default:
1520 return;
1521 }
1522
1523 if (!handled)
1524 return;
1525
1526 if (sendRound)
1527 SendBattlePetRoundResult(*player, round);
1528
1529 if (sendFinal)
1530 {
1531 if (pvpForfeitOpponentGuid)
1532 FinishActivePvpPetBattleAfterForfeit(*player, pvpForfeitOpponentGuid, finalRound);
1533 else if (pvpFinalOpponentGuid)
1534 FinishActivePvpPetBattle(*player, pvpFinalOpponentGuid, finalRound,
1535 OpponentWinnerForFinalRound(finalRound), false);
1536 else
1537 {
1538 SendBattlePetFinalRound(*player, finalRound);
1539 ClearActivePetBattleAndSave(*player);
1540 }
1541 }
1542}
1543
1545{
1546 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_SET_FRONT_PET");
1547
1550
1551 Player* player = GetPlayer();
1552 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1553 if (!battlePetMgr->HasActivePetBattle())
1554 return;
1555
1556 ActivePetBattle const& activeBattle = battlePetMgr->GetActivePetBattle();
1557 if (activeBattle.WaitingForAllyFrontPet)
1558 {
1560 if (!battlePetMgr->ApplyBattlePetSwapInput(activeBattle.RoundID, selection.PetID, round))
1561 return;
1562
1563 SendBattlePetRoundResult(*player, round);
1564 return;
1565 }
1566
1567 if (!battlePetMgr->SelectActivePetBattleFrontPet(selection.PetID))
1568 return;
1569
1570 ActivePetBattle const& selectedBattle = battlePetMgr->GetActivePetBattle();
1572 selectedBattle.RoundID, selectedBattle.AllyFrontPet, selectedBattle.EnemyFrontPet,
1574 player->SendDirectMessage(&firstRound);
1575}
1576
1578{
1579 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_FINAL_NOTIFY");
1580
1581 Player* player = GetPlayer();
1582 if (!player)
1583 return;
1584
1585 SendBattlePetFinished(*player);
1586
1587 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1588 if (battlePetMgr->HasActivePetBattle())
1589 ClearActivePetBattleAndSave(*player);
1590}
1591
1593{
1594 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_QUIT_NOTIFY");
1595
1596 Player* player = GetPlayer();
1597 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1598 if (!battlePetMgr->HasActivePetBattle())
1599 return;
1600
1601 ActivePetBattle const& activeBattle = battlePetMgr->GetActivePetBattle();
1602 uint64 const pvpOpponentGuid = activeBattle.IsPvP() ? activeBattle.EnemyGUID : 0;
1604 if (battlePetMgr->ApplyBattlePetForfeitInput(activeBattle.RoundID, finalRound))
1605 {
1606 if (pvpOpponentGuid)
1607 {
1608 FinishActivePvpPetBattleAfterForfeit(*player, pvpOpponentGuid, finalRound);
1609 return;
1610 }
1611
1612 SendBattlePetFinalRound(*player, finalRound);
1613 }
1614
1615 ClearActivePetBattleAndSave(*player);
1616}
1617
1619{
1620 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PET_BATTLE_REQUEST_UPDATE");
1621
1622 Player* player = GetPlayer();
1623 if (!player)
1624 return;
1625
1626 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1629
1630 if (!battlePetMgr->HasActivePetBattle())
1631 {
1632 if (HandlePendingPetBattlePvpChallengeResponse(*player, request))
1633 return;
1634
1635 if (ExpirePetBattlePvpProposal(*player))
1636 return;
1637
1638 if (battlePetMgr->IsPetBattlePvpQueued())
1639 SendPetBattleQueueStatus(*this, *player, Skyfire::BattlePetPackets::PET_BATTLE_QUEUE_STATUS_QUEUED);
1640
1641 return;
1642 }
1643
1644 if (!request.Cancelled)
1645 return;
1646
1647 ActivePetBattle const& activeBattle = battlePetMgr->GetActivePetBattle();
1648 uint64 const pvpOpponentGuid = activeBattle.IsPvP() ? activeBattle.EnemyGUID : 0;
1650 if (!battlePetMgr->ApplyBattlePetForfeitInput(activeBattle.RoundID, finalRound))
1651 return;
1652
1653 if (pvpOpponentGuid)
1654 FinishActivePvpPetBattleAfterForfeit(*player, pvpOpponentGuid, finalRound);
1655 else
1656 {
1657 SendBattlePetFinalRound(*player, finalRound);
1658 ClearActivePetBattleAndSave(*player);
1659 }
1660}
1661
1663{
1664 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BATTLE_PET_WILD_REQUEST");
1665 ObjectGuid guid;
1666 bool missingOrientation;
1667 bool missingResult;
1668
1669 PetBattleRequest petBattleRequest = { };
1670
1671 for (uint8 i = 0; i < 2; i++) // team positions
1672 {
1673 recvData >> petBattleRequest.Positions[i].x;
1674 recvData >> petBattleRequest.Positions[i].z;
1675 recvData >> petBattleRequest.Positions[i].y;
1676 }
1677
1678 // origin position
1679 recvData >> petBattleRequest.Origin.z;
1680 recvData >> petBattleRequest.Origin.y;
1681 recvData >> petBattleRequest.Origin.x;
1682
1683 recvData.ReadGuidMask(guid, 0);
1684 missingOrientation = recvData.ReadBit();
1685 recvData.ReadGuidMask(guid, 6, 3, 5, 2, 7, 1, 4);
1686 missingResult = recvData.ReadBit();
1687
1688 recvData.ReadGuidBytes(guid, 3, 6, 5, 2, 7, 1, 0, 4);
1689
1690 if (!missingOrientation)
1691 recvData >> petBattleRequest.Orientation;
1692
1693 if (!missingResult)
1694 recvData >> petBattleRequest.LocationResult;
1695
1696 Player* player = GetPlayer();
1697 if (!player)
1698 return;
1699
1700 BattlePetMgr* battlePetMgr = player->GetBattlePetMgr();
1701 if (player->IsInCombat())
1702 {
1704 return;
1705 }
1706
1707 Creature* wildBattlePet = ObjectAccessor::GetCreatureOrPetOrVehicle(*player, guid);
1708 if (!wildBattlePet)
1709 {
1711 return;
1712 }
1713
1715 {
1717 return;
1718 }
1719
1720 if (!battlePetMgr->HasLoadoutBattlePet())
1721 {
1723 return;
1724 }
1725
1726 BattlePet* activeBattlePet = battlePetMgr->GetFirstAliveLoadoutBattlePet();
1727 if (!activeBattlePet)
1728 {
1730 return;
1731 }
1732
1734 uint8 activeBattlePetIndex = 0;
1735 for (uint8 slot = 0; slot < BATTLE_PET_MAX_LOADOUT_SLOTS
1737 {
1738 BattlePet* loadoutBattlePet = battlePetMgr->GetBattlePet(battlePetMgr->GetLoadoutSlot(slot));
1739 if (!loadoutBattlePet)
1740 continue;
1741
1742 uint8 const petIndex = teams[0].PetCount;
1743 teams[0].Pets[petIndex] = Skyfire::BattlePetPackets::BuildInitialUpdatePetData(*loadoutBattlePet);
1744 teams[0].PetCount++;
1745
1746 if (loadoutBattlePet == activeBattlePet)
1747 activeBattlePetIndex = petIndex;
1748 }
1749
1750 teams[0].FrontPet = activeBattlePetIndex;
1751 teams[0].OwnerGuid = player->GetGUID();
1752 teams[0].TrapAbility = battlePetMgr->GetTrapAbility();
1753 teams[1].PetCount = 1;
1755
1756 uint8 wildPetBreed = 0;
1757 if (!BuildWildInitialUpdatePetData(*wildBattlePet, teams[1].Pets[0], wildPetBreed))
1758 {
1760 return;
1761 }
1762
1763 petBattleRequest.EnemyGUID = wildBattlePet->GetGUID();
1765 petBattleRequest.Challenger = player;
1766 petBattleRequest.Enemy = wildBattlePet;
1767 bool const hasClientOrientation = !missingOrientation;
1769 hasClientOrientation, petBattleRequest.Orientation, petBattleRequest.Origin, petBattleRequest.Positions);
1770
1771 battlePetMgr->ApplyActivePetBattlePlayerState(petBattleRequest.Positions[1].x, petBattleRequest.Positions[1].y);
1772
1774 petBattleRequest.Origin, petBattleRequest.Positions, true, petBattleRequest.Orientation,
1775 !missingResult, petBattleRequest.LocationResult);
1776 player->SendDirectMessage(&data);
1777
1778 battlePetMgr->StartWildPetBattle(petBattleRequest.EnemyGUID,
1779 activeBattlePet->GetId(), activeBattlePet->GetMaxHealth(), activeBattlePet->GetCurrentHealth(),
1780 teams[1].Pets[0].Id, teams[1].Pets[0].MaxHealth, teams[1].Pets[0].CurrentHealth,
1781 uint16(teams[1].Pets[0].Species), uint8(teams[1].Pets[0].Level), uint8(teams[1].Pets[0].Quality),
1782 wildPetBreed, activeBattlePetIndex);
1783
1784 for (uint8 petIndex = 0; petIndex < teams[0].PetCount; petIndex++)
1785 battlePetMgr->SetActivePetBattleAllyPet(petIndex, teams[0].Pets[petIndex].Id,
1786 teams[0].Pets[petIndex].MaxHealth, teams[0].Pets[petIndex].CurrentHealth);
1787
1788 battlePetMgr->SelectActivePetBattleFrontPet(activeBattlePetIndex);
1789 teams[0].TrapStatus = battlePetMgr->GetActivePetBattleTrapStatus();
1790
1792 petBattleRequest.EnemyGUID, teams, 2, petBattleRequest.Type != PetBattleRequest::PET_BATTLE_TYPE_PVE);
1793 player->SendDirectMessage(&data2);
1794 battlePetMgr->HideActivePetBattleWorldObject(wildBattlePet);
1795}
1796
1798{
1799
1800}
uint32 BattlePetInputEffectForAbility(uint32 abilityId)
uint8 BattlePetNormalizeWildLevel(uint8 level)
uint16 BattlePetSpeciesIdByNpcId(uint32 npcId)
uint32 BattlePetDamageFromStats(uint32 abilityId, uint16 power, uint8 level)
uint8 BattlePetIncomingDamageReductionRounds(uint32 abilityId)
uint32 BattlePetInputIncomingDamageReductionForAbility(uint32 abilityId, BattlePet const *caster)
uint16 BattlePetAbilityCooldown(uint32 abilityId)
uint16 BattlePetPowerFromBattleState(uint16 species, uint8 level, uint8 quality, uint8 breed)
uint32 BattlePetInputDamageForAbility(uint32 abilityId, BattlePet const *caster)
uint32 BattlePetIncomingDamageReductionFromStats(uint32 abilityId, uint16 power, uint8 level)
#define BATTLE_PET_MAX_NAME_LENGTH
Definition BattlePet.h:13
BattlePetAchievementSource
Definition BattlePet.h:19
@ BATTLE_PET_ACHIEVEMENT_SOURCE_PVP_DUEL
Definition BattlePet.h:21
@ BATTLE_PET_ACHIEVEMENT_SOURCE_PVP_MATCHMAKING
Definition BattlePet.h:22
constexpr uint8 BATTLE_PET_ABILITY_SLOT_INVALID
Definition BattlePet.h:16
uint8 BattlePetAbilitySlotForJournalFlag(uint32 flag)
Definition BattlePet.h:179
constexpr uint8 BATTLE_PET_ABILITY_SLOT_COUNT
Definition BattlePet.h:15
@ BATTLE_PET_JOURNAL_FLAG_ABILITY_2
Definition BattlePet.h:175
@ BATTLE_PET_JOURNAL_FLAG_ABILITY_3
Definition BattlePet.h:176
@ BATTLE_PET_JOURNAL_FLAG_FAVORITES
Definition BattlePet.h:170
@ BATTLE_PET_JOURNAL_FLAG_ABILITY_1
Definition BattlePet.h:174
@ PET_BATTLE_TRAP_STATUS_UNAVAILABLE
@ PET_BATTLE_WINNER_ALLY
@ PET_BATTLE_WINNER_NONE
@ PET_BATTLE_WINNER_ENEMY
BattlePetFlagModes
@ BATTLE_PET_FLAG_MODE_UNSET
@ BATTLE_PET_FLAG_MODE_SET
#define BATTLE_PET_MAX_DECLINED_NAMES
@ PET_BATTLE_REQUEST_FAILED_INVALID_TARGET
@ PET_BATTLE_REQUEST_FAILED_NO_PETS
@ PET_BATTLE_REQUEST_FAILED_ALL_PETS_DEAD
#define BATTLE_PET_MAX_LOADOUT_SLOTS
@ BATTLE_PET_LOADOUT_SLOT_NONE
PetBattlePvpStateStore & GetPetBattlePvpStateStore()
@ BATTLE_PET_FLAG_RELEASABLE
Definition DB2Enums.h:15
@ BATTLE_PET_FLAG_COMPANION
Definition DB2Enums.h:19
uint32 BattlePetGetSpeciesAbility(uint16 speciesId, uint8 abilitySlot, uint16 flags, uint8 level)
bool BattlePetSpeciesHasFlag(uint16 speciesId, uint16 flag)
BattlePetItemXSpeciesStore sBattlePetItemXSpeciesStore
Definition DB2Stores.cpp:48
bool BattlePetHasSpeciesAbility(uint16 speciesId, uint8 abilitySlot, bool alternateAbility, uint8 level)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore(BattlePetSpeciesfmt)
uint32 BattlePetGetSummonSpell(uint16 speciesId)
#define UI64FMTD
Definition Define.h:64
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
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define sObjectAccessor
#define sObjectMgr
Definition ObjectMgr.h:1617
@ UNIT_NPC_FLAG_WILDPET_CAPTURABLE
Definition Unit.h:716
@ UNIT_FIELD_BATTLE_PET_COMPANION_NAME_TIMESTAMP
@ UNIT_FIELD_NPC_FLAGS
void SetFlag(uint16 flag)
void SetNickname(std::string const &nickname)
void UnSetFlag(uint16 flag)
uint8 GetLevel() const
Definition BattlePet.h:219
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
std::string GetNickname() const
Definition BattlePet.h:217
void SetTimestamp(uint32 timestamp)
uint32 GetTimestamp() const
Definition BattlePet.h:218
uint16 GetFlags() const
Definition BattlePet.h:237
bool SetActivePetBattleAllyPet(uint8 petIndex, uint64 petId, uint32 maxHealth, uint32 health)
bool IsPetBattlePvpQueued() const
TempSummon * GetCurrentSummon() const
void StartPvpPetBattle(uint64 opponentGuid, uint64 allyPetId, uint32 allyMaxHealth, uint32 allyHealth, uint64 enemyPetId, uint32 enemyMaxHealth, uint32 enemyHealth, uint16 enemySpecies=0, uint8 enemyLevel=0, uint8 enemyQuality=0, uint8 allyFrontPet=0, uint8 enemyFrontPet=3, BattlePetAchievementSource source=BATTLE_PET_ACHIEVEMENT_SOURCE_PVP_DUEL)
uint8 GetActivePetBattleTrapStatus() const
uint32 GetTrapAbility() const
void HideActivePetBattleWorldObject(Creature *creature)
void SendBattlePetJournal()
void Delete(BattlePet *battlePet)
ActivePetBattle const & GetActivePetBattle() const
void ClearActivePetBattle()
BattlePet * GetFirstAliveLoadoutBattlePet() const
bool ApplyBattlePetAbilityExchangeInput(uint32 roundId, uint32 allyDamage, uint32 allyAbilityEffectId, uint8 allyAbilitySlot, uint32 allyAbilityId, uint16 allyAbilityCooldown, uint32 enemyDamage, uint32 enemyAbilityEffectId, uint32 allyIncomingDamageReduction, uint8 allyIncomingDamageReductionRounds, uint32 enemyIncomingDamageReduction, uint8 enemyIncomingDamageReductionRounds, Skyfire::BattlePetPackets::BattlePetRoundResult &round, Skyfire::BattlePetPackets::BattlePetFinalRound *finalRound=NULL)
void SendBattlePetSlotUpdate(uint8 slot, bool notification, uint64 id=0)
void FinishActivePetBattle(uint8 winner)
bool ApplyBattlePetTrapInput(uint32 roundId, uint32 trapAbilityEffectId, uint32 enemyDamage, uint32 enemyAbilityEffectId, Skyfire::BattlePetPackets::BattlePetRoundResult &round, Skyfire::BattlePetPackets::BattlePetFinalRound &finalRound)
BattlePet * Create(uint16 speciesId)
void SetCurrentSummonId(uint64 summonId)
bool ApplyBattlePetSwapInput(uint32 roundId, uint8 newFrontPet, Skyfire::BattlePetPackets::BattlePetRoundResult &round)
void SendBattlePetJournalLock()
uint64 GetLoadoutSlot(uint8 slot) const
uint64 GetCurrentSummonId() const
uint8 GetLoadoutSlotForBattlePet(uint64 id) const
bool HasLoadoutSlot(uint8 slot) const
void StartWildPetBattle(uint64 enemyGuid, uint64 allyPetId, uint32 allyMaxHealth, uint32 allyHealth, uint64 enemyPetId, uint32 enemyMaxHealth, uint32 enemyHealth, uint16 enemySpecies=0, uint8 enemyLevel=0, uint8 enemyQuality=0, uint8 enemyBreed=0, uint8 allyFrontPet=0)
void SetPetBattlePvpQueued(bool queued)
bool ApplyBattlePetForfeitInput(uint32 roundId, Skyfire::BattlePetPackets::BattlePetFinalRound &finalRound)
BattlePet * GetBattlePet(uint64 id) const
void SetLoadoutSlot(uint8 slot, uint64 id, bool save=false)
void SendBattlePetUpdate(BattlePet *battlePet, bool notification)
bool BuildActivePetBattleFinalRound(bool abandoned, Skyfire::BattlePetPackets::BattlePetFinalRound &finalRound, bool captured=false)
void UnSummonCurrentBattlePet(bool temporary)
void ApplyActivePetBattlePlayerState(float faceX, float faceY)
void SendPetBattleRequestFailed(uint8 reason)
bool HasActivePetBattle() const
bool HasLoadoutBattlePet() const
bool SelectActivePetBattleFrontPet(uint8 frontPet)
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
size_t rpos() const
Definition ByteBuffer.h:470
void WriteString(std::string const &str)
Definition ByteBuffer.h:578
uint32 ReadBits(size_t bits)
Definition ByteBuffer.h:198
void ReadGuidBytes(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:256
void ReadByteSeq(uint8 &b)
Definition ByteBuffer.h:215
std::string ReadString(size_t length)
Definition ByteBuffer.h:565
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 FlushBits()
Definition ByteBuffer.h:154
uint8 * contents()
Definition ByteBuffer.h:605
bool ReadBit()
Definition ByteBuffer.h:180
Definition Item.h:202
uint8 GetSlot() const
Definition Item.h:265
uint8 GetBagSlot() const
Definition Item.cpp:734
static Creature * GetCreatureOrPetOrVehicle(WorldObject const &, uint64)
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
uint32 GetGUIDLow() const
Definition Object.h:120
uint32 GetEntry() const
Definition Object.h:125
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
void ClearProposal(uint64 playerGuid)
ChallengeMap::iterator FindChallengeForPlayer(uint64 playerGuid)
void EraseChallengeForTarget(uint64 targetGuid)
void AddQueueEntry(uint64 playerGuid)
void AddProposalPair(uint64 playerGuid, uint64 opponentGuid, time_t createdAt)
void AddChallenge(PetBattlePvpChallenge const &challenge)
ChallengeTargetMap & ChallengeTargetByChallenger()
void RemoveQueueEntry(uint64 playerGuid)
ChallengeMap & ChallengesByTarget()
QueueContainer & Queue()
BattlePetMgr * GetBattlePetMgr()
Definition Player.h:2573
void SendDirectMessage(WorldPacket *data)
Definition Player.cpp:6904
WorldSession * GetSession() const
Definition Player.h:2417
Item * GetItemByGuid(uint64 guid) const
void DestroyItem(uint8 bag, uint8 slot, bool update)
Player * GetSelectedPlayer() const
Definition Player.cpp:18392
Unit * GetSummoner() const
Definition Unit.h:1367
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void NearTeleportTo(float x, float y, float z, float orientation, bool casting=false)
Definition Unit.cpp:8393
TempSummon * ToTempSummon()
Definition Unit.h:2821
uint8 getLevel() const
Definition Unit.h:1528
bool IsInCombat() const
Definition Unit.h:1896
uint32 GetMapId() const
Definition Object.h:546
Player session in the World.
void HandleBattlePetInputFirstPet(WorldPacket &recvData)
void HandleBattlePetInput(WorldPacket &recvData)
void HandleBattlePetDelete(WorldPacket &recvData)
void HandleBattlePetModifyName(WorldPacket &recvData)
void HandleBattlePetRequestJournal(WorldPacket &recvData)
void HandleBattlePetFinalNotify(WorldPacket &recvData)
void HandleBattlePetCage(WorldPacket &recvData)
void HandlePetBattleRequestPvp(WorldPacket &recvData)
Player * GetPlayer() const
void HandleBattlePetQuitNotify(WorldPacket &recvData)
void ClearPetBattlePvpQueueState()
void UpdatePetBattlePvpQueueState()
void HandlePetBattleStopPvpMatchmaking(WorldPacket &recvData)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void HandleBattlePetRequestUpdate(WorldPacket &recvData)
void HandleBattlePetQueryName(WorldPacket &recvData)
void HandleBattlePetSummonCompanion(WorldPacket &recvData)
void HandlePetBattleQueueProposeMatchResult(WorldPacket &recvData)
void HandleBattlePetLearn(WorldPacket &recvData)
void HandleBattlePetWildRequest(WorldPacket &recvData)
void HandleBattlePetSetBattleSlot(WorldPacket &recvData)
void HandleBattlePetSetFlags(WorldPacket &recvData)
void HandlePetBattleStartPvpMatchmaking(WorldPacket &recvData)
bool HandlePendingPetBattlePvpDuelResponse(bool accepted)
@ SMSG_BATTLE_PET_QUERY_NAME_RESPONSE
Definition Opcodes.h:560
@ SMSG_DUEL_REQUESTED
Definition Opcodes.h:644
WorldPacket BuildQueueStatusPacket(ObjectGuid requesterGuid, uint32 status, uint32 const *slotResults)
BattlePetInput ReadBattlePetInput(WorldPacket &data)
InitialUpdatePetData BuildInitialUpdatePetData(BattlePet const &battlePet)
BattlePetFirstPetSelection ReadBattlePetFirstPetSelection(WorldPacket &data)
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)
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)
WorldPacket BuildRoundResultPacket(BattlePetRoundResult const &round)
float CalculateBattlePetFacing(G3D::Vector3 const &origin, G3D::Vector3 const *positions)
uint8 const INITIAL_UPDATE_MAX_TEAM_PETS
WorldPacket BuildQueueProposeMatchPacket()
float ResolveBattlePetFacing(bool hasClientOrientation, float clientOrientation, G3D::Vector3 const &origin, G3D::Vector3 const *positions)
uint32 NpcId
G3D::Vector3 Positions[2]
G3D::Vector3 Origin
PetBattleType Type
G3D::Vector3 Positions[2]
static float NormalizeOrientation(float o)
Definition Object.h:427
float GetPositionZ() const
Definition Object.h:330
float GetOrientation() const
Definition Object.h:331
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
std::vector< BattlePetFinalRoundPet > Pets
InitialUpdatePetData Pets[INITIAL_UPDATE_MAX_TEAM_PETS]