OregonCore  revision 3611e8a-git
Your Favourite TBC server
GossipDef.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "QuestDef.h"
19 #include "GossipDef.h"
20 #include "ObjectMgr.h"
21 #include "Opcodes.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
24 #include "Formulas.h"
25 
27 {
28  m_gItems.reserve(16); // can be set for max from most often sizes to speedup push_back and less memory use
29  m_gMenuId = 0;
30 }
31 
33 {
34  ClearMenu();
35 }
36 
37 void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded)
38 {
40 
41  GossipMenuItem gItem;
42 
43  gItem.m_gIcon = Icon;
44  gItem.m_gMessage = Message;
45  gItem.m_gCoded = Coded;
46  gItem.m_gSender = dtSender;
47  gItem.m_gOptionId = dtAction;
48  gItem.m_gBoxMessage = BoxMessage;
49  gItem.m_gBoxMoney = BoxMoney;
50 
51  m_gItems.push_back(gItem);
52 }
53 
54 void GossipMenu::AddGossipMenuItemData(uint32 action_menu, uint32 action_poi, uint32 action_script)
55 {
56  GossipMenuItemData pItemData;
57 
58  pItemData.m_gAction_menu = action_menu;
59  pItemData.m_gAction_poi = action_poi;
60  pItemData.m_gAction_script = action_script;
61 
62  m_gItemsData.push_back(pItemData);
63 }
64 
65 void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, bool Coded)
66 {
67  AddMenuItem(Icon, Message, 0, 0, "", 0, Coded);
68 }
69 
70 void GossipMenu::AddMenuItem(uint8 Icon, char const* Message, bool Coded)
71 {
72  AddMenuItem(Icon, std::string(Message ? Message : ""), Coded);
73 }
74 
75 void GossipMenu::AddMenuItem(uint8 Icon, char const* Message, uint32 dtSender, uint32 dtAction, char const* BoxMessage, uint32 BoxMoney, bool Coded)
76 {
77  AddMenuItem(Icon, std::string(Message ? Message : ""), dtSender, dtAction, std::string(BoxMessage ? BoxMessage : ""), BoxMoney, Coded);
78 }
79 
80 uint32 GossipMenu::MenuItemSender(unsigned int ItemId)
81 {
82  if (ItemId >= m_gItems.size()) return 0;
83 
84  return m_gItems[ ItemId ].m_gSender;
85 }
86 
87 uint32 GossipMenu::MenuItemAction(unsigned int ItemId)
88 {
89  if (ItemId >= m_gItems.size()) return 0;
90 
91  return m_gItems[ ItemId ].m_gOptionId;
92 }
93 
94 bool GossipMenu::MenuItemCoded(unsigned int ItemId)
95 {
96  if (ItemId >= m_gItems.size()) return 0;
97 
98  return m_gItems[ ItemId ].m_gCoded;
99 }
100 
102 {
103  m_gItems.clear();
104  m_gItemsData.clear();
105 }
106 
107 PlayerMenu::PlayerMenu(WorldSession* session) : pSession(session)
108 {
109 }
110 
112 {
113  ClearMenus();
114 }
115 
117 {
120 }
121 
122 uint32 PlayerMenu::GossipOptionSender(unsigned int Selection)
123 {
124  return mGossipMenu.MenuItemSender(Selection);
125 }
126 
127 uint32 PlayerMenu::GossipOptionAction(unsigned int Selection)
128 {
129  return mGossipMenu.MenuItemAction(Selection);
130 }
131 
132 bool PlayerMenu::GossipOptionCoded(unsigned int Selection)
133 {
134  return mGossipMenu.MenuItemCoded(Selection);
135 }
136 
137 void PlayerMenu::SendGossipMenu(uint32 TitleTextId, uint64 objectGUID)
138 {
139  WorldPacket data(SMSG_GOSSIP_MESSAGE, (100)); // guess size
140  data << uint64(objectGUID);
141  data << uint32(mGossipMenu.GetMenuId()); // new 2.4.0
142  data << uint32(TitleTextId);
143  data << uint32(mGossipMenu.MenuItemCount()); // max count 0x20
144 
145  for (uint32 iI = 0; iI < mGossipMenu.MenuItemCount(); ++iI)
146  {
147  GossipMenuItem const& gItem = mGossipMenu.GetItem(iI);
148  data << uint32(iI);
149  data << uint8(gItem.m_gIcon);
150  data << uint8(gItem.m_gCoded); // makes pop up box password
151  data << uint32(gItem.m_gBoxMoney); // money required to open menu, 2.0.3
152  data << gItem.m_gMessage; // text for gossip item, max 0x800
153  data << gItem.m_gBoxMessage; // accept text (related to money) pop up box, 2.0.3, max 0x800
154  }
155 
156  data << uint32(mQuestMenu.MenuItemCount()); // max count 0x20
157 
158  // Store this instead of checking the Singleton every loop iteration
159  bool questLevelInTitle = sWorld.getConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS);
160 
161  for (uint32 iI = 0; iI < mQuestMenu.MenuItemCount(); ++iI)
162  {
163  QuestMenuItem const& qItem = mQuestMenu.GetItem(iI);
164  uint32 questID = qItem.m_qId;
165  Quest const* pQuest = sObjectMgr.GetQuestTemplate(questID);
166 
167  data << uint32(questID);
168  data << uint32(qItem.m_qIcon);
169  data << int32(pQuest->GetQuestLevel());
170  std::string Title = pQuest->GetTitle();
171 
172  int loc_idx = pSession->GetSessionDbLocaleIndex();
173  if (loc_idx >= 0)
174  if (QuestLocale const* ql = sObjectMgr.GetQuestLocale(questID))
175  if (ql->Title.size() > uint32(loc_idx) && !ql->Title[loc_idx].empty())
176  Title = ql->Title[loc_idx];
177 
178  if (questLevelInTitle)
179  AddQuestLevelToTitle(Title, pQuest->GetQuestLevel());
180 
181  data << Title;
182  }
183 
184  pSession->SendPacket(&data);
185 }
186 
188 {
190  pSession->SendPacket(&data);
191 }
192 
193 void PlayerMenu::SendPointOfInterest(float X, float Y, uint32 Icon, uint32 Flags, uint32 Data, char const* locName)
194 {
195  WorldPacket data(SMSG_GOSSIP_POI, (4 + 4 + 4 + 4 + 4 + 10)); // guess size
196  data << uint32(Flags);
197  data << float(X);
198  data << float(Y);
199  data << uint32(Icon);
200  data << uint32(Data);
201  data << locName;
202 
203  pSession->SendPacket(&data);
204  //sLog.outDebug("WORLD: Sent SMSG_GOSSIP_POI");
205 }
206 
208 {
209  GossipText const* pGossip = sObjectMgr.GetGossipText(textID);
210 
211  WorldPacket data(SMSG_NPC_TEXT_UPDATE, 100); // guess size
212  data << textID; // can be < 0
213 
214  if (!pGossip)
215  {
216  for (uint32 i = 0; i < 8; ++i)
217  {
218  data << float(0);
219  data << "Greetings $N";
220  data << "Greetings $N";
221  data << uint32(0);
222  data << uint32(0);
223  data << uint32(0);
224  data << uint32(0);
225  data << uint32(0);
226  data << uint32(0);
227  data << uint32(0);
228  }
229  }
230  else
231  {
232  std::string Text_0[8], Text_1[8];
233  for (int i = 0; i < 8; ++i)
234  {
235  Text_0[i] = pGossip->Options[i].Text_0;
236  Text_1[i] = pGossip->Options[i].Text_1;
237  }
238  int loc_idx = pSession->GetSessionDbLocaleIndex();
239  if (loc_idx >= 0)
240  {
241  if (NpcTextLocale const* nl = sObjectMgr.GetNpcTextLocale(textID))
242  {
243  for (int i = 0; i < 8; ++i)
244  {
245  if (nl->Text_0[i].size() > uint32(loc_idx) && !nl->Text_0[i][loc_idx].empty())
246  Text_0[i] = nl->Text_0[i][loc_idx];
247  if (nl->Text_1[i].size() > uint32(loc_idx) && !nl->Text_1[i][loc_idx].empty())
248  Text_1[i] = nl->Text_1[i][loc_idx];
249  }
250  }
251  }
252  for (int i = 0; i < 8; ++i)
253  {
254  data << pGossip->Options[i].Probability;
255 
256  if (Text_0[i].empty())
257  data << Text_1[i];
258  else
259  data << Text_0[i];
260 
261  if (Text_1[i].empty())
262  data << Text_0[i];
263  else
264  data << Text_1[i];
265 
266  data << pGossip->Options[i].Language;
267 
268  data << pGossip->Options[i].Emotes[0]._Delay;
269  data << pGossip->Options[i].Emotes[0]._Emote;
270 
271  data << pGossip->Options[i].Emotes[1]._Delay;
272  data << pGossip->Options[i].Emotes[1]._Emote;
273 
274  data << pGossip->Options[i].Emotes[2]._Delay;
275  data << pGossip->Options[i].Emotes[2]._Emote;
276  }
277  }
278  pSession->SendPacket(&data);
279 
280  sLog.outDebug("WORLD: Sent SMSG_NPC_TEXT_UPDATE ");
281 }
282 
283 void PlayerMenu::SendTalking(char const* title, char const* text)
284 {
285  WorldPacket data(SMSG_NPC_TEXT_UPDATE, 50); // guess size
286  data << uint32(0);
287  for (uint32 i = 0; i < 8; ++i)
288  {
289  data << float(0);
290  data << title;
291  data << text;
292  data << uint32(0);
293  data << uint32(0);
294  data << uint32(0);
295  data << uint32(0);
296  data << uint32(0);
297  data << uint32(0);
298  data << uint32(0);
299  }
300 
301  pSession->SendPacket(&data);
302 
303  sLog.outDebug("WORLD: Sent SMSG_NPC_TEXT_UPDATE ");
304 }
305 
306 /*********************************************************/
307 /*** QUEST SYSTEM ***/
308 /*********************************************************/
309 
311 {
312  m_qItems.reserve(16); // can be set for max from most often sizes to speedup push_back and less memory use
313 }
314 
316 {
317  ClearMenu();
318 }
319 
321 {
322  Quest const* qinfo = sObjectMgr.GetQuestTemplate(QuestId);
323  if (!qinfo) return;
324 
325  ASSERT(m_qItems.size() <= GOSSIP_MAX_MENU_ITEMS);
326 
327  QuestMenuItem qItem;
328 
329  qItem.m_qId = QuestId;
330  qItem.m_qIcon = Icon;
331 
332  m_qItems.push_back(qItem);
333 }
334 
336 {
337  for (QuestMenuItemList::iterator i = m_qItems.begin(); i != m_qItems.end(); ++i)
338  if (i->m_qId == questid)
339  return true;
340  return false;
341 }
342 
344 {
345  m_qItems.clear();
346 }
347 
348 void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title, uint64 npcGUID)
349 {
350  WorldPacket data(SMSG_QUESTGIVER_QUEST_LIST, 100); // guess size
351  data << uint64(npcGUID);
352  data << Title;
353  data << uint32(eEmote._Delay); // player emote
354  data << uint32(eEmote._Emote); // NPC emote
355  data << uint8 (mQuestMenu.MenuItemCount());
356 
357  // Store this instead of checking the Singleton every loop iteration
358  bool questLevelInTitle = sWorld.getConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS);
359 
360  for (uint32 iI = 0; iI < mQuestMenu.MenuItemCount(); iI++)
361  {
362  QuestMenuItem const& qmi = mQuestMenu.GetItem(iI);
363 
364  uint32 questID = qmi.m_qId;
365  Quest const* pQuest = sObjectMgr.GetQuestTemplate(questID);
366 
367  std::string title = pQuest ? pQuest->GetTitle() : "";
368 
369  int loc_idx = pSession->GetSessionDbLocaleIndex();
370  if (loc_idx >= 0)
371  {
372  if (QuestLocale const* ql = sObjectMgr.GetQuestLocale(questID))
373  {
374  if (ql->Title.size() > uint32(loc_idx) && !ql->Title[loc_idx].empty())
375  title = ql->Title[loc_idx];
376  }
377  }
378 
379  if (questLevelInTitle)
380  AddQuestLevelToTitle(title, pQuest->GetQuestLevel());
381 
382  data << uint32(questID);
383  data << uint32(qmi.m_qIcon);
384  data << int32(pQuest->GetQuestLevel());
385  data << title;
386  }
387  pSession->SendPacket(&data);
388  DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC Guid=%u", GUID_LOPART(npcGUID));
389 }
390 
392 {
394  data << uint64(npcGUID);
395  data << uint8(questStatus);
396 
397  pSession->SendPacket(&data);
398  DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u", GUID_LOPART(npcGUID), questStatus);
399 }
400 
401 void PlayerMenu::SendQuestGiverQuestDetails(Quest const* pQuest, uint64 npcGUID, bool ActivateAccept)
402 {
403  std::string Title = pQuest->GetTitle();
404  std::string Details = pQuest->GetDetails();
405  std::string Objectives = pQuest->GetObjectives();
406  std::string EndText = pQuest->GetEndText();
407 
408  int loc_idx = pSession->GetSessionDbLocaleIndex();
409  if (loc_idx >= 0)
410  {
411  QuestLocale const* ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId());
412  if (ql)
413  {
414  if (ql->Title.size() > uint32(loc_idx) && !ql->Title[loc_idx].empty())
415  Title = ql->Title[loc_idx];
416  if (ql->Details.size() > uint32(loc_idx) && !ql->Details[loc_idx].empty())
417  Details = ql->Details[loc_idx];
418  if (ql->Objectives.size() > uint32(loc_idx) && !ql->Objectives[loc_idx].empty())
419  Objectives = ql->Objectives[loc_idx];
420  if (ql->EndText.size() > uint32(loc_idx) && !ql->EndText[loc_idx].empty())
421  EndText = ql->EndText[loc_idx];
422  }
423  }
424 
426  AddQuestLevelToTitle(Title, pQuest->GetQuestLevel());
427 
428  WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size
429  data << uint64(npcGUID);
430  data << uint32(pQuest->GetQuestId());
431  data << Title;
432  data << Details;
433  data << Objectives;
434  data << uint32(ActivateAccept);
435  data << uint32(pQuest->GetSuggestedPlayers());
436 
437  if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
438  {
439  data << uint32(0); // Rewarded chosen items hidden
440  data << uint32(0); // Rewarded items hidden
441  data << uint32(0); // Rewarded money hidden
442  }
443  else
444  {
445  ItemTemplate const* IProto;
446 
447  data << uint32(pQuest->GetRewChoiceItemsCount());
448  for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
449  {
450  if (!pQuest->RewChoiceItemId[i])
451  continue;
452 
453  data << uint32(pQuest->RewChoiceItemId[i]);
454  data << uint32(pQuest->RewChoiceItemCount[i]);
455 
456  IProto = sObjectMgr.GetItemTemplate(pQuest->RewChoiceItemId[i]);
457  if (IProto)
458  data << uint32(IProto->DisplayInfoID);
459  else
460  data << uint32(0x00);
461  }
462 
463  data << uint32(pQuest->GetRewItemsCount());
464 
465  for (uint32 i = 0; i < QUEST_REWARDS_COUNT; ++i)
466  {
467  if (!pQuest->RewItemId[i])
468  continue;
469 
470  data << uint32(pQuest->RewItemId[i]);
471  data << uint32(pQuest->RewItemCount[i]);
472 
473  IProto = sObjectMgr.GetItemTemplate(pQuest->RewItemId[i]);
474  if (IProto)
475  data << uint32(IProto->DisplayInfoID);
476  else
477  data << uint32(0);
478  }
479 
480  data << uint32(pQuest->GetRewOrReqMoney());
481  }
482 
483  // rewarded honor points. Multiply with 10 to satisfy client
485  data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
486  data << uint32(pQuest->GetRewSpellCast()); // casted spell
487  data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
488 
489  data << uint32(QUEST_EMOTE_COUNT);
490  for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
491  {
492  data << uint32(pQuest->DetailsEmote[i]);
493  data << uint32(0); // DetailsEmoteDelay
494  }
495  pSession->SendPacket(&data);
496 
497  DEBUG_LOG("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId());
498 }
499 
501 {
502  std::string Title, Details, Objectives, EndText;
503  std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
504  Title = pQuest->GetTitle();
505  Details = pQuest->GetDetails();
506  Objectives = pQuest->GetObjectives();
507  EndText = pQuest->GetEndText();
508  for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
509  ObjectiveText[i] = pQuest->ObjectiveText[i];
510 
511  int loc_idx = pSession->GetSessionDbLocaleIndex();
512  if (loc_idx >= 0)
513  {
514  if (QuestLocale const* ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId()))
515  {
516  if (ql->Title.size() > uint32(loc_idx) && !ql->Title[loc_idx].empty())
517  Title = ql->Title[loc_idx];
518  if (ql->Details.size() > uint32(loc_idx) && !ql->Details[loc_idx].empty())
519  Details = ql->Details[loc_idx];
520  if (ql->Objectives.size() > uint32(loc_idx) && !ql->Objectives[loc_idx].empty())
521  Objectives = ql->Objectives[loc_idx];
522  if (ql->EndText.size() > uint32(loc_idx) && !ql->EndText[loc_idx].empty())
523  EndText = ql->EndText[loc_idx];
524 
525  for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
526  if (ql->ObjectiveText[i].size() > loc_idx && !ql->ObjectiveText[i][loc_idx].empty())
527  ObjectiveText[i] = ql->ObjectiveText[i][loc_idx];
528  }
529  }
530 
531  WorldPacket data(SMSG_QUEST_QUERY_RESPONSE, 100); // guess size
532 
533  data << uint32(pQuest->GetQuestId()); // quest id
534  data << uint32(pQuest->GetQuestMethod()); // Accepted values: 0, 1 or 2. 0 == IsAutoComplete() (skip objectives/details)
535  data << int32(pQuest->GetQuestLevel()); // may be 0, -1, static data, in other cases must be used dynamic level: Player::GetQuestLevelForPlayer
536  data << uint32(pQuest->GetZoneOrSort()); // zone or sort to display in quest log
537 
538  data << uint32(pQuest->GetType()); // quest type
539  data << uint32(pQuest->GetSuggestedPlayers()); // suggested players count
540 
541  data << uint32(pQuest->GetRepObjectiveFaction()); // shown in quest log as part of quest objective
542  data << uint32(pQuest->GetRepObjectiveValue()); // shown in quest log as part of quest objective
543 
544  data << uint32(0); // RequiredOpositeRepFaction
545  data << uint32(0); // RequiredOpositeRepValue, required faction value with another (oposite) faction (objective)
546 
547  data << uint32(pQuest->GetNextQuestInChain()); // client will request this quest from NPC, if not 0
548 
549  if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
550  data << uint32(0); // Hide money rewarded
551  else
552  data << uint32(pQuest->GetRewOrReqMoney()); // reward money (below max lvl)
553 
554  data << uint32(pQuest->GetRewMoneyMaxLevel()); // used in XP calculation at client
555  data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
556  data << uint32(pQuest->GetRewSpellCast()); // casted spell
557 
558  // rewarded honor points
560  data << uint32(pQuest->GetSrcItemId());
561  data << uint32(pQuest->GetFlags() & 0xFFFF);
562  data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
563 
564  int iI;
565 
566  if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
567  {
568  for (iI = 0; iI < QUEST_REWARDS_COUNT; ++iI)
569  data << uint32(0) << uint32(0);
570  for (iI = 0; iI < QUEST_REWARD_CHOICES_COUNT; ++iI)
571  data << uint32(0) << uint32(0);
572  }
573  else
574  {
575  for (iI = 0; iI < QUEST_REWARDS_COUNT; ++iI)
576  {
577  data << uint32(pQuest->RewItemId[iI]);
578  data << uint32(pQuest->RewItemCount[iI]);
579  }
580  for (iI = 0; iI < QUEST_REWARD_CHOICES_COUNT; ++iI)
581  {
582  data << uint32(pQuest->RewChoiceItemId[iI]);
583  data << uint32(pQuest->RewChoiceItemCount[iI]);
584  }
585  }
586 
587  data << pQuest->GetPointMapId();
588  data << pQuest->GetPointX();
589  data << pQuest->GetPointY();
590  data << pQuest->GetPointOpt();
591 
592  data << Title;
593  data << Objectives;
594  data << Details;
595  data << EndText;
596 
597  for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; ++iI)
598  {
599  if (pQuest->ReqCreatureOrGOId[iI] < 0)
600  {
601  // client expected gameobject template id in form (id|0x80000000)
602  data << uint32((pQuest->ReqCreatureOrGOId[iI] * (-1)) | 0x80000000);
603  }
604  else
605  data << uint32(pQuest->ReqCreatureOrGOId[iI]);
606  data << uint32(pQuest->ReqCreatureOrGOCount[iI]);
607  data << uint32(pQuest->ReqItemId[iI]);
608  data << uint32(pQuest->ReqItemCount[iI]);
609  }
610 
611  for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; ++iI)
612  data << ObjectiveText[iI];
613 
614  pSession->SendPacket(&data);
615  DEBUG_LOG("WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", pQuest->GetQuestId());
616 }
617 
618 void PlayerMenu::SendQuestGiverOfferReward(Quest const* pQuest, uint64 npcGUID, bool EnableNext)
619 {
620  std::string Title = pQuest->GetTitle();
621  std::string OfferRewardText = pQuest->GetOfferRewardText();
622 
623  int loc_idx = pSession->GetSessionDbLocaleIndex();
624  if (loc_idx >= 0)
625  {
626  if (QuestLocale const* ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId()))
627  {
628  if (ql->Title.size() > uint32(loc_idx) && !ql->Title[loc_idx].empty())
629  Title = ql->Title[loc_idx];
630  if (ql->OfferRewardText.size() > uint32(loc_idx) && !ql->OfferRewardText[loc_idx].empty())
631  OfferRewardText = ql->OfferRewardText[loc_idx];
632  }
633  }
634 
635  WorldPacket data(SMSG_QUESTGIVER_OFFER_REWARD, 50); // guess size
636 
637  data << uint64(npcGUID);
638  data << uint32(pQuest->GetQuestId());
639  data << Title;
640  data << OfferRewardText;
641 
642  data << uint32(EnableNext);
643  data << uint32(0); // unk
644 
645  uint32 EmoteCount = 0;
646  for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i)
647  {
648  if (pQuest->OfferRewardEmote[i] <= 0)
649  break;
650  ++EmoteCount;
651  }
652 
653  data << EmoteCount; // Emote Count
654  for (uint32 i = 0; i < EmoteCount; ++i)
655  {
656  data << uint32(0); // Delay Emote
657  data << uint32(pQuest->OfferRewardEmote[i]);
658  }
659 
660  ItemTemplate const* pItem;
661 
662  data << uint32(pQuest->GetRewChoiceItemsCount());
663  for (uint32 i = 0; i < pQuest->GetRewChoiceItemsCount(); ++i)
664  {
665  pItem = sObjectMgr.GetItemTemplate(pQuest->RewChoiceItemId[i]);
666 
667  data << uint32(pQuest->RewChoiceItemId[i]);
668  data << uint32(pQuest->RewChoiceItemCount[i]);
669 
670  if (pItem)
671  data << uint32(pItem->DisplayInfoID);
672  else
673  data << uint32(0);
674  }
675 
676  data << uint32(pQuest->GetRewItemsCount());
677  for (uint32 i = 0; i < pQuest->GetRewItemsCount(); ++i)
678  {
679  pItem = sObjectMgr.GetItemTemplate(pQuest->RewItemId[i]);
680  data << uint32(pQuest->RewItemId[i]);
681  data << uint32(pQuest->RewItemCount[i]);
682 
683  if (pItem)
684  data << uint32(pItem->DisplayInfoID);
685  else
686  data << uint32(0);
687  }
688 
689  data << uint32(pQuest->GetRewOrReqMoney());
690 
691  // rewarded honor points. Multiply with 10 to satisfy client
693  data << uint32(0x08); // unused by client?
694  data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0)
695  data << uint32(pQuest->GetRewSpellCast()); // casted spell
696  data << uint32(0); // unknown
697  pSession->SendPacket(&data);
698  sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId());
699 }
700 
701 void PlayerMenu::SendQuestGiverRequestItems(Quest const* pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel)
702 {
703  // We can always call to RequestItems, but this packet only goes out if there are actually
704  // items. Otherwise, we'll skip straight to the OfferReward
705 
706  std::string Title = pQuest->GetTitle();
707  std::string RequestItemsText = pQuest->GetRequestItemsText();
708 
709  int loc_idx = pSession->GetSessionDbLocaleIndex();
710  if (loc_idx >= 0)
711  {
712  if (QuestLocale const* ql = sObjectMgr.GetQuestLocale(pQuest->GetQuestId()))
713  {
714  if (ql->Title.size() > uint32(loc_idx) && !ql->Title[loc_idx].empty())
715  Title = ql->Title[loc_idx];
716  if (ql->RequestItemsText.size() > uint32(loc_idx) && !ql->RequestItemsText[loc_idx].empty())
717  RequestItemsText = ql->RequestItemsText[loc_idx];
718  }
719  }
720 
721  // We may wish a better check, perhaps checking the real quest requirements
722  if (pQuest->GetRequestItemsText().empty() && Completable)
723  {
724  SendQuestGiverOfferReward(pQuest, npcGUID, true);
725  return;
726  }
727 
729  AddQuestLevelToTitle(Title, pQuest->GetQuestLevel());
730 
731  WorldPacket data(SMSG_QUESTGIVER_REQUEST_ITEMS, 50); // guess size
732  data << uint64(npcGUID);
733  data << uint32(pQuest->GetQuestId());
734  data << Title;
735  data << RequestItemsText;
736 
737  data << uint32(0x00); // unknown
738 
739  if (Completable)
740  data << pQuest->GetCompleteEmote();
741  else
742  data << pQuest->GetIncompleteEmote();
743 
744  // Close Window after cancel
745  if (CloseOnCancel)
746  data << uint32(0x01);
747  else
748  data << uint32(0x00);
749 
750  data << uint32(0x00); // unknown
751 
752  // Required Money
753  data << uint32(pQuest->GetRewOrReqMoney() < 0 ? -pQuest->GetRewOrReqMoney() : 0);
754 
755  data << uint32(pQuest->GetReqItemsCount());
756  ItemTemplate const* pItem;
757  for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
758  {
759  if (!pQuest->ReqItemId[i])
760  continue;
761 
762  pItem = sObjectMgr.GetItemTemplate(pQuest->ReqItemId[i]);
763 
764  data << uint32(pQuest->ReqItemId[i]);
765  data << uint32(pQuest->ReqItemCount[i]);
766 
767  if (pItem)
768  data << uint32(pItem->DisplayInfoID);
769  else
770  data << uint32(0);
771  }
772 
773  if (!Completable)
774  data << uint32(0x00);
775  else
776  data << uint32(0x03);
777 
778  data << uint32(0x04);
779  data << uint32(0x08);
780  data << uint32(0x10);
781 
782  pSession->SendPacket(&data);
783  sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId());
784 }
785 
786 void PlayerMenu::AddQuestLevelToTitle(std::string& title, int32 level)
787 {
788  // Adds the quest level to the front of the quest title
789  // example: [13] Westfall Stew
790 
791  std::stringstream questTitlePretty;
792  questTitlePretty << "[" << level << "] " << title;
793  title = questTitlePretty.str();
794 }
795 
uint32 GetRewChoiceItemsCount() const
Definition: QuestDef.h:403
uint32 MenuItemSender(unsigned int ItemId)
Definition: GossipDef.cpp:80
std::vector< std::string > Details
Definition: QuestDef.h:161
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
void SendQuestQueryResponse(Quest const *pQuest)
Definition: GossipDef.cpp:500
QuestMenuItem const & GetItem(uint16 Id)
Definition: GossipDef.h:224
std::string GetTitle() const
Definition: QuestDef.h:285
uint32 DetailsEmote[QUEST_EMOTE_COUNT]
Definition: QuestDef.h:398
std::string Text_1
Definition: NPCHandler.h:52
uint32 GetSuggestedPlayers() const
Definition: QuestDef.h:245
void ClearMenus()
Definition: GossipDef.cpp:116
uint32 GetIncompleteEmote() const
Definition: QuestDef.h:351
int32 GetZoneOrSort() const
Definition: QuestDef.h:189
void AddQuestLevelToTitle(std::string &title, int32 level)
Definition: GossipDef.cpp:786
void SendTalking(uint32 textID)
Definition: GossipDef.cpp:207
uint32 GetRewItemsCount() const
Definition: QuestDef.h:404
#define QUEST_EMOTE_COUNT
Definition: QuestDef.h:39
uint32 ReqItemId[QUEST_OBJECTIVES_COUNT]
Definition: QuestDef.h:385
uint32 m_gAction_menu
Definition: GossipDef.h:131
uint32 GetFlags() const
Definition: QuestDef.h:374
int32 ReqCreatureOrGOId[QUEST_OBJECTIVES_COUNT]
Definition: QuestDef.h:389
uint32 m_qId
Definition: GossipDef.h:140
uint32 GetPointMapId() const
Definition: QuestDef.h:335
uint32 GetNextQuestInChain() const
Definition: QuestDef.h:265
std::string GetEndText() const
Definition: QuestDef.h:305
std::vector< std::string > Objectives
Definition: QuestDef.h:162
#define sLog
Log class singleton.
Definition: Log.h:187
std::vector< std::string > Title
Definition: QuestDef.h:160
void SendQuestGiverQuestDetails(Quest const *pQuest, uint64 npcGUID, bool ActivateAccept)
Definition: GossipDef.cpp:401
ACE_INT32 int32
Definition: Define.h:67
int32 GetRepObjectiveValue() const
Definition: QuestDef.h:225
uint8 MenuItemCount() const
Definition: GossipDef.h:212
std::string Text_0
Definition: NPCHandler.h:51
float GetPointY() const
Definition: QuestDef.h:343
Player * GetPlayer() const
Definition: WorldSession.h:104
void AddMenuItem(uint32 QuestId, uint8 Icon)
Definition: GossipDef.cpp:320
uint32 m_gBoxMoney
Definition: GossipDef.h:124
void SendGossipMenu(uint32 TitleTextId, uint64 npcGUID)
Definition: GossipDef.cpp:137
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
uint32 GetRewHonorableKills() const
Definition: QuestDef.h:310
uint32 m_gMenuId
Definition: GossipDef.h:200
uint32 GetCharTitleId() const
Definition: QuestDef.h:269
QuestMenu mQuestMenu
Definition: GossipDef.h:237
void AddGossipMenuItemData(uint32 action_menu, uint32 action_poi, uint32 action_script)
Definition: GossipDef.cpp:54
uint32 MenuItemAction(unsigned int ItemId)
Definition: GossipDef.cpp:87
std::string GetObjectives() const
Definition: QuestDef.h:293
uint32 GossipOptionSender(unsigned int Selection)
Definition: GossipDef.cpp:122
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT]
Definition: QuestDef.h:384
std::string GetRequestItemsText() const
Definition: QuestDef.h:301
uint32 GetSrcItemId() const
Definition: QuestDef.h:273
ACE_UINT8 uint8
Definition: Define.h:73
uint32 GossipOptionAction(unsigned int Selection)
Definition: GossipDef.cpp:127
bool MenuItemCoded(unsigned int ItemId)
Definition: GossipDef.cpp:94
uint32 DisplayInfoID
bool HasItem(uint32 questid)
Definition: GossipDef.cpp:335
bool GossipOptionCoded(unsigned int Selection)
Definition: GossipDef.cpp:132
uint32 GetQuestId() const
Definition: QuestDef.h:186
uint32 RewChoiceItemCount[QUEST_REWARD_CHOICES_COUNT]
Definition: QuestDef.h:393
GossipMenuItem const & GetItem(unsigned int Id)
Definition: GossipDef.h:180
void SendQuestGiverOfferReward(Quest const *pQuest, uint64 npcGUID, bool EnbleNext)
Definition: GossipDef.cpp:618
uint32 GetCompleteEmote() const
Definition: QuestDef.h:355
uint32 RewChoiceItemId[QUEST_REWARD_CHOICES_COUNT]
Definition: QuestDef.h:392
GossipTextOption Options[8]
Definition: NPCHandler.h:61
void SendQuestGiverStatus(uint8 questStatus, uint64 npcGUID)
Definition: GossipDef.cpp:391
#define DEBUG_LOG(...)
Definition: Log.h:194
uint32 GetRewSpell() const
Definition: QuestDef.h:319
PlayerMenu(WorldSession *Session)
Definition: GossipDef.cpp:107
float GetPointX() const
Definition: QuestDef.h:339
WorldSession * pSession
Definition: GossipDef.h:238
void SendQuestGiverRequestItems(Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel)
Definition: GossipDef.cpp:701
void SendQuestGiverQuestList(QEmote eEmote, const std::string &Title, uint64 npcGUID)
Definition: GossipDef.cpp:348
GossipMenuItemList m_gItems
Definition: GossipDef.h:197
std::string m_gBoxMessage
Definition: GossipDef.h:123
QEmote Emotes[3]
Definition: NPCHandler.h:55
std::string m_gMessage
Definition: GossipDef.h:120
uint32 GetQuestMethod() const
Definition: QuestDef.h:187
uint32 GetReqItemsCount() const
Definition: QuestDef.h:401
uint32 GetType() const
Definition: QuestDef.h:201
uint32 GetRewSpellCast() const
Definition: QuestDef.h:323
uint32 ReqItemCount[QUEST_OBJECTIVES_COUNT]
Definition: QuestDef.h:386
ACE_UINT64 uint64
Definition: Define.h:70
void CloseGossip()
Definition: GossipDef.cpp:187
uint32 m_gAction_script
Definition: GossipDef.h:133
void ClearMenu()
Definition: GossipDef.cpp:101
uint32 m_gAction_poi
Definition: GossipDef.h:132
std::string GetDetails() const
Definition: QuestDef.h:289
unsigned int MenuItemCount() const
Definition: GossipDef.h:170
GossipMenuItemDataList m_gItemsData
Definition: GossipDef.h:198
int GetSessionDbLocaleIndex() const
Definition: WorldSession.h:237
uint32 _Delay
Definition: NPCHandler.h:46
uint32 hk_honor_at_level(uint32 level, uint32 count=1)
Definition: Formulas.h:27
int32 GetRewOrReqMoney() const
Definition: QuestDef.cpp:190
#define QUEST_REWARD_CHOICES_COUNT
Definition: QuestDef.h:35
bool HasFlag(uint32 flag) const
Definition: QuestDef.h:179
std::string GetOfferRewardText() const
Definition: QuestDef.h:297
#define GOSSIP_MAX_MENU_ITEMS
Definition: GossipDef.h:27
#define QUEST_REWARDS_COUNT
Definition: QuestDef.h:36
#define ASSERT
Definition: Errors.h:33
uint32 GetRepObjectiveFaction() const
Definition: QuestDef.h:221
uint32 RewItemId[QUEST_REWARDS_COUNT]
Definition: QuestDef.h:394
uint32 _Emote
Definition: NPCHandler.h:45
uint32 RewItemCount[QUEST_REWARDS_COUNT]
Definition: QuestDef.h:395
#define sWorld
Definition: World.h:860
GossipMenu mGossipMenu
Definition: GossipDef.h:236
uint32 GetMenuId()
Definition: GossipDef.h:163
int32 GetQuestLevel() const
Definition: QuestDef.h:197
ACE_UINT32 uint32
Definition: Define.h:71
uint32 GetPointOpt() const
Definition: QuestDef.h:347
void AddMenuItem(uint8 Icon, const std::string &Message, bool Coded=false)
Definition: GossipDef.cpp:65
void SendPointOfInterest(float X, float Y, uint32 Icon, uint32 Flags, uint32 Data, const char *locName)
Definition: GossipDef.cpp:193
uint32 getLevel() const
Definition: Unit.h:1029
#define QUEST_OBJECTIVES_COUNT
Definition: QuestDef.h:33
uint32 ReqCreatureOrGOCount[QUEST_OBJECTIVES_COUNT]
Definition: QuestDef.h:390
uint32 OfferRewardEmote[QUEST_EMOTE_COUNT]
Definition: QuestDef.h:399
std::vector< std::string > EndText
Definition: QuestDef.h:165
uint32 GetRewMoneyMaxLevel() const
Definition: QuestDef.h:314
void ClearMenu()
Definition: GossipDef.cpp:343
uint8 m_qIcon
Definition: GossipDef.h:141