Action nodes work better now
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "GUIModule.h"
|
||||
#include "GUIModuleCommon.h"
|
||||
#include "LuaData.h"
|
||||
#include "PhysicsModule.h"
|
||||
#include "PlayerActionModule.h"
|
||||
|
||||
namespace ECS
|
||||
@@ -252,27 +253,28 @@ struct LuaNarrationHandler : GUI::NarrationHandler {
|
||||
};
|
||||
|
||||
struct SimpleWordHandler : PlayerActionModule::ActionWordHandler {
|
||||
void operator()(flecs::entity town, int index,
|
||||
const Ogre::String &word) override
|
||||
void operator()(int actor, flecs::entity town, int index,
|
||||
const Ogre::String &word, int actionNode) 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 : npc.actionNodes) {
|
||||
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;
|
||||
if (index >= 0) {
|
||||
TestNarrativeHandler *handle =
|
||||
OGRE_NEW TestNarrativeHandler();
|
||||
/* this is for NPCs only, right? */
|
||||
const TownNPCs::NPCData &npc =
|
||||
town.get<TownNPCs>().npcs.at(index);
|
||||
flecs::entity e = npc.e;
|
||||
for (const auto &anode : npc.actionNodes) {
|
||||
if (anode.action == word) {
|
||||
nlohmann::json props = anode.props;
|
||||
props["initiator"] = actor;
|
||||
props["recipient"] = index;
|
||||
handle->setProperties(props.dump());
|
||||
break;
|
||||
}
|
||||
}
|
||||
ECS::get_mut<GUI>().addNarrationHandler(handle);
|
||||
ECS::modified<GUI>();
|
||||
}
|
||||
ECS::get_mut<GUI>().addNarrationHandler(handle);
|
||||
ECS::modified<GUI>();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -346,11 +348,13 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
|
||||
.selected]
|
||||
.action) {
|
||||
(*it->second)(
|
||||
town, index,
|
||||
-1, town, index,
|
||||
list.dynamicNodes
|
||||
[list.getUIData()
|
||||
.selected]
|
||||
.action);
|
||||
.action,
|
||||
list.getUIData()
|
||||
.selected);
|
||||
list.setBusy();
|
||||
}
|
||||
}
|
||||
@@ -358,6 +362,19 @@ PlayerActionModule::PlayerActionModule(flecs::world &ecs)
|
||||
if (!ECS::get<GUI>().enabled)
|
||||
list.setReady();
|
||||
});
|
||||
ecs.system<const EngineData>("UpdateActivatedWords")
|
||||
.kind(flecs::OnUpdate)
|
||||
.each([this](const EngineData &eng) {
|
||||
for (auto it = activatedWords.begin();
|
||||
it != activatedWords.end();) {
|
||||
int ret = it->second->_update(eng.delta);
|
||||
if (ret != ActivatedWordHandler::BUSY) {
|
||||
delete it->second;
|
||||
it = activatedWords.erase(it);
|
||||
} else
|
||||
it++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PlayerActionModule::addWordHandler(const Ogre::String &word,
|
||||
@@ -377,11 +394,197 @@ void PlayerActionModule::removeWordHandler(const Ogre::String &word,
|
||||
}
|
||||
}
|
||||
|
||||
static std::set<int> activeActors;
|
||||
struct TestActivatedWordHandler : PlayerActionModule::ActivatedWordHandler {
|
||||
int actor;
|
||||
flecs::entity town;
|
||||
int index;
|
||||
Ogre::String word;
|
||||
int actionNode;
|
||||
ActionNodeList::ActionNode anode;
|
||||
flecs::entity ch;
|
||||
int state;
|
||||
float delay;
|
||||
std::unordered_map<Ogre::String, Ogre::Vector3> placeLocalOffset;
|
||||
std::unordered_map<Ogre::String, Ogre::Quaternion> placeLocalRotation;
|
||||
TestActivatedWordHandler(int actor, flecs::entity town, int index,
|
||||
const Ogre::String &word, int actionNode)
|
||||
: PlayerActionModule::ActivatedWordHandler()
|
||||
, actor(actor)
|
||||
, town(town)
|
||||
, index(index)
|
||||
, word(word)
|
||||
, actionNode(actionNode)
|
||||
, state(0)
|
||||
, delay(0)
|
||||
{
|
||||
activeActors.insert(actor);
|
||||
// dynamic nodes can disappear on us so to avoid that use a copy
|
||||
anode = ECS::get<ActionNodeList>().dynamicNodes[actionNode];
|
||||
if (actor == -1)
|
||||
ch = ECS::get<CharacterManagerModule>().getPlayer();
|
||||
else if (actor >= 0) {
|
||||
const TownNPCs &npcs = town.get<TownNPCs>();
|
||||
ch = npcs.npcs.at(actor).e;
|
||||
}
|
||||
if (anode.props.find("positions") == anode.props.end())
|
||||
goto out;
|
||||
for (const auto &position : anode.props["positions"]) {
|
||||
if (position.find("name") == position.end())
|
||||
continue;
|
||||
Ogre::Vector3 localPosition;
|
||||
Ogre::Quaternion localRotation;
|
||||
localPosition.x = position["position_x"].get<float>();
|
||||
localPosition.y = position["position_y"].get<float>();
|
||||
localPosition.z = position["position_z"].get<float>();
|
||||
localRotation.w = position["rotation_w"].get<float>();
|
||||
localRotation.x = position["rotation_x"].get<float>();
|
||||
localRotation.y = position["rotation_y"].get<float>();
|
||||
localRotation.z = position["rotation_z"].get<float>();
|
||||
placeLocalOffset[position["name"].get<Ogre::String>()] =
|
||||
localPosition;
|
||||
placeLocalRotation[position["name"].get<Ogre::String>()] =
|
||||
localRotation;
|
||||
}
|
||||
out:;
|
||||
}
|
||||
void teleport(const Ogre::String &place)
|
||||
{
|
||||
if (placeLocalOffset.find(place) == placeLocalOffset.end())
|
||||
return;
|
||||
Ogre::Quaternion newRotation =
|
||||
anode.rotation * placeLocalRotation[place];
|
||||
Ogre::Vector3 newPosition =
|
||||
anode.position + newRotation * placeLocalOffset[place];
|
||||
if (ch.is_valid() && ch.has<CharacterBase>()) {
|
||||
ch.get<CharacterBase>()
|
||||
.mBodyNode->_setDerivedOrientation(newRotation);
|
||||
ch.get<CharacterBase>().mBodyNode->_setDerivedPosition(
|
||||
newPosition);
|
||||
}
|
||||
if (actor >= 0) {
|
||||
town.get_mut<TownNPCs>().npcs[actor].position =
|
||||
newPosition;
|
||||
town.get_mut<TownNPCs>().npcs[actor].orientation =
|
||||
newRotation;
|
||||
town.modified<TownNPCs>();
|
||||
}
|
||||
}
|
||||
int update(float delta)
|
||||
{
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (ECS::get<Input>().act)
|
||||
delay += delta;
|
||||
// activate anly after delay
|
||||
if (ECS::get<Input>().act == 0 && delay > 0.2f) {
|
||||
// Yay!!!
|
||||
std::cout << "Node data: " << std::endl;
|
||||
std::cout << anode.props.dump(4) << std::endl;
|
||||
if (ch.is_valid()) {
|
||||
PhysicsModule::controlPhysics(ch,
|
||||
false);
|
||||
// no control by player or ai
|
||||
ch.add<CharacterControlDisable>();
|
||||
if (word == "sit")
|
||||
ch.set<CharacterInActuator>(
|
||||
{ "sitting-chair",
|
||||
{ 0, 0, 0 } });
|
||||
// else
|
||||
// ch.set<CharacterInActuator>(
|
||||
// { "idle", { 0, 0, 0 } });
|
||||
}
|
||||
teleport("enter");
|
||||
delay = 0.0f;
|
||||
state = 5;
|
||||
} else if (ECS::get<Input>().act == 0 &&
|
||||
delay <= 0.2f) {
|
||||
delay = 0.0f;
|
||||
state = 10;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
// teleport again to handle possible problems caused by root motion
|
||||
delay = 0.0f;
|
||||
teleport("enter");
|
||||
state++;
|
||||
break;
|
||||
case 6:
|
||||
// do not move anywhere until we depress key and wait a bit
|
||||
if (ECS::get<Input>().act == 0)
|
||||
delay += delta;
|
||||
if (delay > 1.0f) {
|
||||
delay = 0.0f;
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
// if the key is pressed for a second move to next state
|
||||
if (ECS::get<Input>().act)
|
||||
delay += delta;
|
||||
if (delay > 1.0f) {
|
||||
delay = 0.0f;
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
delay = 0.0;
|
||||
state = 10;
|
||||
break;
|
||||
case 10:
|
||||
delay = 0.0;
|
||||
state++;
|
||||
break;
|
||||
case 11:
|
||||
// wait until key is depressed for a second
|
||||
if (ECS::get<Input>().act == 0)
|
||||
delay += delta;
|
||||
if (delay > 1.0f) {
|
||||
delay = 0.0;
|
||||
state++;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
delay = 0.0f;
|
||||
state = 0;
|
||||
return OK;
|
||||
break;
|
||||
}
|
||||
std::cout << this << " delay: " << delay << " state: " << state
|
||||
<< std::endl;
|
||||
return BUSY;
|
||||
}
|
||||
void enter()
|
||||
{
|
||||
delay = 0.0f;
|
||||
state = 0;
|
||||
ECS::get_mut<GUI>().enableActions = false;
|
||||
ECS::modified<GUI>();
|
||||
std::cout << "enter" << std::endl;
|
||||
}
|
||||
void exit(int result)
|
||||
{
|
||||
ch.remove<CharacterInActuator>();
|
||||
ch.remove<CharacterControlDisable>();
|
||||
PhysicsModule::controlPhysics(ch, true);
|
||||
// OgreAssert(false, "exit");
|
||||
delay = 0.0f;
|
||||
state = 0;
|
||||
ECS::get_mut<GUI>().enableActions = true;
|
||||
ECS::modified<GUI>();
|
||||
std::cout << "exit" << std::endl;
|
||||
}
|
||||
virtual ~TestActivatedWordHandler()
|
||||
{
|
||||
activeActors.erase(actor);
|
||||
}
|
||||
};
|
||||
|
||||
struct LuaWordHandler : PlayerActionModule::ActionWordHandler {
|
||||
lua_State *L;
|
||||
int ref;
|
||||
void operator()(flecs::entity town, int index,
|
||||
const Ogre::String &word) override
|
||||
void operator()(int actor, flecs::entity town, int index,
|
||||
const Ogre::String &word, int actionNode) override
|
||||
{
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
|
||||
if (lua_type(L, -1) == LUA_TFUNCTION) {
|
||||
@@ -397,25 +600,39 @@ struct LuaWordHandler : PlayerActionModule::ActionWordHandler {
|
||||
} 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 : npc.actionNodes) {
|
||||
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;
|
||||
/* trying to talk to NPC activates narration mode */
|
||||
if (index >= 0 && word == "talk") {
|
||||
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 : npc.actionNodes) {
|
||||
if (anode.action == word) {
|
||||
nlohmann::json props =
|
||||
anode.props;
|
||||
props["initiator"] = actor;
|
||||
props["recipient"] = index;
|
||||
handle->setProperties(
|
||||
props.dump());
|
||||
break;
|
||||
}
|
||||
}
|
||||
ECS::get_mut<GUI>().addNarrationHandler(handle);
|
||||
ECS::modified<GUI>();
|
||||
} else {
|
||||
if (activeActors.find(actor) ==
|
||||
activeActors.end()) {
|
||||
TestActivatedWordHandler *handler =
|
||||
OGRE_NEW TestActivatedWordHandler(
|
||||
actor, town, index,
|
||||
word, actionNode);
|
||||
ECS::get_mut<PlayerActionModule>()
|
||||
.addActivatedWordHandler(
|
||||
word, handler);
|
||||
ECS::modified<PlayerActionModule>();
|
||||
}
|
||||
}
|
||||
ECS::get_mut<GUI>().addNarrationHandler(handle);
|
||||
ECS::modified<GUI>();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -460,6 +677,26 @@ int PlayerActionModule::setupLuaActionHandler(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PlayerActionModule::addActivatedWordHandler(const Ogre::String &word,
|
||||
ActivatedWordHandler *handler)
|
||||
{
|
||||
for (auto it = activatedWords.begin(); it != activatedWords.end();
|
||||
it++) {
|
||||
}
|
||||
activatedWords.insert({ word, handler });
|
||||
}
|
||||
|
||||
void PlayerActionModule::removeActivatedWordHandler(
|
||||
const Ogre::String &word, ActivatedWordHandler *handler)
|
||||
{
|
||||
for (auto it = activatedWords.begin(); it != activatedWords.end();) {
|
||||
if (it->first == word && it->second == handler)
|
||||
it = activatedWords.erase(it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void ActionNodeList::updateDynamicNodes()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*nodeMutex);
|
||||
|
||||
Reference in New Issue
Block a user