Core/Quests: update quest_template fields to 4.4.0

This commit is contained in:
Ovahlord
2024-06-13 18:56:13 +02:00
parent 992c4bc13e
commit 3d8602276d
8 changed files with 119 additions and 152 deletions

View File

@@ -0,0 +1,6 @@
ALTER TABLE `quest_template`
DROP COLUMN `ContentTuningID`,
ADD COLUMN `QuestLevel` INT DEFAULT 0 NOT NULL AFTER `QuestType`,
ADD COLUMN `QuestScalingFactionGroup` INT DEFAULT 0 NOT NULL AFTER `QuestLevel`,
ADD COLUMN `QuestMaxScalingLevel` INT DEFAULT 0 NOT NULL AFTER `QuestScalingFactionGroup`,
ADD COLUMN `MinLevel` INT DEFAULT 0 NOT NULL AFTER `QuestPackageID`;

View File

@@ -279,7 +279,6 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID)
{
WorldPackets::NPC::ClientGossipText& text = packet.GossipText[count];
text.QuestID = questID;
text.ContentTuningID = quest->GetContentTuningId();
text.QuestType = item.QuestIcon;
text.QuestFlags[0] = quest->GetFlags();
text.QuestFlags[1] = quest->GetFlagsEx();
@@ -407,7 +406,6 @@ void PlayerMenu::SendQuestGiverQuestListMessage(Object* questgiver)
questList.QuestDataText.emplace_back();
WorldPackets::NPC::ClientGossipText& text = questList.QuestDataText.back();
text.QuestID = questID;
text.ContentTuningID = quest->GetContentTuningId();
text.QuestType = questMenuItem.QuestIcon;
text.QuestFlags[0] = quest->GetFlags();
text.QuestFlags[1] = quest->GetFlagsEx();

View File

@@ -13813,23 +13813,10 @@ uint32 Player::GetGossipMenuForSource(WorldObject const* source) const
int32 Player::GetQuestMinLevel(Quest const* quest) const
{
return GetQuestMinLevel(quest->GetContentTuningId());
}
if (!quest)
return 0;
int32 Player::GetQuestMinLevel(uint32 contentTuningId) const
{
if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(contentTuningId, 0 /*m_playerData->CtrOptions->ContentTuningConditionMask*/))
{
ChrRacesEntry const* race = sChrRacesStore.AssertEntry(GetRace());
FactionTemplateEntry const* raceFaction = sFactionTemplateStore.AssertEntry(race->FactionID);
int32 questFactionGroup = sContentTuningStore.AssertEntry(contentTuningId)->GetScalingFactionGroup();
if (questFactionGroup && raceFaction->FactionGroup != questFactionGroup)
return questLevels->MaxLevel;
return questLevels->MinLevelWithDelta;
}
return 0;
return quest->GetQuestMinLevel();
}
int32 Player::GetQuestLevel(Quest const* quest) const
@@ -13837,23 +13824,7 @@ int32 Player::GetQuestLevel(Quest const* quest) const
if (!quest)
return 0;
return GetQuestLevel(quest->GetContentTuningId());
}
int32 Player::GetQuestLevel(uint32 contentTuningId) const
{
if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(contentTuningId, 0 /*m_playerData->CtrOptions->ContentTuningConditionMask*/))
{
int32 minLevel = GetQuestMinLevel(contentTuningId);
int32 maxLevel = questLevels->MaxLevel;
int32 level = GetLevel();
if (level >= minLevel)
return std::min(level, maxLevel);
return minLevel;
}
return 0;
return quest->GetQuestLevel();
}
void Player::PrepareQuestMenu(ObjectGuid guid)

View File

@@ -1524,9 +1524,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
/*********************************************************/
int32 GetQuestMinLevel(Quest const* quest) const;
int32 GetQuestMinLevel(uint32 contentTuningId) const;
int32 GetQuestLevel(Quest const* quest) const;
int32 GetQuestLevel(uint32 contentTuningId) const;
void PrepareQuestMenu(ObjectGuid guid);
void SendPreparedQuest(WorldObject* source);
bool IsActiveQuest(uint32 quest_id) const;

View File

@@ -4515,37 +4515,39 @@ void ObjectMgr::LoadQuests()
_exclusiveQuestGroups.clear();
QueryResult result = WorldDatabase.Query("SELECT "
//0 1 2 3 4 5 6 7 8 9
"ID, QuestType, QuestPackageID, ContentTuningID, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, "
//10 11 12 13 14 15 16
//0 1 2 3 4 5 6
"ID, QuestType, QuestLevel, QuestScalingFactionGroup, QuestMaxScalingLevel, QuestPackageID, MinLevel, "
//7 8 8 10 11 12
"QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, "
//13 14 15 16 17 18 19
"RewardMoneyDifficulty, RewardMoneyMultiplier, RewardBonusMoney, RewardSpell, RewardHonor, RewardKillHonor, StartItem, "
//17 18 19 20 21 22
//20 21 22 23 24 25
"RewardArtifactXPDifficulty, RewardArtifactXPMultiplier, RewardArtifactCategoryID, Flags, FlagsEx, FlagsEx2, "
//23 24 25 26 27 28 29 30
//26 27 28 29 30 31 32 33
"RewardItem1, RewardAmount1, ItemDrop1, ItemDropQuantity1, RewardItem2, RewardAmount2, ItemDrop2, ItemDropQuantity2, "
//31 32 33 34 35 36 37 38
//34 35 36 37 38 39 40 41
"RewardItem3, RewardAmount3, ItemDrop3, ItemDropQuantity3, RewardItem4, RewardAmount4, ItemDrop4, ItemDropQuantity4, "
//39 40 41 42 43 44
//42 43 44 45 46 47
"RewardChoiceItemID1, RewardChoiceItemQuantity1, RewardChoiceItemDisplayID1, RewardChoiceItemID2, RewardChoiceItemQuantity2, RewardChoiceItemDisplayID2, "
//45 46 47 48 49 50
//48 49 50 51 52 53
"RewardChoiceItemID3, RewardChoiceItemQuantity3, RewardChoiceItemDisplayID3, RewardChoiceItemID4, RewardChoiceItemQuantity4, RewardChoiceItemDisplayID4, "
//51 52 53 54 55 56
//54 55 56 57 58 59
"RewardChoiceItemID5, RewardChoiceItemQuantity5, RewardChoiceItemDisplayID5, RewardChoiceItemID6, RewardChoiceItemQuantity6, RewardChoiceItemDisplayID6, "
//57 58 59 60 61 62 63 64
//60 61 62 63 64 65 66 67
"POIContinent, POIx, POIy, POIPriority, RewardTitle, RewardArenaPoints, RewardSkillLineID, RewardNumSkillUps, "
//65 66 67 68
//68 69 70 71
"PortraitGiver, PortraitGiverMount, PortraitGiverModelSceneID, PortraitTurnIn, "
//69 70 71 72 73 74 75 76
//72 73 74 75 76 77 78 79
"RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionCapIn1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, RewardFactionCapIn2, "
//77 78 79 80 81 82 83 84
//80 81 82 83 84 85 86 87
"RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionCapIn3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, RewardFactionCapIn4, "
//85 86 87 88 89
//88 89 90 91 92
"RewardFactionID5, RewardFactionValue5, RewardFactionOverride5, RewardFactionCapIn5, RewardFactionFlags, "
//90 91 92 93 94 95 96 97
//93 94 95 96 97 98 99 100
"RewardCurrencyID1, RewardCurrencyQty1, RewardCurrencyID2, RewardCurrencyQty2, RewardCurrencyID3, RewardCurrencyQty3, RewardCurrencyID4, RewardCurrencyQty4, "
//98 99 100 101 102 103 104 105 106
//101 102 103 104 105 106 107 108 109
"AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, TreasurePickerID, Expansion, ManagedWorldStateID, QuestSessionBonus, "
//107 108 109 110 111 112 113 114 115
//110 111 112 113 114 115 116 117 118
"LogTitle, LogDescription, QuestDescription, AreaDescription, PortraitGiverText, PortraitGiverName, PortraitTurnInText, PortraitTurnInName, QuestCompletionLog "
"FROM quest_template");
if (!result)
@@ -4757,12 +4759,6 @@ void ObjectMgr::LoadQuests()
}
}
if (qinfo->_contentTuningID && !sContentTuningStore.LookupEntry(qinfo->_contentTuningID))
{
TC_LOG_ERROR("sql.sql", "Quest {} has `ContentTuningID` = {} but content tuning with this id does not exist.",
qinfo->GetQuestId(), qinfo->_contentTuningID);
}
// client quest log visual (area case)
if (qinfo->_questSortID > 0)
{

View File

@@ -33,34 +33,37 @@ Quest::Quest(Field* questRecord)
{
_id = questRecord[0].GetUInt32();
_type = questRecord[1].GetUInt8();
_packageID = questRecord[2].GetUInt32();
_contentTuningID = questRecord[3].GetInt32();
_questSortID = questRecord[4].GetInt16();
_questInfoID = questRecord[5].GetUInt16();
_suggestedPlayers = questRecord[6].GetUInt8();
_nextQuestInChain = questRecord[7].GetUInt32();
_rewardXPDifficulty = questRecord[8].GetUInt32();
_rewardXPMultiplier = questRecord[9].GetFloat();
_rewardMoneyDifficulty = questRecord[10].GetUInt32();
_rewardMoneyMultiplier = questRecord[11].GetFloat();
_rewardBonusMoney = questRecord[12].GetUInt32();
_rewardSpell = questRecord[13].GetUInt32();
_rewardHonor = questRecord[14].GetUInt32();
_rewardKillHonor = questRecord[15].GetUInt32();
_sourceItemId = questRecord[16].GetUInt32();
_rewardArtifactXPDifficulty = questRecord[17].GetUInt32();
_rewardArtifactXPMultiplier = questRecord[18].GetFloat();
_rewardArtifactCategoryID = questRecord[19].GetUInt32();
_flags = questRecord[20].GetUInt32();
_flagsEx = questRecord[21].GetUInt32();
_flagsEx2 = questRecord[22].GetUInt32();
_level = questRecord[2].GetInt32();
_scalingFactionGroup = questRecord[3].GetInt32();
_maxScalingLevel = questRecord[4].GetInt32();
_packageID = questRecord[5].GetUInt32();
_minLevel = questRecord[6].GetInt32();
_questSortID = questRecord[7].GetInt16();
_questInfoID = questRecord[8].GetUInt16();
_suggestedPlayers = questRecord[9].GetUInt8();
_nextQuestInChain = questRecord[10].GetUInt32();
_rewardXPDifficulty = questRecord[11].GetUInt32();
_rewardXPMultiplier = questRecord[12].GetFloat();
_rewardMoneyDifficulty = questRecord[13].GetUInt32();
_rewardMoneyMultiplier = questRecord[14].GetFloat();
_rewardBonusMoney = questRecord[15].GetUInt32();
_rewardSpell = questRecord[16].GetUInt32();
_rewardHonor = questRecord[17].GetUInt32();
_rewardKillHonor = questRecord[18].GetUInt32();
_sourceItemId = questRecord[19].GetUInt32();
_rewardArtifactXPDifficulty = questRecord[20].GetUInt32();
_rewardArtifactXPMultiplier = questRecord[21].GetFloat();
_rewardArtifactCategoryID = questRecord[22].GetUInt32();
_flags = questRecord[21].GetUInt32();
_flagsEx = questRecord[22].GetUInt32();
_flagsEx2 = questRecord[23].GetUInt32();
for (uint32 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i)
{
RewardItemId[i] = questRecord[23 + i * 4].GetUInt32();
RewardItemCount[i] = questRecord[24 + i * 4].GetUInt32();
ItemDrop[i] = questRecord[25 + i * 4].GetUInt32();
ItemDropQuantity[i] = questRecord[26 + i * 4].GetUInt32();
RewardItemId[i] = questRecord[26 + i * 4].GetUInt32();
RewardItemCount[i] = questRecord[27 + i * 4].GetUInt32();
ItemDrop[i] = questRecord[28 + i * 4].GetUInt32();
ItemDropQuantity[i] = questRecord[29 + i * 4].GetUInt32();
if (RewardItemId[i])
++_rewItemsCount;
@@ -68,67 +71,67 @@ Quest::Quest(Field* questRecord)
for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
RewardChoiceItemId[i] = questRecord[39 + i * 3].GetUInt32();
RewardChoiceItemCount[i] = questRecord[40 + i * 3].GetUInt32();
RewardChoiceItemDisplayId[i] = questRecord[41 + i * 3].GetUInt32();
RewardChoiceItemId[i] = questRecord[42 + i * 3].GetUInt32();
RewardChoiceItemCount[i] = questRecord[44 + i * 3].GetUInt32();
RewardChoiceItemDisplayId[i] = questRecord[45 + i * 3].GetUInt32();
if (RewardChoiceItemId[i])
++_rewChoiceItemsCount;
}
_poiContinent = questRecord[57].GetUInt32();
_poix = questRecord[58].GetFloat();
_poiy = questRecord[59].GetFloat();
_poiPriority = questRecord[60].GetUInt32();
_poiContinent = questRecord[60].GetUInt32();
_poix = questRecord[61].GetFloat();
_poiy = questRecord[62].GetFloat();
_poiPriority = questRecord[63].GetUInt32();
_rewardTitleId = questRecord[61].GetUInt32();
_rewardArenaPoints = questRecord[62].GetUInt32();
_rewardSkillId = questRecord[63].GetUInt32();
_rewardSkillPoints = questRecord[64].GetUInt32();
_rewardTitleId = questRecord[64].GetUInt32();
_rewardArenaPoints = questRecord[65].GetUInt32();
_rewardSkillId = questRecord[66].GetUInt32();
_rewardSkillPoints = questRecord[67].GetUInt32();
_questGiverPortrait = questRecord[65].GetUInt32();
_questGiverPortraitMount = questRecord[66].GetUInt32();
_questGiverPortraitModelSceneId = questRecord[67].GetInt32();
_questTurnInPortrait = questRecord[68].GetUInt32();
_questGiverPortrait = questRecord[68].GetUInt32();
_questGiverPortraitMount = questRecord[69].GetUInt32();
_questGiverPortraitModelSceneId = questRecord[70].GetInt32();
_questTurnInPortrait = questRecord[71].GetUInt32();
for (uint32 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i)
{
RewardFactionId[i] = questRecord[69 + i * 4].GetUInt32();
RewardFactionValue[i] = questRecord[70 + i * 4].GetInt32();
RewardFactionOverride[i] = questRecord[71 + i * 4].GetInt32();
RewardFactionCapIn[i] = questRecord[72 + i * 4].GetInt32();
RewardFactionId[i] = questRecord[72 + i * 4].GetUInt32();
RewardFactionValue[i] = questRecord[73 + i * 4].GetInt32();
RewardFactionOverride[i] = questRecord[74 + i * 4].GetInt32();
RewardFactionCapIn[i] = questRecord[75 + i * 4].GetInt32();
}
_rewardReputationMask = questRecord[89].GetUInt32();
_rewardReputationMask = questRecord[92].GetUInt32();
for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i)
{
RewardCurrencyId[i] = questRecord[90 + i * 2].GetUInt32();
RewardCurrencyCount[i] = questRecord[91 + i * 2].GetUInt32();
RewardCurrencyId[i] = questRecord[93 + i * 2].GetUInt32();
RewardCurrencyCount[i] = questRecord[94 + i * 2].GetUInt32();
if (RewardCurrencyId[i])
++_rewCurrencyCount;
}
_soundAccept = questRecord[98].GetUInt32();
_soundTurnIn = questRecord[99].GetUInt32();
_areaGroupID = questRecord[100].GetUInt32();
_limitTime = questRecord[101].GetInt64();
_allowableRaces.RawValue = questRecord[102].GetUInt64();
_treasurePickerID = questRecord[103].GetInt32();
_expansion = questRecord[104].GetInt32();
_managedWorldStateID = questRecord[105].GetInt32();
_questSessionBonus = questRecord[106].GetInt32();
_soundAccept = questRecord[101].GetUInt32();
_soundTurnIn = questRecord[102].GetUInt32();
_areaGroupID = questRecord[103].GetUInt32();
_limitTime = questRecord[104].GetInt64();
_allowableRaces.RawValue = questRecord[105].GetUInt64();
_treasurePickerID = questRecord[106].GetInt32();
_expansion = questRecord[107].GetInt32();
_managedWorldStateID = questRecord[108].GetInt32();
_questSessionBonus = questRecord[109].GetInt32();
_logTitle = questRecord[107].GetString();
_logDescription = questRecord[108].GetString();
_questDescription = questRecord[109].GetString();
_areaDescription = questRecord[110].GetString();
_portraitGiverText = questRecord[111].GetString();
_portraitGiverName = questRecord[112].GetString();
_portraitTurnInText = questRecord[113].GetString();
_portraitTurnInName = questRecord[114].GetString();
_questCompletionLog = questRecord[115].GetString();
_logTitle = questRecord[110].GetString();
_logDescription = questRecord[111].GetString();
_questDescription = questRecord[112].GetString();
_areaDescription = questRecord[113].GetString();
_portraitGiverText = questRecord[114].GetString();
_portraitGiverName = questRecord[115].GetString();
_portraitTurnInText = questRecord[116].GetString();
_portraitTurnInName = questRecord[117].GetString();
_questCompletionLog = questRecord[118].GetString();
}
Quest::~Quest()
@@ -388,14 +391,14 @@ void Quest::LoadConditionalConditionalQuestCompletionLog(Field* fields)
uint32 Quest::XPValue(Player const* player) const
{
return XPValue(player, GetContentTuningId(), _rewardXPDifficulty, _rewardXPMultiplier, _expansion);
return XPValue(player, 0, _rewardXPDifficulty, _rewardXPMultiplier, _expansion);
}
uint32 Quest::XPValue(Player const* player, uint32 contentTuningId, uint32 xpDifficulty, float xpMultiplier /*= 1.0f*/, int32 expansion /*= -1*/)
uint32 Quest::XPValue(Player const* player, uint32 /*contentTuningId*/, uint32 xpDifficulty, float xpMultiplier /*= 1.0f*/, int32 expansion /*= -1*/)
{
if (player)
{
uint32 questLevel = player->GetQuestLevel(contentTuningId);
uint32 questLevel = 0; // player->GetQuestLevel(contentTuningId);
QuestXPEntry const* questXp = sQuestXPStore.LookupEntry(questLevel);
if (!questXp || xpDifficulty >= 10)
return 0;
@@ -445,7 +448,7 @@ uint32 Quest::MoneyValue(Player const* player) const
uint32 Quest::MaxMoneyValue() const
{
uint32 value = 0;
if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(GetContentTuningId(), 0))
if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(0, 0))
if (QuestMoneyRewardEntry const* money = sQuestMoneyRewardStore.LookupEntry(questLevels->MaxLevel))
value = money->Difficulty[GetRewMoneyDifficulty()] * GetMoneyMultiplier();
@@ -640,7 +643,11 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc, Player* player) const
response.Info.QuestID = GetQuestId();
response.Info.QuestType = GetQuestType();
response.Info.QuestLevel = GetQuestLevel();
response.Info.QuestScalingFactionGroup = GetQuestScalingFactionGroup();
response.Info.QuestMaxScalingLevel = GetQuestMaxScalingLevel();
response.Info.QuestPackageID = GetQuestPackageID();
response.Info.QuestMinLevel = GetQuestMinLevel();
response.Info.QuestSortID = GetZoneOrSort();
response.Info.QuestInfoID = GetQuestInfoID();
response.Info.SuggestedGroupNum = GetSuggestedPlayers();

View File

@@ -559,8 +559,11 @@ class TC_GAME_API Quest
// table data accessors:
uint32 GetQuestId() const { return _id; }
uint32 GetQuestType() const { return _type; }
int32 GetQuestLevel() const { return _level; }
int32 GetQuestScalingFactionGroup() const { return _scalingFactionGroup; }
int32 GetQuestMaxScalingLevel() const { return _maxScalingLevel; }
uint32 GetQuestPackageID() const { return _packageID; }
uint32 GetContentTuningId() const { return _contentTuningID; }
int32 GetQuestMinLevel() const { return _minLevel; }
int32 GetZoneOrSort() const { return _questSortID; }
uint32 GetMaxLevel() const { return _maxLevel; }
uint32 GetQuestInfoID() const { return _questInfoID; }
@@ -708,8 +711,11 @@ class TC_GAME_API Quest
// wdb data (quest query response)
uint32 _id = 0;
uint32 _type = 0;
int32 _level = 0;
int32 _scalingFactionGroup = 0;
int32 _maxScalingLevel = 0;
uint32 _packageID = 0;
uint32 _contentTuningID = 0;
int32 _minLevel = 0;
int32 _questSortID = 0;
uint32 _questInfoID = 0;
uint32 _suggestedPlayers = 0;

View File

@@ -683,13 +683,8 @@ public:
if (handler->GetSession())
{
int32 maxLevel = 0;
if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(questTemplatePair.second->GetContentTuningId(), 0))
maxLevel = questLevels->MaxLevel;
int32 scalingFactionGroup = 0;
if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(questTemplatePair.second->GetContentTuningId()))
scalingFactionGroup = contentTuning->GetScalingFactionGroup();
int32 maxLevel = questTemplatePair.second->GetQuestMaxScalingLevel();
int32 scalingFactionGroup = questTemplatePair.second->GetQuestScalingFactionGroup();
handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first,
handler->GetSession()->GetPlayer()->GetQuestLevel(questTemplatePair.second.get()),
@@ -742,13 +737,8 @@ public:
if (handler->GetSession())
{
int32 maxLevel = 0;
if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(questTemplatePair.second->GetContentTuningId(), 0))
maxLevel = questLevels->MaxLevel;
int32 scalingFactionGroup = 0;
if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(questTemplatePair.second->GetContentTuningId()))
scalingFactionGroup = contentTuning->GetScalingFactionGroup();
int32 maxLevel = questTemplatePair.second->GetQuestMaxScalingLevel();
int32 scalingFactionGroup = questTemplatePair.second->GetQuestScalingFactionGroup();
handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first,
handler->GetSession()->GetPlayer()->GetQuestLevel(questTemplatePair.second.get()),
@@ -811,13 +801,8 @@ public:
if (handler->GetSession())
{
int32 maxLevel = 0;
if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(quest->GetContentTuningId(), 0))
maxLevel = questLevels->MaxLevel;
int32 scalingFactionGroup = 0;
if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(quest->GetContentTuningId()))
scalingFactionGroup = contentTuning->GetScalingFactionGroup();
int32 maxLevel = quest->GetQuestMaxScalingLevel();
int32 scalingFactionGroup = quest->GetQuestScalingFactionGroup();
handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, id, id,
handler->GetSession()->GetPlayer()->GetQuestLevel(quest),