AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
quest_commandscript Class Reference
Inheritance diagram for quest_commandscript:
CommandScript ScriptObject

Public Member Functions

 quest_commandscript ()
 
ChatCommandTable GetCommands () const override
 
- Public Member Functions inherited from ScriptObject
virtual bool IsDatabaseBound () const
 
virtual bool isAfterLoadScript () const
 
virtual void checkValidity ()
 
const std::string & GetName () const
 
uint16 GetTotalAvailableHooks ()
 

Static Public Member Functions

static bool HandleQuestAdd (ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
 
static bool HandleQuestRemove (ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
 
static bool HandleQuestComplete (ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
 
static bool HandleQuestReward (ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
 
static bool HandleQuestStatus (ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
 

Additional Inherited Members

- Protected Member Functions inherited from CommandScript
 CommandScript (const char *name)
 
- Protected Member Functions inherited from ScriptObject
 ScriptObject (const char *name, uint16 totalAvailableHooks=0)
 
virtual ~ScriptObject ()=default
 

Detailed Description

Constructor & Destructor Documentation

◆ quest_commandscript()

quest_commandscript::quest_commandscript ( )
inline
30: CommandScript("quest_commandscript") { }
Definition CommandScript.h:25

Member Function Documentation

◆ GetCommands()

ChatCommandTable quest_commandscript::GetCommands ( ) const
inlineoverridevirtual

Implements CommandScript.

33 {
34 static ChatCommandTable questCommandTable =
35 {
36 { "add", HandleQuestAdd, SEC_GAMEMASTER, Console::Yes },
37 { "complete", HandleQuestComplete, SEC_GAMEMASTER, Console::Yes },
38 { "remove", HandleQuestRemove, SEC_GAMEMASTER, Console::Yes },
39 { "reward", HandleQuestReward, SEC_GAMEMASTER, Console::Yes },
40 { "status", HandleQuestStatus, SEC_GAMEMASTER, Console::Yes },
41 };
42 static ChatCommandTable commandTable =
43 {
44 { "quest", questCommandTable },
45 };
46 return commandTable;
47 }
@ SEC_GAMEMASTER
Definition Common.h:59
static bool HandleQuestComplete(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:218
static bool HandleQuestReward(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:484
static bool HandleQuestRemove(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:128
static bool HandleQuestAdd(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:49
static bool HandleQuestStatus(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:729
std::vector< ChatCommandBuilder > ChatCommandTable
Definition ChatCommand.h:46

References HandleQuestAdd(), HandleQuestComplete(), HandleQuestRemove(), HandleQuestReward(), HandleQuestStatus(), and SEC_GAMEMASTER.

◆ HandleQuestAdd()

static bool quest_commandscript::HandleQuestAdd ( ChatHandler handler,
Quest const *  quest,
Optional< PlayerIdentifier playerTarget 
)
inlinestatic
50 {
51 if (!playerTarget)
52 {
53 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
54 }
55
56 if (!playerTarget)
57 {
59 return false;
60 }
61
62 uint32 entry = quest->GetQuestId();
63
64 // check item starting quest (it can work incorrectly if added without item in inventory)
65 ItemTemplateContainer const* itc = sObjectMgr->GetItemTemplateStore();
66 ItemTemplateContainer::const_iterator result = find_if(itc->begin(), itc->end(), Finder<uint32, ItemTemplate>(entry, &ItemTemplate::StartQuest));
67
68 if (result != itc->end())
69 {
70 handler->SendErrorMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, result->second.ItemId);
71 return false;
72 }
73
74 if (Player* player = playerTarget->GetConnectedPlayer())
75 {
76 if (player->IsActiveQuest(entry))
77 {
78 handler->SendErrorMessage(LANG_COMMAND_QUEST_ACTIVE, quest->GetTitle().c_str(), entry);
79 return false;
80 }
81
82 // ok, normal (creature/GO starting) quest
83 if (player->CanAddQuest(quest, true))
84 {
85 player->AddQuestAndCheckCompletion(quest, nullptr);
86 }
87 }
88 else
89 {
90 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
91 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {}", guid, entry);
92
93 if (result)
94 {
95 handler->SendErrorMessage(LANG_COMMAND_QUEST_ACTIVE, quest->GetTitle().c_str(), entry);
96 return false;
97 }
98
99 uint8 index = 0;
100
102 stmt->SetData(index++, guid);
103 stmt->SetData(index++, entry);
104 stmt->SetData(index++, 1);
105 stmt->SetData(index++, false);
106 stmt->SetData(index++, 0);
107
108 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
109 {
110 stmt->SetData(index++, 0);
111 }
112
113 for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
114 {
115 stmt->SetData(index++, 0);
116 }
117
118 stmt->SetData(index, 0);
119
120 CharacterDatabase.Execute(stmt);
121 }
122
123 handler->PSendSysMessage(LANG_COMMAND_QUEST_ADD, quest->GetTitle(), entry);
124 handler->SetSentErrorMessage(false);
125 return true;
126 }
@ CHAR_REP_CHAR_QUESTSTATUS
Definition CharacterDatabase.h:438
std::shared_ptr< ResultSet > QueryResult
Definition DatabaseEnvFwd.h:27
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition DatabaseEnv.cpp:21
std::uint8_t uint8
Definition Define.h:109
std::uint32_t uint32
Definition Define.h:107
std::unordered_map< uint32, ItemTemplate > ItemTemplateContainer
Definition ItemTemplate.h:831
@ LANG_COMMAND_QUEST_STARTFROMITEM
Definition Language.h:511
@ LANG_COMMAND_QUEST_ACTIVE
Definition Language.h:515
@ LANG_PLAYER_NOT_FOUND
Definition Language.h:545
@ LANG_COMMAND_QUEST_ADD
Definition Language.h:1132
#define sObjectMgr
Definition ObjectMgr.h:1686
#define QUEST_ITEM_OBJECTIVES_COUNT
Definition QuestDef.h:36
#define QUEST_OBJECTIVES_COUNT
Definition QuestDef.h:35
void PSendSysMessage(std::string_view str, bool escapeCharacters=false)
Definition Chat.cpp:211
void SendErrorMessage(uint32 entry)
Definition Chat.cpp:216
void SetSentErrorMessage(bool val)
Definition Chat.h:238
uint32 LowType
Definition ObjectGuid.h:122
Definition Player.h:1066
Acore::Types::is_default< T > SetData(const uint8 index, T value)
Definition PreparedStatement.h:77
Definition PreparedStatement.h:157
static Optional< PlayerIdentifier > FromTargetOrSelf(ChatHandler *handler)
Definition ChatCommandTags.h:184
Definition Util.h:35
uint32 StartQuest
Definition ItemTemplate.h:668

References CHAR_REP_CHAR_QUESTSTATUS, CharacterDatabase, Acore::ChatCommands::PlayerIdentifier::FromTargetOrSelf(), Quest::GetQuestId(), Quest::GetTitle(), LANG_COMMAND_QUEST_ACTIVE, LANG_COMMAND_QUEST_ADD, LANG_COMMAND_QUEST_STARTFROMITEM, LANG_PLAYER_NOT_FOUND, ChatHandler::PSendSysMessage(), QUEST_ITEM_OBJECTIVES_COUNT, QUEST_OBJECTIVES_COUNT, ChatHandler::SendErrorMessage(), PreparedStatementBase::SetData(), ChatHandler::SetSentErrorMessage(), sObjectMgr, and ItemTemplate::StartQuest.

Referenced by GetCommands().

◆ HandleQuestComplete()

static bool quest_commandscript::HandleQuestComplete ( ChatHandler handler,
Quest const *  quest,
Optional< PlayerIdentifier playerTarget 
)
inlinestatic
219 {
220 if (!playerTarget)
221 {
222 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
223 }
224
225 if (!playerTarget)
226 {
228 return false;
229 }
230
231 uint32 entry = quest->GetQuestId();
232
233 if (Player* player = playerTarget->GetConnectedPlayer())
234 {
235 // If player doesn't have the quest
236 if (player->GetQuestStatus(entry) == QUEST_STATUS_NONE)
237 {
239 return false;
240 }
241
242 // Add quest items for quests that require items
243 for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x)
244 {
245 uint32 id = quest->RequiredItemId[x];
246 uint32 count = quest->RequiredItemCount[x];
247 if (!id || !count)
248 {
249 continue;
250 }
251
252 uint32 curItemCount = player->GetItemCount(id, true);
253
254 ItemPosCountVec dest;
255 uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count - curItemCount);
256 if (msg == EQUIP_ERR_OK)
257 {
258 Item* item = player->StoreNewItem(dest, id, true);
259 player->SendNewItem(item, count - curItemCount, true, false);
260 }
261 }
262
263 // All creature/GO slain/casted (not required, but otherwise it will display "Creature slain 0/10")
264 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
265 {
266 int32 creature = quest->RequiredNpcOrGo[i];
267 uint32 creatureCount = quest->RequiredNpcOrGoCount[i];
268
269 if (creature > 0)
270 {
271 if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature))
272 {
273 for (uint16 z = 0; z < creatureCount; ++z)
274 {
275 player->KilledMonster(creatureInfo, ObjectGuid::Empty);
276 }
277 }
278 }
279 else if (creature < 0)
280 {
281 for (uint16 z = 0; z < creatureCount; ++z)
282 {
283 player->KillCreditGO(creature);
284 }
285 }
286 }
287
288 // player kills
289 if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL))
290 {
291 if (uint32 reqPlayers = quest->GetPlayersSlain())
292 {
293 player->KilledPlayerCreditForQuest(reqPlayers, quest);
294 }
295 }
296
297 // If the quest requires reputation to complete
298 if (uint32 repFaction = quest->GetRepObjectiveFaction())
299 {
300 uint32 repValue = quest->GetRepObjectiveValue();
301 uint32 curRep = player->GetReputationMgr().GetReputation(repFaction);
302 if (curRep < repValue)
303 {
304 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction))
305 {
306 player->GetReputationMgr().SetReputation(factionEntry, static_cast<float>(repValue));
307 }
308 }
309 }
310
311 // If the quest requires a SECOND reputation to complete
312 if (uint32 repFaction = quest->GetRepObjectiveFaction2())
313 {
314 uint32 repValue2 = quest->GetRepObjectiveValue2();
315 uint32 curRep = player->GetReputationMgr().GetReputation(repFaction);
316 if (curRep < repValue2)
317 {
318 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction))
319 {
320 player->GetReputationMgr().SetReputation(factionEntry, static_cast<float>(repValue2));
321 }
322 }
323 }
324
325 // If the quest requires money
326 int32 ReqOrRewMoney = quest->GetRewOrReqMoney(player->GetLevel());
327 if (ReqOrRewMoney < 0)
328 {
329 player->ModifyMoney(-ReqOrRewMoney);
330 }
331
332 player->CompleteQuest(entry);
333 }
334 else
335 {
336 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
337 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {}", guid, entry);
338
339 if (!result)
340 {
341 handler->SendErrorMessage(LANG_COMMAND_QUEST_NOT_FOUND_IN_LOG, quest->GetTitle(), entry);
342 return false;
343 }
344
345 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
346
347 typedef std::pair<uint32, uint32> items;
348 std::vector<items> questItems;
349
350 for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x)
351 {
352 uint32 id = quest->RequiredItemId[x];
353 uint32 count = quest->RequiredItemCount[x];
354 if (!id || !count)
355 {
356 continue;
357 }
358
359 questItems.emplace_back(id, count);
360 }
361
362 if (!questItems.empty())
363 {
365 // fill mail
366 MailDraft draft(quest->GetTitle(), std::string());
367
368 for (auto const& itr : questItems)
369 {
370 if (Item* item = Item::CreateItem(itr.first, itr.second))
371 {
372 item->SaveToDB(trans);
373 draft.AddItem(item);
374 }
375 }
376
377 draft.SendMailTo(trans, MailReceiver(nullptr, guid), sender);
378 }
379
380 uint8 index = 0;
381
383 stmt->SetData(index++, guid);
384 stmt->SetData(index++, entry);
385 stmt->SetData(index++, 1);
386 stmt->SetData(index++, quest->HasFlag(QUEST_FLAGS_EXPLORATION));
387 stmt->SetData(index++, 0);
388
389 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
390 {
391 stmt->SetData(index++, quest->RequiredNpcOrGoCount[i]);
392 }
393
394 for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
395 {
396 // Will be updated once they loot the items from the mailbox.
397 stmt->SetData(index++, 0);
398 }
399
400 stmt->SetData(index, 0);
401
402 trans->Append(stmt);
403
404 // If the quest requires reputation to complete, set the player rep to the required amount.
405 if (uint32 repFaction = quest->GetRepObjectiveFaction())
406 {
407 uint32 repValue = quest->GetRepObjectiveValue();
408
409 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
410 stmt->SetData(0, repFaction);
411 stmt->SetData(1, guid);
412 PreparedQueryResult result = CharacterDatabase.Query(stmt);
413
414 if (result)
415 {
416 Field* fields = result->Fetch();
417 uint32 curRep = fields[0].Get<uint32>();
418
419 if (curRep < repValue)
420 {
421 if (sFactionStore.LookupEntry(repFaction))
422 {
423 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
424 stmt->SetData(0, repFaction);
425 stmt->SetData(1, repValue);
426 stmt->SetData(2, repFaction);
427 stmt->SetData(3, guid);
428 trans->Append(stmt);
429 }
430 }
431 }
432 }
433
434 // If the quest requires reputation to complete, set the player rep to the required amount.
435 if (uint32 repFaction = quest->GetRepObjectiveFaction2())
436 {
437 uint32 repValue = quest->GetRepObjectiveValue();
438
439 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
440 stmt->SetData(0, repFaction);
441 stmt->SetData(1, guid);
442 PreparedQueryResult result = CharacterDatabase.Query(stmt);
443
444 if (result)
445 {
446 Field* fields = result->Fetch();
447 uint32 curRep = fields[0].Get<uint32>();
448
449 if (curRep < repValue)
450 {
451 if (sFactionStore.LookupEntry(repFaction))
452 {
453 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
454 stmt->SetData(0, repFaction);
455 stmt->SetData(1, repValue);
456 stmt->SetData(2, repFaction);
457 stmt->SetData(3, guid);
458 trans->Append(stmt);
459 }
460 }
461 }
462 }
463
464 CharacterDatabase.CommitTransaction(trans);
465 }
466
467 // check if Quest Tracker is enabled
468 if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER))
469 {
470 // prepare Quest Tracker datas
471 auto stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE);
472 stmt->SetData(0, entry);
473 stmt->SetData(1, playerTarget->GetGUID().GetCounter());
474
475 // add to Quest Tracker
476 CharacterDatabase.Execute(stmt);
477 }
478
479 handler->PSendSysMessage(LANG_COMMAND_QUEST_COMPLETE, quest->GetTitle(), entry);
480 handler->SetSentErrorMessage(false);
481 return true;
482 }
@ CHAR_SEL_CHAR_REP_BY_FACTION
Definition CharacterDatabase.h:401
@ CHAR_UPD_QUEST_TRACK_GM_COMPLETE
Definition CharacterDatabase.h:504
@ CHAR_UPD_CHAR_REP_FACTION_CHANGE
Definition CharacterDatabase.h:403
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
Definition DatabaseEnvFwd.h:69
std::shared_ptr< PreparedResultSet > PreparedQueryResult
Definition DatabaseEnvFwd.h:45
std::int32_t int32
Definition Define.h:103
std::uint16_t uint16
Definition Define.h:108
@ EQUIP_ERR_OK
Definition Item.h:47
@ NULL_BAG
Definition Item.h:40
@ NULL_SLOT
Definition Item.h:41
@ LANG_COMMAND_QUEST_COMPLETE
Definition Language.h:514
@ LANG_COMMAND_QUEST_NOTFOUND
Definition Language.h:510
@ LANG_COMMAND_QUEST_NOT_FOUND_IN_LOG
Definition Language.h:1133
@ MAIL_STATIONERY_GM
Definition Mail.h:59
@ MAIL_NORMAL
Definition Mail.h:37
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:758
@ QUEST_FLAGS_EXPLORATION
Definition QuestDef.h:134
@ QUEST_STATUS_NONE
Definition QuestDef.h:100
@ QUEST_SPECIAL_FLAGS_PLAYER_KILL
Definition QuestDef.h:179
@ CONFIG_QUEST_ENABLE_QUEST_TRACKER
Definition WorldConfig.h:107
Class used to access individual fields of database query result.
Definition Field.h:98
std::enable_if_t< std::is_arithmetic_v< T >, T > Get() const
Definition Field.h:112
Definition Item.h:220
static Item * CreateItem(uint32 item, uint32 count, Player const *player=nullptr, bool clone=false, uint32 randomPropertyId=0)
Definition Item.cpp:1087
virtual void SaveToDB(CharacterDatabaseTransaction trans)
Definition Item.cpp:336
Definition Mail.h:119
Definition Mail.h:105
Definition Mail.h:83
LowType GetCounter() const
Definition ObjectGuid.h:145
static ObjectGuid const Empty
Definition ObjectGuid.h:120
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:113
#define sWorld
Definition World.h:316
Definition CreatureData.h:186
Definition DBCStructure.h:907

References MailDraft::AddItem(), CHAR_REP_CHAR_QUESTSTATUS, CHAR_SEL_CHAR_REP_BY_FACTION, CHAR_UPD_CHAR_REP_FACTION_CHANGE, CHAR_UPD_QUEST_TRACK_GM_COMPLETE, CharacterDatabase, CONFIG_QUEST_ENABLE_QUEST_TRACKER, Item::CreateItem(), ObjectGuid::Empty, EQUIP_ERR_OK, Acore::ChatCommands::PlayerIdentifier::FromTargetOrSelf(), Field::Get(), Quest::GetPlayersSlain(), Quest::GetQuestId(), Quest::GetRepObjectiveFaction(), Quest::GetRepObjectiveFaction2(), Quest::GetRepObjectiveValue(), Quest::GetRepObjectiveValue2(), Quest::GetRewOrReqMoney(), Quest::GetTitle(), Quest::HasFlag(), Quest::HasSpecialFlag(), LANG_COMMAND_QUEST_COMPLETE, LANG_COMMAND_QUEST_NOT_FOUND_IN_LOG, LANG_COMMAND_QUEST_NOTFOUND, LANG_PLAYER_NOT_FOUND, MAIL_NORMAL, MAIL_STATIONERY_GM, NULL_BAG, NULL_SLOT, ChatHandler::PSendSysMessage(), QUEST_FLAGS_EXPLORATION, QUEST_ITEM_OBJECTIVES_COUNT, QUEST_OBJECTIVES_COUNT, QUEST_SPECIAL_FLAGS_PLAYER_KILL, QUEST_STATUS_NONE, Quest::RequiredItemCount, Quest::RequiredItemId, Quest::RequiredNpcOrGo, Quest::RequiredNpcOrGoCount, ChatHandler::SendErrorMessage(), MailDraft::SendMailTo(), PreparedStatementBase::SetData(), ChatHandler::SetSentErrorMessage(), sFactionStore, sObjectMgr, and sWorld.

Referenced by GetCommands().

◆ HandleQuestRemove()

static bool quest_commandscript::HandleQuestRemove ( ChatHandler handler,
Quest const *  quest,
Optional< PlayerIdentifier playerTarget 
)
inlinestatic
129 {
130 if (!playerTarget)
131 {
132 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
133 }
134
135 if (!playerTarget)
136 {
138 return false;
139 }
140
141 uint32 entry = quest->GetQuestId();
142
143 if (!quest)
144 {
146 return false;
147 }
148
149 if (Player* player = playerTarget->GetConnectedPlayer())
150 {
151 // remove all quest entries for 'entry' from quest log
152 for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
153 {
154 uint32 logQuest = player->GetQuestSlotQuestId(slot);
155 if (logQuest == entry)
156 {
157 player->SetQuestSlot(slot, 0);
158
159 // we ignore unequippable quest items in this case, its' still be equipped
160 player->TakeQuestSourceItem(logQuest, false);
161
162 if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
163 {
164 player->pvpInfo.IsHostile = player->pvpInfo.IsInHostileArea || player->HasPvPForcingQuest();
165 player->UpdatePvPState();
166 }
167 }
168 }
169
170 player->RemoveRewardedQuest(entry);
171 player->RemoveActiveQuest(entry, false);
172 }
173 else
174 {
175 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
176 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
177
179 stmt->SetData(0, guid);
180 stmt->SetData(1, entry);
181 trans->Append(stmt);
182
183 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST);
184 stmt->SetData(0, guid);
185 stmt->SetData(1, entry);
186 trans->Append(stmt);
187
188 for (uint32 const& requiredItem : quest->RequiredItemId)
189 {
191 stmt->SetData(0, requiredItem);
192 stmt->SetData(1, guid);
193
194 PreparedQueryResult result = CharacterDatabase.Query(stmt);
195
196 if (result)
197 {
198 Field* fields = result->Fetch();
199
200 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
201 stmt->SetData(0, fields[0].Get<uint32>());
202 trans->Append(stmt);
203
204 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
205 stmt->SetData(0, fields[0].Get<uint32>());
206 trans->Append(stmt);
207 }
208 }
209
210 CharacterDatabase.CommitTransaction(trans);
211 }
212
213 handler->PSendSysMessage(LANG_COMMAND_QUEST_REMOVED, quest->GetTitle(), entry);
214 handler->SetSentErrorMessage(false);
215 return true;
216 }
@ CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST
Definition CharacterDatabase.h:441
@ CHAR_DEL_ITEM_INSTANCE
Definition CharacterDatabase.h:127
@ CHAR_DEL_CHAR_INVENTORY_BY_ITEM
Definition CharacterDatabase.h:435
@ CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY_AND_OWNER
Definition CharacterDatabase.h:361
@ CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST
Definition CharacterDatabase.h:439
@ LANG_COMMAND_QUEST_REMOVED
Definition Language.h:512
@ QUEST_FLAGS_FLAGS_PVP
Definition QuestDef.h:145
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:33

References CHAR_DEL_CHAR_INVENTORY_BY_ITEM, CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST, CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST, CHAR_DEL_ITEM_INSTANCE, CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY_AND_OWNER, CharacterDatabase, Acore::ChatCommands::PlayerIdentifier::FromTargetOrSelf(), Quest::GetQuestId(), Quest::GetTitle(), Quest::HasFlag(), LANG_COMMAND_QUEST_NOTFOUND, LANG_COMMAND_QUEST_REMOVED, LANG_PLAYER_NOT_FOUND, MAX_QUEST_LOG_SIZE, ChatHandler::PSendSysMessage(), QUEST_FLAGS_FLAGS_PVP, Quest::RequiredItemId, ChatHandler::SendErrorMessage(), PreparedStatementBase::SetData(), and ChatHandler::SetSentErrorMessage().

Referenced by GetCommands().

◆ HandleQuestReward()

static bool quest_commandscript::HandleQuestReward ( ChatHandler handler,
Quest const *  quest,
Optional< PlayerIdentifier playerTarget 
)
inlinestatic
485 {
486 if (!playerTarget)
487 {
488 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
489 }
490
491 if (!playerTarget)
492 {
494 return false;
495 }
496
497 uint32 entry = quest->GetQuestId();
498
499 if (Player* player = playerTarget->GetConnectedPlayer())
500 {
501 // If player doesn't have the quest
502 if (player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE)
503 {
505 return false;
506 }
507
508 player->RewardQuest(quest, 0, player);
509 }
510 else
511 {
512 // Achievement criteria updates correctly the next time a quest is rewarded.
513 // Titles are already awarded correctly the next time they login (only one quest awards title - 11549).
514 // Rewarded talent points (Death Knights) and spells (e.g Druid forms) are also granted on login.
515 // No reputation gains - too troublesome to calculate them when the player is offline.
516
517 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
518 uint8 charLevel = sCharacterCache->GetCharacterLevelByGuid(ObjectGuid(HighGuid::Player, guid));
519 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
521
522 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {} AND status = 1", guid, entry);
523
524 if (!result)
525 {
527 return false;
528 }
529
530 for (uint32 const& requiredItem : quest->RequiredItemId)
531 {
533 stmt->SetData(0, requiredItem);
534 stmt->SetData(1, guid);
535
536 PreparedQueryResult result = CharacterDatabase.Query(stmt);
537
538 if (result)
539 {
540 Field* fields = result->Fetch();
541
542 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
543 stmt->SetData(0, fields[0].Get<uint32>());
544 trans->Append(stmt);
545
546 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
547 stmt->SetData(0, fields[0].Get<uint32>());
548 trans->Append(stmt);
549 }
550 }
551
552 for (uint32 const& sourceItem : quest->ItemDrop)
553 {
555 stmt->SetData(0, sourceItem);
556 stmt->SetData(1, guid);
557
558 PreparedQueryResult result = CharacterDatabase.Query(stmt);
559
560 if (result)
561 {
562 Field* fields = result->Fetch();
563
564 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
565 stmt->SetData(0, fields[0].Get<uint32>());
566 trans->Append(stmt);
567
568 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
569 stmt->SetData(0, fields[0].Get<uint32>());
570 trans->Append(stmt);
571 }
572 }
573
574 typedef std::pair<uint32, uint32> items;
575 std::vector<items> questRewardItems;
576
577 if (quest->GetRewChoiceItemsCount())
578 {
579 for (uint32 const& itemId : quest->RewardChoiceItemId)
580 {
581 uint8 index = 0;
582 questRewardItems.emplace_back(itemId, quest->RewardChoiceItemCount[index++]);
583 }
584 }
585
586 if (quest->GetRewItemsCount())
587 {
588 for (uint32 const& itemId : quest->RewardItemId)
589 {
590 uint8 index = 0;
591 questRewardItems.emplace_back(itemId, quest->RewardItemIdCount[index++]);
592 }
593 }
594
595 if (!questRewardItems.empty())
596 {
598 // fill mail
599 MailDraft draft(quest->GetTitle(), "This quest has been manually rewarded to you. This mail contains your quest rewards.");
600
601 for (auto const& itr : questRewardItems)
602 {
603 if (!itr.first || !itr.second)
604 {
605 continue;
606 }
607
608 // Skip invalid items.
609 if (!sObjectMgr->GetItemTemplate(itr.first))
610 {
611 continue;
612 }
613
614 if (Item* item = Item::CreateItem(itr.first, itr.second))
615 {
616 item->SaveToDB(trans);
617 draft.AddItem(item);
618 }
619 }
620
621 draft.SendMailTo(trans, MailReceiver(nullptr, guid), sender);
622 }
623
624 // Send quest giver mail, if any.
625 if (uint32 mail_template_id = quest->GetRewMailTemplateId())
626 {
627 if (quest->GetRewMailSenderEntry() != 0)
628 {
629 MailDraft(mail_template_id).SendMailTo(trans, MailReceiver(nullptr, guid), quest->GetRewMailSenderEntry(), MAIL_CHECK_MASK_HAS_BODY, quest->GetRewMailDelaySecs());
630 }
631 }
632
633 if (quest->IsDaily() || quest->IsDFQuest())
634 {
635 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
636 stmt->SetData(0, guid);
637 stmt->SetData(1, entry);
638 stmt->SetData(2, GameTime::GetGameTime().count());
639 trans->Append(stmt);
640 }
641 else if (quest->IsWeekly())
642 {
643 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS);
644 stmt->SetData(0, guid);
645 stmt->SetData(1, entry);
646 trans->Append(stmt);
647 }
648 else if (quest->IsMonthly())
649 {
650 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_MONTHLYQUESTSTATUS);
651 stmt->SetData(0, guid);
652 stmt->SetData(1, entry);
653 trans->Append(stmt);
654 }
655 else if (quest->IsSeasonal())
656 {
657 // We can't know which event is the quest linked to, so we can't do anything about this.
658 /* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS);
659 stmt->SetData(0, guid);
660 stmt->SetData(1, entry);
661 stmt->SetData(2, event_id);
662 trans->Append(stmt);*/
663 }
664
665 if (uint32 honor = quest->CalculateHonorGain(charLevel))
666 {
668 stmt->SetData(0, honor);
669 stmt->SetData(1, guid);
670 trans->Append(stmt);
671 }
672
673 if (quest->GetRewArenaPoints())
674 {
676 stmt->SetData(0, quest->GetRewArenaPoints());
677 stmt->SetData(1, guid);
678 trans->Append(stmt);
679 }
680
681 int32 rewMoney = 0;
682
683 if (charLevel >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
684 {
685 rewMoney = quest->GetRewMoneyMaxLevel();
686 }
687 else
688 {
689 // Some experience might get lost on level up.
690 uint32 xp = uint32(quest->XPValue(charLevel) * sWorld->getRate(RATE_XP_QUEST));
691 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_XP_ACCUMULATIVE);
692 stmt->SetData(0, xp);
693 stmt->SetData(1, guid);
694 trans->Append(stmt);
695 }
696
697 if (int32 rewOrReqMoney = quest->GetRewOrReqMoney(charLevel))
698 {
699 rewMoney += rewOrReqMoney;
700 }
701
702 // Only reward money, don't subtract, let's not cause an overflow...
703 if (rewMoney > 0)
704 {
706 stmt->SetData(0, rewMoney);
707 stmt->SetData(1, guid);
708 trans->Append(stmt);
709 }
710
711 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_REWARDED);
712 stmt->SetData(0, guid);
713 stmt->SetData(1, entry);
714 trans->Append(stmt);
715
716 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST);
717 stmt->SetData(0, guid);
718 stmt->SetData(1, entry);
719 trans->Append(stmt);
720
721 CharacterDatabase.CommitTransaction(trans);
722 }
723
724 handler->PSendSysMessage(LANG_COMMAND_QUEST_REWARDED, quest->GetTitle(), entry);
725 handler->SetSentErrorMessage(false);
726 return true;
727 }
#define sCharacterCache
Definition CharacterCache.h:83
@ CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS
Definition CharacterDatabase.h:75
@ CHAR_INS_CHARACTER_MONTHLYQUESTSTATUS
Definition CharacterDatabase.h:76
@ CHAR_UDP_CHAR_MONEY_ACCUMULATIVE
Definition CharacterDatabase.h:430
@ CHAR_UDP_CHAR_HONOR_POINTS_ACCUMULATIVE
Definition CharacterDatabase.h:426
@ CHAR_UPD_XP_ACCUMULATIVE
Definition CharacterDatabase.h:298
@ CHAR_INS_CHARACTER_DAILYQUESTSTATUS
Definition CharacterDatabase.h:74
@ CHAR_UDP_CHAR_ARENA_POINTS_ACCUMULATIVE
Definition CharacterDatabase.h:428
@ CHAR_INS_CHAR_QUESTSTATUS_REWARDED
Definition CharacterDatabase.h:440
@ LANG_COMMAND_QUEST_REWARDED
Definition Language.h:513
@ LANG_COMMAND_QUEST_NOT_COMPLETE
Definition Language.h:1134
@ MAIL_CHECK_MASK_HAS_BODY
Definition Mail.h:51
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:101
@ CONFIG_MAX_PLAYER_LEVEL
Definition WorldConfig.h:190
@ RATE_XP_QUEST
Definition WorldConfig.h:435
void SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const &receiver, MailSender const &sender, MailCheckMask checked=MAIL_CHECK_MASK_NONE, uint32 deliver_delay=0, uint32 custom_expiration=0, bool deleteMailItemsFromDB=false, bool sendMail=true)
Definition Mail.cpp:185
Definition ObjectGuid.h:118
Seconds GetGameTime()
Definition GameTime.cpp:38

References MailDraft::AddItem(), Quest::CalculateHonorGain(), CHAR_DEL_CHAR_INVENTORY_BY_ITEM, CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST, CHAR_DEL_ITEM_INSTANCE, CHAR_INS_CHAR_QUESTSTATUS_REWARDED, CHAR_INS_CHARACTER_DAILYQUESTSTATUS, CHAR_INS_CHARACTER_MONTHLYQUESTSTATUS, CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS, CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY_AND_OWNER, CHAR_UDP_CHAR_ARENA_POINTS_ACCUMULATIVE, CHAR_UDP_CHAR_HONOR_POINTS_ACCUMULATIVE, CHAR_UDP_CHAR_MONEY_ACCUMULATIVE, CHAR_UPD_XP_ACCUMULATIVE, CharacterDatabase, CONFIG_MAX_PLAYER_LEVEL, Item::CreateItem(), Acore::ChatCommands::PlayerIdentifier::FromTargetOrSelf(), GameTime::GetGameTime(), Quest::GetQuestId(), Quest::GetRewArenaPoints(), Quest::GetRewChoiceItemsCount(), Quest::GetRewItemsCount(), Quest::GetRewMailDelaySecs(), Quest::GetRewMailSenderEntry(), Quest::GetRewMailTemplateId(), Quest::GetRewMoneyMaxLevel(), Quest::GetRewOrReqMoney(), Quest::GetTitle(), Quest::IsDaily(), Quest::IsDFQuest(), Quest::IsMonthly(), Quest::IsSeasonal(), Quest::IsWeekly(), Quest::ItemDrop, LANG_COMMAND_QUEST_NOT_COMPLETE, LANG_COMMAND_QUEST_NOTFOUND, LANG_COMMAND_QUEST_REWARDED, LANG_PLAYER_NOT_FOUND, MAIL_CHECK_MASK_HAS_BODY, MAIL_NORMAL, MAIL_STATIONERY_GM, Player, ChatHandler::PSendSysMessage(), QUEST_STATUS_COMPLETE, RATE_XP_QUEST, Quest::RequiredItemId, Quest::RewardChoiceItemCount, Quest::RewardChoiceItemId, Quest::RewardItemId, Quest::RewardItemIdCount, sCharacterCache, ChatHandler::SendErrorMessage(), MailDraft::SendMailTo(), PreparedStatementBase::SetData(), ChatHandler::SetSentErrorMessage(), sObjectMgr, sWorld, and Quest::XPValue().

Referenced by GetCommands().

◆ HandleQuestStatus()

static bool quest_commandscript::HandleQuestStatus ( ChatHandler handler,
Quest const *  quest,
Optional< PlayerIdentifier playerTarget 
)
inlinestatic
730 {
731 if (!playerTarget)
732 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
733
734 if (!playerTarget)
735 {
737 return false;
738 }
739
740 uint32 entry = quest->GetQuestId();
741 std::string status;
742 if (Player* player = playerTarget->GetConnectedPlayer())
743 {
744 QuestStatus qs = player->GetQuestStatus(entry);
745 switch (qs)
746 {
748 status = "Not Taken";
749 break;
751 status = "Complete";
752 break;
754 status = "Incomplete";
755 break;
757 status = "Failed";
758 break;
760 status = "Rewarded";
761 break;
762 default:
763 status = "Unknown";
764 break;
765 }
766
767 handler->PSendSysMessage(LANG_CMD_QUEST_STATUS, quest->GetTitle(), entry, status);
768
769 if (!player->CanTakeQuest(quest, true))
770 handler->PSendSysMessage(LANG_CMD_QUEST_UNAVAILABLE, entry, status);
771 }
772
773 return true;
774 }
@ LANG_CMD_QUEST_UNAVAILABLE
Definition Language.h:1163
@ LANG_CMD_QUEST_STATUS
Definition Language.h:1162
QuestStatus
Definition QuestDef.h:99
@ QUEST_STATUS_REWARDED
Definition QuestDef.h:106
@ QUEST_STATUS_FAILED
Definition QuestDef.h:105
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:103

References Acore::ChatCommands::PlayerIdentifier::FromTargetOrSelf(), Quest::GetQuestId(), Quest::GetTitle(), LANG_CMD_QUEST_STATUS, LANG_CMD_QUEST_UNAVAILABLE, LANG_PLAYER_NOT_FOUND, ChatHandler::PSendSysMessage(), QUEST_STATUS_COMPLETE, QUEST_STATUS_FAILED, QUEST_STATUS_INCOMPLETE, QUEST_STATUS_NONE, QUEST_STATUS_REWARDED, and ChatHandler::SendErrorMessage().

Referenced by GetCommands().


The documentation for this class was generated from the following file: