Implement quest_relations table. Based on work by @Hozen

This commit is contained in:
Antz 2019-01-08 20:59:22 +00:00 committed by Antz
parent 25fac44c28
commit a479a2ccc5
5 changed files with 44 additions and 31 deletions

View file

@ -5332,7 +5332,7 @@ void ObjectMgr::LoadQuestAreaTriggers()
{ {
mQuestAreaTriggerMap.clear(); // need for reload case mQuestAreaTriggerMap.clear(); // need for reload case
QueryResult* result = WorldDatabase.Query("SELECT id,quest FROM areatrigger_involvedrelation"); QueryResult* result = WorldDatabase.PQuery("SELECT entry, quest FROM quest_relations WHERE actor = %d", QA_AREATRIGGER);
uint32 count = 0; uint32 count = 0;
@ -5361,20 +5361,20 @@ void ObjectMgr::LoadQuestAreaTriggers()
AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(trigger_ID); AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(trigger_ID);
if (!atEntry) if (!atEntry)
{ {
sLog.outErrorDb("Table `areatrigger_involvedrelation` has area trigger (ID: %u) not listed in `AreaTrigger.dbc`.", trigger_ID); sLog.outErrorDb("Table `quest_relations` has area trigger (ID: %u) not listed in `AreaTrigger.dbc`.", trigger_ID);
continue; continue;
} }
Quest const* quest = GetQuestTemplate(quest_ID); Quest const* quest = GetQuestTemplate(quest_ID);
if (!quest) if (!quest)
{ {
sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not existing quest %u", trigger_ID, quest_ID); sLog.outErrorDb("Table `quest_relations` has record (id: %u) for not existing quest %u", trigger_ID, quest_ID);
continue; continue;
} }
if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT)) if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT))
{ {
sLog.outErrorDb("Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID); sLog.outErrorDb("Table `quest_relations` has record (id: %u) for not quest %u, but quest not have flag QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID);
// this will prevent quest completing without objective // this will prevent quest completing without objective
const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT); const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT);
@ -7506,13 +7506,13 @@ void ObjectMgr::DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_
cell_guids.corpses.erase(player_guid); cell_guids.corpses.erase(player_guid);
} }
void ObjectMgr::LoadQuestRelationsHelper(QuestRelationsMap& map, char const* table) void ObjectMgr::LoadQuestRelationsHelper(QuestRelationsMap& map, QuestActor actor, QuestRole role)
{ {
map.clear(); // need for reload case map.clear(); // need for reload case
uint32 count = 0; uint32 count = 0;
QueryResult* result = WorldDatabase.PQuery("SELECT id,quest FROM %s", table); QueryResult* result = WorldDatabase.PQuery("SELECT entry, quest FROM quest_relations WHERE actor = %d AND role = %d", actor, role);
if (!result) if (!result)
{ {
@ -7521,7 +7521,7 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelationsMap& map, char const* tab
bar.step(); bar.step();
sLog.outString(); sLog.outString();
sLog.outErrorDb(">> Loaded 0 quest relations from %s. DB table `%s` is empty.", table, table); sLog.outErrorDb(">> Loaded 0 quest relations. DB table `quest_relations` is empty.");
return; return;
} }
@ -7537,7 +7537,7 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelationsMap& map, char const* tab
if (mQuestTemplates.find(quest) == mQuestTemplates.end()) if (mQuestTemplates.find(quest) == mQuestTemplates.end())
{ {
sLog.outErrorDb("Table `%s: Quest %u listed for entry %u does not exist.", table, quest, id); sLog.outErrorDb("Table `quest_relations`: Quest %u listed for entry %u does not exist.", quest, id);
continue; continue;
} }
@ -7550,62 +7550,62 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelationsMap& map, char const* tab
delete result; delete result;
sLog.outString(); sLog.outString();
sLog.outString(">> Loaded %u quest relations from %s", count, table); sLog.outString(">> Loaded %u %s quest %s from `quest_relations`", count, (actor == 1) ? "gameobject" : "creature", (role == 1) ? "takers" : "givers");
} }
void ObjectMgr::LoadGameobjectQuestRelations() void ObjectMgr::LoadGameobjectQuestRelations()
{ {
LoadQuestRelationsHelper(m_GOQuestRelations, "gameobject_questrelation"); LoadQuestRelationsHelper(m_GOQuestRelations, QA_GAMEOBJECT, QR_START);
for (QuestRelationsMap::iterator itr = m_GOQuestRelations.begin(); itr != m_GOQuestRelations.end(); ++itr) for (QuestRelationsMap::iterator itr = m_GOQuestRelations.begin(); itr != m_GOQuestRelations.end(); ++itr)
{ {
GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first);
if (!goInfo) if (!goInfo)
sLog.outErrorDb("Table `gameobject_questrelation` have data for nonexistent gameobject entry (%u) and existing quest %u", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` have data for nonexistent gameobject entry (%u) and existing quest %u", itr->first, itr->second); }
else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER)
sLog.outErrorDb("Table `gameobject_questrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER", itr->first, itr->second); }
} }
} }
void ObjectMgr::LoadGameobjectInvolvedRelations() void ObjectMgr::LoadGameobjectInvolvedRelations()
{ {
LoadQuestRelationsHelper(m_GOQuestInvolvedRelations, "gameobject_involvedrelation"); LoadQuestRelationsHelper(m_GOQuestInvolvedRelations, QA_GAMEOBJECT, QR_END);
for (QuestRelationsMap::iterator itr = m_GOQuestInvolvedRelations.begin(); itr != m_GOQuestInvolvedRelations.end(); ++itr) for (QuestRelationsMap::iterator itr = m_GOQuestInvolvedRelations.begin(); itr != m_GOQuestInvolvedRelations.end(); ++itr)
{ {
GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first); GameObjectInfo const* goInfo = GetGameObjectInfo(itr->first);
if (!goInfo) if (!goInfo)
sLog.outErrorDb("Table `gameobject_involvedrelation` have data for nonexistent gameobject entry (%u) and existing quest %u", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` have data for nonexistent gameobject entry (%u) and existing quest %u", itr->first, itr->second); }
else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER) else if (goInfo->type != GAMEOBJECT_TYPE_QUESTGIVER)
sLog.outErrorDb("Table `gameobject_involvedrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER", itr->first, itr->second); }
} }
} }
void ObjectMgr::LoadCreatureQuestRelations() void ObjectMgr::LoadCreatureQuestRelations()
{ {
LoadQuestRelationsHelper(m_CreatureQuestRelations, "creature_questrelation"); LoadQuestRelationsHelper(m_CreatureQuestRelations, QA_CREATURE, QR_START);
for (QuestRelationsMap::iterator itr = m_CreatureQuestRelations.begin(); itr != m_CreatureQuestRelations.end(); ++itr) for (QuestRelationsMap::iterator itr = m_CreatureQuestRelations.begin(); itr != m_CreatureQuestRelations.end(); ++itr)
{ {
CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); CreatureInfo const* cInfo = GetCreatureTemplate(itr->first);
if (!cInfo) if (!cInfo)
sLog.outErrorDb("Table `creature_involvedrelation` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second); }
else if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_QUESTGIVER)) else if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_QUESTGIVER))
sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but NpcFlags does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second); }
} }
} }
void ObjectMgr::LoadCreatureInvolvedRelations() void ObjectMgr::LoadCreatureInvolvedRelations()
{ {
LoadQuestRelationsHelper(m_CreatureQuestInvolvedRelations, "creature_involvedrelation"); LoadQuestRelationsHelper(m_CreatureQuestInvolvedRelations, QA_CREATURE, QR_END);
for (QuestRelationsMap::iterator itr = m_CreatureQuestInvolvedRelations.begin(); itr != m_CreatureQuestInvolvedRelations.end(); ++itr) for (QuestRelationsMap::iterator itr = m_CreatureQuestInvolvedRelations.begin(); itr != m_CreatureQuestInvolvedRelations.end(); ++itr)
{ {
CreatureInfo const* cInfo = GetCreatureTemplate(itr->first); CreatureInfo const* cInfo = GetCreatureTemplate(itr->first);
if (!cInfo) if (!cInfo)
sLog.outErrorDb("Table `creature_involvedrelation` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` have data for nonexistent creature entry (%u) and existing quest %u", itr->first, itr->second); }
else if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_QUESTGIVER)) else if (!(cInfo->NpcFlags & UNIT_NPC_FLAG_QUESTGIVER))
sLog.outErrorDb("Table `creature_involvedrelation` has creature entry (%u) for quest %u, but NpcFlags does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second); { sLog.outErrorDb("Table `quest_relations` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER", itr->first, itr->second); }
} }
} }

View file

@ -1313,7 +1313,7 @@ class ObjectMgr
private: private:
void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment); void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment);
void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr);
void LoadQuestRelationsHelper(QuestRelationsMap& map, char const* table); void LoadQuestRelationsHelper(QuestRelationsMap& map, QuestActor actor, QuestRole role);
void LoadVendors(char const* tableName, bool isTemplates); void LoadVendors(char const* tableName, bool isTemplates);
void LoadTrainers(char const* tableName, bool isTemplates); void LoadTrainers(char const* tableName, bool isTemplates);

View file

@ -530,7 +530,7 @@ ChatCommand* ChatHandler::getCommandTable()
{ "achievement_criteria_requirement", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementCriteriaRequirementCommand, "", NULL }, { "achievement_criteria_requirement", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementCriteriaRequirementCommand, "", NULL },
{ "achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementRewardCommand, "", NULL }, { "achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementRewardCommand, "", NULL },
{ "areatrigger_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL }, { "areatrigger_quest_end", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL },
{ "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL }, { "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL },
{ "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL }, { "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL },
{ "autobroadcast", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAutoBroadcastCommand, "", NULL }, { "autobroadcast", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAutoBroadcastCommand, "", NULL },
@ -540,10 +540,10 @@ ChatCommand* ChatHandler::getCommandTable()
{ "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL }, { "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL },
{ "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL }, { "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL },
{ "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL }, { "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
{ "creature_template_classlevelstats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreaturesStatsCommand, "", NULL }, { "creature_quest_end", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand, "", NULL },
{ "creature_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand, "", NULL },
{ "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL }, { "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL },
{ "creature_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL }, { "creature_quest_start", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL },
{ "creature_template_classlevelstats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreaturesStatsCommand, "", NULL },
{ "db_script_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDbScriptStringCommand, "", NULL }, { "db_script_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDbScriptStringCommand, "", NULL },
{ "dbscripts_on_creature_death", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand, "", NULL }, { "dbscripts_on_creature_death", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand, "", NULL },
{ "dbscripts_on_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnEventCommand, "", NULL }, { "dbscripts_on_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnEventCommand, "", NULL },
@ -556,9 +556,9 @@ ChatCommand* ChatHandler::getCommandTable()
{ "fishing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesFishingCommand, "", NULL }, { "fishing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesFishingCommand, "", NULL },
{ "game_graveyard_zone", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameGraveyardZoneCommand, "", NULL }, { "game_graveyard_zone", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameGraveyardZoneCommand, "", NULL },
{ "game_tele", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameTeleCommand, "", NULL }, { "game_tele", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameTeleCommand, "", NULL },
{ "gameobject_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestInvRelationsCommand, "", NULL }, { "gameobject_quest_end", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestInvRelationsCommand, "", NULL },
{ "gameobject_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL }, { "gameobject_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL },
{ "gameobject_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL }, { "gameobject_quest_start", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL },
{ "gameobject_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL }, { "gameobject_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
{ "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL }, { "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },
{ "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL }, { "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },

View file

@ -187,6 +187,19 @@ enum QuestSpecialFlags
#define QUEST_SPECIAL_FLAG_DB_ALLOWED (QUEST_SPECIAL_FLAG_REPEATABLE | QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAG_MONTHLY) #define QUEST_SPECIAL_FLAG_DB_ALLOWED (QUEST_SPECIAL_FLAG_REPEATABLE | QUEST_SPECIAL_FLAG_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAG_MONTHLY)
enum QuestActor
{
QA_CREATURE = 0,
QA_GAMEOBJECT = 1,
QA_AREATRIGGER = 2,
};
enum QuestRole
{
QR_START = 0,
QR_END = 1,
};
struct QuestLocale struct QuestLocale
{ {
QuestLocale() { ObjectiveText.resize(QUEST_OBJECTIVES_COUNT); } QuestLocale() { ObjectiveText.resize(QUEST_OBJECTIVES_COUNT); }

View file

@ -24,7 +24,7 @@
#ifndef MANGOS_H_REVISION #ifndef MANGOS_H_REVISION
#define MANGOS_H_REVISION #define MANGOS_H_REVISION
#define REVISION_NR "210708" #define REVISION_NR "2109001"
#define REALMD_DB_VERSION_NR 21 #define REALMD_DB_VERSION_NR 21
#define REALMD_DB_STRUCTURE_NR 1 #define REALMD_DB_STRUCTURE_NR 1
@ -37,7 +37,7 @@
#define CHAR_DB_UPDATE_DESCRIPTION "Remove DbDocs" #define CHAR_DB_UPDATE_DESCRIPTION "Remove DbDocs"
#define WORLD_DB_VERSION_NR 21 #define WORLD_DB_VERSION_NR 21
#define WORLD_DB_STRUCTURE_NR 8 #define WORLD_DB_STRUCTURE_NR 9
#define WORLD_DB_CONTENT_NR 1 #define WORLD_DB_CONTENT_NR 1
#define WORLD_DB_UPDATE_DESCRIPTION "force_version_change" #define WORLD_DB_UPDATE_DESCRIPTION "quest_relations"
#endif // __REVISION_H__ #endif // __REVISION_H__