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
32: CommandScript("quest_commandscript") { }
Definition CommandScript.h:25

Member Function Documentation

◆ GetCommands()

ChatCommandTable quest_commandscript::GetCommands ( ) const
inlineoverridevirtual

Implements CommandScript.

35 {
36 static ChatCommandTable questCommandTable =
37 {
38 { "add", HandleQuestAdd, SEC_GAMEMASTER, Console::Yes },
39 { "complete", HandleQuestComplete, SEC_GAMEMASTER, Console::Yes },
40 { "remove", HandleQuestRemove, SEC_GAMEMASTER, Console::Yes },
41 { "reward", HandleQuestReward, SEC_GAMEMASTER, Console::Yes },
42 { "status", HandleQuestStatus, SEC_GAMEMASTER, Console::Yes },
43 };
44 static ChatCommandTable commandTable =
45 {
46 { "quest", questCommandTable },
47 };
48 return commandTable;
49 }
@ SEC_GAMEMASTER
Definition Common.h:59
static bool HandleQuestComplete(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:220
static bool HandleQuestReward(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:486
static bool HandleQuestRemove(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:130
static bool HandleQuestAdd(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:51
static bool HandleQuestStatus(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:731
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
52 {
53 if (!playerTarget)
54 {
55 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
56 }
57
58 if (!playerTarget)
59 {
61 return false;
62 }
63
64 uint32 entry = quest->GetQuestId();
65
66 // check item starting quest (it can work incorrectly if added without item in inventory)
67 ItemTemplateContainer const* itc = sObjectMgr->GetItemTemplateStore();
68 ItemTemplateContainer::const_iterator result = find_if(itc->begin(), itc->end(), Finder<uint32, ItemTemplate>(entry, &ItemTemplate::StartQuest));
69
70 if (result != itc->end())
71 {
72 handler->SendErrorMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, result->second.ItemId);
73 return false;
74 }
75
76 if (Player* player = playerTarget->GetConnectedPlayer())
77 {
78 if (player->IsActiveQuest(entry))
79 {
80 handler->SendErrorMessage(LANG_COMMAND_QUEST_ACTIVE, quest->GetTitle().c_str(), entry);
81 return false;
82 }
83
84 // ok, normal (creature/GO starting) quest
85 if (player->CanAddQuest(quest, true))
86 {
87 player->AddQuestAndCheckCompletion(quest, nullptr);
88 }
89 }
90 else
91 {
92 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
93 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {}", guid, entry);
94
95 if (result)
96 {
97 handler->SendErrorMessage(LANG_COMMAND_QUEST_ACTIVE, quest->GetTitle().c_str(), entry);
98 return false;
99 }
100
101 uint8 index = 0;
102
104 stmt->SetData(index++, guid);
105 stmt->SetData(index++, entry);
106 stmt->SetData(index++, 1);
107 stmt->SetData(index++, false);
108 stmt->SetData(index++, 0);
109
110 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
111 {
112 stmt->SetData(index++, 0);
113 }
114
115 for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
116 {
117 stmt->SetData(index++, 0);
118 }
119
120 stmt->SetData(index, 0);
121
122 CharacterDatabase.Execute(stmt);
123 }
124
125 handler->PSendSysMessage(LANG_COMMAND_QUEST_ADD, quest->GetTitle(), entry);
126 handler->SetSentErrorMessage(false);
127 return true;
128 }
@ CHAR_REP_CHAR_QUESTSTATUS
Definition CharacterDatabase.h:440
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:1133
#define sObjectMgr
Definition ObjectMgr.h:1712
#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:1084
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
221 {
222 if (!playerTarget)
223 {
224 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
225 }
226
227 if (!playerTarget)
228 {
230 return false;
231 }
232
233 uint32 entry = quest->GetQuestId();
234
235 if (Player* player = playerTarget->GetConnectedPlayer())
236 {
237 // If player doesn't have the quest
238 if (player->GetQuestStatus(entry) == QUEST_STATUS_NONE)
239 {
241 return false;
242 }
243
244 // Add quest items for quests that require items
245 for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x)
246 {
247 uint32 id = quest->RequiredItemId[x];
248 uint32 count = quest->RequiredItemCount[x];
249 if (!id || !count)
250 {
251 continue;
252 }
253
254 uint32 curItemCount = player->GetItemCount(id, true);
255
256 ItemPosCountVec dest;
257 uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count - curItemCount);
258 if (msg == EQUIP_ERR_OK)
259 {
260 Item* item = player->StoreNewItem(dest, id, true);
261 player->SendNewItem(item, count - curItemCount, true, false);
262 }
263 }
264
265 // All creature/GO slain/casted (not required, but otherwise it will display "Creature slain 0/10")
266 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
267 {
268 int32 creature = quest->RequiredNpcOrGo[i];
269 uint32 creatureCount = quest->RequiredNpcOrGoCount[i];
270
271 if (creature > 0)
272 {
273 if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature))
274 {
275 for (uint16 z = 0; z < creatureCount; ++z)
276 {
277 player->KilledMonster(creatureInfo, ObjectGuid::Empty);
278 }
279 }
280 }
281 else if (creature < 0)
282 {
283 for (uint16 z = 0; z < creatureCount; ++z)
284 {
285 player->KillCreditGO(creature);
286 }
287 }
288 }
289
290 // player kills
291 if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL))
292 {
293 if (uint32 reqPlayers = quest->GetPlayersSlain())
294 {
295 player->KilledPlayerCreditForQuest(reqPlayers, quest);
296 }
297 }
298
299 // If the quest requires reputation to complete
300 if (uint32 repFaction = quest->GetRepObjectiveFaction())
301 {
302 uint32 repValue = quest->GetRepObjectiveValue();
303 uint32 curRep = player->GetReputationMgr().GetReputation(repFaction);
304 if (curRep < repValue)
305 {
306 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction))
307 {
308 player->GetReputationMgr().SetReputation(factionEntry, static_cast<float>(repValue));
309 }
310 }
311 }
312
313 // If the quest requires a SECOND reputation to complete
314 if (uint32 repFaction = quest->GetRepObjectiveFaction2())
315 {
316 uint32 repValue2 = quest->GetRepObjectiveValue2();
317 uint32 curRep = player->GetReputationMgr().GetReputation(repFaction);
318 if (curRep < repValue2)
319 {
320 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction))
321 {
322 player->GetReputationMgr().SetReputation(factionEntry, static_cast<float>(repValue2));
323 }
324 }
325 }
326
327 // If the quest requires money
328 int32 ReqOrRewMoney = quest->GetRewOrReqMoney(player->GetLevel());
329 if (ReqOrRewMoney < 0)
330 {
331 player->ModifyMoney(-ReqOrRewMoney);
332 }
333
334 player->CompleteQuest(entry);
335 }
336 else
337 {
338 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
339 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {}", guid, entry);
340
341 if (!result)
342 {
343 handler->SendErrorMessage(LANG_COMMAND_QUEST_NOT_FOUND_IN_LOG, quest->GetTitle(), entry);
344 return false;
345 }
346
347 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
348
349 typedef std::pair<uint32, uint32> items;
350 std::vector<items> questItems;
351
352 for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x)
353 {
354 uint32 id = quest->RequiredItemId[x];
355 uint32 count = quest->RequiredItemCount[x];
356 if (!id || !count)
357 {
358 continue;
359 }
360
361 questItems.emplace_back(id, count);
362 }
363
364 if (!questItems.empty())
365 {
367 // fill mail
368 MailDraft draft(quest->GetTitle(), std::string());
369
370 for (auto const& itr : questItems)
371 {
372 if (Item* item = Item::CreateItem(itr.first, itr.second))
373 {
374 item->SaveToDB(trans);
375 draft.AddItem(item);
376 }
377 }
378
379 draft.SendMailTo(trans, MailReceiver(nullptr, guid), sender);
380 }
381
382 uint8 index = 0;
383
385 stmt->SetData(index++, guid);
386 stmt->SetData(index++, entry);
387 stmt->SetData(index++, 1);
388 stmt->SetData(index++, quest->HasFlag(QUEST_FLAGS_EXPLORATION));
389 stmt->SetData(index++, 0);
390
391 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
392 {
393 stmt->SetData(index++, quest->RequiredNpcOrGoCount[i]);
394 }
395
396 for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
397 {
398 // Will be updated once they loot the items from the mailbox.
399 stmt->SetData(index++, 0);
400 }
401
402 stmt->SetData(index, 0);
403
404 trans->Append(stmt);
405
406 // If the quest requires reputation to complete, set the player rep to the required amount.
407 if (uint32 repFaction = quest->GetRepObjectiveFaction())
408 {
409 uint32 repValue = quest->GetRepObjectiveValue();
410
411 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
412 stmt->SetData(0, repFaction);
413 stmt->SetData(1, guid);
414 PreparedQueryResult result = CharacterDatabase.Query(stmt);
415
416 if (result)
417 {
418 Field* fields = result->Fetch();
419 uint32 curRep = fields[0].Get<uint32>();
420
421 if (curRep < repValue)
422 {
423 if (sFactionStore.LookupEntry(repFaction))
424 {
425 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
426 stmt->SetData(0, repFaction);
427 stmt->SetData(1, repValue);
428 stmt->SetData(2, repFaction);
429 stmt->SetData(3, guid);
430 trans->Append(stmt);
431 }
432 }
433 }
434 }
435
436 // If the quest requires reputation to complete, set the player rep to the required amount.
437 if (uint32 repFaction = quest->GetRepObjectiveFaction2())
438 {
439 uint32 repValue = quest->GetRepObjectiveValue();
440
441 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
442 stmt->SetData(0, repFaction);
443 stmt->SetData(1, guid);
444 PreparedQueryResult result = CharacterDatabase.Query(stmt);
445
446 if (result)
447 {
448 Field* fields = result->Fetch();
449 uint32 curRep = fields[0].Get<uint32>();
450
451 if (curRep < repValue)
452 {
453 if (sFactionStore.LookupEntry(repFaction))
454 {
455 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
456 stmt->SetData(0, repFaction);
457 stmt->SetData(1, repValue);
458 stmt->SetData(2, repFaction);
459 stmt->SetData(3, guid);
460 trans->Append(stmt);
461 }
462 }
463 }
464 }
465
466 CharacterDatabase.CommitTransaction(trans);
467 }
468
469 // check if Quest Tracker is enabled
470 if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER))
471 {
472 // prepare Quest Tracker datas
473 auto stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE);
474 stmt->SetData(0, entry);
475 stmt->SetData(1, playerTarget->GetGUID().GetCounter());
476
477 // add to Quest Tracker
478 CharacterDatabase.Execute(stmt);
479 }
480
481 handler->PSendSysMessage(LANG_COMMAND_QUEST_COMPLETE, quest->GetTitle(), entry);
482 handler->SetSentErrorMessage(false);
483 return true;
484 }
@ CHAR_SEL_CHAR_REP_BY_FACTION
Definition CharacterDatabase.h:401
@ CHAR_UPD_QUEST_TRACK_GM_COMPLETE
Definition CharacterDatabase.h:506
@ 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:1134
@ MAIL_STATIONERY_GM
Definition Mail.h:59
@ MAIL_NORMAL
Definition Mail.h:37
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:757
@ 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:109
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:114
#define sWorld
Definition World.h:316
Definition CreatureData.h:187
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
131 {
132 if (!playerTarget)
133 {
134 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
135 }
136
137 if (!playerTarget)
138 {
140 return false;
141 }
142
143 uint32 entry = quest->GetQuestId();
144
145 if (!quest)
146 {
148 return false;
149 }
150
151 if (Player* player = playerTarget->GetConnectedPlayer())
152 {
153 // remove all quest entries for 'entry' from quest log
154 for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
155 {
156 uint32 logQuest = player->GetQuestSlotQuestId(slot);
157 if (logQuest == entry)
158 {
159 player->SetQuestSlot(slot, 0);
160
161 // we ignore unequippable quest items in this case, its' still be equipped
162 player->TakeQuestSourceItem(logQuest, false);
163
164 if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
165 {
166 player->pvpInfo.IsHostile = player->pvpInfo.IsInHostileArea || player->HasPvPForcingQuest();
167 player->UpdatePvPState();
168 }
169 }
170 }
171
172 player->RemoveRewardedQuest(entry);
173 player->RemoveActiveQuest(entry, false);
174 }
175 else
176 {
177 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
178 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
179
181 stmt->SetData(0, guid);
182 stmt->SetData(1, entry);
183 trans->Append(stmt);
184
185 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST);
186 stmt->SetData(0, guid);
187 stmt->SetData(1, entry);
188 trans->Append(stmt);
189
190 for (uint32 const& requiredItem : quest->RequiredItemId)
191 {
193 stmt->SetData(0, requiredItem);
194 stmt->SetData(1, guid);
195
196 PreparedQueryResult result = CharacterDatabase.Query(stmt);
197
198 if (result)
199 {
200 Field* fields = result->Fetch();
201
202 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
203 stmt->SetData(0, fields[0].Get<uint32>());
204 trans->Append(stmt);
205
206 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
207 stmt->SetData(0, fields[0].Get<uint32>());
208 trans->Append(stmt);
209 }
210 }
211
212 CharacterDatabase.CommitTransaction(trans);
213 }
214
215 handler->PSendSysMessage(LANG_COMMAND_QUEST_REMOVED, quest->GetTitle(), entry);
216 handler->SetSentErrorMessage(false);
217 return true;
218 }
@ CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST
Definition CharacterDatabase.h:443
@ CHAR_DEL_ITEM_INSTANCE
Definition CharacterDatabase.h:127
@ CHAR_DEL_CHAR_INVENTORY_BY_ITEM
Definition CharacterDatabase.h:437
@ CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY_AND_OWNER
Definition CharacterDatabase.h:361
@ CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST
Definition CharacterDatabase.h:441
@ 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
487 {
488 if (!playerTarget)
489 {
490 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
491 }
492
493 if (!playerTarget)
494 {
496 return false;
497 }
498
499 uint32 entry = quest->GetQuestId();
500
501 if (Player* player = playerTarget->GetConnectedPlayer())
502 {
503 // If player doesn't have the quest
504 if (player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE)
505 {
507 return false;
508 }
509
510 player->RewardQuest(quest, 0, player);
511 }
512 else
513 {
514 // Achievement criteria updates correctly the next time a quest is rewarded.
515 // Titles are already awarded correctly the next time they login (only one quest awards title - 11549).
516 // Rewarded talent points (Death Knights) and spells (e.g Druid forms) are also granted on login.
517 // No reputation gains - too troublesome to calculate them when the player is offline.
518
519 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
520 uint8 charLevel = sCharacterCache->GetCharacterLevelByGuid(ObjectGuid(HighGuid::Player, guid));
521 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
523
524 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {} AND status = 1", guid, entry);
525
526 if (!result)
527 {
529 return false;
530 }
531
532 for (uint32 const& requiredItem : quest->RequiredItemId)
533 {
535 stmt->SetData(0, requiredItem);
536 stmt->SetData(1, guid);
537
538 PreparedQueryResult result = CharacterDatabase.Query(stmt);
539
540 if (result)
541 {
542 Field* fields = result->Fetch();
543
544 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
545 stmt->SetData(0, fields[0].Get<uint32>());
546 trans->Append(stmt);
547
548 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
549 stmt->SetData(0, fields[0].Get<uint32>());
550 trans->Append(stmt);
551 }
552 }
553
554 for (uint32 const& sourceItem : quest->ItemDrop)
555 {
557 stmt->SetData(0, sourceItem);
558 stmt->SetData(1, guid);
559
560 PreparedQueryResult result = CharacterDatabase.Query(stmt);
561
562 if (result)
563 {
564 Field* fields = result->Fetch();
565
566 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
567 stmt->SetData(0, fields[0].Get<uint32>());
568 trans->Append(stmt);
569
570 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
571 stmt->SetData(0, fields[0].Get<uint32>());
572 trans->Append(stmt);
573 }
574 }
575
576 typedef std::pair<uint32, uint32> items;
577 std::vector<items> questRewardItems;
578
579 if (quest->GetRewChoiceItemsCount())
580 {
581 for (uint32 const& itemId : quest->RewardChoiceItemId)
582 {
583 uint8 index = 0;
584 questRewardItems.emplace_back(itemId, quest->RewardChoiceItemCount[index++]);
585 }
586 }
587
588 if (quest->GetRewItemsCount())
589 {
590 for (uint32 const& itemId : quest->RewardItemId)
591 {
592 uint8 index = 0;
593 questRewardItems.emplace_back(itemId, quest->RewardItemIdCount[index++]);
594 }
595 }
596
597 if (!questRewardItems.empty())
598 {
600 // fill mail
601 MailDraft draft(quest->GetTitle(), "This quest has been manually rewarded to you. This mail contains your quest rewards.");
602
603 for (auto const& itr : questRewardItems)
604 {
605 if (!itr.first || !itr.second)
606 {
607 continue;
608 }
609
610 // Skip invalid items.
611 if (!sObjectMgr->GetItemTemplate(itr.first))
612 {
613 continue;
614 }
615
616 if (Item* item = Item::CreateItem(itr.first, itr.second))
617 {
618 item->SaveToDB(trans);
619 draft.AddItem(item);
620 }
621 }
622
623 draft.SendMailTo(trans, MailReceiver(nullptr, guid), sender);
624 }
625
626 // Send quest giver mail, if any.
627 if (uint32 mail_template_id = quest->GetRewMailTemplateId())
628 {
629 if (quest->GetRewMailSenderEntry() != 0)
630 {
631 MailDraft(mail_template_id).SendMailTo(trans, MailReceiver(nullptr, guid), quest->GetRewMailSenderEntry(), MAIL_CHECK_MASK_HAS_BODY, quest->GetRewMailDelaySecs());
632 }
633 }
634
635 if (quest->IsDaily() || quest->IsDFQuest())
636 {
637 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
638 stmt->SetData(0, guid);
639 stmt->SetData(1, entry);
640 stmt->SetData(2, GameTime::GetGameTime().count());
641 trans->Append(stmt);
642 }
643 else if (quest->IsWeekly())
644 {
645 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS);
646 stmt->SetData(0, guid);
647 stmt->SetData(1, entry);
648 trans->Append(stmt);
649 }
650 else if (quest->IsMonthly())
651 {
652 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_MONTHLYQUESTSTATUS);
653 stmt->SetData(0, guid);
654 stmt->SetData(1, entry);
655 trans->Append(stmt);
656 }
657 else if (quest->IsSeasonal())
658 {
659 // We can't know which event is the quest linked to, so we can't do anything about this.
660 /* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS);
661 stmt->SetData(0, guid);
662 stmt->SetData(1, entry);
663 stmt->SetData(2, event_id);
664 trans->Append(stmt);*/
665 }
666
667 if (uint32 honor = quest->CalculateHonorGain(charLevel))
668 {
670 stmt->SetData(0, honor);
671 stmt->SetData(1, guid);
672 trans->Append(stmt);
673 }
674
675 if (quest->GetRewArenaPoints())
676 {
678 stmt->SetData(0, quest->GetRewArenaPoints());
679 stmt->SetData(1, guid);
680 trans->Append(stmt);
681 }
682
683 int32 rewMoney = 0;
684
685 if (charLevel >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
686 {
687 rewMoney = quest->GetRewMoneyMaxLevel();
688 }
689 else
690 {
691 // Some experience might get lost on level up.
692 uint32 xp = uint32(quest->XPValue(charLevel) * sWorld->getRate(RATE_XP_QUEST));
693 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_XP_ACCUMULATIVE);
694 stmt->SetData(0, xp);
695 stmt->SetData(1, guid);
696 trans->Append(stmt);
697 }
698
699 if (int32 rewOrReqMoney = quest->GetRewOrReqMoney(charLevel))
700 {
701 rewMoney += rewOrReqMoney;
702 }
703
704 // Only reward money, don't subtract, let's not cause an overflow...
705 if (rewMoney > 0)
706 {
708 stmt->SetData(0, rewMoney);
709 stmt->SetData(1, guid);
710 trans->Append(stmt);
711 }
712
713 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_REWARDED);
714 stmt->SetData(0, guid);
715 stmt->SetData(1, entry);
716 trans->Append(stmt);
717
718 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST);
719 stmt->SetData(0, guid);
720 stmt->SetData(1, entry);
721 trans->Append(stmt);
722
723 CharacterDatabase.CommitTransaction(trans);
724 }
725
726 handler->PSendSysMessage(LANG_COMMAND_QUEST_REWARDED, quest->GetTitle(), entry);
727 handler->SetSentErrorMessage(false);
728 return true;
729 }
#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:432
@ 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:442
@ LANG_COMMAND_QUEST_REWARDED
Definition Language.h:513
@ LANG_COMMAND_QUEST_NOT_COMPLETE
Definition Language.h:1135
@ MAIL_CHECK_MASK_HAS_BODY
Definition Mail.h:51
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:101
@ CONFIG_MAX_PLAYER_LEVEL
Definition WorldConfig.h:193
@ RATE_XP_QUEST
Definition WorldConfig.h:438
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
732 {
733 if (!playerTarget)
734 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
735
736 if (!playerTarget)
737 {
739 return false;
740 }
741
742 uint32 entry = quest->GetQuestId();
743 std::string status;
744 if (Player* player = playerTarget->GetConnectedPlayer())
745 {
746 QuestStatus qs = player->GetQuestStatus(entry);
747 switch (qs)
748 {
750 status = "Not Taken";
751 break;
753 status = "Complete";
754 break;
756 status = "Incomplete";
757 break;
759 status = "Failed";
760 break;
762 status = "Rewarded";
763 break;
764 default:
765 status = "Unknown";
766 break;
767 }
768
769 handler->PSendSysMessage(LANG_CMD_QUEST_STATUS, quest->GetTitle(), entry, status);
770
771 if (!player->CanTakeQuest(quest, false))
772 {
774
775 if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_QUEST, entry, player))
777
778 if (!player->SatisfyQuestStatus(quest, false))
780
781 if (!player->SatisfyQuestClass(quest, false))
783
784 if (!player->SatisfyQuestRace(quest, false))
786
787 if (player->GetLevel() < quest->GetMinLevel())
788 handler->PSendSysMessage(LANG_CMD_QUEST_STATUS_LOW_LEVEL, quest->GetMinLevel());
789
790 if (quest->GetMaxLevel() > 0 && player->GetLevel() > quest->GetMaxLevel())
791 handler->PSendSysMessage(LANG_CMD_QUEST_STATUS_HIGH_LEVEL, quest->GetMaxLevel());
792
793 if (!player->SatisfyQuestSkill(quest, false))
795
796 if (!player->SatisfyQuestReputation(quest, false))
798
799 if (!player->SatisfyQuestPreviousQuest(quest, false))
801
802 if (!player->SatisfyQuestTimed(quest, false))
804
805 if (!player->SatisfyQuestExclusiveGroup(quest, false))
807
808 if (!player->SatisfyQuestNextChain(quest, false))
810
811 if (!player->SatisfyQuestPrevChain(quest, false))
813
814 if (!player->SatisfyQuestBreadcrumb(quest, false))
816
817 if (!player->SatisfyQuestDay(quest, false))
819
820 if (!player->SatisfyQuestWeek(quest, false))
822
823 if (!player->SatisfyQuestMonth(quest, false))
825
826 if (!player->SatisfyQuestSeasonal(quest, false))
828
829 if (!player->SatisfyQuestConditions(quest, false))
830 {
832
833 ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_AVAILABLE, entry);
835 for (Condition* cond : conditions)
836 {
837 if (!cond->Meets(srcInfo))
838 handler->PSendSysMessage(LANG_CMD_QUEST_STATUS_COND_DETAIL, uint32(cond->ConditionType), cond->ConditionValue1, cond->ConditionValue2, cond->ConditionValue3);
839 }
840 }
841
842 if (!player->SatisfyQuestLog(false))
844 }
845 }
846 else
847 {
849 return false;
850 }
851
852 return true;
853 }
#define sConditionMgr
Definition ConditionMgr.h:292
@ CONDITION_SOURCE_TYPE_QUEST_AVAILABLE
Definition ConditionMgr.h:144
std::list< Condition * > ConditionList
Definition ConditionMgr.h:239
#define sDisableMgr
Definition DisableMgr.h:88
@ DISABLE_TYPE_QUEST
Definition DisableMgr.h:29
@ LANG_CMD_QUEST_STATUS_REPUTATION
Definition Language.h:1172
@ LANG_CMD_QUEST_STATUS_CLASS
Definition Language.h:1167
@ LANG_CMD_QUEST_STATUS_COND_DETAIL
Definition Language.h:1185
@ LANG_CMD_QUEST_STATUS_RACE
Definition Language.h:1168
@ LANG_CMD_QUEST_STATUS_PREV_CHAIN
Definition Language.h:1177
@ LANG_CMD_QUEST_STATUS_HIGH_LEVEL
Definition Language.h:1170
@ LANG_CMD_QUEST_STATUS_DAY
Definition Language.h:1179
@ LANG_CMD_QUEST_STATUS_LOG_FULL
Definition Language.h:1184
@ LANG_CMD_QUEST_STATUS_WEEK
Definition Language.h:1180
@ LANG_CMD_QUEST_STATUS_MONTH
Definition Language.h:1181
@ LANG_CMD_QUEST_STATUS_NEXT_CHAIN
Definition Language.h:1176
@ LANG_CMD_QUEST_STATUS_SKILL
Definition Language.h:1171
@ LANG_CMD_QUEST_STATUS_BREADCRUMB
Definition Language.h:1178
@ LANG_CMD_QUEST_STATUS_EXCLUSIVE
Definition Language.h:1175
@ LANG_CMD_QUEST_UNAVAILABLE
Definition Language.h:1164
@ LANG_CMD_QUEST_STATUS_DISABLED
Definition Language.h:1165
@ LANG_CMD_QUEST_STATUS_ALREADY_DONE
Definition Language.h:1166
@ LANG_CMD_QUEST_STATUS_SEASONAL
Definition Language.h:1182
@ LANG_CMD_QUEST_STATUS_PREV_QUEST
Definition Language.h:1173
@ LANG_CMD_QUEST_STATUS_TIMED
Definition Language.h:1174
@ LANG_CMD_QUEST_STATUS_LOW_LEVEL
Definition Language.h:1169
@ LANG_CMD_QUEST_STATUS
Definition Language.h:1163
@ LANG_CMD_QUEST_STATUS_CONDITION
Definition Language.h:1183
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
virtual void SendSysMessage(std::string_view str, bool escapeCharacters=false)
Definition Chat.cpp:160
Definition ConditionMgr.h:184
Definition ConditionMgr.h:197

References CONDITION_SOURCE_TYPE_QUEST_AVAILABLE, DISABLE_TYPE_QUEST, Acore::ChatCommands::PlayerIdentifier::FromTargetOrSelf(), Quest::GetMaxLevel(), Quest::GetMinLevel(), Quest::GetQuestId(), Quest::GetTitle(), LANG_CMD_QUEST_STATUS, LANG_CMD_QUEST_STATUS_ALREADY_DONE, LANG_CMD_QUEST_STATUS_BREADCRUMB, LANG_CMD_QUEST_STATUS_CLASS, LANG_CMD_QUEST_STATUS_COND_DETAIL, LANG_CMD_QUEST_STATUS_CONDITION, LANG_CMD_QUEST_STATUS_DAY, LANG_CMD_QUEST_STATUS_DISABLED, LANG_CMD_QUEST_STATUS_EXCLUSIVE, LANG_CMD_QUEST_STATUS_HIGH_LEVEL, LANG_CMD_QUEST_STATUS_LOG_FULL, LANG_CMD_QUEST_STATUS_LOW_LEVEL, LANG_CMD_QUEST_STATUS_MONTH, LANG_CMD_QUEST_STATUS_NEXT_CHAIN, LANG_CMD_QUEST_STATUS_PREV_CHAIN, LANG_CMD_QUEST_STATUS_PREV_QUEST, LANG_CMD_QUEST_STATUS_RACE, LANG_CMD_QUEST_STATUS_REPUTATION, LANG_CMD_QUEST_STATUS_SEASONAL, LANG_CMD_QUEST_STATUS_SKILL, LANG_CMD_QUEST_STATUS_TIMED, LANG_CMD_QUEST_STATUS_WEEK, 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, sConditionMgr, sDisableMgr, ChatHandler::SendErrorMessage(), and ChatHandler::SendSysMessage().

Referenced by GetCommands().


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