Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
QuestHandler.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 "Common.h"
8#include "GameObjectAI.h"
9#include "GossipDef.h"
10#include "Group.h"
11#include "Log.h"
12#include "ObjectAccessor.h"
13#include "ObjectMgr.h"
14#include "Opcodes.h"
15#include "Player.h"
16#include "QuestDef.h"
17#include "ScriptMgr.h"
18#include "World.h"
19#include "WorldPacket.h"
20#include "WorldSession.h"
21
23{
24 if (!_player || _player->IsInCinematic() || isLogingOut())
25 return;
26
27 ObjectGuid guid;
28
29 recvData.ReadGuidMask(guid, 4, 3, 2, 1, 0, 5, 7, 6);
30 recvData.ReadGuidBytes(guid, 5, 7, 4, 0, 2, 1, 6, 3);
31
32 uint32 questStatus = DIALOG_STATUS_NONE;
33 uint32 defstatus = DIALOG_STATUS_NONE;
34
36 if (!questgiver)
37 {
38 SF_LOG_INFO("network", "Error in CMSG_QUEST_GIVER_STATUS_QUERY, called for non-existing questgiver (Typeid: %u GUID: %u)", uint8(GuidHigh2TypeId(GUID_HIPART(guid))), GUID_LOPART(guid));
39 return;
40 }
41
42 switch (questgiver->GetTypeId())
43 {
45 {
46 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_STATUS_QUERY for npc, guid = %u", uint32(GUID_LOPART(guid)));
47 Creature* cr_questgiver = questgiver->ToCreature();
48 if (!cr_questgiver->IsHostileTo(_player)) // do not show quest status to enemies
49 {
50 questStatus = sScriptMgr->GetDialogStatus(_player, cr_questgiver);
51 if (questStatus > 6)
52 questStatus = getDialogStatus(_player, cr_questgiver, defstatus);
53 }
54 break;
55 }
57 {
58 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_STATUS_QUERY for GameObject guid = %u", uint32(GUID_LOPART(guid)));
59 GameObject* go_questgiver = (GameObject*)questgiver;
60 questStatus = sScriptMgr->GetDialogStatus(_player, go_questgiver);
61 if (questStatus > 6)
62 questStatus = getDialogStatus(_player, go_questgiver, defstatus);
63 break;
64 }
65 default:
66 SF_LOG_ERROR("network", "QuestGiver called for unexpected type %u", uint8(questgiver->GetTypeId()));
67 break;
68 }
69
70 //inform client about status of quest
71 _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid);
72}
73
75{
76 ObjectGuid guid;
77
78 recvData.ReadGuidMask(guid, 5, 6, 7, 3, 4, 2, 1, 0);
79 recvData.ReadGuidBytes(guid, 4, 1, 7, 3, 6, 0, 5, 2);
80
81 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_HELLO npc = %u", GUID_LOPART(guid));
82
84 if (!creature)
85 {
86 SF_LOG_DEBUG("network", "WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.",
87 GUID_LOPART(guid));
88 return;
89 }
90
91 // remove fake death
92 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
94 // Stop the npc if moving
95 creature->StopMoving();
96
97 _player->PlayerTalkClass->ClearMenus();
98 if (sScriptMgr->OnGossipHello(_player, creature) || creature->AI()->OnGossipHello(_player))
99 return;
100
101 _player->PrepareGossipMenu(creature, creature->GetCreatureTemplate()->GossipMenuId, true);
102 _player->SendPreparedGossip(creature);
103}
104
106{
107 ObjectGuid guid;
108 uint32 questId;
109
110 recvData >> questId;
111
112 recvData.ReadGuidMask(guid, 6, 0);
113 recvData.ReadBit();
114 recvData.ReadGuidMask(guid, 2, 7, 5, 4, 3, 1);
115
116 recvData.ReadGuidBytes(guid, 5, 4, 0, 1, 6, 2, 3, 7);
117
118 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_ACCEPT_QUEST npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId);
119
121
122#define CLOSE_GOSSIP_CLEAR_DIVIDER() \
123 do { \
124 _player->PlayerTalkClass->SendCloseGossip(); \
125 _player->SetDivider(0); \
126 } while (0)
127
128 // no or incorrect quest giver
129 if (!object)
130 {
132 return;
133 }
134
135 if (Player* playerQuestObject = object->ToPlayer())
136 {
137 if ((_player->GetDivider() && _player->GetDivider() != guid) || !playerQuestObject->CanShareQuest(questId))
138 {
140 return;
141 }
142 }
143 else
144 {
145 if (!object->hasQuest(questId))
146 {
148 return;
149 }
150 }
151
152 // some kind of WPE protection
153 if (!_player->CanInteractWithQuestGiver(object))
154 return;
155
156 if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
157 {
158 // prevent cheating
159 if (!GetPlayer()->CanTakeQuest(quest, true))
160 {
162 return;
163 }
164
165 if (_player->GetDivider() != 0)
166 {
167 Player* player = ObjectAccessor::FindPlayer(_player->GetDivider());
168 if (player)
169 {
171 _player->SetDivider(0);
172 }
173 }
174
175 if (_player->CanAddQuest(quest, true))
176 {
177 _player->AddQuest(quest, object);
178
179 // QUEST_FLAGS_PARTY_ACCEPT
180 if (quest->HasFlag(QUEST_FLAGS_START_EVENT_MUST_COMPLETE))
181 {
182 if (Group* group = _player->GetGroup())
183 {
184 for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
185 {
186 Player* player = itr->GetSource();
187
188 if (!player || player == _player) // not self
189 continue;
190
191 if (player->CanTakeQuest(quest, true))
192 {
193 player->SetDivider(_player->GetGUID());
194
195 //need confirmation that any gossip window will close
197
198 _player->SendQuestConfirmAccept(quest, player);
199 }
200 }
201 }
202 }
203
204 if (_player->CanCompleteQuest(questId))
205 _player->CompleteQuest(questId);
206
207 switch (object->GetTypeId())
208 {
210 object->ToCreature()->AI()->sQuestAccept(_player, quest);
211 break;
214 {
215 Item* item = (Item*)object;
216
217 // destroy not required for quest finish quest starting item
218 bool destroyItem = true;
219
220 if (!quest->GetQuestObjectiveCountType(QUEST_OBJECTIVE_TYPE_ITEM))
221 break;
222
223 for (QuestObjectiveSet::const_iterator citr = quest->m_questObjectives.begin(); citr != quest->m_questObjectives.end(); ++citr)
224 {
225 if ((*citr)->ObjectId == item->GetEntry() && item->GetTemplate()->MaxCount > 0)
226 {
227 destroyItem = false;
228 break;
229 }
230 }
231
232 if (destroyItem)
233 _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
234
235 break;
236 }
238 object->ToGameObject()->AI()->QuestAccept(_player, quest);
239 break;
240 default:
241 break;
242 }
243 _player->PlayerTalkClass->SendCloseGossip();
244
245 if (quest->GetSrcSpell() > 0)
246 _player->CastSpell(_player, quest->GetSrcSpell(), true);
247
248 return;
249 }
250 }
251
252 _player->PlayerTalkClass->SendCloseGossip();
253
254#undef CLOSE_GOSSIP_CLEAR_DIVIDER
255}
256
258{
259 ObjectGuid guid;
260 uint32 questId;
261
262 recvData >> questId;
263 guid[2] = recvData.ReadBit();
264 guid[6] = recvData.ReadBit();
265 guid[5] = recvData.ReadBit();
266 guid[0] = recvData.ReadBit();
267 guid[4] = recvData.ReadBit();
268 guid[3] = recvData.ReadBit();
269 guid[1] = recvData.ReadBit();
270 guid[7] = recvData.ReadBit();
271 recvData.ReadBit();
272
273 recvData.ReadByteSeq(guid[2]);
274 recvData.ReadByteSeq(guid[0]);
275 recvData.ReadByteSeq(guid[4]);
276 recvData.ReadByteSeq(guid[7]);
277 recvData.ReadByteSeq(guid[5]);
278 recvData.ReadByteSeq(guid[1]);
279 recvData.ReadByteSeq(guid[3]);
280 recvData.ReadByteSeq(guid[6]);
281
282 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_QUERY_QUEST npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId);
283
284 // Verify that the guid is valid and is a questgiver or involved in the requested quest
286 if (!object || (!object->hasQuest(questId) && !object->hasInvolvedQuest(questId)))
287 {
288 _player->PlayerTalkClass->SendCloseGossip();
289 return;
290 }
291
292 if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
293 {
294 // not sure here what should happen to quests with QUEST_FLAGS_AUTOCOMPLETE
295 // if this breaks them, add && object->GetTypeId() == TYPEID_ITEM to this check
296 // item-started quests never have that flag
297 if (!_player->CanTakeQuest(quest, true))
298 return;
299
300 if (quest->IsAutoAccept() && _player->CanAddQuest(quest, true))
301 {
302 _player->AddQuest(quest, object);
303 if (_player->CanCompleteQuest(questId))
304 _player->CompleteQuest(questId);
305 }
306
307 if (quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
308 _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, object->GetGUID(), _player->CanCompleteQuest(quest->GetQuestId()), true);
309 else
310 _player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, object->GetGUID(), true);
311 }
312}
313
315{
316 if (!_player)
317 return;
318
319 ObjectGuid guid;
320 uint32 questId;
321
322 recvData >> questId;
323
324 recvData.ReadGuidMask(guid, 0, 5, 2, 7, 6, 4, 1, 3);
325 recvData.ReadGuidBytes(guid, 4, 1, 7, 5, 2, 3, 6, 0);
326
327 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_QUERY quest = %u", questId);
328
329 if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
330 _player->PlayerTalkClass->SendQuestQueryResponse(quest);
331}
332
334{
335 uint32 questId, reward;
336 ObjectGuid guid;
337
338 recvData >> reward; // 5.x - reward value is now an item ID and not slot ID
339 recvData >> questId;
340
341 recvData.ReadGuidMask(guid, 2, 6, 0, 5, 1, 3, 7, 4);
342 recvData.ReadGuidBytes(guid, 1, 2, 5, 7, 0, 3, 6, 4);
343
344 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_CHOOSE_REWARD npc = %u, quest = %u, reward = %u", uint32(GUID_LOPART(guid)), questId, reward);
345
346 Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
347 if (!quest)
348 return;
349
350 Object* object = _player;
351
352 if (quest->GetRewardPackageItemId() == 0)
353 {
354 if (!quest->IsRewChoiceItemValid(reward))
355 {
356 SF_LOG_ERROR("network", "Error in CMSG_QUEST_GIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUIDLow(), reward);
357 return;
358 }
359 }
360
361 // QUEST_FLAGS_AUTO_SUBMIT
363 {
365 if (!object || !object->hasInvolvedQuest(questId))
366 return;
367
368 // some kind of WPE protection
369 if (!_player->CanInteractWithQuestGiver(object))
370 return;
371 }
372
373 if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) ||
374 (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete()))
375 {
376 SF_LOG_ERROR("network", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
377 _player->GetName().c_str(), _player->GetGUIDLow(), questId);
378 return;
379 }
380 if (_player->CanRewardQuest(quest, reward, true))
381 {
382 _player->RewardQuest(quest, reward, object);
383
384 switch (object->GetTypeId())
385 {
387 {
388 Creature* questgiver = object->ToCreature();
389 if (!sScriptMgr->OnQuestReward(_player, questgiver, quest, reward))
390 {
391 // Send next quest
392 if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
393 {
394 // Only send the quest to the player if the conditions are met
395 if (_player->CanTakeQuest(nextQuest, false))
396 {
397 if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true))
398 _player->AddQuest(nextQuest, object);
399
400 _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
401 }
402 }
403
404 questgiver->AI()->sQuestReward(_player, quest, reward);
405 }
406 break;
407 }
409 {
410 GameObject* questGiver = object->ToGameObject();
411 if (!sScriptMgr->OnQuestReward(_player, questGiver, quest, reward))
412 {
413 // Send next quest
414 if (Quest const* nextQuest = _player->GetNextQuest(guid, quest))
415 {
416 // Only send the quest to the player if the conditions are met
417 if (_player->CanTakeQuest(nextQuest, false))
418 {
419 if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true))
420 _player->AddQuest(nextQuest, object);
421
422 _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true);
423 }
424 }
425
426 questGiver->AI()->QuestReward(_player, quest, reward);
427 }
428 break;
429 }
430 default:
431 break;
432 }
433 }
434 else
435 _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
436}
438{
439 uint32 questId;
440 ObjectGuid guid;
441
442 recvData >> questId;
443
444 recvData.ReadGuidMask(guid, 6, 3, 1, 2, 4, 0, 5, 7);
445 recvData.ReadGuidBytes(guid, 3, 0, 7, 6, 2, 1, 5, 4);
446
447 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_REQUEST_REWARD npc = %u, quest = %u", uint32(GUID_LOPART(guid)), questId);
448
450 if (!object || !object->hasInvolvedQuest(questId))
451 return;
452
453 // some kind of WPE protection
454 if (!_player->CanInteractWithQuestGiver(object))
455 return;
456
457 if (_player->CanCompleteQuest(questId))
458 _player->CompleteQuest(questId);
459
460 if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE)
461 return;
462
463 if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
464 _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
465}
466
468{
469 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_CANCEL");
470
471 _player->PlayerTalkClass->SendCloseGossip();
472}
473
475{
476 uint8 slot1, slot2;
477 recvData >> slot1 >> slot2;
478
479 if (slot1 == slot2 || slot1 >= MAX_QUEST_LOG_SIZE || slot2 >= MAX_QUEST_LOG_SIZE)
480 return;
481
482 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTLOG_SWAP_QUEST slot 1 = %u, slot 2 = %u", slot1, slot2);
483
484 GetPlayer()->SwapQuestSlot(slot1, slot2);
485}
486
488{
489 uint8 slot;
490 recvData >> slot;
491
492 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = %u", slot);
493
494 if (slot < MAX_QUEST_LOG_SIZE)
495 {
496 if (uint32 questId = _player->GetQuestSlotQuestId(slot))
497 {
498 if (!_player->TakeQuestSourceItem(questId, true))
499 return; // can't un-equip some items, reject quest cancel
500
501 if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
502 {
503 if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
504 _player->RemoveTimedQuest(questId);
505
506 if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
507 {
508 _player->pvpInfo.IsHostile = _player->pvpInfo.IsInHostileArea || _player->HasPvPForcingQuest();
509 _player->UpdatePvPState();
510 }
511 }
512
513 _player->TakeQuestSourceItem(questId, true); // remove quest src item from player
514 _player->RemoveActiveQuest(questId);
515 _player->RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, questId);
516
517 SF_LOG_INFO("network", "Player %u abandoned quest %u", _player->GetGUIDLow(), questId);
518 }
519
520 _player->SetQuestSlot(slot, 0);
521
522 _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1);
523 }
524}
525
527{
528 uint32 questId;
529 recvData >> questId;
530
531 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT questId = %u", questId);
532
533 if (const Quest* quest = sObjectMgr->GetQuestTemplate(questId))
534 {
535 // QUEST_FLAGS_PARTY_ACCEPT
536 if (!quest->HasFlag(QUEST_FLAGS_START_EVENT_MUST_COMPLETE))
537 return;
538
539 Player* originalPlayer = ObjectAccessor::FindPlayer(_player->GetDivider());
540 if (!originalPlayer)
541 return;
542
543 if (!_player->IsInSameRaidWith(originalPlayer))
544 return;
545
546 if (!originalPlayer->CanShareQuest(questId))
547 return;
548
549 if (!_player->CanTakeQuest(quest, true))
550 return;
551
552 if (_player->CanAddQuest(quest, true))
553 _player->AddQuest(quest, NULL); // NULL, this prevent DB script from duplicate running
554
555 _player->SetDivider(0);
556 }
557}
558
560{
561 uint32 questId;
562 ObjectGuid playerGuid;
563 bool autoCompleteMode; // 0 - standard complete quest mode with npc, 1 - auto-complete mode
564
565 recvData >> questId;
566
567 recvData.ReadGuidMask(playerGuid, 4, 2, 1, 5, 6, 7, 3);
568 autoCompleteMode = recvData.ReadBit();
569 recvData.ReadGuidMask(playerGuid, 0);
570
571 recvData.ReadGuidBytes(playerGuid, 0, 2, 1, 4, 3, 6, 7, 5);
572
573 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_COMPLETE_QUEST npc = %u, questId = %u", uint32(GUID_LOPART(playerGuid)), questId);
574
575 Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
576 if (!quest)
577 return;
578
580 if (!object || !object->hasInvolvedQuest(questId))
581 return;
582
583 if (autoCompleteMode == 0)
584 {
585 // some kind of WPE protection
586 if (!_player->CanInteractWithQuestGiver(object))
587 return;
588 }
589
590 if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE)
591 {
592 SF_LOG_ERROR("network", "Possible hacking attempt: Player %s [guid: %u] tried to complete quest [entry: %u] without being in possession of the quest!",
593 _player->GetName().c_str(), _player->GetGUIDLow(), questId);
594 return;
595 }
596
597 if (Battleground* bg = _player->GetBattleground())
598 bg->HandleQuestComplete(questId, _player);
599
600 if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE)
601 {
602 if (quest->IsRepeatable())
603 _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanCompleteRepeatableQuest(quest), false);
604 else
605 _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false);
606 }
607 else
608 {
610 _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false);
611 else
612 _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, playerGuid, true);
613 }
614
615 if (Creature* creature = object->ToCreature())
616 sScriptMgr->OnQuestComplete(_player, creature, quest);
617}
618
620{
621 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_QUEST_AUTOLAUNCH");
622}
623
625{
626 uint32 questId;
627 recvPacket >> questId;
628
629 if (!_player->CanShareQuest(questId))
630 return;
631
632 SF_LOG_DEBUG("network", "WORLD: Received CMSG_PUSHQUESTTOPARTY questId = %u", questId);
633
634 Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
635 if (!quest)
636 return;
637
638 Player* const sender = GetPlayer();
639
640 Group* group = sender->GetGroup();
641 if (!group)
642 return;
643
644 for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
645 {
646 Player* receiver = itr->GetSource();
647
648 if (!receiver || receiver == sender)
649 continue;
650
651 if (!receiver->SatisfyQuestStatus(quest, false))
652 {
654 continue;
655 }
656
657 if (receiver->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE)
658 {
660 continue;
661 }
662
663 if (!receiver->CanTakeQuest(quest, false))
664 {
666 continue;
667 }
668
669 if (!receiver->SatisfyQuestLog(false))
670 {
672 continue;
673 }
674
675 if (receiver->GetDivider() != 0)
676 {
678 continue;
679 }
680
682
683 if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true))
684 {
685 receiver->AddQuest(quest, sender);
686 if (receiver->CanCompleteQuest(questId))
687 receiver->CompleteQuest(questId);
688 }
689
690 if ((quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) || quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
691 receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true);
692 else
693 {
694 receiver->SetDivider(sender->GetGUID());
695 receiver->PlayerTalkClass->SendQuestGiverQuestDetails(quest, sender->GetGUID(), true);
696 }
697 }
698}
699
701{
702 ObjectGuid guid;
703 uint32 questId = recvPacket.read<uint32>();
704 uint8 msg = recvPacket.read<uint8>();
705 recvPacket.ReadGuidMask(guid, 5, 3, 0, 6, 1, 2, 7, 4);
706 recvPacket.ReadGuidBytes(guid, 1, 2, 0, 5, 6, 4, 7, 3);
707
708 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_PUSH_RESULT");
709
710 if (_player->GetDivider())
711 {
712 if (_player->GetDivider() == guid)
713 if (Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(_player->GetDivider()))
714 player->SendPushToPartyResponse(_player, msg);
715
716 _player->SetDivider(0);
717 }
718}
719
721{
722 uint32 result = defstatus;
723
726
727 switch (questgiver->GetTypeId())
728 {
730 {
731 qr = sObjectMgr->GetGOQuestRelationBounds(questgiver->GetEntry());
732 qir = sObjectMgr->GetGOQuestInvolvedRelationBounds(questgiver->GetEntry());
733 break;
734 }
736 {
737 qr = sObjectMgr->GetCreatureQuestRelationBounds(questgiver->GetEntry());
738 qir = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(questgiver->GetEntry());
739 break;
740 }
741 default:
742 //its imposible, but check ^)
743 SF_LOG_ERROR("network", "Warning: GetDialogStatus called for unexpected type %u", uint8(questgiver->GetTypeId()));
744 return DIALOG_STATUS_NONE;
745 }
746
747 for (QuestRelations::const_iterator i = qir.first; i != qir.second; ++i)
748 {
749 uint32 result2 = 0;
750 uint32 quest_id = i->second;
751 Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id);
752 if (!quest)
753 continue;
754
755 ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, quest->GetQuestId());
756 if (!sConditionMgr->IsObjectMeetToConditions(player, conditions))
757 continue;
758
759 QuestStatus status = player->GetQuestStatus(quest_id);
760 if ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(quest_id)) ||
761 (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)))
762 {
763 if (quest->IsAutoComplete() && quest->IsRepeatable())
764 result2 = DIALOG_STATUS_REWARD_REP;
765 else
766 result2 = DIALOG_STATUS_REWARD;
767 }
768 else if (status == QUEST_STATUS_INCOMPLETE)
769 result2 = DIALOG_STATUS_INCOMPLETE;
770
771 if (result2 > result)
772 result = result2;
773 }
774
775 for (QuestRelations::const_iterator i = qr.first; i != qr.second; ++i)
776 {
777 uint32 result2 = 0;
778 uint32 quest_id = i->second;
779 Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id);
780 if (!quest)
781 continue;
782
783 ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_ACCEPT, quest->GetQuestId());
784 if (!sConditionMgr->IsObjectMeetToConditions(player, conditions))
785 continue;
786
787 QuestStatus status = player->GetQuestStatus(quest_id);
788 if (status == QUEST_STATUS_NONE)
789 {
790 if (player->CanSeeStartQuest(quest))
791 {
792 if (player->SatisfyQuestLevel(quest, false))
793 {
794 if (quest->IsAutoComplete() || (quest->IsRepeatable() && player->IsQuestRewarded(quest_id)))
795 result2 = DIALOG_STATUS_REWARD_REP;
796 else if (player->getLevel() <= ((player->GetQuestLevel(quest) == -1) ? player->getLevel() : player->GetQuestLevel(quest) + sWorld->getIntConfig(WorldIntConfigs::CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF)))
797 {
800 else
801 result2 = DIALOG_STATUS_AVAILABLE;
802 }
803 else
805 }
806 else
808 }
809 }
810
811 if (result2 > result)
812 result = result2;
813 }
814
815 return result;
816}
817
819{
820 if (!_player || _player->IsInCinematic() || isLogingOut())
821 return;
822
823 SF_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_GIVER_STATUS_MULTIPLE_QUERY");
824
826}
827
829{
830 if (!_player || isLogingOut())
831 return;
832
833 uint32 count = 0;
834 ByteBuffer byteData;
835
836 WorldPacket data(SMSG_QUEST_GIVER_STATUS_MULTIPLE, 3 + count * (1 + 8 + 4));
837
838 size_t pos = data.bitwpos();
839 data.WriteBits(count, 21); // placeholder
840
841 for (Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr)
842 {
843 uint32 questStatus = DIALOG_STATUS_NONE;
844 uint32 defstatus = DIALOG_STATUS_NONE;
845
847 {
848 // need also pet quests case support
850 if (!questgiver || questgiver->IsHostileTo(_player))
851 continue;
853 continue;
854 questStatus = sScriptMgr->GetDialogStatus(_player, questgiver);
855 if (questStatus > 6)
856 questStatus = getDialogStatus(_player, questgiver, defstatus);
857
858 ObjectGuid guid = questgiver->GetGUID();
859
860 data.WriteBit(guid[4]);
861 data.WriteBit(guid[0]);
862 data.WriteBit(guid[3]);
863 data.WriteBit(guid[6]);
864 data.WriteBit(guid[5]);
865 data.WriteBit(guid[7]);
866 data.WriteBit(guid[1]);
867 data.WriteBit(guid[2]);
868
869 byteData.WriteByteSeq(guid[6]);
870 byteData.WriteByteSeq(guid[2]);
871 byteData.WriteByteSeq(guid[7]);
872 byteData.WriteByteSeq(guid[5]);
873 byteData.WriteByteSeq(guid[4]);
874 byteData << uint32(questStatus);
875 byteData.WriteByteSeq(guid[1]);
876 byteData.WriteByteSeq(guid[3]);
877 byteData.WriteByteSeq(guid[0]);
878
879 ++count;
880 }
881 else if (IS_GAMEOBJECT_GUID(*itr))
882 {
883 GameObject* questgiver = GetPlayer()->GetMap()->GetGameObject(*itr);
884 if (!questgiver)
885 continue;
886 if (questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER)
887 continue;
888 questStatus = sScriptMgr->GetDialogStatus(_player, questgiver);
889 if (questStatus > 6)
890 questStatus = getDialogStatus(_player, questgiver, defstatus);
891
892 ObjectGuid guid = questgiver->GetGUID();
893
894 data.WriteBit(guid[4]);
895 data.WriteBit(guid[0]);
896 data.WriteBit(guid[3]);
897 data.WriteBit(guid[6]);
898 data.WriteBit(guid[5]);
899 data.WriteBit(guid[7]);
900 data.WriteBit(guid[1]);
901 data.WriteBit(guid[2]);
902
903 byteData.WriteByteSeq(guid[6]);
904 byteData.WriteByteSeq(guid[2]);
905 byteData.WriteByteSeq(guid[7]);
906 byteData.WriteByteSeq(guid[5]);
907 byteData.WriteByteSeq(guid[4]);
908 byteData << uint32(questStatus);
909 byteData.WriteByteSeq(guid[1]);
910 byteData.WriteByteSeq(guid[3]);
911 byteData.WriteByteSeq(guid[0]);
912
913 ++count;
914 }
915 }
916
917 data.FlushBits();
918 data.PutBits(pos, count, 21);
919 data.append(byteData);
920
921 SendPacket(&data);
922}
923
925{
926 size_t rew_count = _player->GetRewardedQuestCount();
927
928 WorldPacket data(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, 4 + 4 * rew_count);
929 data << uint32(rew_count);
930
931 const RewardedQuestSet& rewQuests = _player->getRewardedQuests();
932 for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr)
933 data << uint32(*itr);
934
935 SendPacket(&data);
936}
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_QUEST_ACCEPT
std::list< Condition * > ConditionList
@ ACHIEVEMENT_TIMED_TYPE_QUEST
Definition DBCEnums.h:159
@ ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED
Definition DBCEnums.h:262
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
TypeID GuidHigh2TypeId(uint32 guid_hi)
Definition Object.cpp:44
@ TYPEID_GAMEOBJECT
Definition Object.h:56
@ TYPEID_UNIT
Definition Object.h:54
@ TYPEID_ITEM
Definition Object.h:52
@ TYPEID_CONTAINER
Definition Object.h:53
@ TYPEMASK_ITEM
Definition Object.h:38
@ TYPEMASK_UNIT
Definition Object.h:40
@ TYPEMASK_GAMEOBJECT
Definition Object.h:42
@ TYPEMASK_PLAYER
Definition Object.h:41
uint32 GUID_LOPART(uint64 x)
bool IS_GAMEOBJECT_GUID(uint64 guid)
bool IS_CRE_OR_VEH_OR_PET_GUID(uint64 guid)
uint32 GUID_HIPART(uint64 guid)
std::pair< QuestRelations::const_iterator, QuestRelations::const_iterator > QuestRelationBounds
Definition ObjectMgr.h:457
#define sObjectMgr
Definition ObjectMgr.h:1617
std::set< uint32 > RewardedQuestSet
Definition Player.h:629
@ QUEST_PARTY_MSG_FINISH_QUEST
Definition QuestDef.h:59
@ QUEST_PARTY_MSG_CANT_TAKE_QUEST
Definition QuestDef.h:53
@ QUEST_PARTY_MSG_BUSY
Definition QuestDef.h:56
@ QUEST_PARTY_MSG_ACCEPT_QUEST
Definition QuestDef.h:54
@ QUEST_PARTY_MSG_HAVE_QUEST
Definition QuestDef.h:58
@ QUEST_PARTY_MSG_SHARING_QUEST
Definition QuestDef.h:52
@ QUEST_PARTY_MSG_LOG_FULL
Definition QuestDef.h:57
@ QUEST_OBJECTIVE_TYPE_ITEM
Definition QuestDef.h:194
@ QUEST_FLAGS_FLAGS_PVP
Definition QuestDef.h:128
@ QUEST_FLAGS_DAILY
Definition QuestDef.h:127
@ QUEST_FLAGS_WEEKLY
Definition QuestDef.h:130
@ QUEST_FLAGS_AUTOCOMPLETE
Definition QuestDef.h:131
@ QUEST_FLAGS_PLAYER_CAST_ACCEPT
Definition QuestDef.h:135
@ QUEST_FLAGS_START_EVENT_MUST_COMPLETE
Definition QuestDef.h:116
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:22
QuestStatus
Definition QuestDef.h:85
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:89
@ QUEST_STATUS_NONE
Definition QuestDef.h:86
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:87
@ DIALOG_STATUS_UNAVAILABLE
Definition QuestDef.h:100
@ DIALOG_STATUS_NONE
Definition QuestDef.h:98
@ DIALOG_STATUS_AVAILABLE
Definition QuestDef.h:107
@ DIALOG_STATUS_REWARD
Definition QuestDef.h:109
@ DIALOG_STATUS_LOW_LEVEL_AVAILABLE
Definition QuestDef.h:101
@ DIALOG_STATUS_REWARD_REP
Definition QuestDef.h:105
@ DIALOG_STATUS_INCOMPLETE
Definition QuestDef.h:104
@ DIALOG_STATUS_AVAILABLE_REP
Definition QuestDef.h:106
@ QUEST_SPECIAL_FLAGS_TIMED
Definition QuestDef.h:187
#define CLOSE_GOSSIP_CLEAR_DIVIDER()
#define sScriptMgr
Definition ScriptMgr.h:764
@ GAMEOBJECT_TYPE_QUESTGIVER
@ SPELL_AURA_FEIGN_DEATH
@ UNIT_NPC_FLAG_NONE
Definition Unit.h:686
@ UNIT_NPC_FLAG_QUESTGIVER
Definition Unit.h:688
@ UNIT_STATE_DIED
Definition Unit.h:512
@ UNIT_FIELD_NPC_FLAGS
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
size_t bitwpos() const
Returns position of last written bit.
Definition ByteBuffer.h:492
void ReadGuidBytes(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:256
void ReadByteSeq(uint8 &b)
Definition ByteBuffer.h:215
void append(T value)
Definition ByteBuffer.h:147
void PutBits(size_t pos, T value, uint32 bitCount)
Definition ByteBuffer.h:283
void ReadGuidMask(ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:240
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void WriteByteSeq(uint8 b)
Definition ByteBuffer.h:227
void FlushBits()
Definition ByteBuffer.h:154
bool ReadBit()
Definition ByteBuffer.h:180
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:524
CreatureAI * AI() const
Definition Creature.h:483
virtual bool QuestReward(Player *, Quest const *, uint32)
GameObjectAI * AI() const
Definition GameObject.h:824
GameobjectTypes GetGoType() const
Definition GameObject.h:719
Definition Group.h:147
GroupReference * GetFirstMember()
Definition Group.h:225
GroupReference * next()
Definition Item.h:202
uint8 GetSlot() const
Definition Item.h:265
ItemTemplate const * GetTemplate() const
Definition Item.cpp:528
uint8 GetBagSlot() const
Definition Item.cpp:734
GameObject * GetGameObject(uint64 guid)
Definition Map.cpp:3184
static Creature * GetCreatureOrPetOrVehicle(WorldObject const &, uint64)
static Object * GetObjectByTypeMask(WorldObject const &, uint64, uint32 typemask)
static Player * FindPlayerInOrOutOfWorld(uint64)
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
virtual bool hasQuest(uint32) const
Definition Object.h:193
TypeID GetTypeId() const
Definition Object.h:131
GameObject * ToGameObject()
Definition Object.h:213
uint32 GetEntry() const
Definition Object.h:125
Creature * ToCreature()
Definition Object.h:207
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
virtual bool hasInvolvedQuest(uint32) const
Definition Object.h:194
int32 GetQuestLevel(Quest const *quest) const
Definition Player.h:1741
void SetDivider(uint64 guid)
Definition Player.h:1842
bool GetQuestRewardStatus(uint32 quest_id) const
bool CanTakeQuest(Quest const *quest, bool msg)
bool CanCompleteQuest(uint32 quest_id)
void AddQuest(Quest const *quest, Object *questGiver)
bool CanAddQuest(Quest const *quest, bool msg)
void CompleteQuest(uint32 quest_id)
bool CanSeeStartQuest(Quest const *quest)
void SwapQuestSlot(uint16 slot1, uint16 slot2)
bool SatisfyQuestStatus(Quest const *qInfo, bool msg)
bool CanShareQuest(uint32 questId) const
uint64 GetDivider() const
Definition Player.h:1838
Creature * GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
Definition Player.cpp:2836
Group * GetGroup()
Definition Player.h:2972
bool SatisfyQuestLog(bool msg)
void SendPushToPartyResponse(Player *player, uint8 msg)
QuestStatus GetQuestStatus(uint32 quest_id) const
bool CanCompleteRepeatableQuest(Quest const *quest)
bool SatisfyQuestLevel(Quest const *qInfo, bool msg)
bool IsQuestRewarded(uint32 quest_id) const
Definition Player.cpp:18380
PlayerMenu * PlayerTalkClass
Definition Player.h:2680
void SendQuestGiverQuestDetails(Quest const *quest, uint64 npcGUID, bool activateAccept, bool displayPopup=false) const
void SendQuestGiverRequestItems(Quest const *quest, uint64 npcGUID, bool canComplete, bool closeOnCancel) const
void SendCloseGossip() const
bool HasFlag(uint32 flag) const
Definition QuestDef.h:261
uint8 GetQuestObjectiveCountType(uint8 type) const
Definition QuestDef.cpp:320
bool IsRewChoiceItemValid(uint32 itemId) const
Definition QuestDef.cpp:275
bool IsRepeatable() const
Definition QuestDef.h:324
bool IsAutoComplete() const
Definition QuestDef.cpp:199
uint32 GetQuestId() const
Definition QuestDef.h:270
bool IsAutoAccept() const
Definition QuestDef.cpp:194
bool IsDailyOrWeekly() const
Definition QuestDef.h:341
uint32 GetRewardPackageItemId() const
Definition QuestDef.h:370
virtual bool OnGossipHello(Player *player)
Definition UnitAI.h:245
virtual void sQuestReward(Player *, Quest const *, uint32)
Definition UnitAI.h:252
void StopMoving()
-------—End of Pet responses methods-------—
Definition Unit.cpp:5877
void RemoveAurasByType(AuraType auraType, uint64 casterGUID=0, Aura *except=NULL, bool negative=true, bool positive=true)
uint8 getLevel() const
Definition Unit.h:1528
bool IsHostileTo(Unit const *unit) const
Definition Unit.cpp:2278
Map * GetMap() const
Definition Object.h:740
void HandleQueryQuestsCompleted(WorldPacket &recvData)
bool isLogingOut() const
Is the user engaged in a log out process?
void HandleQuestConfirmAccept(WorldPacket &recvData)
void HandleQuestLogRemoveQuest(WorldPacket &recvData)
void SendQuestgiverStatusMultiple()
void HandleQuestgiverQuestAutoLaunch(WorldPacket &recvPacket)
void HandleQuestQueryOpcode(WorldPacket &recvPacket)
void HandleQuestgiverAcceptQuestOpcode(WorldPacket &recvPacket)
Player * GetPlayer() const
void HandleQuestgiverStatusQueryOpcode(WorldPacket &recvPacket)
void HandleQuestgiverCompleteQuest(WorldPacket &recvData)
void HandleQuestgiverHelloOpcode(WorldPacket &recvPacket)
void HandleQuestgiverRequestRewardOpcode(WorldPacket &recvPacket)
uint32 getDialogStatus(Player *player, Object *questgiver, uint32 defstatus)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void HandleQuestLogSwapQuest(WorldPacket &recvData)
void HandleQuestPushResult(WorldPacket &recvPacket)
Player * _player
void HandleQuestgiverQueryQuestOpcode(WorldPacket &recvPacket)
void HandleQuestgiverChooseRewardOpcode(WorldPacket &recvPacket)
void HandlePushQuestToParty(WorldPacket &recvPacket)
void HandleQuestgiverCancel(WorldPacket &recvData)
void HandleQuestgiverStatusMultipleQuery(WorldPacket &recvPacket)
@ SMSG_QUEST_GIVER_STATUS_MULTIPLE
Definition Opcodes.h:912
@ SMSG_QUERY_QUESTS_COMPLETED_RESPONSE
Definition Opcodes.h:896
#define sWorld
Definition World.h:910
@ CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF
Definition World.h:273
uint32 GossipMenuId
Definition Creature.h:74