Added startup scripts
This commit is contained in:
1 parent
a479fa4ac1
commit
13ef92160d
26 files changed
+117164
-150
No files matched your search
+9
-8
@@ -164,8 +164,9 @@ namespace ZL
|
||||
params1.gameObjectsJsonPath = "resources/config2/gameobjects.json";
|
||||
params1.npcsJsonPath = "resources/config2/npcs.json";
|
||||
params1.dialoguesJsonPath = "resources/dialogue/sample_dialogues.json";
|
||||
params1.navigationJsonPath = "resources/config2/navigation.json";
|
||||
params1.navigationJsonPaths = {"resources/config2/navigation.json"};
|
||||
params1.teleportsJsonPath = "resources/config2/teleports.json";
|
||||
params1.triggerZonesJsonPath = "resources/config2/trigger_zones.json";
|
||||
params1.scriptPath = "resources/start.lua";
|
||||
params1.playerPosition = Eigen::Vector3f(0.942694, 0, -9.63104);
|
||||
|
||||
@@ -176,8 +177,9 @@ namespace ZL
|
||||
params2.roomMeshPath = "resources/w/exterior/Segmented_Plane002.txt";
|
||||
params2.roomTexturePath = "resources/w/exterior/Segmented_Plane002.png";
|
||||
params2.gameObjectsJsonPath = "resources/config2/gameobjects2.json";
|
||||
params2.navigationJsonPath = "resources/config2/navigation2.json";
|
||||
params2.navigationJsonPaths = {"resources/config2/navigation2.json"};
|
||||
params2.teleportsJsonPath = "resources/config2/teleports2.json";
|
||||
params2.triggerZonesJsonPath = "resources/config2/trigger_zones2.json";
|
||||
params2.scriptPath = "resources/start2.lua";
|
||||
params2.playerPosition = Eigen::Vector3f(5, 0, -18.4);
|
||||
params2.npcsJsonPath = "resources/config2/npcs2.json";
|
||||
@@ -191,11 +193,11 @@ namespace ZL
|
||||
params_dorm.gameObjectsJsonPath = "resources/config2/gameobjects_dorm.json";
|
||||
params_dorm.npcsJsonPath = "resources/config2/npcs_dorm.json";
|
||||
params_dorm.dialoguesJsonPath = "resources/dialogue/dorm_dialogues.json";
|
||||
params_dorm.navigationJsonPath = "resources/config2/navigation_dorm.json";
|
||||
params_dorm.navigationJsonPaths = {"resources/config2/navigation_dorm.json", "resources/config2/navigation_dorm_tutorial001.json" };
|
||||
params_dorm.teleportsJsonPath = "resources/config2/teleports_dorm.json";
|
||||
params_dorm.triggerZonesJsonPath = "resources/config2/trigger_zones_dorm.json";
|
||||
params_dorm.scriptPath = "resources/start_dorm.lua";
|
||||
params_dorm.playerPosition = Eigen::Vector3f(6.0357, 0, -16.0581);
|
||||
|
||||
params_dorm.playerPosition = Eigen::Vector3f(6.76345, 0, -14.6022);
|
||||
|
||||
locations["location_dorm"] = std::make_shared<Location>(renderer, inventory);
|
||||
locations["location_dorm"]->setup(params_dorm);
|
||||
@@ -534,15 +536,14 @@ namespace ZL
|
||||
case SDLK_o:
|
||||
//y = y + 0.002;
|
||||
//currentLocation->player->hp = 200;
|
||||
currentLocation->npcs[0]->walkSpeed += 0.02f;
|
||||
currentLocation->npcs[0]->walkSpeed += 0.01f;
|
||||
std::cout << "Walk speed: " << currentLocation->npcs[0]->walkSpeed << std::endl;
|
||||
|
||||
break;
|
||||
|
||||
case SDLK_k:
|
||||
//y = y - 0.002;
|
||||
std::cout << "Player pos: " << currentLocation->player->position.transpose() << std::endl;
|
||||
currentLocation->npcs[0]->walkSpeed -= 0.02f;
|
||||
currentLocation->npcs[0]->walkSpeed -= 0.01f;
|
||||
std::cout << "Walk speed: " << currentLocation->npcs[0]->walkSpeed << std::endl;
|
||||
break;
|
||||
|
||||
|
||||
+120
-22
@@ -137,6 +137,7 @@ namespace ZL
|
||||
}
|
||||
|
||||
loadTeleportZones(params.teleportsJsonPath, CONST_ZIP_FILE);
|
||||
loadTriggerZones(params.triggerZonesJsonPath, CONST_ZIP_FILE);
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
// Create shadow map (2048x2048, ortho size 40, near 0.1, far 100)
|
||||
@@ -145,7 +146,7 @@ namespace ZL
|
||||
std::cout << "Shadow map initialized" << std::endl;
|
||||
#endif
|
||||
|
||||
setupNavigation(params.navigationJsonPath);
|
||||
setupNavigation(params.navigationJsonPaths);
|
||||
|
||||
dialogueSystem.init(renderer, CONST_ZIP_FILE);
|
||||
dialogueSystem.loadDatabase(params.dialoguesJsonPath);
|
||||
@@ -165,7 +166,7 @@ namespace ZL
|
||||
false
|
||||
});*/
|
||||
|
||||
navigationEditorConfigPath = params.navigationJsonPath;
|
||||
// navigationMapPaths is already populated by setupNavigation
|
||||
|
||||
scriptEngine.init(this, &inventory, params.scriptPath);
|
||||
|
||||
@@ -231,13 +232,84 @@ namespace ZL
|
||||
std::cout << "[TELEPORT] Loaded " << teleportZones.size() << " teleport(s) from " << jsonPath << std::endl;
|
||||
}
|
||||
|
||||
void Location::setupNavigation(const std::string& navigationJsonPath)
|
||||
void Location::loadTriggerZones(const std::string& jsonPath, const char* zipFile)
|
||||
{
|
||||
// Static navigation blockers are defined in the navigation JSON as polygons.
|
||||
// NPC + player are handled as dynamic obstacles, so they are intentionally NOT in JSON.
|
||||
navigation.build({}, navigationJsonPath, CONST_ZIP_FILE);
|
||||
if (jsonPath.empty()) return;
|
||||
|
||||
if (navigationEditorMode) {
|
||||
std::string content;
|
||||
try {
|
||||
if (!zipFile || zipFile[0] == '\0') {
|
||||
content = readTextFile(jsonPath);
|
||||
} else {
|
||||
auto buf = readFileFromZIP(jsonPath, zipFile);
|
||||
if (buf.empty()) {
|
||||
std::cerr << "[TRIGGER] Failed to read " << jsonPath << " from zip" << std::endl;
|
||||
return;
|
||||
}
|
||||
content.assign(buf.begin(), buf.end());
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "[TRIGGER] Failed to open " << jsonPath << ": " << e.what() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
using json = nlohmann::json;
|
||||
json j;
|
||||
try {
|
||||
j = json::parse(content);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "[TRIGGER] JSON parse error in " << jsonPath << ": " << e.what() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!j.contains("trigger_zones") || !j["trigger_zones"].is_array()) return;
|
||||
|
||||
for (const auto& item : j["trigger_zones"]) {
|
||||
TriggerZone tz;
|
||||
tz.id = item.value("id", "");
|
||||
tz.enabled = item.value("enabled", true);
|
||||
tz.radius = item.value("radius", 1.5f);
|
||||
tz.hysteresis = item.value("hysteresis", 0.3f);
|
||||
tz.position = Eigen::Vector3f(
|
||||
item.value("positionX", 0.0f),
|
||||
item.value("positionY", 0.0f),
|
||||
item.value("positionZ", 0.0f)
|
||||
);
|
||||
triggerZones.push_back(std::move(tz));
|
||||
}
|
||||
|
||||
std::cout << "[TRIGGER] Loaded " << triggerZones.size() << " trigger zone(s) from " << jsonPath << std::endl;
|
||||
}
|
||||
|
||||
void Location::updateTriggerZones(const Eigen::Vector3f& playerPos)
|
||||
{
|
||||
for (auto& tz : triggerZones) {
|
||||
if (!tz.enabled) continue;
|
||||
const float dist = (playerPos - tz.position).norm();
|
||||
if (!tz.playerInside && dist <= tz.radius) {
|
||||
tz.playerInside = true;
|
||||
scriptEngine.callTriggerEnterCallback(tz.id);
|
||||
} else if (tz.playerInside && dist > tz.radius + tz.hysteresis) {
|
||||
tz.playerInside = false;
|
||||
scriptEngine.callTriggerExitCallback(tz.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Location::setupNavigation(const std::vector<std::string>& paths)
|
||||
{
|
||||
navigationMapPaths = paths;
|
||||
navigationMaps.clear();
|
||||
navigationMaps.resize(paths.size());
|
||||
|
||||
for (size_t i = 0; i < paths.size(); ++i) {
|
||||
navigationMaps[i].build({}, paths[i], CONST_ZIP_FILE);
|
||||
}
|
||||
|
||||
activeNavigationIndex = 0;
|
||||
navigation = navigationMaps.empty() ? nullptr : &navigationMaps[0];
|
||||
|
||||
if (navigationEditorMode && navigation) {
|
||||
navigationEditorBuildNavMeshes();
|
||||
}
|
||||
|
||||
@@ -245,6 +317,7 @@ namespace ZL
|
||||
|
||||
auto makePlanner = [this](const Character* self) {
|
||||
return [this, self](const Eigen::Vector3f& start, const Eigen::Vector3f& end) {
|
||||
if (!navigation) return std::vector<Eigen::Vector3f>{};
|
||||
std::vector<PathFinder::DynamicObstacle> dynamicObstacles;
|
||||
dynamicObstacles.reserve(npcs.size() + 1);
|
||||
|
||||
@@ -257,7 +330,7 @@ namespace ZL
|
||||
}
|
||||
|
||||
PathFinder::DynamicObstacle obs;
|
||||
obs.position = Eigen::Vector3f(other->position.x(), navigation.getFloorY(), other->position.z());
|
||||
obs.position = Eigen::Vector3f(other->position.x(), navigation->getFloorY(), other->position.z());
|
||||
obs.radius = (std::max)(0.0f, other->collisionRadius);
|
||||
dynamicObstacles.push_back(obs);
|
||||
};
|
||||
@@ -267,7 +340,7 @@ namespace ZL
|
||||
addCharacter(npc.get());
|
||||
}
|
||||
|
||||
return navigation.findPath(start, end, dynamicObstacles);
|
||||
return navigation->findPath(start, end, dynamicObstacles);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -282,12 +355,35 @@ namespace ZL
|
||||
}
|
||||
}
|
||||
|
||||
bool Location::switchNavigation(int index)
|
||||
{
|
||||
if (index < 0 || index >= static_cast<int>(navigationMaps.size())) {
|
||||
std::cerr << "[NAV] switchNavigation: index " << index << " out of range\n";
|
||||
return false;
|
||||
}
|
||||
activeNavigationIndex = index;
|
||||
navigation = &navigationMaps[index];
|
||||
|
||||
// Force all characters to replan their paths against the new nav map.
|
||||
if (player) player->forceReplan();
|
||||
for (auto& npc : npcs) {
|
||||
if (npc) npc->forceReplan();
|
||||
}
|
||||
|
||||
if (navigationEditorMode) {
|
||||
navigationEditorBuildNavMeshes();
|
||||
}
|
||||
std::cout << "[NAV] Switched to navigation map " << index << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
void Location::navigationEditorBuildNavMeshes()
|
||||
{
|
||||
navigationEditorNavMeshes.clear();
|
||||
const float y = navigation.getFloorY() + 0.02f;
|
||||
if (!navigation) return;
|
||||
const float y = navigation->getFloorY() + 0.02f;
|
||||
const Eigen::Vector3f red(1.0f, 0.0f, 0.0f);
|
||||
for (const auto& obs : navigation.getObstaclePolygons()) {
|
||||
for (const auto& obs : navigation->getObstaclePolygons()) {
|
||||
if (obs.polygon.size() < 3) continue;
|
||||
VertexRenderStruct mesh;
|
||||
mesh.data = CreatePolygonFloor(obs.polygon, y, red);
|
||||
@@ -311,7 +407,7 @@ namespace ZL
|
||||
{
|
||||
VertexDataStruct data;
|
||||
const Eigen::Vector3f yellow(1.0f, 1.0f, 0.0f);
|
||||
const float y = navigation.getFloorY() + 0.05f;
|
||||
const float y = navigation ? navigation->getFloorY() + 0.05f : 0.05f;
|
||||
const float s = 0.2f;
|
||||
|
||||
for (const auto& pt : navigationEditorPoints) {
|
||||
@@ -381,13 +477,13 @@ namespace ZL
|
||||
poly.polygon.emplace_back(pt.x(), pt.z());
|
||||
}
|
||||
|
||||
navigation.addObstaclePolygon(poly);
|
||||
if (navigation) navigation->addObstaclePolygon(poly);
|
||||
std::cout << "[NAV_EDITOR] Added obstacle '" << poly.name << "' with "
|
||||
<< poly.polygon.size() << " vertices\n";
|
||||
|
||||
// Add a red mesh for the new obstacle polygon so it's visible immediately.
|
||||
{
|
||||
const float y = navigation.getFloorY() + 0.02f;
|
||||
const float y = navigation ? navigation->getFloorY() + 0.02f : 0.02f;
|
||||
const Eigen::Vector3f red(1.0f, 0.0f, 0.0f);
|
||||
VertexRenderStruct mesh;
|
||||
mesh.data = CreatePolygonFloor(poly.polygon, y, red);
|
||||
@@ -409,7 +505,7 @@ namespace ZL
|
||||
if (!std::filesystem::exists(filename)) break;
|
||||
}
|
||||
|
||||
if (navigation.saveConfig(filename)) {
|
||||
if (navigation && navigation->saveConfig(filename)) {
|
||||
std::cout << "[NAV_EDITOR] Saved navigation config to: " << filename << "\n";
|
||||
} else {
|
||||
std::cerr << "[NAV_EDITOR] Failed to save to: " << filename << "\n";
|
||||
@@ -418,8 +514,8 @@ namespace ZL
|
||||
|
||||
void Location::navigationEditorReload()
|
||||
{
|
||||
setupNavigation(navigationEditorConfigPath);
|
||||
std::cout << "[NAV_EDITOR] Reloaded navigation from: " << navigationEditorConfigPath << "\n";
|
||||
setupNavigation(navigationMapPaths);
|
||||
std::cout << "[NAV_EDITOR] Reloaded navigation maps (" << navigationMapPaths.size() << " maps)\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -821,7 +917,8 @@ namespace ZL
|
||||
|
||||
bool Location::setNavigationAreaAvailable(const std::string& areaName, bool available)
|
||||
{
|
||||
return navigation.setAreaAvailable(areaName, available);
|
||||
if (!navigation) return false;
|
||||
return navigation->setAreaAvailable(areaName, available);
|
||||
}
|
||||
|
||||
void Location::resolveCharacterCollisions()
|
||||
@@ -882,9 +979,9 @@ namespace ZL
|
||||
newB.z() += normal.y() * push;
|
||||
newB.y() = 0.f;
|
||||
|
||||
if (navigation.isReady()) {
|
||||
const bool aOk = navigation.isWalkable(newA);
|
||||
const bool bOk = navigation.isWalkable(newB);
|
||||
if (navigation && navigation->isReady()) {
|
||||
const bool aOk = navigation->isWalkable(newA);
|
||||
const bool bOk = navigation->isWalkable(newB);
|
||||
|
||||
if (aOk && bOk) {
|
||||
a->position = newA;
|
||||
@@ -978,7 +1075,8 @@ namespace ZL
|
||||
{
|
||||
if (player) {
|
||||
player->update(delta);
|
||||
dialogueSystem.update(static_cast<int>(delta), player->position);
|
||||
dialogueSystem.update(static_cast<int>(delta));
|
||||
updateTriggerZones(player->position);
|
||||
}
|
||||
for (auto& npc : npcs)
|
||||
{
|
||||
|
||||
+22
-4
@@ -19,6 +19,16 @@
|
||||
namespace ZL
|
||||
{
|
||||
|
||||
struct TriggerZone
|
||||
{
|
||||
std::string id;
|
||||
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
||||
float radius = 1.5f;
|
||||
float hysteresis = 0.3f; // exit fires at radius + hysteresis to prevent flickering
|
||||
bool enabled = true;
|
||||
bool playerInside = false; // runtime tracking state, not serialized
|
||||
};
|
||||
|
||||
struct LocationSetup
|
||||
{
|
||||
std::string roomMeshPath;
|
||||
@@ -26,9 +36,10 @@ namespace ZL
|
||||
std::string gameObjectsJsonPath;
|
||||
std::string npcsJsonPath;
|
||||
std::string dialoguesJsonPath;
|
||||
std::string navigationJsonPath;
|
||||
std::vector<std::string> navigationJsonPaths;
|
||||
std::string scriptPath;
|
||||
std::string teleportsJsonPath;
|
||||
std::string triggerZonesJsonPath;
|
||||
Eigen::Vector3f playerPosition = Eigen::Vector3f::Zero();
|
||||
};
|
||||
|
||||
@@ -52,7 +63,9 @@ namespace ZL
|
||||
float cameraAzimuth = 0.0f;
|
||||
float cameraInclination = M_PI * 30.f / 180.f;
|
||||
|
||||
PathFinder navigation;
|
||||
std::vector<PathFinder> navigationMaps;
|
||||
PathFinder* navigation = nullptr;
|
||||
int activeNavigationIndex = 0;
|
||||
|
||||
std::unique_ptr<ShadowMap> shadowMap;
|
||||
Eigen::Matrix4f cameraViewMatrix = Eigen::Matrix4f::Identity();
|
||||
@@ -73,13 +86,15 @@ namespace ZL
|
||||
TeleportZone* targetTeleportZone = nullptr;
|
||||
std::function<void(const std::string&, const Eigen::Vector3f&, float)> onTeleport;
|
||||
|
||||
std::vector<TriggerZone> triggerZones;
|
||||
|
||||
// Navigation editor — toggle with 'N', save with 'B', right-click to finalize polygon
|
||||
bool navigationEditorMode = false;
|
||||
|
||||
std::vector<Eigen::Vector3f> navigationEditorPoints;
|
||||
VertexRenderStruct navigationEditorPointsMesh;
|
||||
std::vector<VertexRenderStruct> navigationEditorNavMeshes;
|
||||
std::string navigationEditorConfigPath;
|
||||
std::vector<std::string> navigationMapPaths;
|
||||
int navigationEditorObstacleCounter = 0;
|
||||
|
||||
void navigationEditorBuildNavMeshes();
|
||||
@@ -99,7 +114,8 @@ namespace ZL
|
||||
|
||||
|
||||
void setup(const LocationSetup& params);
|
||||
void setupNavigation(const std::string& navigationJsonPath);
|
||||
void setupNavigation(const std::vector<std::string>& paths);
|
||||
bool switchNavigation(int index);
|
||||
InteractiveObject* raycastInteractiveObjects(const Eigen::Vector3f& rayOrigin, const Eigen::Vector3f& rayDir);
|
||||
Character* raycastNpcs(const Eigen::Vector3f& rayOrigin, const Eigen::Vector3f& rayDir, float maxDistance = 100.0f);
|
||||
|
||||
@@ -127,6 +143,8 @@ namespace ZL
|
||||
void resolveCharacterCollisions();
|
||||
void updateDynamicReplans(int64_t deltaMs);
|
||||
void loadTeleportZones(const std::string& jsonPath, const char* zipFile);
|
||||
void loadTriggerZones(const std::string& jsonPath, const char* zipFile);
|
||||
void updateTriggerZones(const Eigen::Vector3f& playerPos);
|
||||
|
||||
std::unordered_map<Character*, Eigen::Vector3f> lastCharacterPositions;
|
||||
std::unordered_map<Character*, int64_t> replanCooldownRemainingMs;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Game.h"
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include "Location.h"
|
||||
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
@@ -11,6 +12,8 @@ namespace ZL {
|
||||
|
||||
struct ScriptEngine::Impl {
|
||||
sol::state lua;
|
||||
std::unordered_map<std::string, sol::protected_function> triggerEnterCallbacks;
|
||||
std::unordered_map<std::string, sol::protected_function> triggerExitCallbacks;
|
||||
};
|
||||
|
||||
ScriptEngine::ScriptEngine() = default;
|
||||
@@ -133,6 +136,24 @@ namespace ZL {
|
||||
}
|
||||
});
|
||||
|
||||
api.set_function("switch_navigation",
|
||||
[game](int index) {
|
||||
if (!game->switchNavigation(index)) {
|
||||
std::cerr << "[script] switch_navigation: index " << index << " out of range\n";
|
||||
}
|
||||
});
|
||||
|
||||
// set_trigger_zone_callbacks(zone_id, on_enter, on_exit)
|
||||
// on_enter and on_exit are optional Lua functions (pass nil to omit).
|
||||
// Called when the player enters or exits the named trigger zone.
|
||||
api.set_function("set_trigger_zone_callbacks",
|
||||
[this_impl = impl.get()](const std::string& zoneId, sol::object onEnter, sol::object onExit) {
|
||||
if (onEnter.is<sol::protected_function>())
|
||||
this_impl->triggerEnterCallbacks[zoneId] = onEnter.as<sol::protected_function>();
|
||||
if (onExit.is<sol::protected_function>())
|
||||
this_impl->triggerExitCallbacks[zoneId] = onExit.as<sol::protected_function>();
|
||||
});
|
||||
|
||||
// receive_npc_gift(npc_index)
|
||||
api.set_function("receive_npc_gift", [game, inventory](int npcIndex) {
|
||||
std::cout << "[script] receive_npc_gift: npc index " << npcIndex << std::endl;
|
||||
@@ -254,4 +275,26 @@ namespace ZL {
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::callTriggerEnterCallback(const std::string& zoneId) {
|
||||
if (!impl) return;
|
||||
auto it = impl->triggerEnterCallbacks.find(zoneId);
|
||||
if (it == impl->triggerEnterCallbacks.end()) return;
|
||||
auto result = it->second();
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cerr << "[SCRIPT] trigger enter callback error for '" << zoneId << "': " << err.what() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::callTriggerExitCallback(const std::string& zoneId) {
|
||||
if (!impl) return;
|
||||
auto it = impl->triggerExitCallbacks.find(zoneId);
|
||||
if (it == impl->triggerExitCallbacks.end()) return;
|
||||
auto result = it->second();
|
||||
if (!result.valid()) {
|
||||
sol::error err = result;
|
||||
std::cerr << "[SCRIPT] trigger exit callback error for '" << zoneId << "': " << err.what() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
@@ -24,6 +24,9 @@ public:
|
||||
|
||||
void callNpcInteractCallback(int npcIndex);
|
||||
|
||||
void callTriggerEnterCallback(const std::string& zoneId);
|
||||
void callTriggerExitCallback(const std::string& zoneId);
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
@@ -11,23 +11,7 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DialogueSystem::update(int deltaMs) {
|
||||
runtime.update(deltaMs);
|
||||
overlay.update(runtime.getPresentation(), deltaMs);
|
||||
if (overlay.consumeSkipRequested()) {
|
||||
@@ -139,12 +123,4 @@ void DialogueSystem::stopDialogue() {
|
||||
runtime.stop();
|
||||
}
|
||||
|
||||
void DialogueSystem::addTriggerZone(const TriggerZone& zone) {
|
||||
triggerZones.push_back(zone);
|
||||
}
|
||||
|
||||
void DialogueSystem::clearTriggerZones() {
|
||||
triggerZones.clear();
|
||||
}
|
||||
|
||||
} // namespace ZL::Dialogue
|
||||
@@ -2,28 +2,17 @@
|
||||
|
||||
#include "dialogue/DialogueOverlay.h"
|
||||
#include "dialogue/DialogueRuntime.h"
|
||||
#include <Eigen/Dense>
|
||||
#include <SDL.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ZL::Dialogue {
|
||||
|
||||
struct TriggerZone {
|
||||
std::string id;
|
||||
std::string dialogueId;
|
||||
Eigen::Vector3f center = Eigen::Vector3f::Zero();
|
||||
float radius = 1.5f;
|
||||
bool once = true;
|
||||
bool triggered = false;
|
||||
};
|
||||
|
||||
class DialogueSystem {
|
||||
public:
|
||||
bool init(Renderer& renderer, const std::string& zipFile = "");
|
||||
bool loadDatabase(const std::string& path);
|
||||
|
||||
void update(int deltaMs, const Eigen::Vector3f& playerPosition);
|
||||
void update(int deltaMs);
|
||||
void draw(Renderer& renderer);
|
||||
|
||||
bool handleKeyDown(SDL_Keycode key);
|
||||
@@ -40,14 +29,10 @@ 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 addTriggerZone(const TriggerZone& zone);
|
||||
void clearTriggerZones();
|
||||
|
||||
private:
|
||||
DialogueDatabase database;
|
||||
DialogueRuntime runtime;
|
||||
DialogueOverlay overlay;
|
||||
std::vector<TriggerZone> triggerZones;
|
||||
};
|
||||
|
||||
} // namespace ZL::Dialogue
|
||||
Reference in new issue
Block a user