From 8320b143581a282384e85d45f361c75917d46c38 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Fri, 23 Jan 2026 21:28:25 +0300 Subject: [PATCH] Started working on dialogue --- lua-scripts/CMakeLists.txt | 4 +- lua-scripts/data.lua | 87 +++++++++++++++++++++++++---- lua-scripts/stories/talk.ink | 24 ++++++-- src/gamedata/PhysicsModule.cpp | 3 +- src/gamedata/PlayerActionModule.cpp | 53 ++++++++++-------- src/physics/physics.cpp | 84 +++++++++++++++------------- src/physics/physics.h | 11 +++- 7 files changed, 184 insertions(+), 82 deletions(-) diff --git a/lua-scripts/CMakeLists.txt b/lua-scripts/CMakeLists.txt index 14eddb7..568ea0a 100644 --- a/lua-scripts/CMakeLists.txt +++ b/lua-scripts/CMakeLists.txt @@ -3,7 +3,7 @@ set(LUA_SCRIPTS_SRC data.lua ) set(LUA_SCRIPTS_OUTPUT) -set(LUA_PACKAGES narrator stories) +set(LUA_PACKAGES narrator stories json) foreach(LUA_SCRIPT_FILE ${LUA_SCRIPTS_SRC}) get_filename_component(FILE_NAME ${LUA_SCRIPT_FILE} NAME_WE) set(LUA_SCRIPT_OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.lua) @@ -21,4 +21,4 @@ foreach(LUA_PACKAGE ${LUA_PACKAGES}) DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${LUA_PACKAGE}) list(APPEND LUA_PACKAGES_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${LUA_PACKAGE}) endforeach() -add_custom_target(stage_lua_scripts ALL DEPENDS ${LUA_SCRIPTS_OUTPUT} ${LUA_PACKAGES_OUTPUT}) \ No newline at end of file +add_custom_target(stage_lua_scripts ALL DEPENDS ${LUA_SCRIPTS_OUTPUT} ${LUA_PACKAGES_OUTPUT}) diff --git a/lua-scripts/data.lua b/lua-scripts/data.lua index 06d801e..5b1a258 100644 --- a/lua-scripts/data.lua +++ b/lua-scripts/data.lua @@ -62,6 +62,7 @@ dropped you into the sea. Last thing you heard before you hit the water was happ } ]]-- local narrator = require('narrator.narrator') +local json = require('json.json') function dump(o) if type(o) == 'table' then @@ -657,26 +658,90 @@ setup_handler(function(event, trigger_entity, what_entity) end) setup_action_handler("talk", { - count = 0, activate = function(this) - this._narration("Booo!! Lua...", {"One", "Two", "Three"}) + local book = narrator.parse_file('stories.talk') + this.story = narrator.init_story(book) + local crash_bind = function() + crash() + end + this.story:bind('crash', crash_bind) + this.story:begin() + this:narration_update() + local props = this._get_properties() + print(props) + local json_data = json.decode(props) + print(dump(json_data)) + crash() end, event = function(this, event) - this.count = this.count + 1 if event == "narration_progress" then - this.count = this.count + 1 - this._narration("Booo!!!", {}) + this:narration_update() end if event == "narration_answered" then - this.count = this.count + 1 - this._narration("Booo!!!_", {}) - end - if this.count > 10 then - this._finish() + local answer = this._get_narration_answer() + this.story:choose(answer) + this:narration_update() end end, finish = function(this) - this.count = 0 + end, + narration_update = function(this) + local ret = "" + local choices = {} + local have_choice = false + local have_paragraph = false + print("narration_update") + if this.story:can_continue() then + print("CAN continue") + have_paragraph = true + local paragraph = this.story:continue(1) + print(dump(paragraph)) + local text = paragraph.text + if paragraph.tags then + -- text = text .. ' #' .. table.concat(paragraph.tags, ' #') + for i, tag in ipairs(paragraph.tags) do + if tag == 'discard' then + text = '' + elseif tag == 'crash' then + print(text) + crash() + end + this:handle_tag(tag) + end + end + ret = text + if this.story:can_choose() then + have_choice = true + local ch = this.story:get_choices() + for i, choice in ipairs(ch) do + table.insert(choices, choice.text) + print(i, dump(choice)) + end + if #choices == 1 and choices[1] == "Ascend" then + this.story:choose(1) + choices = {} + end + if #choices == 1 and choices[1] == "Continue" then + this.story:choose(1) + choices = {} + end + end + else + print("can NOT continue") + end + print(ret) + if (#choices > 0) then + print("choices!!!") + this._narration(ret, choices) + else + this._narration(ret, {}) + end + if not have_choice and not have_paragraph then + this._finish() + end + end, + handle_tag = function(this, tag) + print("tag: " .. tag) end, }) --[[ diff --git a/lua-scripts/stories/talk.ink b/lua-scripts/stories/talk.ink index 9e2dce9..575f69c 100644 --- a/lua-scripts/stories/talk.ink +++ b/lua-scripts/stories/talk.ink @@ -1,6 +1,20 @@ -Dialogue... -Whatever... -* [Ascend] - ~ crash() -- ->END +Yes? + -> start +=== start === ++ [Common] -> common ++ [Debug] -> debug ++ [Leave] -> END +=== common === + # discard ++ [What do you think about me?] + I don't know. + -> END ++ [How are you?] + I think everything is allright. + -> END +=== debug === +Debug #discard ++ Crash +#crash + -> END diff --git a/src/gamedata/PhysicsModule.cpp b/src/gamedata/PhysicsModule.cpp index 2b246ce..dd8fbb9 100644 --- a/src/gamedata/PhysicsModule.cpp +++ b/src/gamedata/PhysicsModule.cpp @@ -656,7 +656,8 @@ PhysicsModule::PhysicsModule(flecs::world &ecs) } // gr.velocity.y = 0.0f; // v.y = 0.0f; - ch->SetLinearVelocity(JoltPhysics::convert(v)); + ch->SetLinearVelocity( + JoltPhysics::convert(v)); gr.velocity = Ogre::Vector3::ZERO; }); ecs.system( + lua_touserdata( + L, + lua_upvalueindex(1))); + int answer = handler->getNarrationAnswer(); + lua_pushinteger(L, answer); + return 1; + }, + 1); + lua_setfield(L, -2, "_get_narration_answer"); + lua_pushlightuserdata(L, this); + lua_pushcclosure( + L, + [](lua_State *L) { + LuaNarrationHandler *handler = + static_cast( + lua_touserdata( + L, + lua_upvalueindex(1))); + lua_pushstring( + L, handler->getProperties().c_str()); + return 1; + }, + 1); + lua_setfield(L, -2, "_get_properties"); lua_pop(L, 1); } void finish() override @@ -177,8 +207,6 @@ struct LuaNarrationHandler : GUI::NarrationHandler { OgreAssert(false, "lua error"); lua_pop(L, 1); } - // _narration("Greetings...", {}); - // std::cout << getPropsJSON().dump(4) << std::endl; } void event(const Ogre::String &evt) override { @@ -233,25 +261,6 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs) alist.busy = false; }) .add(flecs::Singleton); -#if 0 - ecs.system("testNodeList") - .kind(flecs::OnUpdate) - .each([](ActionNodeList &list) { - if (list.nodes.size() > 0) { - Ogre::Vector3 queryPos = - ECS::get() - .mCameraNode - ->_getDerivedPosition(); - std::vector points; - list.query(queryPos, points); - for (auto &p : points) - std::cout << p << std::endl - << list.nodes[p].props.dump() - << std::endl; - OgreAssert(points.size() == 0, "got result"); - } - }); -#endif ecs.system("updateNodeList") .kind(flecs::OnUpdate) .each([](ActionNodeList &list) { @@ -314,8 +323,6 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs) if (!ECS::get().enabled) list.busy = false; }); - // SimpleWordHandler *handler = OGRE_NEW SimpleWordHandler; - // addWordHandler("talk", handler); } void PlayerActionModule::addWordHandler(const Ogre::String &word, diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index ce55306..cc71854 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -269,11 +269,13 @@ public: void DrawLine(JPH::RVec3Arg inFrom, JPH::RVec3Arg inTo, JPH::ColorArg inColor) override { - JPH::Vec4 color = inColor.ToVec4(); - mLines.push_back({ { inFrom[0], inFrom[1], inFrom[2] }, - { inTo[0], inTo[1], inTo[2] }, - Ogre::ColourValue(color[0], color[1], - color[2], color[3]) }); + JPH::Vec4 color = inColor.ToVec4(); + mLines.push_back( + { { (float)inFrom[0], (float)inFrom[1], + (float)inFrom[2] }, + { (float)inTo[0], (float)inTo[1], (float)inTo[2] }, + Ogre::ColourValue(color[0], color[1], color[2], + color[3]) }); } void DrawTriangle(JPH::RVec3Arg inV1, JPH::RVec3Arg inV2, JPH::RVec3Arg inV3, JPH::ColorArg inColor, @@ -444,7 +446,7 @@ Ogre::Vector3 convert(const JPH::Vec3Arg &vec) { return { vec[0], vec[1], vec[2] }; } -JPH::Vec3 convert(const Ogre::Vector3 &vec) +JPH::RVec3 convert(const Ogre::Vector3 &vec) { return { vec.x, vec.y, vec.z }; } @@ -460,7 +462,7 @@ void CompoundShapeBuilder::addShape(JPH::ShapeRefC shape, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation) { - shapeSettings.AddShape(JoltPhysics::convert(position), + shapeSettings.AddShape(JoltPhysics::convert(position), JoltPhysics::convert(rotation), shape.GetPtr()); } JPH::ShapeRefC CompoundShapeBuilder::build() @@ -769,7 +771,7 @@ public: timeAccumulator -= fixedDeltaTime; } for (JPH::BodyID bID : bodies) { - JPH::Vec3 p; + JPH::RVec3 p; JPH::Quat q; if (id2node.find(bID) == id2node.end()) continue; @@ -810,7 +812,7 @@ public: } static JPH::ShapeRefC createBoxShape(float x, float y, float z) { - return new JPH::BoxShape(JPH::RVec3(x, y, z)); + return new JPH::BoxShape(JPH::Vec3(x, y, z)); } static JPH::ShapeRefC createCylinderShape(float halfHeight, float radius) @@ -818,7 +820,7 @@ public: return new JPH::CylinderShape(halfHeight, radius); } JPH::BodyCreationSettings createBodyCreationSettings( - JPH::Shape *shape, JPH::Vec3 &position, JPH::Quat &rotation, + JPH::Shape *shape, JPH::RVec3 &position, JPH::Quat &rotation, JPH::EMotionType motionType, JPH::ObjectLayer layer) { JPH::BodyCreationSettings body_settings( @@ -827,7 +829,7 @@ public: } JPH::BodyCreationSettings createBodyCreationSettings(JPH::ShapeSettings *shapeSettings, - JPH::Vec3 &position, JPH::Quat &rotation, + JPH::RVec3 &position, JPH::Quat &rotation, JPH::EMotionType motionType, JPH::ObjectLayer layer) { @@ -852,8 +854,8 @@ public: { JPH::BodyInterface &body_interface = physics_system.GetBodyInterface(); - body_interface.AddAngularImpulse(id, - JoltPhysics::convert(impulse)); + body_interface.AddAngularImpulse( + id, JoltPhysics::convert(impulse)); } JPH::BodyID createBody(const JPH::BodyCreationSettings &settings, ActivationListener *listener = nullptr) @@ -964,7 +966,7 @@ public: JPH::MutableCompoundShape *master = static_cast( compoundShape.GetPtr()); - master->AddShape(JoltPhysics::convert(position), + master->AddShape(JoltPhysics::convert(position), JoltPhysics::convert(rotation), childShape.GetPtr()); } @@ -1275,8 +1277,9 @@ public: { int i; JPH::HeightFieldShapeSettings heightfieldSettings( - samples, JoltPhysics::convert(offset), - JoltPhysics::convert(scale), (uint32_t)sampleCount); + samples, JoltPhysics::convert(offset), + JoltPhysics::convert(scale), + (uint32_t)sampleCount); for (i = 0; i < sampleCount; i++) { memcpy(heightfieldSettings.mHeightSamples.data() + sampleCount * i, @@ -1299,9 +1302,10 @@ public: "bad parameters"); JPH::MutableCompoundShapeSettings settings; for (i = 0; i < shapes.size(); i++) - settings.AddShape(JoltPhysics::convert(positions[i]), - JoltPhysics::convert(rotations[i]), - shapes[i].GetPtr()); + settings.AddShape( + JoltPhysics::convert(positions[i]), + JoltPhysics::convert(rotations[i]), + shapes[i].GetPtr()); JPH::ShapeSettings::ShapeResult result = settings.Create(); OgreAssert(result.Get(), "Can not create compound shape"); return result.Get(); @@ -1317,9 +1321,10 @@ public: "bad parameters"); JPH::StaticCompoundShapeSettings settings; for (i = 0; i < shapes.size(); i++) - settings.AddShape(JoltPhysics::convert(positions[i]), - JoltPhysics::convert(rotations[i]), - shapes[i].GetPtr()); + settings.AddShape( + JoltPhysics::convert(positions[i]), + JoltPhysics::convert(rotations[i]), + shapes[i].GetPtr()); JPH::ShapeSettings::ShapeResult result = settings.Create(); OgreAssert(result.Get(), "Can not create compound shape"); return result.Get(); @@ -1329,7 +1334,8 @@ public: JPH::ShapeRefC shape) { JPH::OffsetCenterOfMassShapeSettings settings( - JoltPhysics::convert(offset), shape.GetPtr()); + JoltPhysics::convert(offset), + shape.GetPtr()); JPH::ShapeSettings::ShapeResult result = settings.Create(); OgreAssert(result.Get(), "Can not create com offset shape"); return result.Get(); @@ -1340,7 +1346,7 @@ public: JPH::ShapeRefC shape) { return JPH::RotatedTranslatedShapeSettings( - JoltPhysics::convert(offset), + JoltPhysics::convert(offset), JoltPhysics::convert(rotation), shape) .Create() .Get(); @@ -1356,11 +1362,12 @@ public: JPH::BodyLockWrite lock(physics_system.GetBodyLockInterface(), id); JPH::Body &body = lock.GetBody(); - body.ApplyBuoyancyImpulse(JoltPhysics::convert(surfacePosition), - JoltPhysics::convert(surfaceNormal), - buoyancy, linearDrag, angularDrag, - JoltPhysics::convert(fluidVelocity), - JoltPhysics::convert(gravity), dt); + body.ApplyBuoyancyImpulse( + JoltPhysics::convert(surfacePosition), + JoltPhysics::convert(surfaceNormal), + buoyancy, linearDrag, angularDrag, + JoltPhysics::convert(fluidVelocity), + JoltPhysics::convert(gravity), dt); } void applyBuoyancyImpulse(JPH::BodyID id, const Ogre::Vector3 &surfacePosition, @@ -1372,11 +1379,12 @@ public: JPH::BodyLockWrite lock(physics_system.GetBodyLockInterface(), id); JPH::Body &body = lock.GetBody(); - body.ApplyBuoyancyImpulse(JoltPhysics::convert(surfacePosition), - JoltPhysics::convert(surfaceNormal), - buoyancy, linearDrag, angularDrag, - JoltPhysics::convert(fluidVelocity), - physics_system.GetGravity(), dt); + body.ApplyBuoyancyImpulse( + JoltPhysics::convert(surfacePosition), + JoltPhysics::convert(surfaceNormal), + buoyancy, linearDrag, angularDrag, + JoltPhysics::convert(fluidVelocity), + physics_system.GetGravity(), dt); } bool isActive(JPH::BodyID id) { @@ -1399,7 +1407,7 @@ public: void getPositionAndRotation(JPH::BodyID id, Ogre::Vector3 &position, Ogre::Quaternion &rotation) { - JPH::Vec3 _position; + JPH::RVec3 _position; JPH::Quat _rotation; physics_system.GetBodyInterface().GetPositionAndRotation( id, _position, _rotation); @@ -1457,11 +1465,11 @@ public: void broadphaseQuery(float dt, const Ogre::Vector3 &position, std::set &inWater) { - JPH::Vec3 surface_point = JoltPhysics::convert( + JPH::RVec3 surface_point = JoltPhysics::convert( position + Ogre::Vector3(0, -0.1f, 0)); MyCollector collector(&physics_system, surface_point, - JPH::Vec3::sAxisY(), dt); + JPH::Vec3::sAxisY(), dt); // Apply buoyancy to all bodies that intersect with the water JPH::AABox water_box(-JPH::Vec3(1000, 1000, 1000), JPH::Vec3(1000, 0.1f, 1000)); @@ -1488,7 +1496,7 @@ public: int i; Ogre::Vector3 direction = endPoint - startPoint; JPH::RRayCast ray{ JoltPhysics::convert(startPoint), - JoltPhysics::convert(direction) }; + JoltPhysics::convert(direction) }; JPH::RayCastResult hit; bool hadHit = physics_system.GetNarrowPhaseQuery().CastRay( ray, hit, {}, diff --git a/src/physics/physics.h b/src/physics/physics.h index 0a2aa58..48d59c2 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -44,8 +44,15 @@ static constexpr uint NUM_LAYERS(2); namespace JoltPhysics { -Ogre::Vector3 convert(const JPH::Vec3Arg &vec); -JPH::Vec3 convert(const Ogre::Vector3 &vec); +template +Ogre::Vector3 convert(const T &vec) +{ + return {vec[0], vec[1], vec[2]}; +} +template T convert(const Ogre::Vector3 &vec) +{ + return { vec.x, vec.y, vec.z }; +} Ogre::Quaternion convert(const JPH::QuatArg &rot); JPH::Quat convert(const Ogre::Quaternion &rot); struct ShapeData;