Working on quest system

This commit is contained in:
Vladislav Khorev committed 2026-06-03 14:37:09 +03:00
1 parent aaae368a07
commit e7ae148ead
22 files changed
+357 -103

No files matched your search

+10
View File
@@ -106,6 +106,11 @@ Node DialogueDatabase::parseNode(const json& j) {
node.cutsceneId = j.value("cutsceneId", "");
node.luaCallback = j.value("luaCallback", "");
node.bubbleSlot = j.value("bubbleSlot", "");
node.questUnlock = j.value("questUnlock", "");
node.questComplete = j.value("questComplete", "");
node.questFail = j.value("questFail", "");
node.objectiveComplete = j.value("objectiveComplete", "");
node.objectiveVisible = j.value("objectiveVisible", "");
if (j.contains("conditions") && j["conditions"].is_array()) {
for (const auto& item : j["conditions"]) {
@@ -157,6 +162,11 @@ CutsceneLine DialogueDatabase::parseCutsceneLine(const json& j) {
line.luaCallback = j.value("luaCallback", "");
line.durationMs = j.value("durationMs", 0);
line.waitForConfirm = j.value("waitForConfirm", false);
line.questUnlock = j.value("questUnlock", "");
line.questComplete = j.value("questComplete", "");
line.questFail = j.value("questFail", "");
line.objectiveComplete = j.value("objectiveComplete", "");
line.objectiveVisible = j.value("objectiveVisible", "");
return line;
}
+43 -8
View File
@@ -5,7 +5,13 @@
#include <iostream>
namespace ZL::Dialogue {
static std::pair<std::string, std::string> splitDot(const std::string& s) {
const auto dot = s.find('.');
if (dot == std::string::npos) return {s, ""};
return {s.substr(0, dot), s.substr(dot + 1)};
}
void DialogueRuntime::setDatabase(const DialogueDatabase* value) {
database = value;
}
@@ -309,6 +315,29 @@ int DialogueRuntime::getFlag(const std::string& name) const {
return (it != flags.end()) ? it->second : 0;
}
void DialogueRuntime::setQuestJournal(Quest::QuestJournal* journal) {
questJournal = journal;
}
void DialogueRuntime::applyQuestActions(
const std::string& questUnlock, const std::string& questComplete,
const std::string& questFail, const std::string& objectiveComplete,
const std::string& objectiveVisible)
{
if (!questJournal) return;
if (!questUnlock.empty()) questJournal->unlockQuest(questUnlock);
if (!questComplete.empty()) questJournal->completeQuest(questComplete);
if (!questFail.empty()) questJournal->failQuest(questFail);
if (!objectiveComplete.empty()) {
auto [qId, oId] = splitDot(objectiveComplete);
questJournal->setObjectiveCompleted(qId, oId);
}
if (!objectiveVisible.empty()) {
auto [qId, oId] = splitDot(objectiveVisible);
questJournal->setObjectiveVisible(qId, oId);
}
}
bool DialogueRuntime::evaluateConditions(const std::vector<Condition>& conditions) const {
for (const Condition& condition : conditions) {
const int currentValue = getFlag(condition.flag);
@@ -432,6 +461,8 @@ void DialogueRuntime::presentLine(const Node& node) {
revealCharacters = static_cast<float>(node.text.size());
}
applyQuestActions(node.questUnlock, node.questComplete, node.questFail,
node.objectiveComplete, node.objectiveVisible);
if (!node.luaCallback.empty() && onDialogueLineStarted) {
onDialogueLineStarted(node.luaCallback);
}
@@ -530,9 +561,12 @@ void DialogueRuntime::startCutscene(const std::string& cutsceneId, const std::st
cutsceneTotalDurationMs = cutsceneContentDurationMs + activeCutscene->endFadeOutMs + activeCutscene->endFadeInMs;
refreshCutscenePresentation();
if (!activeCutscene->lines.empty() && onCutsceneLineStarted) {
const std::string& cb = activeCutscene->lines[0].luaCallback;
if (!cb.empty()) onCutsceneLineStarted(cb);
if (!activeCutscene->lines.empty()) {
const CutsceneLine& firstLine = activeCutscene->lines[0];
applyQuestActions(firstLine.questUnlock, firstLine.questComplete,
firstLine.questFail, firstLine.objectiveComplete, firstLine.objectiveVisible);
if (onCutsceneLineStarted && !firstLine.luaCallback.empty())
onCutsceneLineStarted(firstLine.luaCallback);
}
std::cout << "[CUTSCENE] start id=" << cutsceneId
@@ -621,10 +655,11 @@ void DialogueRuntime::advanceCutsceneLine() {
return;
}
if (onCutsceneLineStarted) {
const std::string& cb = activeCutscene->lines[currentCutsceneLine].luaCallback;
if (!cb.empty()) onCutsceneLineStarted(cb);
}
const CutsceneLine& newLine = activeCutscene->lines[currentCutsceneLine];
applyQuestActions(newLine.questUnlock, newLine.questComplete,
newLine.questFail, newLine.objectiveComplete, newLine.objectiveVisible);
if (onCutsceneLineStarted && !newLine.luaCallback.empty())
onCutsceneLineStarted(newLine.luaCallback);
refreshCutscenePresentation();
}
+7
View File
@@ -1,6 +1,7 @@
#pragma once
#include "dialogue/DialogueDatabase.h"
#include "quest/QuestJournal.h"
#include "external/nlohmann/json.hpp"
#include <functional>
#include <string>
@@ -42,6 +43,8 @@ public:
void setFlag(const std::string& name, int value);
int getFlag(const std::string& name) const;
void setQuestJournal(Quest::QuestJournal* journal);
json buildSaveState() const;
bool restoreSaveState(const json& state);
@@ -62,6 +65,7 @@ private:
bool fadeInCallbackFired = false;
const DialogueDatabase* database = nullptr;
Quest::QuestJournal* questJournal = nullptr;
const DialogueDefinition* activeDialogue = nullptr;
const StaticCutsceneDefinition* activeCutscene = nullptr;
@@ -89,6 +93,9 @@ private:
bool evaluateConditions(const std::vector<Condition>& conditions) const;
void applyEffects(const std::vector<Effect>& effects);
void applyQuestActions(const std::string& questUnlock, const std::string& questComplete,
const std::string& questFail, const std::string& objectiveComplete,
const std::string& objectiveVisible);
bool enterNode(const std::string& nodeId);
void presentLine(const Node& node);
+3
View File
@@ -2,6 +2,7 @@
#include "dialogue/DialogueOverlay.h"
#include "dialogue/DialogueRuntime.h"
#include "quest/QuestJournal.h"
#include <SDL.h>
#include <functional>
#include <string>
@@ -37,6 +38,8 @@ public:
void setFlag(const std::string& name, int value) { runtime.setFlag(name, value); }
int getFlag(const std::string& name) const { return runtime.getFlag(name); }
void setQuestJournal(Quest::QuestJournal* journal) { runtime.setQuestJournal(journal); }
private:
DialogueDatabase database;
DialogueRuntime runtime;
+14
View File
@@ -99,6 +99,13 @@ struct Node {
// Name of the UI node (StaticImage) to reveal in the phone chat when this line is shown
std::string bubbleSlot;
// Quest actions fired when this line is presented (empty = no action)
std::string questUnlock;
std::string questComplete;
std::string questFail;
std::string objectiveComplete; // "quest_id.objective_id"
std::string objectiveVisible; // "quest_id.objective_id"
};
struct DialogueDefinition {
@@ -120,6 +127,13 @@ struct CutsceneLine {
int backgroundHeight = 0; // 0 = inherit from cutscene
int durationMs = 0;
bool waitForConfirm = false;
// Quest actions fired when this line is shown (empty = no action)
std::string questUnlock;
std::string questComplete;
std::string questFail;
std::string objectiveComplete; // "quest_id.objective_id"
std::string objectiveVisible; // "quest_id.objective_id"
};
struct CutsceneCameraPose {