#include "dialogue/DialogueSystem.h" namespace ZL::Dialogue { bool DialogueSystem::init(Renderer& renderer, const std::string& zipFile) { runtime.setDatabase(&database); return overlay.init(renderer, zipFile); } bool DialogueSystem::loadDatabase(const std::string& path) { return database.loadFromFile(path); } void DialogueSystem::update(int deltaMs, const Eigen::Vector3f& playerPosition) { if (!runtime.isActive()) { for (TriggerZone& zone : triggerZones) { if (zone.once && zone.triggered) { continue; } const Eigen::Vector3f diff = playerPosition - zone.center; if (diff.norm() <= zone.radius) { if (startDialogue(zone.dialogueId)) { zone.triggered = true; break; } } } } runtime.update(deltaMs); const bool autoSkipEligible = skipDialogs && runtime.isActive() && !runtime.isInChoice() && !runtime.isPlayingCutscene(); if (autoSkipEligible) { const PresentationModel& model = runtime.getPresentation(); if (model.mode == PresentationMode::Dialogue) { if (model.fullText != autoSkipTrackedText) { autoSkipTrackedText = model.fullText; autoSkipTimerMs = 0.0f; } if (model.revealCompleted) { autoSkipTimerMs += static_cast(deltaMs); float target = autoSkipConfig.baseDurationMs + autoSkipConfig.msPerCharacter * static_cast(model.fullText.size()); if (target < autoSkipConfig.minDurationMs) { target = autoSkipConfig.minDurationMs; } if (autoSkipTimerMs >= target) { autoSkipTimerMs = 0.0f; autoSkipTrackedText.clear(); runtime.confirmAdvance(); } } } } else { autoSkipTimerMs = 0.0f; autoSkipTrackedText.clear(); } } void DialogueSystem::draw(Renderer& renderer) { overlay.draw(renderer, runtime.getPresentation()); } bool DialogueSystem::handleKeyDown(SDL_Keycode key) { if (!runtime.isActive()) { return false; } switch (key) { case SDLK_RETURN: case SDLK_SPACE: case SDLK_e: runtime.confirmAdvance(); return true; case SDLK_UP: case SDLK_w: runtime.moveSelection(-1); return true; case SDLK_DOWN: case SDLK_s: runtime.moveSelection(1); return true; case SDLK_ESCAPE: stopDialogue(); return true; default: return false; } } void DialogueSystem::handlePointerDown(float x, float y) { if (!runtime.isActive()) { return; } overlay.handlePointerDown(x, y, runtime.getPresentation()); } void DialogueSystem::handlePointerMoved(float x, float y) { if (!runtime.isActive()) { return; } overlay.handlePointerMoved(x, y, runtime.getPresentation()); } bool DialogueSystem::handlePointerReleased(float x, float y) { if (!runtime.isActive()) { return false; } int choiceIndex = -1; bool advanceDialogue = false; const PresentationModel& model = runtime.getPresentation(); if (!overlay.handlePointerReleased(x, y, model, choiceIndex, advanceDialogue)) { return false; } if (choiceIndex >= 0) { runtime.selectChoice(choiceIndex); runtime.confirmAdvance(); return true; } if (advanceDialogue) { runtime.confirmAdvance(); return true; } return true; } bool DialogueSystem::startDialogue(const std::string& dialogueId, std::function onFinished) { return runtime.startDialogue(dialogueId, std::move(onFinished)); } void DialogueSystem::stopDialogue() { runtime.stop(); } void DialogueSystem::addTriggerZone(const TriggerZone& zone) { triggerZones.push_back(zone); } void DialogueSystem::clearTriggerZones() { triggerZones.clear(); } } // namespace ZL::Dialogue