Much better narration/dialogue/action handling (and for lua too)
This commit is contained in:
@@ -656,6 +656,29 @@ setup_handler(function(event, trigger_entity, what_entity)
|
||||
end
|
||||
end)
|
||||
|
||||
setup_action_handler("talk", {
|
||||
count = 0,
|
||||
activate = function(this)
|
||||
this._narration("Booo!! Lua...", {"One", "Two", "Three"})
|
||||
end,
|
||||
event = function(this, event)
|
||||
this.count = this.count + 1
|
||||
if event == "narration_progress" then
|
||||
this.count = this.count + 1
|
||||
this._narration("Booo!!!", {})
|
||||
end
|
||||
if event == "narration_answered" then
|
||||
this.count = this.count + 1
|
||||
this._narration("Booo!!!_", {})
|
||||
end
|
||||
if this.count > 10 then
|
||||
this._finish()
|
||||
end
|
||||
end,
|
||||
finish = function(this)
|
||||
this.count = 0
|
||||
end,
|
||||
})
|
||||
--[[
|
||||
active_dialogues = {}
|
||||
setup_action_handler("talk", function(town, index, word)
|
||||
|
||||
@@ -12,21 +12,11 @@
|
||||
|
||||
namespace ECS
|
||||
{
|
||||
struct TownNPCs {
|
||||
struct NPCData {
|
||||
flecs::entity e;
|
||||
nlohmann::json props;
|
||||
Ogre::Vector3 position;
|
||||
Ogre::Quaternion orientation;
|
||||
Ogre::String model;
|
||||
};
|
||||
|
||||
std::map<int, NPCData> npcs;
|
||||
};
|
||||
struct LivesIn {};
|
||||
void createNPCActionNodes(flecs::entity town, flecs::entity e, int index)
|
||||
{
|
||||
NPCActionNodes &anodes = e.get_mut<NPCActionNodes>();
|
||||
const TownNPCs &npcs = town.get<TownNPCs>();
|
||||
nlohmann::json npcprops = npcs.npcs.at(index).props;
|
||||
const CharacterBase &ch = e.get<CharacterBase>();
|
||||
Ogre::Vector3 characterPos = ch.mBodyNode->_getDerivedPosition();
|
||||
Ogre::Quaternion characterRot = ch.mBodyNode->_getDerivedOrientation();
|
||||
@@ -66,6 +56,7 @@ void createNPCActionNodes(flecs::entity town, flecs::entity e, int index)
|
||||
anode.props["height"] = anode.height;
|
||||
anode.props["town"] = town.id();
|
||||
anode.props["index"] = index;
|
||||
anode.props["npc"] = npcprops;
|
||||
anodes.anodes.push_back(anode);
|
||||
}
|
||||
{
|
||||
@@ -86,6 +77,7 @@ void createNPCActionNodes(flecs::entity town, flecs::entity e, int index)
|
||||
anode.props["height"] = anode.height;
|
||||
anode.props["town"] = town.id();
|
||||
anode.props["index"] = index;
|
||||
anode.props["npc"] = npcprops;
|
||||
anodes.anodes.push_back(anode);
|
||||
}
|
||||
e.modified<NPCActionNodes>();
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
#ifndef _CHARACTER_MANAGER_MODULE_
|
||||
#define _CHARACTER_MANAGER_MODULE_
|
||||
#include <flecs.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
namespace ECS
|
||||
{
|
||||
struct TownCharacterHolder{int index;};
|
||||
struct TownNPCs {
|
||||
struct NPCData {
|
||||
flecs::entity e;
|
||||
nlohmann::json props;
|
||||
Ogre::Vector3 position;
|
||||
Ogre::Quaternion orientation;
|
||||
Ogre::String model;
|
||||
};
|
||||
|
||||
std::map<int, NPCData> npcs;
|
||||
};
|
||||
struct LivesIn {};
|
||||
struct CharacterManagerModule {
|
||||
std::set<flecs::entity> characters;
|
||||
flecs::entity player;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define __GUIMODULECOMMON_H__
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "Components.h"
|
||||
#include "GameData.h"
|
||||
namespace ECS
|
||||
@@ -21,6 +22,7 @@ struct GUI {
|
||||
Ogre::String mnarrationText;
|
||||
std::vector<Ogre::String> mchoices;
|
||||
int narration_answer;
|
||||
nlohmann::json props;
|
||||
|
||||
private:
|
||||
bool complete;
|
||||
@@ -91,6 +93,18 @@ struct GUI {
|
||||
event(ev);
|
||||
}
|
||||
virtual ~NarrationHandler() {}
|
||||
void setProperties(const Ogre::String &properties)
|
||||
{
|
||||
props = nlohmann::json::parse(properties);
|
||||
}
|
||||
Ogre::String getProperties() const
|
||||
{
|
||||
return props.dump();
|
||||
}
|
||||
const nlohmann::json &getPropsJSON() const
|
||||
{
|
||||
return props;
|
||||
}
|
||||
};
|
||||
|
||||
static void setWindowGrab(bool g = true)
|
||||
|
||||
@@ -302,7 +302,10 @@ LuaData::LuaData()
|
||||
lua_setglobal(L, "setup_handler");
|
||||
lua_pushcfunction(L, [](lua_State *L) -> int {
|
||||
luaL_checktype(L, 1, LUA_TSTRING);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
if (lua_type(L, 2) == LUA_TFUNCTION)
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
else
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
ECS::get_mut<PlayerActionModule>().setupLuaActionHandler(L);
|
||||
ECS::modified<PlayerActionModule>();
|
||||
return 0;
|
||||
|
||||
@@ -72,7 +72,8 @@ struct TestNarrativeHandler : GUI::NarrationHandler {
|
||||
}
|
||||
void activate() override
|
||||
{
|
||||
_narration("Dialogue...", {});
|
||||
_narration("Greetings...", {});
|
||||
std::cout << getPropsJSON().dump(4) << std::endl;
|
||||
count = 0;
|
||||
}
|
||||
void event(const Ogre::String &evt) override
|
||||
@@ -101,11 +102,119 @@ struct TestNarrativeHandler : GUI::NarrationHandler {
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
struct LuaNarrationHandler : GUI::NarrationHandler {
|
||||
int ref;
|
||||
lua_State *L;
|
||||
LuaNarrationHandler(lua_State *L, int ref)
|
||||
: ref(ref)
|
||||
, L(L)
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
||||
lua_pushlightuserdata(L, this);
|
||||
lua_pushcclosure(
|
||||
L,
|
||||
[](lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TSTRING);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
LuaNarrationHandler *handler =
|
||||
static_cast<LuaNarrationHandler *>(
|
||||
lua_touserdata(
|
||||
L,
|
||||
lua_upvalueindex(1)));
|
||||
Ogre::String event = lua_tostring(L, 1);
|
||||
std::vector<Ogre::String> choices;
|
||||
int choicesLen = (int)lua_rawlen(L, 2);
|
||||
choices.reserve(choicesLen);
|
||||
for (int i = 1; i <= choicesLen; ++i) {
|
||||
lua_rawgeti(L, 2, i);
|
||||
if (lua_isstring(L, -1))
|
||||
choices.push_back(
|
||||
lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
handler->_narration(event, choices);
|
||||
return 0;
|
||||
},
|
||||
1);
|
||||
lua_setfield(L, -2, "_narration");
|
||||
lua_pushlightuserdata(L, this);
|
||||
lua_pushcclosure(
|
||||
L,
|
||||
[](lua_State *L) {
|
||||
LuaNarrationHandler *handler =
|
||||
static_cast<LuaNarrationHandler *>(
|
||||
lua_touserdata(
|
||||
L,
|
||||
lua_upvalueindex(1)));
|
||||
handler->_finish();
|
||||
return 0;
|
||||
},
|
||||
1);
|
||||
lua_setfield(L, -2, "_finish");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
void finish() override
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
||||
int type = lua_getfield(L, -1, "finish");
|
||||
OgreAssert(type == LUA_TFUNCTION, "bad finish()");
|
||||
lua_insert(L, -2);
|
||||
if (lua_pcall(L, 1, 0, 0) != 0) {
|
||||
std::cerr << lua_tostring(L, -1) << std::endl;
|
||||
OgreAssert(false, "lua error");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
_clear_narration();
|
||||
}
|
||||
void activate() override
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
||||
int type = lua_getfield(L, -1, "activate");
|
||||
OgreAssert(type == LUA_TFUNCTION, "bad activate()");
|
||||
lua_insert(L, -2);
|
||||
if (lua_pcall(L, 1, 0, 0) != 0) {
|
||||
std::cerr << lua_tostring(L, -1) << std::endl;
|
||||
OgreAssert(false, "lua error");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
// _narration("Greetings...", {});
|
||||
// std::cout << getPropsJSON().dump(4) << std::endl;
|
||||
}
|
||||
void event(const Ogre::String &evt) override
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
||||
int type = lua_getfield(L, -1, "event");
|
||||
OgreAssert(type == LUA_TFUNCTION, "bad event()");
|
||||
lua_insert(L, -2);
|
||||
lua_pushstring(L, evt.c_str());
|
||||
if (lua_pcall(L, 2, 0, 0) != 0) {
|
||||
std::cerr << lua_tostring(L, -1) << std::endl;
|
||||
OgreAssert(false, "lua error");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct SimpleWordHandler : PlayerActionModule::ActionWordHandler {
|
||||
void operator()(flecs::entity town, int index,
|
||||
const Ogre::String &word) override
|
||||
{
|
||||
TestNarrativeHandler *handle = OGRE_NEW TestNarrativeHandler();
|
||||
const TownNPCs::NPCData &npc =
|
||||
town.get<TownNPCs>().npcs.at(index);
|
||||
flecs::entity e = npc.e;
|
||||
for (const auto &anode : e.get<NPCActionNodes>().anodes) {
|
||||
if (anode.action == word) {
|
||||
nlohmann::json props = anode.props;
|
||||
props["initiator"] =
|
||||
ECS::get<CharacterManagerModule>()
|
||||
.getPlayer()
|
||||
.id();
|
||||
props["recipient"] = e.id();
|
||||
handle->setProperties(props.dump());
|
||||
break;
|
||||
}
|
||||
}
|
||||
ECS::get_mut<GUI>().addNarrationHandler(handle);
|
||||
ECS::modified<GUI>();
|
||||
}
|
||||
@@ -205,8 +314,8 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
|
||||
if (!ECS::get<GUI>().enabled)
|
||||
list.busy = false;
|
||||
});
|
||||
SimpleWordHandler *handler = OGRE_NEW SimpleWordHandler;
|
||||
addWordHandler("talk", handler);
|
||||
// SimpleWordHandler *handler = OGRE_NEW SimpleWordHandler;
|
||||
// addWordHandler("talk", handler);
|
||||
}
|
||||
|
||||
void PlayerActionModule::addWordHandler(const Ogre::String &word,
|
||||
@@ -233,13 +342,39 @@ struct LuaWordHandler : PlayerActionModule::ActionWordHandler {
|
||||
const Ogre::String &word) override
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
||||
lua_pushinteger(L, town.id());
|
||||
lua_pushinteger(L, index);
|
||||
lua_pushstring(L, word.c_str());
|
||||
if (lua_pcall(L, 3, 0, 0)) {
|
||||
Ogre::LogManager::getSingleton().stream()
|
||||
<< lua_tostring(L, -1);
|
||||
OgreAssert(false, "Lua error");
|
||||
if (lua_type(L, -1) == LUA_TFUNCTION) {
|
||||
luaL_checktype(L, -1, LUA_TFUNCTION);
|
||||
lua_pushinteger(L, town.id());
|
||||
lua_pushinteger(L, index);
|
||||
lua_pushstring(L, word.c_str());
|
||||
if (lua_pcall(L, 3, 0, 0)) {
|
||||
Ogre::LogManager::getSingleton().stream()
|
||||
<< lua_tostring(L, -1);
|
||||
OgreAssert(false, "Lua error");
|
||||
}
|
||||
} else if (lua_type(L, -1) == LUA_TTABLE) {
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
lua_pop(L, 1);
|
||||
LuaNarrationHandler *handle =
|
||||
OGRE_NEW LuaNarrationHandler(L, ref);
|
||||
const TownNPCs::NPCData &npc =
|
||||
town.get<TownNPCs>().npcs.at(index);
|
||||
flecs::entity e = npc.e;
|
||||
for (const auto &anode :
|
||||
e.get<NPCActionNodes>().anodes) {
|
||||
if (anode.action == word) {
|
||||
nlohmann::json props = anode.props;
|
||||
props["initiator"] =
|
||||
ECS::get<CharacterManagerModule>()
|
||||
.getPlayer()
|
||||
.id();
|
||||
props["recipient"] = e.id();
|
||||
handle->setProperties(props.dump());
|
||||
break;
|
||||
}
|
||||
}
|
||||
ECS::get_mut<GUI>().addNarrationHandler(handle);
|
||||
ECS::modified<GUI>();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -268,11 +403,19 @@ void PlayerActionModule::removeLuaWordHandler(const Ogre::String &word,
|
||||
int PlayerActionModule::setupLuaActionHandler(lua_State *L)
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TSTRING);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
Ogre::String word = lua_tostring(L, 1);
|
||||
lua_pushvalue(L, 2);
|
||||
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
addLuaWordHandler(word, L, ref);
|
||||
if (lua_type(L, 2) == LUA_TFUNCTION) {
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
Ogre::String word = lua_tostring(L, 1);
|
||||
lua_pushvalue(L, 2);
|
||||
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
addLuaWordHandler(word, L, ref);
|
||||
} else if (lua_type(L, 2) == LUA_TTABLE) {
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
Ogre::String word = lua_tostring(L, 1);
|
||||
lua_pushvalue(L, 2);
|
||||
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
addLuaWordHandler(word, L, ref);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2134,6 +2134,8 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
if (ImGui::SmallButton("Add NPC")) {
|
||||
nlohmann::json npc;
|
||||
npc["lastName"] = Ogre::String(lastName);
|
||||
npc["firstName"] = Ogre::String(firstName);
|
||||
npc["tags"] = Ogre::String(tags);
|
||||
Ogre::Vector3 npcPosition =
|
||||
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
|
||||
Ogre::Quaternion npcOrientation =
|
||||
@@ -2142,6 +2144,8 @@ bool editNPCs(nlohmann::json &npcs)
|
||||
to_json(npc["position"], npcPosition);
|
||||
to_json(npc["orientation"], npcOrientation);
|
||||
npc["sex"] = selection;
|
||||
npc["health"] = 100;
|
||||
npc["stamina"] = 100;
|
||||
npcs.push_back(npc);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user