242 lines
9.0 KiB
C++
242 lines
9.0 KiB
C++
#include <Ogre.h>
|
|
#include <OgreConfigFile.h>
|
|
#include "GameData.h"
|
|
#include "Components.h"
|
|
#include "CharacterModule.h"
|
|
#include "CharacterAnimationModule.h"
|
|
#include "StaticGeometryModule.h"
|
|
#include "PhysicsModule.h"
|
|
#include "PlayerActionModule.h"
|
|
#include "items.h"
|
|
#include "CharacterManagerModule.h"
|
|
|
|
namespace ECS
|
|
{
|
|
void createNPCActionNodes(flecs::entity town, int index)
|
|
{
|
|
TownNPCs &npcs = town.get_mut<TownNPCs>();
|
|
TownNPCs::NPCData &npc = npcs.npcs.at(index);
|
|
flecs::entity e = npc.e;
|
|
nlohmann::json npcprops = npc.props;
|
|
const CharacterBase &ch = e.get<CharacterBase>();
|
|
Ogre::Vector3 characterPos = ch.mBodyNode->_getDerivedPosition();
|
|
Ogre::Quaternion characterRot = ch.mBodyNode->_getDerivedOrientation();
|
|
if (npc.actionNodes.size() > 0) {
|
|
int i;
|
|
for (i = 0; i < npc.actionNodes.size(); i++) {
|
|
auto &anode = npc.actionNodes[i];
|
|
Ogre::Vector3 offset = Ogre::Vector3::UNIT_Z * 0.3f +
|
|
Ogre::Vector3::UNIT_Y;
|
|
if (i == 1)
|
|
offset = Ogre::Vector3::NEGATIVE_UNIT_Z * 0.3f +
|
|
Ogre::Vector3::UNIT_Y;
|
|
anode.position = characterPos + characterRot * offset;
|
|
anode.rotation = characterRot;
|
|
to_json(anode.props["position"], anode.position);
|
|
to_json(anode.props["rotation"], anode.rotation);
|
|
}
|
|
return;
|
|
}
|
|
{
|
|
ActionNodeList::ActionNode anode;
|
|
anode.props["action"] = "talk";
|
|
anode.props["action_text"] = "Talk";
|
|
anode.action = "talk";
|
|
anode.action_text = "Talk";
|
|
Ogre::Vector3 offset = Ogre::Vector3::UNIT_Z * 0.25f +
|
|
Ogre::Vector3::UNIT_Y * 1.5f;
|
|
anode.position = characterPos + characterRot * offset;
|
|
anode.rotation = characterRot;
|
|
anode.radius = 0.6f;
|
|
anode.height = 1.0f;
|
|
to_json(anode.props["position"], anode.position);
|
|
to_json(anode.props["rotation"], anode.rotation);
|
|
|
|
anode.props["radius"] = anode.radius;
|
|
anode.props["height"] = anode.height;
|
|
anode.props["town"] = town.id();
|
|
anode.props["index"] = index;
|
|
anode.props["npc"] = npcprops;
|
|
npc.actionNodes.push_back(anode);
|
|
}
|
|
{
|
|
ActionNodeList::ActionNode anode;
|
|
anode.props["action"] = "action";
|
|
anode.props["action_text"] = "Action";
|
|
anode.action = "action";
|
|
anode.action_text = "Action";
|
|
Ogre::Vector3 offset = Ogre::Vector3::NEGATIVE_UNIT_Z * 0.2f +
|
|
Ogre::Vector3::UNIT_Y;
|
|
anode.position = characterPos + characterRot * offset;
|
|
anode.rotation = characterRot;
|
|
anode.radius = 0.3f;
|
|
anode.height = 1.0f;
|
|
to_json(anode.props["position"], anode.position);
|
|
to_json(anode.props["rotation"], anode.rotation);
|
|
anode.props["radius"] = anode.radius;
|
|
anode.props["height"] = anode.height;
|
|
anode.props["town"] = town.id();
|
|
anode.props["index"] = index;
|
|
anode.props["npc"] = npcprops;
|
|
npc.actionNodes.push_back(anode);
|
|
}
|
|
}
|
|
CharacterManagerModule::CharacterManagerModule(flecs::world &ecs)
|
|
{
|
|
ecs.module<CharacterManagerModule>();
|
|
ecs.import <CharacterModule>();
|
|
ecs.import <CharacterAnimationModule>();
|
|
ecs.import <PhysicsModule>();
|
|
ecs.import <PlayerActionModule>();
|
|
ecs.component<TownCharacterHolder>();
|
|
ecs.component<TownNPCs>();
|
|
ecs.component<LivesIn>();
|
|
ecs.system<TerrainItem, TownNPCs>("UpdateCharacters")
|
|
.kind(flecs::OnUpdate)
|
|
.interval(1.0f)
|
|
.write<CharacterBase>()
|
|
.write<CharacterLocation>()
|
|
.write<CharacterConf>()
|
|
.write<Character>()
|
|
.write<LivesIn>()
|
|
.each([this](flecs::entity town, TerrainItem &item,
|
|
TownNPCs &npcs) {
|
|
if (!player.is_valid())
|
|
return;
|
|
if (!player.has<CharacterBase>())
|
|
return;
|
|
|
|
Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask([this,
|
|
town]() {
|
|
flecs::entity player =
|
|
ECS::get<CharacterManagerModule>()
|
|
.getPlayer();
|
|
if (!player.is_valid())
|
|
return;
|
|
if (!player.has<CharacterBase>())
|
|
return;
|
|
TownNPCs &npcs = town.get_mut<TownNPCs>();
|
|
Ogre::Vector3 cameraPos =
|
|
player.get<CharacterBase>()
|
|
.mBodyNode
|
|
->_getDerivedPosition();
|
|
for (auto &npc : npcs.npcs) {
|
|
int index = npc.first;
|
|
TownNPCs::NPCData &data = npc.second;
|
|
Ogre::Vector3 npcPosition =
|
|
data.position;
|
|
Ogre::Quaternion npcOrientation =
|
|
data.orientation;
|
|
if (cameraPos.squaredDistance(
|
|
npcPosition) < 10000.0f) {
|
|
if (!data.e.is_valid()) {
|
|
data.e = createCharacterData(
|
|
data.model,
|
|
data.position,
|
|
data.orientation);
|
|
data.e.add<LivesIn>(
|
|
town);
|
|
break;
|
|
}
|
|
}
|
|
if (cameraPos.squaredDistance(
|
|
npcPosition) > 22500.0f) {
|
|
if (data.e.is_valid()) {
|
|
data.e.destruct();
|
|
data.e =
|
|
flecs::entity();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (auto &npc : npcs.npcs) {
|
|
int index = npc.first;
|
|
TownNPCs::NPCData &data = npc.second;
|
|
Ogre::Vector3 npcPosition =
|
|
data.position;
|
|
Ogre::Quaternion npcOrientation =
|
|
data.orientation;
|
|
if (cameraPos.squaredDistance(
|
|
npcPosition) < 10000.0f) {
|
|
if (data.e.is_valid()) {
|
|
if (data.e.has<
|
|
CharacterBase>() &&
|
|
data.e.has<LivesIn>(
|
|
town))
|
|
createNPCActionNodes(
|
|
town,
|
|
index);
|
|
}
|
|
}
|
|
}
|
|
town.modified<TownNPCs>();
|
|
});
|
|
});
|
|
}
|
|
flecs::entity
|
|
CharacterManagerModule::createPlayer(const Ogre::Vector3 &position,
|
|
const Ogre::Quaternion &rotation)
|
|
{
|
|
static int count = 0;
|
|
OgreAssert(count == 0, "overspawn");
|
|
OgreAssert(!player.is_valid(), "Player already created");
|
|
player = ECS::get().entity("player");
|
|
OgreAssert(player.is_valid(), "Can't create player");
|
|
std::cout << "Begin player create" << std::endl;
|
|
player.add<Player>();
|
|
ECS::get_mut<CharacterModule>().createCharacter(
|
|
player, position, rotation, "normal-male.glb");
|
|
ECS::modified<CharacterModule>();
|
|
std::cout << "End player create" << std::endl;
|
|
count++;
|
|
return player;
|
|
}
|
|
flecs::entity
|
|
CharacterManagerModule::createCharacterData(const Ogre::String model,
|
|
const Ogre::Vector3 &position,
|
|
const Ogre::Quaternion &rotation)
|
|
{
|
|
flecs::entity e = ECS::get().entity();
|
|
ECS::get_mut<CharacterModule>().createCharacter(e, position, rotation,
|
|
model);
|
|
ECS::modified<CharacterModule>();
|
|
return e;
|
|
}
|
|
|
|
void CharacterManagerModule::registerTownCharacters(flecs::entity town)
|
|
{
|
|
Ogre::MeshManager::getSingleton().load("normal-male.glb", "General");
|
|
Ogre::MeshManager::getSingleton().load("normal-female.glb", "General");
|
|
Ogre::String props = StaticGeometryModule::getItemProperties(town);
|
|
nlohmann::json j = nlohmann::json::parse(props);
|
|
nlohmann::json npcs = nlohmann::json::array();
|
|
if (town.has<TownNPCs>())
|
|
return;
|
|
if (j.find("npcs") != j.end())
|
|
npcs = j["npcs"];
|
|
std::cout << npcs.dump(4) << std::endl;
|
|
int index = 0;
|
|
std::map<int, TownNPCs::NPCData> npcMap;
|
|
for (auto &npc : npcs) {
|
|
const char *models[] = { "normal-male.glb",
|
|
"normal-female.glb" };
|
|
int sex = npc["sex"].get<int>();
|
|
Ogre::Vector3 npcPosition;
|
|
Ogre::Quaternion npcOrientation;
|
|
from_json(npc["position"], npcPosition);
|
|
from_json(npc["orientation"], npcOrientation);
|
|
Ogre::String model = models[sex];
|
|
TownNPCs::NPCData npcData;
|
|
npcData.e = flecs::entity();
|
|
npcData.model = model;
|
|
npcData.orientation = npcOrientation;
|
|
npcData.position = npcPosition;
|
|
npcData.props = npc;
|
|
npcMap[index] = npcData;
|
|
index++;
|
|
}
|
|
town.set<TownNPCs>({ npcMap });
|
|
}
|
|
|
|
}
|