Dialog fixing

This commit is contained in:
Vladislav Khorev 2026-05-22 22:32:05 +03:00
parent 8c200974c2
commit 84c8a7a27a
13 changed files with 169 additions and 43 deletions

View File

@ -55,6 +55,7 @@
{ {
"id": "aiperi_dialog001", "id": "aiperi_dialog001",
"start": "line_1", "start": "line_1",
"uninterruptible": true,
"nodes": [ "nodes": [
{ {
"id": "line_1", "id": "line_1",
@ -325,6 +326,7 @@
{ {
"id": "teacher_dialog002", "id": "teacher_dialog002",
"start": "line_1", "start": "line_1",
"uninterruptible": true,
"nodes": [ "nodes": [
{ {
"id": "line_1", "id": "line_1",
@ -475,6 +477,7 @@
{ {
"id": "teacher_dialog005", "id": "teacher_dialog005",
"start": "line_1", "start": "line_1",
"uninterruptible": true,
"nodes": [ "nodes": [
{ {
"id": "line_1", "id": "line_1",
@ -513,7 +516,7 @@
"type": "Line", "type": "Line",
"speaker": "Аида Дженибековна", "speaker": "Аида Дженибековна",
"portrait": "resources/w/avatar_teacher.png", "portrait": "resources/w/avatar_teacher.png",
"text": "Вот держи зачетку с оценкой, положи ее обратно в шкаф.", "text": "Вот держи зачетку с оценкой.",
"next": "line_6" "next": "line_6"
}, },
{ {
@ -521,7 +524,7 @@
"type": "Line", "type": "Line",
"speaker": "Бекзат", "speaker": "Бекзат",
"portrait": "resources/w/gg/gg2_s_podsvetkoy5.png", "portrait": "resources/w/gg/gg2_s_podsvetkoy5.png",
"text": "Хорошо!", "text": "Спасибо!",
"next": "end_1" "next": "end_1"
}, },
{ {
@ -610,6 +613,7 @@
}, },
{ {
"id": "dialog_with_ghost001", "id": "dialog_with_ghost001",
"uninterruptible": true,
"start": "line_1", "start": "line_1",
"nodes": [ "nodes": [
{ {
@ -678,6 +682,7 @@
}, },
{ {
"id": "end_1", "id": "end_1",
"luaCallback" : "on_first_ghost_dialog_over",
"type": "End" "type": "End"
} }
] ]
@ -786,6 +791,7 @@
}, },
{ {
"id": "end_1", "id": "end_1",
"luaCallback" : "on_quest_over",
"type": "End" "type": "End"
} }
] ]
@ -1061,10 +1067,9 @@
] ]
}, },
{ {
"id": "test_cutscene_02", "id": "computer_cutscene001",
"background": "resources/black.png", "onFadeInCallback": "on_sleep_cutscene",
"backgroundWidth" : 1280, "background": "resources/test_cutscene001.png",
"backgroundHeight" : 720,
"durationMs": 5000, "durationMs": 5000,
"fadeOutMs": 500, "fadeOutMs": 500,
"fadeInMs": 500, "fadeInMs": 500,
@ -1108,9 +1113,8 @@
}, },
{ {
"id": "darklands_exit001", "id": "darklands_exit001",
"background": "resources/black.png", "onFadeInCallback": "on_darklands_over",
"backgroundWidth" : 1280, "background": "resources/test_cutscene001.png",
"backgroundHeight" : 720,
"durationMs": 5000, "durationMs": 5000,
"fadeOutMs": 500, "fadeOutMs": 500,
"fadeInMs": 500, "fadeInMs": 500,

View File

@ -25,6 +25,7 @@ function lection_hall_zone001_enter_callback()
--game_api.start_dialogue("") --game_api.start_dialogue("")
--Start cutscene --Start cutscene
if (lection_is_over == false) then if (lection_is_over == false) then
game_api.player_stop()
game_api.start_cutscene("test_cutscene_01") game_api.start_cutscene("test_cutscene_01")
end end
end end
@ -180,25 +181,38 @@ function on_npc_interact(npc_index)
local report_card_signed = game_api.getIntValue("report_card_signed") local report_card_signed = game_api.getIntValue("report_card_signed")
if (report_card_signed==1) then if (report_card_signed==1) then
game_api.start_dialogue("dialog_with_ghost003") game_api.start_dialogue("dialog_with_ghost003")
ghost_gone = true
game_api.set_npc_enabled(2, false)
game_api.set_npc_enabled(3, false)
game_api.set_npc_enabled(4, false)
game_api.set_npc_enabled(5, false)
else else
game_api.start_dialogue("dialog_with_ghost002") game_api.start_dialogue("dialog_with_ghost002")
end end
else else
game_api.start_dialogue("dialog_with_ghost001") game_api.start_dialogue("dialog_with_ghost001")
end
end
end
function on_quest_over()
ghost_gone = true
game_api.set_npc_enabled(2, false)
game_api.set_npc_enabled(3, false)
game_api.set_npc_enabled(4, false)
game_api.set_npc_enabled(5, false)
end
function on_first_ghost_dialog_over()
player_ghost_aware = true player_ghost_aware = true
end end
end
function on_darklands_over()
game_api.set_player_hp(10)
game_api.resetPlayerAfterDeath()
end end
function teacher_zone001_enter_callback() function teacher_zone001_enter_callback()
game_api.start_dialogue("teacher_dialog002") game_api.start_dialogue("teacher_dialog002")
game_api.set_trigger_zone_enabled(2, false) game_api.set_trigger_zone_enabled(2, false)
teacher_told_about_book = true teacher_told_about_book = true
game_api.player_stop()
end end
function on_library_door_click() function on_library_door_click()
@ -406,7 +420,7 @@ print("on_computer_clicked--")
print("on_computer_clicked--3") print("on_computer_clicked--3")
if (player_hold_book) then if (player_hold_book) then
print("on_computer_clicked--4") print("on_computer_clicked--4")
game_api.start_cutscene("test_cutscene_02") game_api.start_cutscene("computer_cutscene001")
else else
print("on_computer_clicked--5") print("on_computer_clicked--5")
game_api.start_dialogue("book_dialog002") game_api.start_dialogue("book_dialog002")
@ -422,25 +436,7 @@ print("on_computer_clicked--")
end end
end end
function on_teacher_arrived_intermediate() function on_sleep_cutscene()
game_api.rotate_object("Room_N_2_Leaf001", -90, 0.5, nil)
game_api.fade_object("Room_Cover_North_3_001", 0, 0.5, function()
game_api.deactivate_interactive_object("Room_Cover_North_3_001")
end)
game_api.switch_navigation(2)
game_api.npc_walk_to(0, 3.19574, 0, 6.45595, on_teacher_arrived)
teacher_arrived = true
end
game_api.set_cutscene_callback("test_cutscene_01", function()
print("Cutscene done!")
lection_is_over = true
game_api.set_npc_enabled(1, true)
game_api.npc_walk_to(0, 0.758123, 0, 6.50063, on_teacher_arrived_intermediate)
end)
game_api.set_cutscene_callback("test_cutscene_02", function()
print("Cutscene 2 done!") print("Cutscene 2 done!")
night_time = true night_time = true
--game_api.set_trigger_zone_enabled(1, false) --game_api.set_trigger_zone_enabled(1, false)
@ -462,9 +458,27 @@ game_api.set_cutscene_callback("test_cutscene_02", function()
game_api.set_object_alpha("Room_Cover_North_1_001", 1) game_api.set_object_alpha("Room_Cover_North_1_001", 1)
game_api.set_object_alpha("Room_Cover_Main_Hall_001", 1) game_api.set_object_alpha("Room_Cover_Main_Hall_001", 1)
game_api.activate_interactive_object("Note001") game_api.activate_interactive_object("Note001")
end
function on_teacher_arrived_intermediate()
game_api.rotate_object("Room_N_2_Leaf001", -90, 0.5, nil)
game_api.fade_object("Room_Cover_North_3_001", 0, 0.5, function()
game_api.deactivate_interactive_object("Room_Cover_North_3_001")
end)
game_api.switch_navigation(2)
game_api.npc_walk_to(0, 3.19574, 0, 6.45595, on_teacher_arrived)
teacher_arrived = true
end
game_api.set_cutscene_callback("test_cutscene_01", function()
print("Cutscene done!")
lection_is_over = true
game_api.set_npc_enabled(1, true)
game_api.npc_walk_to(0, 0.758123, 0, 6.50063, on_teacher_arrived_intermediate)
end) end)
function on_note_pickup() function on_note_pickup()
game_api.start_dialogue("note_dialog001") game_api.start_dialogue("note_dialog001")
game_api.pickup_item("note_spell") game_api.pickup_item("note_spell")
@ -542,11 +556,9 @@ game_api.set_darklands_callbacks(
game_api.set_npc_enabled(5, false) game_api.set_npc_enabled(5, false)
game_api.setIntValue("day", 1) game_api.setIntValue("day", 1)
game_api.setIntValue("need_sleep", 1) game_api.setIntValue("need_sleep", 1)
game_api.set_player_hp(10)
player_left_darklands = true player_left_darklands = true
morning_did_open_door_index = 0 morning_did_open_door_index = 0
setDay1MorningSetup() setDay1MorningSetup()
--game_api.switch_navigation(7)
local px = game_api.get_player_x() local px = game_api.get_player_x()

View File

@ -104,6 +104,19 @@ void Character::stopInPlace()
onArrivedCallback = nullptr; onArrivedCallback = nullptr;
} }
void Character::resetPlayerAfterDeath()
{
if (!isPlayer)
{
return;
}
currentState = AnimationState::STAND;
resetAnim = true;
showWeapon = false;
battle_state = 0;
attack = 0;
}
void Character::forceReplan() void Character::forceReplan()
{ {
if (!pathPlanner) { if (!pathPlanner) {
@ -456,11 +469,6 @@ void Character::update(int64_t deltaMs) {
//onDeathAnimComplete = nullptr; //onDeathAnimComplete = nullptr;
onDeathAnimComplete(); onDeathAnimComplete();
//TODO: need to add some delay here //TODO: need to add some delay here
currentState = AnimationState::STAND;
resetAnim = true;
showWeapon = false;
battle_state = 0;
attack = 0;
} }
} }
} }

View File

@ -66,6 +66,8 @@ public:
// character and we don't want it to walk back to where it was. // character and we don't want it to walk back to where it was.
void stopInPlace(); void stopInPlace();
void resetPlayerAfterDeath();
// attackDirection is a world-space horizontal vector pointing from the // attackDirection is a world-space horizontal vector pointing from the
// attacker toward this character — i.e. the direction the hit pushes // attacker toward this character — i.e. the direction the hit pushes

View File

@ -195,7 +195,6 @@ namespace ZL
uniInteriorParams.npcsJsonPath = "resources/config2/npcs_uni_interior.json"; uniInteriorParams.npcsJsonPath = "resources/config2/npcs_uni_interior.json";
uniInteriorParams.dialoguesJsonPath = "resources/dialogue/uni_interior_dialogues.json"; uniInteriorParams.dialoguesJsonPath = "resources/dialogue/uni_interior_dialogues.json";
uniInteriorParams.navigationJsonPaths = { uniInteriorParams.navigationJsonPaths = {
"resources/navigation/uni_interior0_all_locked.txt", "resources/navigation/uni_interior0_all_locked.txt",
"resources/navigation/uni_interior0_hall.txt", "resources/navigation/uni_interior0_hall.txt",

View File

@ -146,6 +146,25 @@ namespace ZL
scriptEngine.callCutsceneCompleteCallback(cutsceneId); scriptEngine.callCutsceneCompleteCallback(cutsceneId);
}); });
dialogueSystem.setOnDialogueLineStarted([this](const std::string& fn) {
try { scriptEngine.callActivateFunction(fn); }
catch (const std::exception& e) {
std::cerr << "[dialogue] line callback error: " << e.what() << "\n";
}
});
dialogueSystem.setOnCutsceneLineStarted([this](const std::string& fn) {
try { scriptEngine.callActivateFunction(fn); }
catch (const std::exception& e) {
std::cerr << "[cutscene] line callback error: " << e.what() << "\n";
}
});
dialogueSystem.setOnCutsceneFadeInComplete([this](const std::string& fn) {
try { scriptEngine.callActivateFunction(fn); }
catch (const std::exception& e) {
std::cerr << "[cutscene] fade-in callback error: " << e.what() << "\n";
}
});
} }
void Location::loadTeleportZones(const std::string& jsonPath, const char* zipFile) void Location::loadTeleportZones(const std::string& jsonPath, const char* zipFile)

View File

@ -460,6 +460,11 @@ namespace ZL {
std::cerr << "[script] scale_object: object '" << name << "' not found\n"; std::cerr << "[script] scale_object: object '" << name << "' not found\n";
}); });
api.set_function("resetPlayerAfterDeath",
[game]() {
if (game->player) game->player->resetPlayerAfterDeath();
});
// player_stop() — cancels the player's current walk target and stops them immediately. // player_stop() — cancels the player's current walk target and stops them immediately.
api.set_function("player_stop", api.set_function("player_stop",
[game]() { [game]() {

View File

@ -104,6 +104,7 @@ Node DialogueDatabase::parseNode(const json& j) {
node.trueNext = j.value("trueNext", ""); node.trueNext = j.value("trueNext", "");
node.falseNext = j.value("falseNext", ""); node.falseNext = j.value("falseNext", "");
node.cutsceneId = j.value("cutsceneId", ""); node.cutsceneId = j.value("cutsceneId", "");
node.luaCallback = j.value("luaCallback", "");
if (j.contains("conditions") && j["conditions"].is_array()) { if (j.contains("conditions") && j["conditions"].is_array()) {
for (const auto& item : j["conditions"]) { for (const auto& item : j["conditions"]) {
@ -129,6 +130,7 @@ DialogueDefinition DialogueDatabase::parseDialogue(const json& j) {
result.id = j.value("id", ""); result.id = j.value("id", "");
result.displayName = j.value("displayName", result.id); result.displayName = j.value("displayName", result.id);
result.startNode = j.value("start", ""); result.startNode = j.value("start", "");
result.uninterruptible = j.value("uninterruptible", false);
if (j.contains("nodes") && j["nodes"].is_array()) { if (j.contains("nodes") && j["nodes"].is_array()) {
for (const auto& item : j["nodes"]) { for (const auto& item : j["nodes"]) {
@ -151,6 +153,7 @@ CutsceneLine DialogueDatabase::parseCutsceneLine(const json& j) {
line.background = j.value("background", ""); line.background = j.value("background", "");
line.backgroundWidth = j.value("backgroundWidth", 0); line.backgroundWidth = j.value("backgroundWidth", 0);
line.backgroundHeight = j.value("backgroundHeight", 0); line.backgroundHeight = j.value("backgroundHeight", 0);
line.luaCallback = j.value("luaCallback", "");
line.durationMs = j.value("durationMs", 0); line.durationMs = j.value("durationMs", 0);
line.waitForConfirm = j.value("waitForConfirm", false); line.waitForConfirm = j.value("waitForConfirm", false);
return line; return line;
@ -205,6 +208,7 @@ StaticCutsceneDefinition DialogueDatabase::parseCutscene(const json& j) {
cutscene.fadeInMs = j.value("fadeInMs", 0); cutscene.fadeInMs = j.value("fadeInMs", 0);
cutscene.endFadeOutMs = j.value("endFadeOutMs", 0); cutscene.endFadeOutMs = j.value("endFadeOutMs", 0);
cutscene.endFadeInMs = j.value("endFadeInMs", 0); cutscene.endFadeInMs = j.value("endFadeInMs", 0);
cutscene.onFadeInCallback = j.value("onFadeInCallback", "");
if (j.contains("cameraTrack") && j["cameraTrack"].is_array()) { if (j.contains("cameraTrack") && j["cameraTrack"].is_array()) {
for (const auto& item : j["cameraTrack"]) { for (const auto& item : j["cameraTrack"]) {

View File

@ -16,6 +16,11 @@ bool DialogueRuntime::startDialogue(const std::string& dialogueId) {
return false; return false;
} }
if (mode != Mode::Inactive && activeDialogue && activeDialogue->uninterruptible) {
std::cerr << "[dialogue] Blocked: '" << activeDialogue->id << "' is uninterruptible\n";
return false;
}
const DialogueDefinition* dialogue = database->findDialogue(dialogueId); const DialogueDefinition* dialogue = database->findDialogue(dialogueId);
if (!dialogue) { if (!dialogue) {
std::cerr << "[dialogue] Dialogue not found: " << dialogueId << "\n"; std::cerr << "[dialogue] Dialogue not found: " << dialogueId << "\n";
@ -35,6 +40,7 @@ bool DialogueRuntime::startDialogue(const std::string& dialogueId) {
cutsceneTotalDurationMs = 0; cutsceneTotalDurationMs = 0;
cutsceneContentDurationMs = 0; cutsceneContentDurationMs = 0;
currentCutsceneBackground.clear(); currentCutsceneBackground.clear();
fadeInCallbackFired = false;
presentation = {}; presentation = {};
presentation.dialogueId = dialogue->id; presentation.dialogueId = dialogue->id;
@ -53,6 +59,7 @@ bool DialogueRuntime::startStandaloneCutscene(const std::string& cutsceneId) {
} }
activeDialogue = nullptr; activeDialogue = nullptr;
activeCutsceneId = cutsceneId; activeCutsceneId = cutsceneId;
fadeInCallbackFired = false;
presentation = {}; presentation = {};
startCutscene(cutsceneId, ""); startCutscene(cutsceneId, "");
return true; return true;
@ -62,6 +69,18 @@ void DialogueRuntime::setOnCutsceneFinished(std::function<void(const std::string
onCutsceneFinished = std::move(cb); onCutsceneFinished = std::move(cb);
} }
void DialogueRuntime::setOnDialogueLineStarted(std::function<void(const std::string&)> cb) {
onDialogueLineStarted = std::move(cb);
}
void DialogueRuntime::setOnCutsceneLineStarted(std::function<void(const std::string&)> cb) {
onCutsceneLineStarted = std::move(cb);
}
void DialogueRuntime::setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb) {
onCutsceneFadeInComplete = std::move(cb);
}
void DialogueRuntime::stop() { void DialogueRuntime::stop() {
activeDialogue = nullptr; activeDialogue = nullptr;
activeCutscene = nullptr; activeCutscene = nullptr;
@ -76,6 +95,7 @@ void DialogueRuntime::stop() {
cutsceneTotalDurationMs = 0; cutsceneTotalDurationMs = 0;
cutsceneContentDurationMs = 0; cutsceneContentDurationMs = 0;
currentCutsceneBackground.clear(); currentCutsceneBackground.clear();
fadeInCallbackFired = false;
mode = Mode::Inactive; mode = Mode::Inactive;
presentation = {}; presentation = {};
} }
@ -128,6 +148,18 @@ void DialogueRuntime::update(int deltaMs) {
return; return;
} }
if (!fadeInCallbackFired && onCutsceneFadeInComplete && activeCutscene) {
const int fadeInCompleteMs = activeCutscene->fadeOutMs + activeCutscene->fadeInMs;
if (cutsceneElapsedMs >= fadeInCompleteMs && !activeCutscene->onFadeInCallback.empty()) {
fadeInCallbackFired = true;
onCutsceneFadeInComplete(activeCutscene->onFadeInCallback);
}
}
if (!activeCutscene || mode != Mode::PlayingCutscene) {
return;
}
const bool subtitlesFinished = const bool subtitlesFinished =
activeCutscene->lines.empty() || activeCutscene->lines.empty() ||
currentCutsceneLine >= static_cast<int>(activeCutscene->lines.size()); currentCutsceneLine >= static_cast<int>(activeCutscene->lines.size());
@ -395,6 +427,10 @@ void DialogueRuntime::presentLine(const Node& node) {
presentation.visibleText = node.text; presentation.visibleText = node.text;
revealCharacters = static_cast<float>(node.text.size()); revealCharacters = static_cast<float>(node.text.size());
} }
if (!node.luaCallback.empty() && onDialogueLineStarted) {
onDialogueLineStarted(node.luaCallback);
}
} }
void DialogueRuntime::presentChoices(const Node& node) { void DialogueRuntime::presentChoices(const Node& node) {
@ -464,6 +500,7 @@ void DialogueRuntime::startCutscene(const std::string& cutsceneId, const std::st
mode = Mode::PlayingCutscene; mode = Mode::PlayingCutscene;
cutsceneElapsedMs = 0; cutsceneElapsedMs = 0;
cutsceneTimerMs = 0; cutsceneTimerMs = 0;
fadeInCallbackFired = false;
currentCutsceneLine = activeCutscene->lines.empty() ? -1 : 0; currentCutsceneLine = activeCutscene->lines.empty() ? -1 : 0;
int imageTrackDurationMs = 0; int imageTrackDurationMs = 0;
for (size_t i = 0; i < activeCutscene->images.size(); ++i) { for (size_t i = 0; i < activeCutscene->images.size(); ++i) {
@ -486,6 +523,11 @@ void DialogueRuntime::startCutscene(const std::string& cutsceneId, const std::st
cutsceneTotalDurationMs = cutsceneContentDurationMs + activeCutscene->endFadeOutMs + activeCutscene->endFadeInMs; cutsceneTotalDurationMs = cutsceneContentDurationMs + activeCutscene->endFadeOutMs + activeCutscene->endFadeInMs;
refreshCutscenePresentation(); refreshCutscenePresentation();
if (!activeCutscene->lines.empty() && onCutsceneLineStarted) {
const std::string& cb = activeCutscene->lines[0].luaCallback;
if (!cb.empty()) onCutsceneLineStarted(cb);
}
std::cout << "[CUTSCENE] start id=" << cutsceneId std::cout << "[CUTSCENE] start id=" << cutsceneId
<< " lines=" << activeCutscene->lines.size() << " lines=" << activeCutscene->lines.size()
<< " totalDuration=" << cutsceneTotalDurationMs << " totalDuration=" << cutsceneTotalDurationMs
@ -572,6 +614,11 @@ void DialogueRuntime::advanceCutsceneLine() {
return; return;
} }
if (onCutsceneLineStarted) {
const std::string& cb = activeCutscene->lines[currentCutsceneLine].luaCallback;
if (!cb.empty()) onCutsceneLineStarted(cb);
}
refreshCutscenePresentation(); refreshCutscenePresentation();
} }

View File

@ -19,6 +19,9 @@ public:
bool startDialogue(const std::string& dialogueId); bool startDialogue(const std::string& dialogueId);
bool startStandaloneCutscene(const std::string& cutsceneId); bool startStandaloneCutscene(const std::string& cutsceneId);
void setOnCutsceneFinished(std::function<void(const std::string&)> cb); void setOnCutsceneFinished(std::function<void(const std::string&)> cb);
void setOnDialogueLineStarted(std::function<void(const std::string&)> cb);
void setOnCutsceneLineStarted(std::function<void(const std::string&)> cb);
void setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb);
void stop(); void stop();
void update(int deltaMs); void update(int deltaMs);
@ -50,7 +53,11 @@ private:
}; };
std::function<void(const std::string&)> onCutsceneFinished; std::function<void(const std::string&)> onCutsceneFinished;
std::function<void(const std::string&)> onDialogueLineStarted;
std::function<void(const std::string&)> onCutsceneLineStarted;
std::function<void(const std::string&)> onCutsceneFadeInComplete;
std::string activeCutsceneId; std::string activeCutsceneId;
bool fadeInCallbackFired = false;
const DialogueDatabase* database = nullptr; const DialogueDatabase* database = nullptr;
const DialogueDefinition* activeDialogue = nullptr; const DialogueDefinition* activeDialogue = nullptr;

View File

@ -127,6 +127,18 @@ void DialogueSystem::setOnCutsceneFinished(std::function<void(const std::string&
runtime.setOnCutsceneFinished(std::move(cb)); runtime.setOnCutsceneFinished(std::move(cb));
} }
void DialogueSystem::setOnDialogueLineStarted(std::function<void(const std::string&)> cb) {
runtime.setOnDialogueLineStarted(std::move(cb));
}
void DialogueSystem::setOnCutsceneLineStarted(std::function<void(const std::string&)> cb) {
runtime.setOnCutsceneLineStarted(std::move(cb));
}
void DialogueSystem::setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb) {
runtime.setOnCutsceneFadeInComplete(std::move(cb));
}
void DialogueSystem::stopDialogue() { void DialogueSystem::stopDialogue() {
runtime.stop(); runtime.stop();
} }

View File

@ -24,6 +24,9 @@ public:
bool startDialogue(const std::string& dialogueId); bool startDialogue(const std::string& dialogueId);
bool startCutscene(const std::string& cutsceneId); bool startCutscene(const std::string& cutsceneId);
void setOnCutsceneFinished(std::function<void(const std::string&)> cb); void setOnCutsceneFinished(std::function<void(const std::string&)> cb);
void setOnDialogueLineStarted(std::function<void(const std::string&)> cb);
void setOnCutsceneLineStarted(std::function<void(const std::string&)> cb);
void setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb);
void stopDialogue(); void stopDialogue();
bool isActive() const { return runtime.isActive(); } bool isActive() const { return runtime.isActive(); }

View File

@ -83,6 +83,7 @@ struct Node {
std::string text; std::string text;
std::string portrait; std::string portrait;
std::string next; std::string next;
std::string luaCallback;
// For Condition nodes // For Condition nodes
std::string trueNext; std::string trueNext;
@ -101,6 +102,7 @@ struct DialogueDefinition {
std::string id; std::string id;
std::string displayName; std::string displayName;
std::string startNode; std::string startNode;
bool uninterruptible = false;
std::unordered_map<std::string, Node> nodes; std::unordered_map<std::string, Node> nodes;
}; };
@ -110,6 +112,7 @@ struct CutsceneLine {
std::string portrait; std::string portrait;
std::string sfx; std::string sfx;
std::string background; std::string background;
std::string luaCallback;
int backgroundWidth = 0; // 0 = inherit from cutscene int backgroundWidth = 0; // 0 = inherit from cutscene
int backgroundHeight = 0; // 0 = inherit from cutscene int backgroundHeight = 0; // 0 = inherit from cutscene
int durationMs = 0; int durationMs = 0;
@ -151,6 +154,7 @@ struct StaticCutsceneDefinition {
int backgroundWidth = 1280; int backgroundWidth = 1280;
int backgroundHeight = 720; int backgroundHeight = 720;
std::string music; std::string music;
std::string onFadeInCallback;
bool skippable = true; bool skippable = true;
int durationMs = 0; int durationMs = 0;
int fadeOutMs = 0; int fadeOutMs = 0;