diff --git a/tools/editor/sql_exporter.cpp b/tools/editor/sql_exporter.cpp index 71c633aa..a72e6b96 100644 --- a/tools/editor/sql_exporter.cpp +++ b/tools/editor/sql_exporter.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace wowee { namespace editor { @@ -157,7 +158,23 @@ bool SQLExporter::exportCreatures(const std::vector& spawns, bool SQLExporter::exportQuests(const std::vector& quests, const std::string& path, - uint32_t startEntry) { + uint32_t startEntry, + const std::vector* spawns, + uint32_t creatureStartEntry) { + // Build a spawn.id -> SQL creature entry map. Allows quest hooks defined + // by the editor's UI (which uses spawn.id) to point at the matching + // creature_template row (which uses creatureStartEntry + index). + std::unordered_map spawnIdToEntry; + if (spawns) { + for (size_t i = 0; i < spawns->size(); i++) { + spawnIdToEntry[(*spawns)[i].id] = creatureStartEntry + static_cast(i); + } + } + auto resolveCreatureEntry = [&](uint32_t spawnId) { + if (!spawns || spawns->empty()) return spawnId; + auto it = spawnIdToEntry.find(spawnId); + return it != spawnIdToEntry.end() ? it->second : spawnId; + }; namespace fs = std::filesystem; fs::create_directories(fs::path(path).parent_path()); @@ -188,7 +205,9 @@ bool SQLExporter::exportQuests(const std::vector& quests, uint32_t id = 0; try { id = static_cast(std::stoul(obj.targetName)); } catch (...) {} if (obj.type == QuestObjectiveType::KillCreature && npcSlot < 4) { - reqNpcOrGo[npcSlot] = id; + // Editor UI fills targetName with a spawn.id for Kill objectives; + // resolve to the matching SQL creature entry. + reqNpcOrGo[npcSlot] = resolveCreatureEntry(id); reqNpcOrGoCount[npcSlot] = obj.targetCount; npcSlot++; } else if (obj.type == QuestObjectiveType::CollectItem && itemSlot < 6) { @@ -231,11 +250,11 @@ bool SQLExporter::exportQuests(const std::vector& quests, uint32_t entry = startEntry + q.id; if (q.questGiverNpcId > 0) { f << "INSERT IGNORE INTO `creature_queststarter` (`id`, `quest`) VALUES (" - << q.questGiverNpcId << ", " << entry << ");\n"; + << resolveCreatureEntry(q.questGiverNpcId) << ", " << entry << ");\n"; } if (q.turnInNpcId > 0) { f << "INSERT IGNORE INTO `creature_questender` (`id`, `quest`) VALUES (" - << q.turnInNpcId << ", " << entry << ");\n"; + << resolveCreatureEntry(q.turnInNpcId) << ", " << entry << ");\n"; } } @@ -249,7 +268,7 @@ bool SQLExporter::exportAll(const std::vector& spawns, uint32_t mapId, uint32_t startEntry) { if (!exportCreatures(spawns, path, mapId, startEntry)) return false; - if (!quests.empty()) exportQuests(quests, path, startEntry); + if (!quests.empty()) exportQuests(quests, path, startEntry, &spawns, startEntry); return true; } diff --git a/tools/editor/sql_exporter.hpp b/tools/editor/sql_exporter.hpp index 2de00bd6..5e589a10 100644 --- a/tools/editor/sql_exporter.hpp +++ b/tools/editor/sql_exporter.hpp @@ -16,10 +16,16 @@ public: uint32_t mapId = 9000, uint32_t startEntry = 100000); - // Export quest definitions as AzerothCore quest_template SQL + // Export quest definitions as AzerothCore quest_template SQL. + // `spawns` is used to translate the editor's per-spawn .id values stored + // in quest links (questGiverNpcId, turnInNpcId, KillCreature targetName) + // into the matching SQL `entry` (which is `creatureStartEntry + index`). + // Pass an empty spawns vector if no translation is needed. static bool exportQuests(const std::vector& quests, const std::string& path, - uint32_t startEntry = 100000); + uint32_t startEntry = 100000, + const std::vector* spawns = nullptr, + uint32_t creatureStartEntry = 100000); // Export everything to a single SQL file static bool exportAll(const std::vector& spawns,