Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
NPCHandler.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 "Battleground.h"
7#include "BattlegroundMgr.h"
8#include "BlackMarketMgr.h"
9#include "Common.h"
10#include "Creature.h"
11#include "CreatureAI.h"
12#include "DatabaseEnv.h"
13#include "GossipDef.h"
14#include "Language.h"
15#include "Log.h"
16#include "ObjectAccessor.h"
17#include "ObjectMgr.h"
18#include "Opcodes.h"
19#include "Pet.h"
20#include "Player.h"
21#include "ReputationMgr.h"
22#include "ScriptMgr.h"
23#include "SpellInfo.h"
24#include "SpellMgr.h"
25#include "UpdateMask.h"
26#include "WorldPacket.h"
27#include "WorldSession.h"
28
30{
31 STABLE_ERR_MONEY = 0x01, // "you don't have enough money"
32 STABLE_ERR_INVALID_SLOT = 0x03, // "That slot is locked"
33 STABLE_SUCCESS_STABLE = 0x08, // stable success
34 STABLE_SUCCESS_UNSTABLE = 0x09, // unstable/swap success
35 STABLE_SUCCESS_BUY_SLOT = 0x0A, // buy slot success
36 STABLE_ERR_EXOTIC = 0x0B, // "you are unable to control exotic creatures"
37 STABLE_ERR_STABLE = 0x0C, // "Internal pet error"
38};
39
41{
42 ObjectGuid Guid = guid;
44
45 data.WriteGuidMask(Guid, 1, 5, 0, 7, 4, 6, 3, 2);
46 data.WriteGuidBytes(Guid, 5, 4, 2, 3, 6, 0, 1, 7);
47
48 SendPacket(&data);
49}
50
52{
53 ObjectGuid guid;
54
55 SF_LOG_DEBUG("network", "WORLD: Received CMSG_BANKER_ACTIVATE");
56
57 recvData.ReadGuidMask(guid, 4, 5, 0, 6, 1, 2, 7, 3);
58 recvData.ReadGuidBytes(guid, 1, 7, 2, 5, 6, 3, 0, 4);
59
61 if (!unit)
62 {
63 SF_LOG_DEBUG("network", "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid)));
64 return;
65 }
66
67 // remove fake death
68 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
70
71 SendShowBank(guid);
72}
73
75{
76 WorldPacket data(SMSG_SHOW_BANK, 1 + 8);
77
78 data.WriteGuidMask(guid, 2, 4, 3, 6, 5, 1, 7, 0);
79 data.WriteGuidBytes(guid, 7, 0, 5, 3, 6, 1, 4, 2);
80
81 SendPacket(&data);
82}
83
85{
86 ObjectGuid guid;
87
88 recvData.ReadGuidMask(guid, 0, 2, 7, 6, 1, 4, 5, 3);
89 recvData.ReadGuidBytes(guid, 3, 6, 7, 5, 1, 0, 2, 4);
90
91 SendTrainerList(guid);
92}
93
95{
96 std::string str = GetSkyFireString(LANG_NPC_TAINER_HELLO);
97 SendTrainerList(guid, str);
98}
99
100void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
101{
102 SF_LOG_DEBUG("network", "WORLD: SendTrainerList");
103
105 if (!unit)
106 {
107 SF_LOG_DEBUG("network", "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid)));
108 return;
109 }
110
111 // remove fake death
112 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
114
115 CreatureTemplate const* ci = unit->GetCreatureTemplate();
116
117 if (!ci)
118 {
119 SF_LOG_DEBUG("network", "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!", GUID_LOPART(guid));
120 return;
121 }
122
123 TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
124 if (!trainer_spells)
125 {
126 SF_LOG_DEBUG("network", "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)",
127 GUID_LOPART(guid), unit->GetEntry());
128 return;
129 }
130
131 ObjectGuid oGuid = guid;
132
133 WorldPacket data(SMSG_TRAINER_LIST, 1 + 8 + 4 + (trainer_spells->spellList.size() * 30) + 4 + 4 + strTitle.size());
134 data.WriteGuidMask(oGuid, 4, 5);
135
136 size_t count_pos = data.bitwpos();
137 data.WriteBits(0, 19); // placeholder
138
139 data.WriteBits(strTitle.size(), 11);
140 data.WriteGuidMask(oGuid, 6, 2, 7, 1, 3, 0);
141 data.FlushBits();
142
143 data.WriteGuidBytes(oGuid, 4);
144
145 // reputation discount
146 float fDiscountMod = _player->GetReputationPriceDiscount(unit);
147
148 uint32 count = 0;
149 for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
150 {
151 TrainerSpell const* tSpell = &itr->second;
152
153 bool valid = true;
154 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
155 {
156 if (!tSpell->learnedSpell[i])
157 continue;
158 if (!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell[i]))
159 {
160 valid = false;
161 break;
162 }
163 }
164 if (!valid)
165 continue;
166
167 data << uint8(tSpell->reqLevel);
168 data << uint32(floor(tSpell->spellCost * fDiscountMod));
169 data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case)
170
171 // spells required (3 max)
172 uint8 maxReq = 0;
173 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
174 {
175 if (!tSpell->learnedSpell[i])
176 continue;
177 SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]);
178 for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2)
179 {
180 data << uint32(itr2->second);
181 ++maxReq;
182 }
183 if (maxReq == 3)
184 break;
185 }
186 while (maxReq < 3)
187 {
188 data << uint32(0);
189 ++maxReq;
190 }
191
192 data << uint32(tSpell->reqSkill);
193 data << uint32(tSpell->reqSkillValue);
194
195 TrainerSpellState state = _player->GetTrainerSpellState(tSpell);
196 data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state);
197
198 ++count;
199 }
200
201 data.WriteString(strTitle);
202 data.WriteGuidBytes(oGuid, 6, 7, 1, 3);
203 data << uint32(1); // different value for each trainer, also found in CMSG_TRAINER_BUY_SPELL
204 data.WriteGuidBytes(oGuid, 5, 0, 2);
205 data << uint32(trainer_spells->trainerType);
206
207 data.PutBits(count_pos, count, 19);
208 SendPacket(&data);
209}
210
212{
213 ObjectGuid guid;
214 uint32 spellId;
215 uint32 trainerId;
216
217 recvData >> spellId >> trainerId;
218
219 recvData.ReadGuidMask(guid, 1, 4, 0, 6, 3, 2, 5, 7);
220 recvData.ReadGuidBytes(guid, 3, 1, 4, 7, 0, 5, 6, 2);
221
222 SF_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u", uint32(GUID_LOPART(guid)), spellId);
223
225 if (!unit)
226 {
227 SF_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid)));
228 return;
229 }
230
231 // remove fake death
232 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
234
235 // check present spell in trainer spell list
236 TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
237 if (!trainer_spells)
238 {
239 SendTrainerBuyFailed(guid, spellId, 0);
240 return;
241 }
242
243 // not found, cheat?
244 TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
245 if (!trainer_spell)
246 {
247 SendTrainerBuyFailed(guid, spellId, 0);
248 return;
249 }
250
251 // can't be learn, cheat? Or double learn with lags...
252 //if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
253 // SendTrainerBuyFailed(guid, spellId, 0);
254 // return;
255 //}
256
257 // apply reputation discount
258 uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit)));
259
260 // check money requirement
261 if (!_player->HasEnoughMoney(uint64(nSpellCost)))
262 {
263 SendTrainerBuyFailed(guid, spellId, 1);
264 return;
265 }
266
267 _player->ModifyMoney(-int64(nSpellCost));
268
269 unit->SendPlaySpellVisualKit(179, 0, 0); // 53 SpellCastDirected
270 _player->SendPlaySpellVisualKit(362, 1, 0); // 113 EmoteSalute
271
272 // learn explicitly or cast explicitly
273 if (trainer_spell->IsCastable())
274 _player->CastSpell(_player, trainer_spell->spell, true);
275 else
276 _player->learnSpell(spellId, false);
277}
278
280{
281 WorldPacket data(SMSG_TRAINER_BUY_FAILED, 8 + 4 + 4);
282 data.WriteGuidMask(guid, 3, 0, 4, 7, 6, 1, 5, 2);
283
284 data.WriteGuidBytes(guid, 1, 2, 0, 3, 4);
285 data << uint32(reason); // 1 == "Not enough money for trainer service." 0 == "Trainer service %d unavailable."
286 data.WriteGuidBytes(guid, 5, 6, 7);
287 data << uint32(spellId); // should be same as in packet from client
288 SendPacket(&data);
289}
290
292{
293 SF_LOG_DEBUG("network", "WORLD: Received CMSG_GOSSIP_HELLO");
294
295 ObjectGuid guid;
296 recvData.ReadGuidMask(guid, 2, 4, 0, 3, 6, 7, 5, 1);
297 recvData.ReadGuidBytes(guid, 4, 7, 1, 0, 5, 3, 6, 2);
298
300 if (!unit)
301 {
302 SF_LOG_DEBUG("network", "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid)));
303 return;
304 }
305
306 // set faction visible if needed
307 if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction()))
308 _player->GetReputationMgr().SetVisible(factionTemplateEntry);
309
311 // remove fake death
312 //if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
313 // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
314
315 if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard())
316 unit->StopMoving();
317
318 if (unit->IsBMAuctioner())
319 {
320 _player->GetSession()->SendBlackMarketHello(unit->GetGUID(), sBlackMarketMgr->isBlackMarketOpen());
321 return;
322 }
323
324 // If spiritguide, no need for gossip menu, just put player into resurrect queue
325 if (unit->IsSpiritGuide())
326 {
327 Battleground* bg = _player->GetBattleground();
328 if (bg)
329 {
330 bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
331 sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
332 return;
333 }
334 }
335
336 _player->PlayerTalkClass->ClearMenus();
337 if (!sScriptMgr->OnGossipHello(_player, unit) && !unit->AI()->OnGossipHello(_player))
338 {
339 _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID());
340 _player->PrepareGossipMenu(unit, unit->GetCreatureTemplate()->GossipMenuId, true);
341 _player->SendPreparedGossip(unit);
342 }
343}
344
345/*void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recvData)
346{
347 SF_LOG_DEBUG("network", "WORLD: CMSG_GOSSIP_SELECT_OPTION");
348
349 uint32 option;
350 uint32 unk;
351 uint64 guid;
352 std::string code = "";
353
354 recvData >> guid >> unk >> option;
355
356 if (_player->PlayerTalkClass->GossipOptionCoded(option))
357 {
358 SF_LOG_DEBUG("network", "reading string");
359 recvData >> code;
360 SF_LOG_DEBUG("network", "string read: %s", code.c_str());
361 }
362
363 Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE);
364 if (!unit)
365 {
366 SF_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
367 return;
368 }
369
370 // remove fake death
371 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
372 GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
373
374 if (!code.empty())
375 {
376 if (!Script->GossipSelectWithCode(_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction(option), code.c_str()))
377 unit->OnGossipSelect (_player, option);
378 }
379 else
380 {
381 if (!Script->OnGossipSelect (_player, unit, _player->PlayerTalkClass->GossipOptionSender (option), _player->PlayerTalkClass->GossipOptionAction (option)))
382 unit->OnGossipSelect (_player, option);
383 }
384}*/
385
387{
388 SF_LOG_DEBUG("network", "WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
389
390 ObjectGuid UnitGUID;
391
392 recvData.ReadGuidMask(UnitGUID, 2, 7, 6, 0, 5, 4, 1, 3);
393 recvData.ReadGuidBytes(UnitGUID, 1, 5, 6, 3, 2, 0, 7, 4);
394
396 if (!unit)
397 {
398 SF_LOG_DEBUG("network", "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(UnitGUID)));
399 return;
400 }
401
402 // remove fake death
403 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
405
407}
408
410{
411 _player->ResurrectPlayer(0.5f, true);
412
413 _player->DurabilityLossAll(0.25f, true);
414
415 // get corpse nearest graveyard
416 WorldSafeLocsEntry const* corpseGrave = NULL;
417 Corpse* corpse = _player->GetCorpse();
418 if (corpse)
419 corpseGrave = sObjectMgr->GetClosestGraveYard(
420 corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam());
421
422 // now can spawn bones
423 _player->SpawnCorpseBones();
424
425 // teleport to nearest from corpse graveyard, if different from nearest to player ghost
426 if (corpseGrave)
427 {
428 WorldSafeLocsEntry const* ghostGrave = sObjectMgr->GetClosestGraveYard(
429 _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam());
430
431 if (corpseGrave != ghostGrave)
432 _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
433 // or update at original position
434 else
435 _player->UpdateObjectVisibility();
436 }
437 // or update at original position
438 else
439 _player->UpdateObjectVisibility();
440}
441
443{
444 ObjectGuid npcGuid;
445
446 recvData.ReadGuidMask(npcGuid, 0, 5, 4, 7, 6, 2, 1, 3);
447 recvData.ReadGuidBytes(npcGuid, 0, 4, 2, 3, 7, 1, 5, 6);
448
449 if (!GetPlayer()->IsInWorld() || !GetPlayer()->IsAlive())
450 return;
451
453 if (!unit)
454 {
455 SF_LOG_DEBUG("network", "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGuid)));
456 return;
457 }
458
459 // remove fake death
460 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
462
463 SendBindPoint(unit);
464}
465
467{
468 // prevent set homebind to instances in any case
469 if (GetPlayer()->GetMap()->Instanceable())
470 return;
471
472 uint32 bindspell = 3286;
473
474 // send spell for homebinding (3286)
475 npc->CastSpell(_player, bindspell, true);
476
477 _player->PlayerTalkClass->SendCloseGossip();
478}
479
481{
482 SF_LOG_DEBUG("network", "WORLD: Recv CMSG_REQUEST_STABLED_PETS");
483 ObjectGuid npcGUID;
484
485 recvData.ReadGuidMask(npcGUID, 0, 5, 1, 3, 6, 7, 2, 4);
486 recvData.ReadGuidBytes(npcGUID, 0, 5, 7, 1, 2, 3, 4, 6);
487
488 if (!CheckStableMaster(npcGUID))
489 return;
490
491 // remove fake death
492 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
494
495 // remove mounts this fix bug where getting pet from stable while mounted deletes pet.
496 if (GetPlayer()->IsMounted())
498
499 SendStablePet(npcGUID);
500}
501
503{
505
506 stmt->setUInt32(0, _player->GetGUIDLow());
509
510 _sendStabledPetCallback.SetParam(guid);
511 _sendStabledPetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
512}
513
515{
516 if (!GetPlayer())
517 return;
518
519 SF_LOG_DEBUG("network", "WORLD: Recv MSG_LIST_STABLED_PETS Send.");
520
521 WorldPacket data(SMSG_PET_STABLE_LIST, 200); // guess size
522
523 data << uint64(guid);
524
525 Pet* pet = _player->GetPet();
526
527 size_t wpos = data.wpos();
528 data << uint8(0); // place holder for slot show number
529
530 data << uint8(GetPlayer()->m_stableSlots);
531
532 uint8 num = 0; // counter for place holder
533
534 // not let move dead pet in slot
535 if (pet && pet->IsAlive() && pet->getPetType() == PetType::HUNTER_PET)
536 {
537 data << uint32(0); // 4.x unknown, some kind of order?
538 data << uint32(pet->GetCharmInfo()->GetPetNumber());
539 data << uint32(pet->GetEntry());
540 data << uint32(pet->getLevel());
541 data << pet->GetName(); // petname
542 data << uint8(1); // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)
543 ++num;
544 }
545
546 if (result)
547 {
548 do
549 {
550 Field* fields = result->Fetch();
551
552 data << uint32(fields[1].GetUInt32()); // petnumber
553 data << uint32(fields[2].GetUInt32()); // creature entry
554 data << uint32(fields[3].GetUInt16()); // level
555 data << fields[4].GetString(); // name
556 data << uint8(2); // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)
557
558 ++num;
559 } while (result->NextRow());
560 }
561
562 data.put<uint8>(wpos, num); // set real data to placeholder
563 SendPacket(&data);
564}
565
567{
569 data << uint8(res);
570 SendPacket(&data);
571}
572
574{
575 SF_LOG_DEBUG("network", "WORLD: Recv CMSG_STABLE_PET");
576 uint64 npcGUID;
577
578 recvData >> npcGUID;
579
580 if (!GetPlayer()->IsAlive())
581 {
583 return;
584 }
585
586 if (!CheckStableMaster(npcGUID))
587 {
589 return;
590 }
591
592 // remove fake death
593 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
595
596 Pet* pet = _player->GetPet();
597
598 // can't place in stable dead pet
599 if (!pet || !pet->IsAlive() || pet->getPetType() != PetType::HUNTER_PET)
600 {
602 return;
603 }
604
605 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOTS);
606
607 stmt->setUInt32(0, _player->GetGUIDLow());
610
611 _stablePetCallback = CharacterDatabase.AsyncQuery(stmt);
612}
613
615{
616 if (!GetPlayer())
617 return;
618
619 uint8 freeSlot = 1;
620 if (result)
621 {
622 do
623 {
624 Field* fields = result->Fetch();
625
626 uint8 slot = fields[1].GetUInt8();
627
628 // slots ordered in query, and if not equal then free
629 if (slot != freeSlot)
630 break;
631
632 // this slot not free, skip
633 ++freeSlot;
634 } while (result->NextRow());
635 }
636
637 if (freeSlot > 0 && freeSlot <= GetPlayer()->m_stableSlots)
638 {
639 _player->RemovePet(_player->GetPet(), PetSaveMode(freeSlot));
641 }
642 else
644}
645
647{
648 SF_LOG_DEBUG("network", "WORLD: Recv CMSG_UNSTABLE_PET.");
649 uint64 npcGUID;
650 uint32 petnumber;
651
652 recvData >> npcGUID >> petnumber;
653
654 if (!CheckStableMaster(npcGUID))
655 {
657 return;
658 }
659
660 // remove fake death
661 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
663
664 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_ENTRY);
665
666 stmt->setUInt32(0, _player->GetGUIDLow());
667 stmt->setUInt32(1, petnumber);
670
671 _unstablePetCallback.SetParam(petnumber);
672 _unstablePetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
673}
674
676{
677 if (!GetPlayer())
678 return;
679
680 uint32 petEntry = 0;
681 if (result)
682 {
683 Field* fields = result->Fetch();
684 petEntry = fields[0].GetUInt32();
685 }
686
687 if (!petEntry)
688 {
690 return;
691 }
692
693 CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry);
694 if (!creatureInfo || !creatureInfo->IsTameable(_player->CanTameExoticPets()))
695 {
696 // if problem in exotic pet
697 if (creatureInfo && creatureInfo->IsTameable(true))
699 else
701 return;
702 }
703
704 Pet* pet = _player->GetPet();
705 if (pet && pet->IsAlive())
706 {
708 return;
709 }
710
711 // delete dead pet
712 if (pet)
713 _player->RemovePet(pet, PET_SAVE_AS_DELETED);
714
715 Pet* newPet = new Pet(_player, PetType::HUNTER_PET);
716 if (!newPet->LoadPetFromDB(_player, petEntry, petId))
717 {
718 delete newPet;
719 newPet = NULL;
721 return;
722 }
723
725}
726
728{
729 SF_LOG_DEBUG("network", "WORLD: Recv CMSG_BUY_STABLE_SLOT.");
730 uint64 npcGUID;
731
732 recvData >> npcGUID;
733
734 if (!CheckStableMaster(npcGUID))
735 {
737 return;
738 }
739
740 // remove fake death
741 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
743
744 if (GetPlayer()->m_stableSlots < MAX_PET_STABLES)
745 {
746 /*StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
747 if (_player->HasEnoughMoney(SlotPrice->Price))
748 {
749 ++GetPlayer()->m_stableSlots;
750 _player->ModifyMoney(-int32(SlotPrice->Price));
751 SendStableResult(STABLE_SUCCESS_BUY_SLOT);
752 }
753 else
754 SendStableResult(STABLE_ERR_MONEY);*/
755 }
756 else
758}
759
761{
762 SF_LOG_DEBUG("network", "HandleStableRevivePet: Not implemented");
763}
764
766{
767 SF_LOG_DEBUG("network", "WORLD: Recv CMSG_STABLE_SWAP_PET.");
768 uint64 npcGUID;
769 uint32 petId;
770
771 recvData >> npcGUID >> petId;
772
773 if (!CheckStableMaster(npcGUID))
774 {
776 return;
777 }
778
779 // remove fake death
780 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
782
783 Pet* pet = _player->GetPet();
784
785 if (!pet || pet->getPetType() != PetType::HUNTER_PET)
786 {
788 return;
789 }
790
791 // Find swapped pet slot in stable
792
793 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOT_BY_ID);
794
795 stmt->setUInt32(0, _player->GetGUIDLow());
796 stmt->setUInt32(1, petId);
797
798 _stableSwapCallback.SetParam(petId);
799 _stableSwapCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
800}
801
803{
804 if (!GetPlayer())
805 return;
806
807 if (!result)
808 {
810 return;
811 }
812
813 Field* fields = result->Fetch();
814
815 uint32 slot = fields[0].GetUInt8();
816 uint32 petEntry = fields[1].GetUInt32();
817
818 if (!petEntry)
819 {
821 return;
822 }
823
824 CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry);
825 if (!creatureInfo || !creatureInfo->IsTameable(true))
826 {
828 return;
829 }
830
831 if (!creatureInfo->IsTameable(_player->CanTameExoticPets()))
832 {
834 return;
835 }
836
837 Pet* pet = _player->GetPet();
838 // The player's pet could have been removed during the delay of the DB callback
839 if (!pet)
840 {
842 return;
843 }
844
845 // move alive pet to slot or delete dead pet
846 _player->RemovePet(pet, pet->IsAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
847
848 // summon unstabled pet
849 Pet* newPet = new Pet(_player);
850 if (!newPet->LoadPetFromDB(_player, petEntry, petId))
851 {
852 delete newPet;
854 }
855 else
857}
858
860{
861 SF_LOG_DEBUG("network", "WORLD: CMSG_REPAIR_ITEM");
862
863 ObjectGuid npcGuid, itemGuid;
864 bool guildBank; // new in 2.3.2, bool that means from guild bank money
865
866 recvData.ReadGuidMask(itemGuid, 2, 5);
867 recvData.ReadGuidMask(npcGuid, 3);
868 guildBank = recvData.ReadBit();
869 recvData.ReadGuidMask(npcGuid, 7);
870 recvData.ReadGuidMask(itemGuid, 4);
871 recvData.ReadGuidMask(npcGuid, 2);
872 recvData.ReadGuidMask(itemGuid, 0, 3);
873 recvData.ReadGuidMask(npcGuid, 6, 1, 4);
874 recvData.ReadGuidMask(itemGuid, 6);
875 recvData.ReadGuidMask(npcGuid, 5, 0);
876 recvData.ReadGuidMask(itemGuid, 7, 1);
877
878 recvData.ReadGuidBytes(itemGuid, 2);
879 recvData.ReadGuidBytes(npcGuid, 1);
880 recvData.ReadGuidBytes(itemGuid, 1);
881 recvData.ReadGuidBytes(npcGuid, 4, 7, 3, 2);
882 recvData.ReadGuidBytes(itemGuid, 7);
883 recvData.ReadGuidBytes(npcGuid, 5, 0);
884 recvData.ReadGuidBytes(itemGuid, 5, 3, 4, 6);
885 recvData.ReadGuidBytes(npcGuid, 6);
886 recvData.ReadGuidBytes(itemGuid, 0);
887
889 if (!unit)
890 {
891 SF_LOG_DEBUG("network", "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(npcGuid)));
892 return;
893 }
894
895 // remove fake death
896 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
898
899 // reputation discount
900 float discountMod = _player->GetReputationPriceDiscount(unit);
901
902 if (itemGuid)
903 {
904 SF_LOG_DEBUG("network", "ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGuid), GUID_LOPART(npcGuid));
905
906 Item* item = _player->GetItemByGuid(itemGuid);
907 if (item)
908 _player->DurabilityRepair(item->GetPos(), true, discountMod, guildBank);
909 }
910 else
911 {
912 SF_LOG_DEBUG("network", "ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGuid));
913 _player->DurabilityRepairAll(true, discountMod, guildBank);
914 }
915}
#define sBattlegroundMgr
#define sBlackMarketMgr
@ CHAR_SEL_PET_ENTRY
@ CHAR_SEL_PET_SLOTS
@ CHAR_SEL_PET_SLOT_BY_ID
@ CHAR_SEL_PET_SLOTS_DETAIL
DBCStorage< FactionTemplateEntry > sFactionTemplateStore(FactionTemplateEntryfmt)
#define MAX_SPELL_EFFECTS
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::int64_t int64
Definition Define.h:72
@ LANG_NPC_TAINER_HELLO
Definition Language.h:64
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
StableResultCode
@ STABLE_ERR_INVALID_SLOT
@ STABLE_ERR_MONEY
@ STABLE_SUCCESS_STABLE
@ STABLE_SUCCESS_BUY_SLOT
@ STABLE_ERR_EXOTIC
@ STABLE_ERR_STABLE
@ STABLE_SUCCESS_UNSTABLE
uint32 GUID_LOPART(uint64 x)
#define sObjectMgr
Definition ObjectMgr.h:1617
PetSaveMode
Definition PetDefines.h:20
@ PET_SAVE_FIRST_STABLE_SLOT
Definition PetDefines.h:23
@ PET_SAVE_LAST_STABLE_SLOT
Definition PetDefines.h:24
@ PET_SAVE_AS_DELETED
Definition PetDefines.h:21
#define MAX_PET_STABLES
Definition PetDefines.h:16
@ HUNTER_PET
Definition PetDefines.h:12
TrainerSpellState
Definition Player.h:309
@ TRAINER_SPELL_GREEN
Definition Player.h:311
@ TRAINER_SPELL_GREEN_DISABLED
Definition Player.h:313
Skyfire::AutoPtr< PreparedResultSet, Skyfire::Mutex > PreparedQueryResult
Definition QueryResult.h:94
#define sScriptMgr
Definition ScriptMgr.h:764
@ SPELL_AURA_MOUNTED
@ SPELL_AURA_FEIGN_DEATH
std::pair< SpellsRequiringSpellMap::const_iterator, SpellsRequiringSpellMap::const_iterator > SpellsRequiringSpellMapBounds
Definition SpellMgr.h:520
#define sSpellMgr
Definition SpellMgr.h:744
@ UNIT_NPC_FLAG_BANKER
Definition Unit.h:704
@ UNIT_NPC_FLAG_NONE
Definition Unit.h:686
@ UNIT_NPC_FLAG_INNKEEPER
Definition Unit.h:703
@ UNIT_NPC_FLAG_REPAIR
Definition Unit.h:699
@ UNIT_NPC_FLAG_TRAINER
Definition Unit.h:691
@ UNIT_NPC_FLAG_SPIRITHEALER
Definition Unit.h:701
@ AURA_INTERRUPT_FLAG_TALK
Definition Unit.h:51
@ UNIT_STATE_DIED
Definition Unit.h:512
void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid)
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
void put(size_t pos, T value)
Definition ByteBuffer.h:233
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
size_t bitwpos() const
Returns position of last written bit.
Definition ByteBuffer.h:492
void WriteString(std::string const &str)
Definition ByteBuffer.h:578
void ReadGuidBytes(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:256
void PutBits(size_t pos, T value, uint32 bitCount)
Definition ByteBuffer.h:283
size_t wpos() const
Definition ByteBuffer.h:483
void ReadGuidMask(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:240
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void FlushBits()
Definition ByteBuffer.h:154
bool ReadBit()
Definition ByteBuffer.h:180
bool IsCivilian() const
Definition Creature.h:453
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:524
TrainerSpellData const * GetTrainerSpells() const
bool IsGuard() const
Definition Creature.h:455
CreatureAI * AI() const
Definition Creature.h:483
Definition Field.h:16
uint8 GetUInt8() const
Definition Field.h:26
std::string GetString() const
Definition Field.h:228
uint32 GetUInt32() const
Definition Field.h:105
Definition Item.h:202
uint16 GetPos() const
Definition Item.h:269
uint64 GetGUID() const
Definition Object.h:119
uint32 GetEntry() const
Definition Object.h:125
Definition Pet.h:28
PetType getPetType() const
Definition Pet.h:38
bool LoadPetFromDB(Player *owner, uint32 petentry=0, uint32 petnumber=0, bool current=false)
Definition Pet.cpp:91
Creature * GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
Definition Player.cpp:2836
void setUInt32(const uint8 index, const uint32 value)
void setUInt8(const uint8 index, const uint8 value)
virtual bool OnGossipHello(Player *player)
Definition UnitAI.h:245
uint32 getFaction() const
Definition Unit.h:1695
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except=0)
bool IsArmorer() const
Definition Unit.h:1877
bool IsAlive() const
Definition Unit.h:2032
void StopMoving()
-------—End of Pet responses methods-------—
Definition Unit.cpp:5877
bool IsQuestGiver() const
Definition Unit.h:1833
CharmInfo * GetCharmInfo()
Definition Unit.h:2148
bool IsBMAuctioner() const
Definition Unit.h:1886
void RemoveAurasByType(AuraType auraType, uint64 casterGUID=0, Aura *except=NULL, bool negative=true, bool positive=true)
uint8 getLevel() const
Definition Unit.h:1528
bool IsServiceProvider() const
Definition Unit.cpp:3786
void SendPlaySpellVisualKit(uint32 SpellVisualId, uint32 Duration, int32 Type)
Definition Unit.cpp:7377
bool IsSpiritGuide() const
Definition Unit.h:1865
uint32 GetMapId() const
Definition Object.h:546
std::string const & GetName() const
Definition Object.h:664
void HandleUnstablePetCallback(PreparedQueryResult result, uint32 petId)
const char * GetSkyFireString(int32 entry) const
PreparedQueryResultFuture _stablePetCallback
void HandleUnstablePet(WorldPacket &recvPacket)
void SendTrainerList(uint64 guid)
void HandleTrainerBuySpellOpcode(WorldPacket &recvPacket)
bool CheckStableMaster(uint64 guid)
void SendStablePet(uint64 guid)
void HandleStableRevivePet(WorldPacket &recvPacket)
void HandleBinderActivateOpcode(WorldPacket &recvPacket)
void HandleStablePet(WorldPacket &recvPacket)
Player * GetPlayer() const
void SendTrainerBuyFailed(ObjectGuid guid, uint32 spellId, uint32 reason)
void SendBindPoint(Creature *npc)
void HandleTrainerListOpcode(WorldPacket &recvPacket)
void SendSpiritResurrect()
void HandleBuyStableSlot(WorldPacket &recvPacket)
void SendTabardVendorActivate(uint64 guid)
void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId)
void HandleBankerActivateOpcode(WorldPacket &recvPacket)
QueryCallback< PreparedQueryResult, uint32 > _unstablePetCallback
void HandleGossipHelloOpcode(WorldPacket &recvPacket)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void HandleRepairItemOpcode(WorldPacket &recvPacket)
void HandleRequestStabledPetsOpcode(WorldPacket &recvPacket)
Player * _player
void SendShowBank(ObjectGuid guid)
void HandleSpiritHealerActivateOpcode(WorldPacket &recvPacket)
void SendStableResult(uint8 guid)
QueryCallback< PreparedQueryResult, uint32 > _stableSwapCallback
void SendStablePetCallback(PreparedQueryResult result, uint64 guid)
void HandleStablePetCallback(PreparedQueryResult result)
void HandleStableSwapPet(WorldPacket &recvPacket)
QueryCallback< PreparedQueryResult, uint64 > _sendStabledPetCallback
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
@ SMSG_TABARD_VENDOR_ACTIVATE
Definition Opcodes.h:1023
@ SMSG_TRAINER_BUY_FAILED
Definition Opcodes.h:1035
@ SMSG_PET_STABLE_LIST
Definition Opcodes.h:873
@ SMSG_SHOW_BANK
Definition Opcodes.h:966
@ SMSG_STABLE_RESULT
Definition Opcodes.h:1016
@ SMSG_TRAINER_LIST
Definition Opcodes.h:1036
uint32 GetPetNumber() const
Definition Unit.h:1241
uint32 GossipMenuId
Definition Creature.h:74
bool IsTameable(bool canTameExotic) const
Definition Creature.h:153
float GetPositionZ() const
Definition Object.h:330
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
TrainerSpellMap spellList
Definition Creature.h:413
uint32 trainerType
Definition Creature.h:414
TrainerSpell const * Find(uint32 spell_id) const
Definition Creature.cpp:46
uint32 reqSkillValue
Definition Creature.h:398
bool IsCastable() const
Definition Creature.h:403
uint32 spellCost
Definition Creature.h:396
uint32 reqSkill
Definition Creature.h:397
uint32 reqLevel
Definition Creature.h:399
uint32 learnedSpell[MAX_SPELL_EFFECTS]
Definition Creature.h:400
uint32 spell
Definition Creature.h:395
float x
float z
float y
uint32 map_id