#include #include #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::NPCData &npc = npcs.npcs.at(index); flecs::entity e = npc.e; nlohmann::json npcprops = npc.props; const CharacterBase &ch = e.get(); 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(); ecs.import (); ecs.import (); ecs.import (); ecs.import (); ecs.component(); ecs.component(); ecs.component(); ecs.system("UpdateCharacters") .kind(flecs::OnUpdate) .interval(1.0f) .write() .write() .write() .write() .write() .each([this](flecs::entity town, TerrainItem &item, TownNPCs &npcs) { if (!player.is_valid()) return; if (!player.has()) return; Ogre::Root::getSingleton().getWorkQueue()->addMainThreadTask([this, town]() { flecs::entity player = ECS::get() .getPlayer(); if (!player.is_valid()) return; if (!player.has()) return; TownNPCs &npcs = town.get_mut(); Ogre::Vector3 cameraPos = player.get() .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( 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( town)) createNPCActionNodes( town, index); } } } town.modified(); }); }); } 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(); ECS::get_mut().createCharacter( player, position, rotation, "normal-male.glb"); ECS::modified(); 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().createCharacter(e, position, rotation, model); ECS::modified(); 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()) return; if (j.find("npcs") != j.end()) npcs = j["npcs"]; std::cout << npcs.dump(4) << std::endl; int index = 0; std::map npcMap; for (auto &npc : npcs) { const char *models[] = { "normal-male.glb", "normal-female.glb" }; int sex = npc["sex"].get(); 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({ npcMap }); } }