diff options
| author | Intel <chemicstry@gmail.com> | 2014-12-28 22:55:53 +0200 |
|---|---|---|
| committer | Intel <chemicstry@gmail.com> | 2014-12-28 22:55:53 +0200 |
| commit | a782515246d5583a4c0e5cc8834133d425920b56 (patch) | |
| tree | f181c34ad982c8f63b3772f2ddf0b90a4986740f /src/server/game/Globals/ObjectMgr.cpp | |
| parent | 0dec23b43ad8692189b511bb114ef3b772678fe3 (diff) | |
Core/Quests: Updated Quest System to new Format
All quest requirements are now in quest_objectives table
quest_template table contains _ONLY_ WDB data and must not be modified
Currently supported objectives are MONSTER, GAMEOBJECT, ITEM, TALKTO, CURRENCY, REPUTATION, MONEY, PLAYERKILLS, AREATRIGGER
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
| -rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 553 |
1 files changed, 310 insertions, 243 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index dd2a1697e6a..476b340cb2a 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1049,7 +1049,7 @@ void ObjectMgr::LoadCreatureAddons() } if (AdditionalSpellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE)) - TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); creatureAddon.auras[i++] = atoul(*itr); @@ -3464,40 +3464,34 @@ void ObjectMgr::LoadQuests() mExclusiveQuestGroups.clear(); QueryResult result = WorldDatabase.Query("SELECT " - //0 1 2 3 4 5 6 7 8 9 10 11 12 - "Id, Method, Level, MinLevel, MaxLevel, ZoneOrSort, Type, SuggestedPlayers, LimitTime, RequiredClasses, RequiredRaces, RequiredSkillId, RequiredSkillPoints, " - // 13 14 15 16 17 18 19 20 - "RequiredFactionId1, RequiredFactionId2, RequiredFactionValue1, RequiredFactionValue2, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, " - // 21 22 23 24 25 26 27 28 29 30 31 - "PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestIdChain, RewardXPId, RewardOrRequiredMoney, RewardMoneyMaxLevel, RewardSpell, RewardSpellCast, RewardHonor, RewardHonorMultiplier, " - // 32 33 34 35 36 37 38 39 40 41 42 43 - "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, MinimapTargetMark, RewardTitleId, RequiredPlayerKills, RewardTalents, RewardArenaPoints, " - // 44 45 46 47 48 49 50 51 52 53 54 55 56 - "RewardSkillId, RewardSkillPoints, RewardReputationMask, QuestGiverPortrait, QuestTurnInPortrait, RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4, RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4, " - // 57 58 59 60 61 62 63 64 65 66 67 68 - "RewardChoiceItemId1, RewardChoiceItemId2, RewardChoiceItemId3, RewardChoiceItemId4, RewardChoiceItemId5, RewardChoiceItemId6, RewardChoiceItemCount1, RewardChoiceItemCount2, RewardChoiceItemCount3, RewardChoiceItemCount4, RewardChoiceItemCount5, RewardChoiceItemCount6, " - // 69 70 71 72 73 74 75 76 77 78 - "RewardFactionId1, RewardFactionId2, RewardFactionId3, RewardFactionId4, RewardFactionId5, RewardFactionValueId1, RewardFactionValueId2, RewardFactionValueId3, RewardFactionValueId4, RewardFactionValueId5, " - // 79 80 81 82 83 - "RewardFactionValueIdOverride1, RewardFactionValueIdOverride2, RewardFactionValueIdOverride3, RewardFactionValueIdOverride4, RewardFactionValueIdOverride5, " - // 84 85 86 87 88 89 90 91 92 93 94 - "PointMapId, PointX, PointY, PointOption, Title, Objectives, Details, EndText, CompletedText, OfferRewardText, RequestItemsText, " - // 95 96 97 98 99 100 101 102 - "RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, " - // 103 104 105 106 107 108 109 110 - "RequiredSourceItemId1, RequiredSourceItemId2, RequiredSourceItemId3, RequiredSourceItemId4, RequiredSourceItemCount1, RequiredSourceItemCount2, RequiredSourceItemCount3, RequiredSourceItemCount4, " - // 111 112 113 114 115 116 117 118 119 120 121 122 - "RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, " - // 123 124 125 126 127 128 129 130 131 132 133 134 135 - "RequiredSpell, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, RewardCurrencyId1, RewardCurrencyId2, RewardCurrencyId3, RewardCurrencyId4, RewardCurrencyCount1, RewardCurrencyCount2, RewardCurrencyCount3, RewardCurrencyCount4, " - // 136 137 138 139 140 141 142 143 - "RequiredCurrencyId1, RequiredCurrencyId2, RequiredCurrencyId3, RequiredCurrencyId4, RequiredCurrencyCount1, RequiredCurrencyCount2, RequiredCurrencyCount3, RequiredCurrencyCount4, " - // 144 145 146 147 148 149 - "QuestGiverTextWindow, QuestGiverTargetName, QuestTurnTextWindow, QuestTurnTargetName, SoundAccept, SoundTurnIn, " - // 150 151 152 153 154 155 156 157 158 159 - "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, EmoteOnIncomplete, EmoteOnComplete, " - // 160 161 162 163 164 165 166 167 - "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4" + //0 1 2 3 4 5 6 7 8 9 10 11 12 + "ID, QuestType, QuestLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, Float10, RewardMoney, RewardMoneyDifficulty, " + //13 14 15 16 17 18 19 20 21 + "Float13, RewardBonusMoney, RewardDisplaySpell, RewardSpell, RewardHonor, RewardKillHonor, StartItem, Flags, FlagsEx, " + //22 23 24 25 26 27 28 29 + "RewardItem1, RewardAmount1, ItemDrop1, ItemDropQuantity1, RewardItem2, RewardAmount2, ItemDrop2, ItemDropQuantity2, " + //30 31 32 33 34 35 36 37 + "RewardItem3, RewardAmount3, ItemDrop3, ItemDropQuantity3, RewardItem4, RewardAmount4, ItemDrop4, ItemDropQuantity4, " + //38 39 40 41 42 43 + "RewardChoiceItemID1, RewardChoiceItemQuantity1, RewardChoiceItemDisplayID1, RewardChoiceItemID2, RewardChoiceItemQuantity2, RewardChoiceItemDisplayID2, " + //44 45 46 47 48 49 + "RewardChoiceItemID3, RewardChoiceItemQuantity3, RewardChoiceItemDisplayID3, RewardChoiceItemID4, RewardChoiceItemQuantity4, RewardChoiceItemDisplayID4, " + //50 51 52 53 54 55 + "RewardChoiceItemID5, RewardChoiceItemQuantity5, RewardChoiceItemDisplayID5, RewardChoiceItemID6, RewardChoiceItemQuantity6, RewardChoiceItemDisplayID6, " + //56 57 58 59 60 61 62 63 64 65 66 + "POIContinent, POIx, POIy, POIPriority, RewardTitle, RewardTalents, RewardArenaPoints, RewardSkillLineID, RewardNumSkillUps, PortraitGiver, PortraitTurnIn, " + //67 68 69 70 71 72 + "RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, " + //73 74 75 76 77 78 + "RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, " + //79 80 81 82 + "RewardFactionID5, RewardFactionValue5, RewardFactionOverride5, RewardFactionFlags, " + //83 84 85 86 87 88 89 90 + "RewardCurrencyID1, RewardCurrencyQty1, RewardCurrencyID2, RewardCurrencyQty2, RewardCurrencyID3, RewardCurrencyQty3, RewardCurrencyID4, RewardCurrencyQty4, " + //91 92 93 94 95 + "AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, " + //96 97 98 99 100 101 102 103 104 + "LogTitle, LogDescription, QuestDescription, AreaDescription, PortraitGiverText, PortraitGiverName, PortraitTurnInText, PortraitTurnInName, QuestCompletionLog" " FROM quest_template"); if (!result) { @@ -3516,6 +3510,161 @@ void ObjectMgr::LoadQuests() _questTemplates[newQuest->GetQuestId()] = newQuest; } while (result->NextRow()); + // Load `quest_details` + // 0 1 2 3 4 5 6 7 8 + result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4 FROM quest_details"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest details. DB table `quest_details` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestDetails(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_details` has data for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + + // Load `quest_request_items` + // 0 1 2 3 4 5 + result = WorldDatabase.Query("SELECT ID, EmoteOnComplete, EmoteOnIncomplete, EmoteOnCompleteDelay, EmoteOnIncompleteDelay, CompletionText FROM quest_request_items"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest request items. DB table `quest_request_items` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestRequestItems(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_request_items` has data for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + + // Load `quest_offer_reward` + // 0 1 2 3 4 5 6 7 8 9 + result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4, RewardText FROM quest_offer_reward"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest reward emotes. DB table `quest_offer_reward` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestOfferReward(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_offer_reward` has data for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + + // Load `quest_template_addon` + // 0 1 2 3 4 5 6 7 8 + result = WorldDatabase.Query("SELECT ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay, " + //9 10 11 12 13 14 15 16 + "RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, SpecialFlags FROM quest_template_addon"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest template addons. DB table `quest_template_addon` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestTemplateAddon(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_template_addon` has data for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + + // Load `quest_objectives` order by descending storage index to reduce resizes + // 0 1 2 3 4 5 6 7 8 + result = WorldDatabase.Query("SELECT ID, QuestID, Type, StorageIndex, ObjectID, Amount, Flags, UnkFloat, Description FROM quest_objectives ORDER BY StorageIndex DESC"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest objectives. DB table `quest_objectives` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[1].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestObjective(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_objectives` has objective for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + + // Load `quest_visual_effect` join table with quest_objectives because visual effects are based on objective ID (core stores objectives by their index in quest) + // 0 1 2 3 4 5 + result = WorldDatabase.Query("SELECT v.ID, o.ID, o.QuestID, o.StorageIndex, v.Index, v.VisualEffect FROM quest_visual_effect AS v LEFT JOIN quest_objectives AS o ON v.ID = o.ID ORDER BY v.Index DESC"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest visual effects. DB table `quest_visual_effect` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 vID = fields[0].GetUInt32(); + uint32 oID = fields[1].GetUInt32(); + + if (!vID) + { + TC_LOG_ERROR("server.loading", "Table `quest_visual_effect` has visual effect for null objective id"); + continue; + } + + // objID will be null if match for table join is not found + if (vID != oID) + { + TC_LOG_ERROR("server.loading", "Table `quest_visual_effect` has visual effect for objective %u but such objective does not exist.", vID); + continue; + } + + uint32 questId = fields[2].GetUInt32(); + + // Do not throw error here because error for non existing quest is thrown while loading quest objectives. we do not need duplication + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestObjectiveVisualEffect(fields); + } while (result->NextRow()); + } + std::map<uint32, uint32> usedMailTemplates; // Post processing @@ -3624,23 +3773,23 @@ void ObjectMgr::LoadQuests() } } - // RequiredClasses, can be 0/CLASSMASK_ALL_PLAYABLE to allow any class - if (qinfo->RequiredClasses) + // AllowableClasses, can be 0/CLASSMASK_ALL_PLAYABLE to allow any class + if (qinfo->AllowableClasses) { - if (!(qinfo->RequiredClasses & CLASSMASK_ALL_PLAYABLE)) + if (!(qinfo->AllowableClasses & CLASSMASK_ALL_PLAYABLE)) { - TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable classes in `RequiredClasses` (%u), value set to 0 (all classes).", qinfo->GetQuestId(), qinfo->RequiredClasses); - qinfo->RequiredClasses = 0; + TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable classes in `AllowableClasses` (%u), value set to 0 (all classes).", qinfo->GetQuestId(), qinfo->AllowableClasses); + qinfo->AllowableClasses = 0; } } - // RequiredRaces, can be 0/RACEMASK_ALL_PLAYABLE to allow any race - if (qinfo->RequiredRaces) + // AllowableRaces, can be -1/RACEMASK_ALL_PLAYABLE to allow any race + if (qinfo->AllowableRaces != -1) { - if (!(qinfo->RequiredRaces & RACEMASK_ALL_PLAYABLE)) - { - TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable races in `RequiredRaces` (%u), value set to 0 (all races).", qinfo->GetQuestId(), qinfo->RequiredRaces); - qinfo->RequiredRaces = 0; - } + if (qinfo->AllowableRaces > 0 && !(uint32(qinfo->AllowableRaces) & RACEMASK_ALL_PLAYABLE)) + { + TC_LOG_ERROR("sql.sql", "Quest %u does not contain any playable races in `AllowableRaces` (%d), value set to 0 (all races).", qinfo->GetQuestId(), qinfo->AllowableRaces); + qinfo->AllowableRaces = -1; + } } // RequiredSkillId, can be 0 if (qinfo->RequiredSkillId) @@ -3663,20 +3812,6 @@ void ObjectMgr::LoadQuests() } // else Skill quests can have 0 skill level, this is ok - if (qinfo->RequiredFactionId2 && !sFactionStore.LookupEntry(qinfo->RequiredFactionId2)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredFactionId2` = %u but faction template %u does not exist, quest can't be done.", - qinfo->GetQuestId(), qinfo->RequiredFactionId2, qinfo->RequiredFactionId2); - // no changes, quest can't be done for this requirement - } - - if (qinfo->RequiredFactionId1 && !sFactionStore.LookupEntry(qinfo->RequiredFactionId1)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredFactionId1` = %u but faction template %u does not exist, quest can't be done.", - qinfo->GetQuestId(), qinfo->RequiredFactionId1, qinfo->RequiredFactionId1); - // no changes, quest can't be done for this requirement - } - if (qinfo->RequiredMinRepFaction && !sFactionStore.LookupEntry(qinfo->RequiredMinRepFaction)) { TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMinRepFaction` = %u but faction template %u does not exist, quest can't be done.", @@ -3705,20 +3840,6 @@ void ObjectMgr::LoadQuests() // no changes, quest can't be done for this requirement } - if (!qinfo->RequiredFactionId1 && qinfo->RequiredFactionValue1 != 0) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredFactionValue1` = %d but `RequiredFactionId1` is 0, value has no effect", - qinfo->GetQuestId(), qinfo->RequiredFactionValue1); - // warning - } - - if (!qinfo->RequiredFactionId2 && qinfo->RequiredFactionValue2 != 0) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredFactionValue2` = %d but `RequiredFactionId2` is 0, value has no effect", - qinfo->GetQuestId(), qinfo->RequiredFactionValue2); - // warning - } - if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue != 0) { TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect", @@ -3736,7 +3857,7 @@ void ObjectMgr::LoadQuests() if (qinfo->RewardTitleId && !sCharTitlesStore.LookupEntry(qinfo->RewardTitleId)) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardTitleId` = %u but CharTitle Id %u does not exist, quest can't be rewarded with title.", - qinfo->GetQuestId(), qinfo->GetCharTitleId(), qinfo->GetCharTitleId()); + qinfo->GetQuestId(), qinfo->RewardTitleId, qinfo->RewardTitleId); qinfo->RewardTitleId = 0; // quest can't reward this title } @@ -3763,55 +3884,94 @@ void ObjectMgr::LoadQuests() qinfo->SourceItemIdCount=0; // no quest work changes in fact } - if (qinfo->SourceSpellid) + if (qinfo->SourceSpellID) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->SourceSpellid); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->SourceSpellID); if (!spellInfo) { TC_LOG_ERROR("sql.sql", "Quest %u has `SourceSpellid` = %u but spell %u doesn't exist, quest can't be done.", - qinfo->GetQuestId(), qinfo->SourceSpellid, qinfo->SourceSpellid); - qinfo->SourceSpellid = 0; // quest can't be done for this requirement + qinfo->GetQuestId(), qinfo->SourceSpellID, qinfo->SourceSpellID); + qinfo->SourceSpellID = 0; // quest can't be done for this requirement } else if (!SpellMgr::IsSpellValid(spellInfo)) { TC_LOG_ERROR("sql.sql", "Quest %u has `SourceSpellid` = %u but spell %u is broken, quest can't be done.", - qinfo->GetQuestId(), qinfo->SourceSpellid, qinfo->SourceSpellid); - qinfo->SourceSpellid = 0; // quest can't be done for this requirement + qinfo->GetQuestId(), qinfo->SourceSpellID, qinfo->SourceSpellID); + qinfo->SourceSpellID = 0; // quest can't be done for this requirement } } - for (uint8 j = 0; j < QUEST_ITEM_OBJECTIVES_COUNT; ++j) + for (uint32 j = 0; j < qinfo->Objectives.size(); ++j) { - uint32 id = qinfo->RequiredItemId[j]; - if (id) - { - if (qinfo->RequiredItemCount[j] == 0) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredItemId%d` = %u but `RequiredItemCount%d` = 0, quest can't be done.", - qinfo->GetQuestId(), j+1, id, j+1); - // no changes, quest can't be done for this requirement - } + QuestObjective& obj = qinfo->Objectives[j]; - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER); + if (!obj.ObjectID) + { + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has `ObjectID` = 0, quest can't be done.", qinfo->GetQuestId(), j); + // no changes, quest can't be done for this requirement + continue; + } - if (!sObjectMgr->GetItemTemplate(id)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredItemId%d` = %u but item with entry %u does not exist, quest can't be done.", - qinfo->GetQuestId(), j+1, id, id); - qinfo->RequiredItemCount[j] = 0; // prevent incorrect work of quest - } + if (!obj.Amount) + { + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has `Amount` = 0, quest can't be done.", qinfo->GetQuestId(), j); + // no changes, quest can't be done for this requirement + continue; } - else if (qinfo->RequiredItemCount[j] > 0) + + switch (obj.Type) { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredItemId%d` = 0 but `RequiredItemCount%d` = %u, quest can't be done.", - qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredItemCount[j]); - qinfo->RequiredItemCount[j] = 0; // prevent incorrect work of quest + case QUEST_OBJECTIVE_ITEM: + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER); + if (!sObjectMgr->GetItemTemplate(obj.ObjectID)) + { + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing item entry %u, quest can't be done.", + qinfo->GetQuestId(), j, obj.ObjectID); + obj.Amount = 0; // prevent incorrect work of quest + } + break; + case QUEST_OBJECTIVE_MONSTER: + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO); + if (!sObjectMgr->GetCreatureTemplate(obj.ObjectID)) + { + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing creature entry %u, quest can't be done.", + qinfo->GetQuestId(), j, uint32(obj.ObjectID)); + obj.Amount = 0; // quest can't be done for this requirement + } + break; + case QUEST_OBJECTIVE_GAMEOBJECT: + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO); + if (!sObjectMgr->GetGameObjectTemplate(obj.ObjectID)) + { + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing gameobject entry %u, quest can't be done.", + qinfo->GetQuestId(), j, uint32(obj.ObjectID)); + obj.Amount = 0; // quest can't be done for this requirement + } + break; + case QUEST_OBJECTIVE_MIN_REPUTATION: + case QUEST_OBJECTIVE_MAX_REPUTATION: + if (!sFactionStore.LookupEntry(obj.ObjectID)) + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing faction id %u", qinfo->GetQuestId(), j, obj.ObjectID); + break; + case QUEST_OBJECTIVE_PLAYERKILLS: + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL); + if (obj.Amount <= 0) + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has invalid player kills count %d", qinfo->GetQuestId(), j, obj.Amount); + break; + case QUEST_OBJECTIVE_CURRENCY: + if (!sCurrencyTypesStore.LookupEntry(obj.ObjectID)) + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing currency %u", qinfo->GetQuestId(), j, obj.ObjectID); + if (obj.Amount <= 0) + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has invalid currency amount %d", qinfo->GetQuestId(), j, obj.Amount); + break; + default: + TC_LOG_ERROR("sql.sql", "Quest %u objective %u has unknown type %u", qinfo->GetQuestId(), j, obj.Type); } } - for (uint8 j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j) + for (uint8 j = 0; j < QUEST_ITEM_DROP_COUNT; ++j) { - uint32 id = qinfo->RequiredSourceItemId[j]; + uint32 id = qinfo->ItemDrop[j]; if (id) { if (!sObjectMgr->GetItemTemplate(id)) @@ -3823,53 +3983,15 @@ void ObjectMgr::LoadQuests() } else { - if (qinfo->RequiredSourceItemCount[j]>0) + if (qinfo->ItemDropQuantity[j]>0) { TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSourceItemId%d` = 0 but `RequiredSourceItemCount%d` = %u.", - qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredSourceItemCount[j]); + qinfo->GetQuestId(), j+1, j+1, qinfo->ItemDropQuantity[j]); // no changes, quest ignore this data } } } - for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) - { - int32 id = qinfo->RequiredNpcOrGo[j]; - if (id < 0 && !sObjectMgr->GetGameObjectTemplate(-id)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredNpcOrGo%d` = %i but gameobject %u does not exist, quest can't be done.", - qinfo->GetQuestId(), j+1, id, uint32(-id)); - qinfo->RequiredNpcOrGo[j] = 0; // quest can't be done for this requirement - } - - if (id > 0 && !sObjectMgr->GetCreatureTemplate(id)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredNpcOrGo%d` = %i but creature with entry %u does not exist, quest can't be done.", - qinfo->GetQuestId(), j+1, id, uint32(id)); - qinfo->RequiredNpcOrGo[j] = 0; // quest can't be done for this requirement - } - - if (id) - { - // In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast - - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO); - - if (!qinfo->RequiredNpcOrGoCount[j]) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredNpcOrGo%d` = %u but `RequiredNpcOrGoCount%d` = 0, quest can't be done.", - qinfo->GetQuestId(), j+1, id, j+1); - // no changes, quest can be incorrectly done, but we already report this - } - } - else if (qinfo->RequiredNpcOrGoCount[j]>0) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredNpcOrGo%d` = 0 but `RequiredNpcOrGoCount%d` = %u.", - qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredNpcOrGoCount[j]); - // no changes, quest ignore this data - } - } - for (uint8 j = 0; j < QUEST_REWARD_CHOICES_COUNT; ++j) { uint32 id = qinfo->RewardChoiceItemId[j]; @@ -3897,7 +4019,7 @@ void ObjectMgr::LoadQuests() } } - for (uint8 j = 0; j < QUEST_REWARDS_COUNT; ++j) + for (uint8 j = 0; j < QUEST_REWARD_ITEM_COUNT; ++j) { uint32 id = qinfo->RewardItemId[j]; if (id) @@ -3909,28 +4031,28 @@ void ObjectMgr::LoadQuests() qinfo->RewardItemId[j] = 0; // no changes, quest will not reward this item } - if (!qinfo->RewardItemIdCount[j]) + if (!qinfo->RewardItemCount[j]) { - TC_LOG_ERROR("sql.sql", "Quest %u has `RewardItemId%d` = %u but `RewardItemIdCount%d` = 0, quest will not reward this item.", + TC_LOG_ERROR("sql.sql", "Quest %u has `RewardItemId%d` = %u but `RewardItemCount%d` = 0, quest will not reward this item.", qinfo->GetQuestId(), j+1, id, j+1); // no changes } } - else if (qinfo->RewardItemIdCount[j]>0) + else if (qinfo->RewardItemCount[j]>0) { - TC_LOG_ERROR("sql.sql", "Quest %u has `RewardItemId%d` = 0 but `RewardItemIdCount%d` = %u.", - qinfo->GetQuestId(), j+1, j+1, qinfo->RewardItemIdCount[j]); + TC_LOG_ERROR("sql.sql", "Quest %u has `RewardItemId%d` = 0 but `RewardItemCount%d` = %u.", + qinfo->GetQuestId(), j+1, j+1, qinfo->RewardItemCount[j]); // no changes, quest ignore this data } } - for (uint8 j = 0; j < QUEST_REPUTATIONS_COUNT; ++j) + for (uint8 j = 0; j < QUEST_REWARD_REPUTATIONS_COUNT; ++j) { if (qinfo->RewardFactionId[j]) { - if (abs(qinfo->RewardFactionValueId[j]) > 9) + if (abs(qinfo->RewardFactionValue[j]) > 9) { - TC_LOG_ERROR("sql.sql", "Quest %u has RewardFactionValueId%d = %i. That is outside the range of valid values (-9 to 9).", qinfo->GetQuestId(), j+1, qinfo->RewardFactionValueId[j]); + TC_LOG_ERROR("sql.sql", "Quest %u has RewardFactionValueId%d = %i. That is outside the range of valid values (-9 to 9).", qinfo->GetQuestId(), j+1, qinfo->RewardFactionValue[j]); } if (!sFactionStore.LookupEntry(qinfo->RewardFactionId[j])) { @@ -3939,49 +4061,49 @@ void ObjectMgr::LoadQuests() } } - else if (qinfo->RewardFactionValueIdOverride[j] != 0) + else if (qinfo->RewardFactionOverride[j] != 0) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardFactionId%d` = 0 but `RewardFactionValueIdOverride%d` = %i.", - qinfo->GetQuestId(), j+1, j+1, qinfo->RewardFactionValueIdOverride[j]); + qinfo->GetQuestId(), j+1, j+1, qinfo->RewardFactionOverride[j]); // no changes, quest ignore this data } } - if (qinfo->RewardSpell) + if (qinfo->RewardDisplaySpell) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardSpell); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardDisplaySpell); if (!spellInfo) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u does not exist, spell removed as display reward.", - qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell); - qinfo->RewardSpell = 0; // no spell reward will display for this quest + qinfo->GetQuestId(), qinfo->RewardDisplaySpell, qinfo->RewardDisplaySpell); + qinfo->RewardDisplaySpell = 0; // no spell reward will display for this quest } else if (!SpellMgr::IsSpellValid(spellInfo)) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is broken, quest will not have a spell reward.", - qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell); - qinfo->RewardSpell = 0; // no spell reward will display for this quest + qinfo->GetQuestId(), qinfo->RewardDisplaySpell, qinfo->RewardDisplaySpell); + qinfo->RewardDisplaySpell = 0; // no spell reward will display for this quest } } - if (qinfo->RewardSpellCast > 0) + if (qinfo->RewardSpell > 0) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardSpellCast); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RewardSpell); if (!spellInfo) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u does not exist, quest will not have a spell reward.", - qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); - qinfo->RewardSpellCast = 0; // no spell will be cast on player + qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell); + qinfo->RewardSpell = 0; // no spell will be cast on player } else if (!SpellMgr::IsSpellValid(spellInfo)) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u is broken, quest will not have a spell reward.", - qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); - qinfo->RewardSpellCast = 0; // no spell will be cast on player + qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell); + qinfo->RewardSpell = 0; // no spell will be cast on player } } @@ -4006,14 +4128,14 @@ void ObjectMgr::LoadQuests() usedMailTemplates[qinfo->RewardMailTemplateId] = qinfo->GetQuestId(); } - if (qinfo->NextQuestIdChain) + if (qinfo->NextQuestInChain) { - QuestMap::iterator qNextItr = _questTemplates.find(qinfo->NextQuestIdChain); + QuestMap::iterator qNextItr = _questTemplates.find(qinfo->NextQuestInChain); if (qNextItr == _questTemplates.end()) { - TC_LOG_ERROR("sql.sql", "Quest %u has `NextQuestIdChain` = %u but quest %u does not exist, quest chain will not work.", - qinfo->GetQuestId(), qinfo->NextQuestIdChain, qinfo->NextQuestIdChain); - qinfo->NextQuestIdChain = 0; + TC_LOG_ERROR("sql.sql", "Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.", + qinfo->GetQuestId(), qinfo->NextQuestInChain, qinfo->NextQuestInChain); + qinfo->NextQuestInChain = 0; } else qNextItr->second->prevChainQuests.push_back(qinfo->GetQuestId()); @@ -4045,32 +4167,6 @@ void ObjectMgr::LoadQuests() } } - for (uint8 j = 0; j < QUEST_REQUIRED_CURRENCY_COUNT; ++j) - { - if (qinfo->RequiredCurrencyId[j]) - { - if (qinfo->RequiredCurrencyCount[j] == 0) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredCurrencyId%d` = %u but `RequiredCurrencyCount%d` = 0, quest can't be done.", - qinfo->GetQuestId(), j+1, qinfo->RequiredCurrencyId[j], j+1); - // no changes, quest can't be done for this requirement - } - - if (!sCurrencyTypesStore.LookupEntry(qinfo->RequiredCurrencyId[j])) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredCurrencyId%d` = %u but currency with entry %u does not exist, quest can't be done.", - qinfo->GetQuestId(), j+1, qinfo->RequiredCurrencyId[j], qinfo->RequiredCurrencyId[j]); - qinfo->RequiredCurrencyCount[j] = 0; // prevent incorrect work of quest - } - } - else if (qinfo->RequiredCurrencyCount[j] > 0) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredCurrencyId%d` = 0 but `RequiredCurrencyCount%d` = %u, quest can't be done.", - qinfo->GetQuestId(), j+1, j+1, qinfo->RequiredCurrencyCount[j]); - qinfo->RequiredCurrencyCount[j] = 0; // prevent incorrect work of quest - } - } - if (qinfo->SoundAccept) { if (!sSoundEntriesStore.LookupEntry(qinfo->SoundAccept)) @@ -4091,34 +4187,6 @@ void ObjectMgr::LoadQuests() } } - if (qinfo->RequiredSpell > 0) - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->RequiredSpell); - - if (!spellInfo) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSpell` = %u but spell %u does not exist, quest will not require a spell.", - qinfo->GetQuestId(), qinfo->RequiredSpell, qinfo->RequiredSpell); - qinfo->RequiredSpell = 0; // no spell will be required - } - - else if (!SpellMgr::IsSpellValid(spellInfo)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RequiredSpell` = %u but spell %u is broken, quest will not require a spell.", - qinfo->GetQuestId(), qinfo->RequiredSpell, qinfo->RequiredSpell); - qinfo->RequiredSpell = 0; // no spell will be required - } - - /* Can we require talents? - else if (GetTalentSpellCost(qinfo->RewardSpellCast)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.", - qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); - qinfo->RewardSpellCast = 0; // no spell will be casted on player - } - }*/ - } - if (qinfo->RewardSkillId) { if (!sSkillLineStore.LookupEntry(qinfo->RewardSkillId)) @@ -4149,22 +4217,22 @@ void ObjectMgr::LoadQuests() } // fill additional data stores - if (qinfo->PrevQuestId) + if (qinfo->PrevQuestID) { if (_questTemplates.find(abs(qinfo->GetPrevQuestId())) == _questTemplates.end()) TC_LOG_ERROR("sql.sql", "Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId()); else - qinfo->prevQuests.push_back(qinfo->PrevQuestId); + qinfo->prevQuests.push_back(qinfo->PrevQuestID); } - if (qinfo->NextQuestId) + if (qinfo->NextQuestID) { QuestMap::iterator qNextItr = _questTemplates.find(abs(qinfo->GetNextQuestId())); if (qNextItr == _questTemplates.end()) TC_LOG_ERROR("sql.sql", "Quest %d has NextQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId()); else { - int32 signedQuestId = qinfo->NextQuestId < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId()); + int32 signedQuestId = qinfo->NextQuestID < 0 ? -int32(qinfo->GetQuestId()) : int32(qinfo->GetQuestId()); qNextItr->second->prevQuests.push_back(signedQuestId); } } @@ -4173,8 +4241,6 @@ void ObjectMgr::LoadQuests() mExclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->ExclusiveGroup, qinfo->GetQuestId())); if (qinfo->LimitTime) qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED); - if (qinfo->RequiredPlayerKills) - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL); } // check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE @@ -4242,21 +4308,22 @@ void ObjectMgr::LoadQuestLocales() { LocaleConstant locale = (LocaleConstant) i; - AddLocaleString(fields[1 + 15 * (i - 1)].GetString(), locale, data.Title); - AddLocaleString(fields[1 + 15 * (i - 1) + 1].GetString(), locale, data.Details); - AddLocaleString(fields[1 + 15 * (i - 1) + 2].GetString(), locale, data.Objectives); + AddLocaleString(fields[1 + 15 * (i - 1)].GetString(), locale, data.LogTitle); + AddLocaleString(fields[1 + 15 * (i - 1) + 1].GetString(), locale, data.LogDescription); + AddLocaleString(fields[1 + 15 * (i - 1) + 2].GetString(), locale, data.QuestDescription); AddLocaleString(fields[1 + 15 * (i - 1) + 3].GetString(), locale, data.OfferRewardText); AddLocaleString(fields[1 + 15 * (i - 1) + 4].GetString(), locale, data.RequestItemsText); - AddLocaleString(fields[1 + 15 * (i - 1) + 5].GetString(), locale, data.EndText); - AddLocaleString(fields[1 + 15 * (i - 1) + 6].GetString(), locale, data.CompletedText); + //AddLocaleString(fields[1 + 15 * (i - 1) + 5].GetString(), locale, data.EndText); Probably deprecated + AddLocaleString(fields[1 + 15 * (i - 1) + 6].GetString(), locale, data.QuestCompletionLog); + data.ObjectiveDescription.resize(4); for (uint8 k = 0; k < 4; ++k) - AddLocaleString(fields[1 + 15 * (i - 1) + 7 + k].GetString(), locale, data.ObjectiveText[k]); + AddLocaleString(fields[1 + 15 * (i - 1) + 7 + k].GetString(), locale, data.ObjectiveDescription[k]); - AddLocaleString(fields[1 + 15 * (i - 1) + 11].GetString(), locale, data.QuestGiverTextWindow); - AddLocaleString(fields[1 + 15 * (i - 1) + 12].GetString(), locale, data.QuestGiverTargetName); - AddLocaleString(fields[1 + 15 * (i - 1) + 13].GetString(), locale, data.QuestTurnTextWindow); - AddLocaleString(fields[1 + 15 * (i - 1) + 14].GetString(), locale, data.QuestTurnTargetName); + AddLocaleString(fields[1 + 15 * (i - 1) + 11].GetString(), locale, data.PortraitGiverText); + AddLocaleString(fields[1 + 15 * (i - 1) + 12].GetString(), locale, data.PortraitGiverName); + AddLocaleString(fields[1 + 15 * (i - 1) + 13].GetString(), locale, data.PortraitTurnInText); + AddLocaleString(fields[1 + 15 * (i - 1) + 14].GetString(), locale, data.PortraitTurnInName); } } while (result->NextRow()); |
