Better narration processing

This commit is contained in:
2026-01-22 17:15:19 +03:00
parent 4b24d85123
commit cd91174f5d
23 changed files with 1301 additions and 367 deletions

View File

@@ -18,6 +18,7 @@
#include "PhysicsModule.h"
#include "LuaData.h"
#include "PlayerActionModule.h"
#include "CharacterManagerModule.h"
#include "items.h"
#include "town.h"
@@ -2088,6 +2089,65 @@ void runAllScriptsForTown(flecs::entity e)
j["districts"] = districts;
StaticGeometryModule::setItemProperties(e, j.dump());
}
bool editNPCs(nlohmann::json &npcs)
{
bool changed = false;
ImGui::Text("NPC");
int id = 0;
for (auto &npc : npcs) {
ImGui::Text("%s", npc["lastName"].get<Ogre::String>().c_str());
if (ImGui::SmallButton(
("Spawn##" + Ogre::StringConverter::toString(id))
.c_str())) {
int sex = npc["sex"].get<int>();
const char *models[] = { "normal-male.glb",
"normal-female.glb" };
Ogre::Vector3 npcPosition;
Ogre::Quaternion npcOrientation;
from_json(npc["position"], npcPosition);
from_json(npc["orientation"], npcOrientation);
// FIXME: create TownCharacterManager and register NPCs through there
ECS::get_mut<CharacterManagerModule>()
.createCharacterData(models[sex], npcPosition,
npcOrientation);
}
if (ImGui::SmallButton(
("Delete##" + Ogre::StringConverter::toString(id))
.c_str())) {
npcs.erase(id);
changed = true;
break;
}
id++;
}
ImGui::Text("New NPC");
static char lastName[64] = { 0 };
ImGui::InputText("Last name", lastName, sizeof(lastName));
static char firstName[64] = { 0 };
ImGui::InputText("First name", firstName, sizeof(firstName));
static char tags[256] = { 0 };
ImGui::InputText("Tags", tags, sizeof(firstName));
static int selection = 0;
const char *items[] = { "Male", "Female" };
ImGui::Combo("Sex", &selection, items, 2);
if (ImGui::SmallButton("Add NPC")) {
nlohmann::json npc;
npc["lastName"] = Ogre::String(lastName);
Ogre::Vector3 npcPosition =
ECS::get<EditorGizmo>().sceneNode->_getDerivedPosition();
Ogre::Quaternion npcOrientation =
ECS::get<EditorGizmo>()
.sceneNode->_getDerivedOrientation();
to_json(npc["position"], npcPosition);
to_json(npc["orientation"], npcOrientation);
npc["sex"] = selection;
npcs.push_back(npc);
changed = true;
}
ImGui::Separator();
return changed;
}
void createTownPopup(const std::pair<flecs::entity, Ogre::String> item)
{
Ogre::String prop = StaticGeometryModule::getItemProperties(item.first);
@@ -2124,6 +2184,11 @@ void createTownPopup(const std::pair<flecs::entity, Ogre::String> item)
changed = changed || editColorRects(colorRects);
ImGui::Separator();
}
nlohmann::json npcs = nlohmann::json::array();
if (j.find("npcs") != j.end())
npcs = j["npcs"];
changed = changed || editNPCs(npcs);
nlohmann::json districts = nlohmann::json::array();
for (auto &district : j["districts"])
districts.push_back(district);
@@ -2168,6 +2233,7 @@ void createTownPopup(const std::pair<flecs::entity, Ogre::String> item)
ImGui::Separator();
ImGui::Text("%s", j.dump(4).c_str());
if (changed) {
j["npcs"] = npcs;
j["districts"] = districts;
j["colorRects"] = colorRects;
j["lotTemplates"] = lotTemplates;
@@ -5458,6 +5524,7 @@ struct TownDecorateFurniture : TownTask {
.child_of(e)
.set<FurnitureInstance>(
{ node });
#if 0
if (furniture.find(
"sensors") !=
furniture.end()) {
@@ -5599,6 +5666,93 @@ struct TownDecorateFurniture : TownTask {
#endif
}
}
#endif
if (furniture.find(
"actions") !=
furniture.end()) {
for (const auto &
action :
furniture["actions"]) {
std::cout
<< "SENSOR: "
<< action.dump()
<< std::endl;
std::cout
<< furniture
.dump()
<< std::endl;
Ogre::Vector3
actionPosition;
actionPosition
.x =
action["position_x"]
.get<float>();
actionPosition
.y =
action["position_y"]
.get<float>();
actionPosition
.z =
action["position_z"]
.get<float>();
Ogre::Quaternion worldSensorRotation =
worldCenterOrientation *
Ogre::Quaternion(
Ogre::Degree(
90.0f *
(float)rotation),
Ogre::Vector3::
UNIT_Y);
Ogre::Vector3 worldSensorPosition =
worldCenterPosition +
offsetX +
offsetZ +
offsetY +
offset +
worldSensorRotation *
actionPosition;
float height =
action["height"]
.get<float>();
float radius =
action["radius"]
.get<float>();
if (ECS::get()
.has<ActionNodeList>()) {
ActionNodeList::ActionNode
anode;
anode.action =
action["action"]
.get<Ogre::String>();
anode.action_text =
action["action_text"]
.get<Ogre::String>();
anode.radius =
action["radius"]
.get<float>();
anode.height =
action["height"]
.get<float>();
anode.props =
action;
anode.position =
worldSensorPosition;
anode.rotation =
worldSensorRotation;
ECS::get_mut<
ActionNodeList>()
.addNode(
anode);
std::cout
<< "action: "
<< action.dump(
4)
<< std::endl;
ECS::modified<
ActionNodeList>();
}
}
}
}
}
}
@@ -5620,6 +5774,11 @@ struct TownDecorateFurniture : TownTask {
}
};
void registerTownNPCs(flecs::entity e)
{
ECS::get_mut<CharacterManagerModule>().registerTownCharacters(e);
ECS::modified<CharacterManagerModule>();
}
void createTown(flecs::entity e, Ogre::SceneNode *sceneNode,
Ogre::StaticGeometry *geo)
{
@@ -5693,6 +5852,7 @@ void createTown(flecs::entity e, Ogre::SceneNode *sceneNode,
geo->build();
});
});
registerTownNPCs(e);
}
}
}