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)
 

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 };
41 static ChatCommandTable commandTable =
42 {
43 { "quest", questCommandTable },
44 };
45 return commandTable;
46 }
@ SEC_GAMEMASTER
Definition Common.h:59
static bool HandleQuestComplete(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:217
static bool HandleQuestReward(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:483
static bool HandleQuestRemove(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:127
static bool HandleQuestAdd(ChatHandler *handler, Quest const *quest, Optional< PlayerIdentifier > playerTarget)
Definition cs_quest.cpp:48
std::vector< ChatCommandBuilder > ChatCommandTable
Definition ChatCommand.h:46

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

◆ HandleQuestAdd()

static bool quest_commandscript::HandleQuestAdd ( ChatHandler handler,
Quest const *  quest,
Optional< PlayerIdentifier playerTarget 
)
inlinestatic
49 {
50 if (!playerTarget)
51 {
52 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
53 }
54
55 if (!playerTarget)
56 {
58 return false;
59 }
60
61 uint32 entry = quest->GetQuestId();
62
63 // check item starting quest (it can work incorrectly if added without item in inventory)
64 ItemTemplateContainer const* itc = sObjectMgr->GetItemTemplateStore();
65 ItemTemplateContainer::const_iterator result = find_if(itc->begin(), itc->end(), Finder<uint32, ItemTemplate>(entry, &ItemTemplate::StartQuest));
66
67 if (result != itc->end())
68 {
69 handler->SendErrorMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, result->second.ItemId);
70 return false;
71 }
72
73 if (Player* player = playerTarget->GetConnectedPlayer())
74 {
75 if (player->IsActiveQuest(entry))
76 {
77 handler->SendErrorMessage(LANG_COMMAND_QUEST_ACTIVE, quest->GetTitle().c_str(), entry);
78 return false;
79 }
80
81 // ok, normal (creature/GO starting) quest
82 if (player->CanAddQuest(quest, true))
83 {
84 player->AddQuestAndCheckCompletion(quest, nullptr);
85 }
86 }
87 else
88 {
89 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
90 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {}", guid, entry);
91
92 if (result)
93 {
94 handler->SendErrorMessage(LANG_COMMAND_QUEST_ACTIVE, quest->GetTitle().c_str(), entry);
95 return false;
96 }
97
98 uint8 index = 0;
99
101 stmt->SetData(index++, guid);
102 stmt->SetData(index++, entry);
103 stmt->SetData(index++, 1);
104 stmt->SetData(index++, false);
105 stmt->SetData(index++, 0);
106
107 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
108 {
109 stmt->SetData(index++, 0);
110 }
111
112 for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
113 {
114 stmt->SetData(index++, 0);
115 }
116
117 stmt->SetData(index, 0);
118
119 CharacterDatabase.Execute(stmt);
120 }
121
122 handler->PSendSysMessage(LANG_COMMAND_QUEST_ADD, quest->GetTitle(), entry);
123 handler->SetSentErrorMessage(false);
124 return true;
125 }
@ 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:835
@ LANG_COMMAND_QUEST_STARTFROMITEM
Definition Language.h:506
@ LANG_COMMAND_QUEST_ACTIVE
Definition Language.h:510
@ LANG_PLAYER_NOT_FOUND
Definition Language.h:540
@ LANG_COMMAND_QUEST_ADD
Definition Language.h:1122
#define sObjectMgr
Definition ObjectMgr.h:1650
#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:1082
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
218 {
219 if (!playerTarget)
220 {
221 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
222 }
223
224 if (!playerTarget)
225 {
227 return false;
228 }
229
230 uint32 entry = quest->GetQuestId();
231
232 if (Player* player = playerTarget->GetConnectedPlayer())
233 {
234 // If player doesn't have the quest
235 if (player->GetQuestStatus(entry) == QUEST_STATUS_NONE)
236 {
238 return false;
239 }
240
241 // Add quest items for quests that require items
242 for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x)
243 {
244 uint32 id = quest->RequiredItemId[x];
245 uint32 count = quest->RequiredItemCount[x];
246 if (!id || !count)
247 {
248 continue;
249 }
250
251 uint32 curItemCount = player->GetItemCount(id, true);
252
253 ItemPosCountVec dest;
254 uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, id, count - curItemCount);
255 if (msg == EQUIP_ERR_OK)
256 {
257 Item* item = player->StoreNewItem(dest, id, true);
258 player->SendNewItem(item, count - curItemCount, true, false);
259 }
260 }
261
262 // All creature/GO slain/casted (not required, but otherwise it will display "Creature slain 0/10")
263 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
264 {
265 int32 creature = quest->RequiredNpcOrGo[i];
266 uint32 creatureCount = quest->RequiredNpcOrGoCount[i];
267
268 if (creature > 0)
269 {
270 if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature))
271 {
272 for (uint16 z = 0; z < creatureCount; ++z)
273 {
274 player->KilledMonster(creatureInfo, ObjectGuid::Empty);
275 }
276 }
277 }
278 else if (creature < 0)
279 {
280 for (uint16 z = 0; z < creatureCount; ++z)
281 {
282 player->KillCreditGO(creature);
283 }
284 }
285 }
286
287 // player kills
288 if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL))
289 {
290 if (uint32 reqPlayers = quest->GetPlayersSlain())
291 {
292 player->KilledPlayerCreditForQuest(reqPlayers, quest);
293 }
294 }
295
296 // If the quest requires reputation to complete
297 if (uint32 repFaction = quest->GetRepObjectiveFaction())
298 {
299 uint32 repValue = quest->GetRepObjectiveValue();
300 uint32 curRep = player->GetReputationMgr().GetReputation(repFaction);
301 if (curRep < repValue)
302 {
303 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction))
304 {
305 player->GetReputationMgr().SetReputation(factionEntry, static_cast<float>(repValue));
306 }
307 }
308 }
309
310 // If the quest requires a SECOND reputation to complete
311 if (uint32 repFaction = quest->GetRepObjectiveFaction2())
312 {
313 uint32 repValue2 = quest->GetRepObjectiveValue2();
314 uint32 curRep = player->GetReputationMgr().GetReputation(repFaction);
315 if (curRep < repValue2)
316 {
317 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(repFaction))
318 {
319 player->GetReputationMgr().SetReputation(factionEntry, static_cast<float>(repValue2));
320 }
321 }
322 }
323
324 // If the quest requires money
325 int32 ReqOrRewMoney = quest->GetRewOrReqMoney(player->GetLevel());
326 if (ReqOrRewMoney < 0)
327 {
328 player->ModifyMoney(-ReqOrRewMoney);
329 }
330
331 player->CompleteQuest(entry);
332 }
333 else
334 {
335 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
336 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {}", guid, entry);
337
338 if (!result)
339 {
340 handler->SendErrorMessage(LANG_COMMAND_QUEST_NOT_FOUND_IN_LOG, quest->GetTitle(), entry);
341 return false;
342 }
343
344 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
345
346 typedef std::pair<uint32, uint32> items;
347 std::vector<items> questItems;
348
349 for (uint8 x = 0; x < QUEST_ITEM_OBJECTIVES_COUNT; ++x)
350 {
351 uint32 id = quest->RequiredItemId[x];
352 uint32 count = quest->RequiredItemCount[x];
353 if (!id || !count)
354 {
355 continue;
356 }
357
358 questItems.emplace_back(id, count);
359 }
360
361 if (!questItems.empty())
362 {
364 // fill mail
365 MailDraft draft(quest->GetTitle(), std::string());
366
367 for (auto const& itr : questItems)
368 {
369 if (Item* item = Item::CreateItem(itr.first, itr.second))
370 {
371 item->SaveToDB(trans);
372 draft.AddItem(item);
373 }
374 }
375
376 draft.SendMailTo(trans, MailReceiver(nullptr, guid), sender);
377 }
378
379 uint8 index = 0;
380
382 stmt->SetData(index++, guid);
383 stmt->SetData(index++, entry);
384 stmt->SetData(index++, 1);
385 stmt->SetData(index++, quest->HasFlag(QUEST_FLAGS_EXPLORATION));
386 stmt->SetData(index++, 0);
387
388 for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
389 {
390 stmt->SetData(index++, quest->RequiredNpcOrGoCount[i]);
391 }
392
393 for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++)
394 {
395 // Will be updated once they loot the items from the mailbox.
396 stmt->SetData(index++, 0);
397 }
398
399 stmt->SetData(index, 0);
400
401 trans->Append(stmt);
402
403 // If the quest requires reputation to complete, set the player rep to the required amount.
404 if (uint32 repFaction = quest->GetRepObjectiveFaction())
405 {
406 uint32 repValue = quest->GetRepObjectiveValue();
407
408 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
409 stmt->SetData(0, repFaction);
410 stmt->SetData(1, guid);
411 PreparedQueryResult result = CharacterDatabase.Query(stmt);
412
413 if (result)
414 {
415 Field* fields = result->Fetch();
416 uint32 curRep = fields[0].Get<uint32>();
417
418 if (curRep < repValue)
419 {
420 if (sFactionStore.LookupEntry(repFaction))
421 {
422 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
423 stmt->SetData(0, repFaction);
424 stmt->SetData(1, repValue);
425 stmt->SetData(2, repFaction);
426 stmt->SetData(3, guid);
427 trans->Append(stmt);
428 }
429 }
430 }
431 }
432
433 // If the quest requires reputation to complete, set the player rep to the required amount.
434 if (uint32 repFaction = quest->GetRepObjectiveFaction2())
435 {
436 uint32 repValue = quest->GetRepObjectiveValue();
437
438 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
439 stmt->SetData(0, repFaction);
440 stmt->SetData(1, guid);
441 PreparedQueryResult result = CharacterDatabase.Query(stmt);
442
443 if (result)
444 {
445 Field* fields = result->Fetch();
446 uint32 curRep = fields[0].Get<uint32>();
447
448 if (curRep < repValue)
449 {
450 if (sFactionStore.LookupEntry(repFaction))
451 {
452 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
453 stmt->SetData(0, repFaction);
454 stmt->SetData(1, repValue);
455 stmt->SetData(2, repFaction);
456 stmt->SetData(3, guid);
457 trans->Append(stmt);
458 }
459 }
460 }
461 }
462
463 CharacterDatabase.CommitTransaction(trans);
464 }
465
466 // check if Quest Tracker is enabled
467 if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER))
468 {
469 // prepare Quest Tracker datas
470 auto stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE);
471 stmt->SetData(0, entry);
472 stmt->SetData(1, playerTarget->GetGUID().GetCounter());
473
474 // add to Quest Tracker
475 CharacterDatabase.Execute(stmt);
476 }
477
478 handler->PSendSysMessage(LANG_COMMAND_QUEST_COMPLETE, quest->GetTitle(), entry);
479 handler->SetSentErrorMessage(false);
480 return true;
481 }
@ 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
@ CONFIG_QUEST_ENABLE_QUEST_TRACKER
Definition IWorld.h:144
@ 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:509
@ LANG_COMMAND_QUEST_NOTFOUND
Definition Language.h:505
@ LANG_COMMAND_QUEST_NOT_FOUND_IN_LOG
Definition Language.h:1123
@ MAIL_STATIONERY_GM
Definition Mail.h:59
@ MAIL_NORMAL
Definition Mail.h:37
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:777
@ QUEST_FLAGS_EXPLORATION
Definition QuestDef.h:134
@ QUEST_STATUS_NONE
Definition QuestDef.h:100
@ QUEST_SPECIAL_FLAGS_PLAYER_KILL
Definition QuestDef.h:179
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:357
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
128 {
129 if (!playerTarget)
130 {
131 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
132 }
133
134 if (!playerTarget)
135 {
137 return false;
138 }
139
140 uint32 entry = quest->GetQuestId();
141
142 if (!quest)
143 {
145 return false;
146 }
147
148 if (Player* player = playerTarget->GetConnectedPlayer())
149 {
150 // remove all quest entries for 'entry' from quest log
151 for (uint8 slot = 0; slot < MAX_QUEST_LOG_SIZE; ++slot)
152 {
153 uint32 logQuest = player->GetQuestSlotQuestId(slot);
154 if (logQuest == entry)
155 {
156 player->SetQuestSlot(slot, 0);
157
158 // we ignore unequippable quest items in this case, its' still be equipped
159 player->TakeQuestSourceItem(logQuest, false);
160
161 if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP))
162 {
163 player->pvpInfo.IsHostile = player->pvpInfo.IsInHostileArea || player->HasPvPForcingQuest();
164 player->UpdatePvPState();
165 }
166 }
167 }
168
169 player->RemoveRewardedQuest(entry);
170 player->RemoveActiveQuest(entry, false);
171 }
172 else
173 {
174 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
175 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
176
178 stmt->SetData(0, guid);
179 stmt->SetData(1, entry);
180 trans->Append(stmt);
181
182 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST);
183 stmt->SetData(0, guid);
184 stmt->SetData(1, entry);
185 trans->Append(stmt);
186
187 for (uint32 const& requiredItem : quest->RequiredItemId)
188 {
190 stmt->SetData(0, requiredItem);
191 stmt->SetData(1, guid);
192
193 PreparedQueryResult result = CharacterDatabase.Query(stmt);
194
195 if (result)
196 {
197 Field* fields = result->Fetch();
198
199 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
200 stmt->SetData(0, fields[0].Get<uint32>());
201 trans->Append(stmt);
202
203 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
204 stmt->SetData(0, fields[0].Get<uint32>());
205 trans->Append(stmt);
206 }
207 }
208
209 CharacterDatabase.CommitTransaction(trans);
210 }
211
212 handler->PSendSysMessage(LANG_COMMAND_QUEST_REMOVED, quest->GetTitle(), entry);
213 handler->SetSentErrorMessage(false);
214 return true;
215 }
@ 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:507
@ 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
484 {
485 if (!playerTarget)
486 {
487 playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
488 }
489
490 if (!playerTarget)
491 {
493 return false;
494 }
495
496 uint32 entry = quest->GetQuestId();
497
498 if (Player* player = playerTarget->GetConnectedPlayer())
499 {
500 // If player doesn't have the quest
501 if (player->GetQuestStatus(entry) != QUEST_STATUS_COMPLETE)
502 {
504 return false;
505 }
506
507 player->RewardQuest(quest, 0, player);
508 }
509 else
510 {
511 // Achievement criteria updates correctly the next time a quest is rewarded.
512 // Titles are already awarded correctly the next time they login (only one quest awards title - 11549).
513 // Rewarded talent points (Death Knights) and spells (e.g Druid forms) are also granted on login.
514 // No reputation gains - too troublesome to calculate them when the player is offline.
515
516 ObjectGuid::LowType guid = playerTarget->GetGUID().GetCounter();
517 uint8 charLevel = sCharacterCache->GetCharacterLevelByGuid(ObjectGuid(HighGuid::Player, guid));
518 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
520
521 QueryResult result = CharacterDatabase.Query("SELECT 1 FROM character_queststatus WHERE guid = {} AND quest = {} AND status = 1", guid, entry);
522
523 if (!result)
524 {
526 return false;
527 }
528
529 for (uint32 const& requiredItem : quest->RequiredItemId)
530 {
532 stmt->SetData(0, requiredItem);
533 stmt->SetData(1, guid);
534
535 PreparedQueryResult result = CharacterDatabase.Query(stmt);
536
537 if (result)
538 {
539 Field* fields = result->Fetch();
540
541 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
542 stmt->SetData(0, fields[0].Get<uint32>());
543 trans->Append(stmt);
544
545 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
546 stmt->SetData(0, fields[0].Get<uint32>());
547 trans->Append(stmt);
548 }
549 }
550
551 for (uint32 const& sourceItem : quest->ItemDrop)
552 {
554 stmt->SetData(0, sourceItem);
555 stmt->SetData(1, guid);
556
557 PreparedQueryResult result = CharacterDatabase.Query(stmt);
558
559 if (result)
560 {
561 Field* fields = result->Fetch();
562
563 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
564 stmt->SetData(0, fields[0].Get<uint32>());
565 trans->Append(stmt);
566
567 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
568 stmt->SetData(0, fields[0].Get<uint32>());
569 trans->Append(stmt);
570 }
571 }
572
573 typedef std::pair<uint32, uint32> items;
574 std::vector<items> questRewardItems;
575
576 if (quest->GetRewChoiceItemsCount())
577 {
578 for (uint32 const& itemId : quest->RewardChoiceItemId)
579 {
580 uint8 index = 0;
581 questRewardItems.emplace_back(itemId, quest->RewardChoiceItemCount[index++]);
582 }
583 }
584
585 if (quest->GetRewItemsCount())
586 {
587 for (uint32 const& itemId : quest->RewardItemId)
588 {
589 uint8 index = 0;
590 questRewardItems.emplace_back(itemId, quest->RewardItemIdCount[index++]);
591 }
592 }
593
594 if (!questRewardItems.empty())
595 {
597 // fill mail
598 MailDraft draft(quest->GetTitle(), "This quest has been manually rewarded to you. This mail contains your quest rewards.");
599
600 for (auto const& itr : questRewardItems)
601 {
602 if (!itr.first || !itr.second)
603 {
604 continue;
605 }
606
607 // Skip invalid items.
608 if (!sObjectMgr->GetItemTemplate(itr.first))
609 {
610 continue;
611 }
612
613 if (Item* item = Item::CreateItem(itr.first, itr.second))
614 {
615 item->SaveToDB(trans);
616 draft.AddItem(item);
617 }
618 }
619
620 draft.SendMailTo(trans, MailReceiver(nullptr, guid), sender);
621 }
622
623 // Send quest giver mail, if any.
624 if (uint32 mail_template_id = quest->GetRewMailTemplateId())
625 {
626 if (quest->GetRewMailSenderEntry() != 0)
627 {
628 MailDraft(mail_template_id).SendMailTo(trans, MailReceiver(nullptr, guid), quest->GetRewMailSenderEntry(), MAIL_CHECK_MASK_HAS_BODY, quest->GetRewMailDelaySecs());
629 }
630 }
631
632 if (quest->IsDaily() || quest->IsDFQuest())
633 {
634 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS);
635 stmt->SetData(0, guid);
636 stmt->SetData(1, entry);
637 stmt->SetData(2, GameTime::GetGameTime().count());
638 trans->Append(stmt);
639 }
640 else if (quest->IsWeekly())
641 {
642 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS);
643 stmt->SetData(0, guid);
644 stmt->SetData(1, entry);
645 trans->Append(stmt);
646 }
647 else if (quest->IsMonthly())
648 {
649 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_MONTHLYQUESTSTATUS);
650 stmt->SetData(0, guid);
651 stmt->SetData(1, entry);
652 trans->Append(stmt);
653 }
654 else if (quest->IsSeasonal())
655 {
656 // We can't know which event is the quest linked to, so we can't do anything about this.
657 /* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS);
658 stmt->SetData(0, guid);
659 stmt->SetData(1, entry);
660 stmt->SetData(2, event_id);
661 trans->Append(stmt);*/
662 }
663
664 if (uint32 honor = quest->CalculateHonorGain(charLevel))
665 {
667 stmt->SetData(0, honor);
668 stmt->SetData(1, guid);
669 trans->Append(stmt);
670 }
671
672 if (quest->GetRewArenaPoints())
673 {
675 stmt->SetData(0, quest->GetRewArenaPoints());
676 stmt->SetData(1, guid);
677 trans->Append(stmt);
678 }
679
680 int32 rewMoney = 0;
681
682 if (charLevel >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
683 {
684 rewMoney = quest->GetRewMoneyMaxLevel();
685 }
686 else
687 {
688 // Some experience might get lost on level up.
689 uint32 xp = uint32(quest->XPValue(charLevel) * sWorld->getRate(RATE_XP_QUEST));
690 stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_XP_ACCUMULATIVE);
691 stmt->SetData(0, xp);
692 stmt->SetData(1, guid);
693 trans->Append(stmt);
694 }
695
696 if (int32 rewOrReqMoney = quest->GetRewOrReqMoney(charLevel))
697 {
698 rewMoney += rewOrReqMoney;
699 }
700
701 // Only reward money, don't subtract, let's not cause an overflow...
702 if (rewMoney > 0)
703 {
705 stmt->SetData(0, rewMoney);
706 stmt->SetData(1, guid);
707 trans->Append(stmt);
708 }
709
710 stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_REWARDED);
711 stmt->SetData(0, guid);
712 stmt->SetData(1, entry);
713 trans->Append(stmt);
714
715 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST);
716 stmt->SetData(0, guid);
717 stmt->SetData(1, entry);
718 trans->Append(stmt);
719
720 CharacterDatabase.CommitTransaction(trans);
721 }
722
723 handler->PSendSysMessage(LANG_COMMAND_QUEST_REWARDED, quest->GetTitle(), entry);
724 handler->SetSentErrorMessage(false);
725 return true;
726 }
#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
@ CONFIG_MAX_PLAYER_LEVEL
Definition IWorld.h:236
@ RATE_XP_QUEST
Definition IWorld.h:482
@ LANG_COMMAND_QUEST_REWARDED
Definition Language.h:508
@ LANG_COMMAND_QUEST_NOT_COMPLETE
Definition Language.h:1124
@ MAIL_CHECK_MASK_HAS_BODY
Definition Mail.h:51
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:101
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().


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