Lots of updates - lua, narrator, logic, models

This commit is contained in:
2025-09-19 04:35:20 +03:00
parent 4249a0238b
commit 62e14cf075
19 changed files with 924 additions and 157 deletions

View File

@@ -0,0 +1,35 @@
#include <iostream>
#include <OgreMeshManager.h>
#include "Components.h"
#include "GameData.h"
#include "BoatModule.h"
namespace ECS
{
BoatModule::BoatModule(flecs::world &ecs)
{
ecs.module<BoatModule>();
ecs.component<BoatBase>();
ecs.component<BoatBody>();
ecs.component<BoatType>().on_set([](flecs::entity e, BoatType &type) {
int i;
if (e.has<BoatBody>() || e.has<BoatBase>())
return;
BoatBase &boat = e.ensure<BoatBase>();
boat.mEnt = ECS::get<EngineData>().mScnMgr->createEntity(
type.resourceName);
boat.mNode = ECS::get<EngineData>()
.mScnMgr->getRootSceneNode()
->createChildSceneNode(type.position,
type.orientation);
boat.mNode->attachObject(boat.mEnt);
BoatBody &body = e.ensure<BoatBody>();
body.body = ECS::get<EngineData>().mWorld->addRigidBody(
0, boat.mEnt, Ogre::Bullet::CT_HULL, nullptr, 2,
0x7fffffff);
e.modified<BoatBody>();
});
}
}

28
src/gamedata/BoatModule.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef BOAT_MODULE_H_
#define BOAT_MODULE_H_
#include <flecs.h>
#include <Ogre.h>
namespace Ogre
{
class Entity;
class SceneNode;
}
namespace ECS
{
struct BoatType {
Ogre::String resourceName;
Ogre::Vector3 position;
Ogre::Quaternion orientation;
};
struct BoatBase {
Ogre::Entity *mEnt;
Ogre::SceneNode *mNode;
};
struct BoatBody {
btRigidBody *body;
};
struct BoatModule {
BoatModule(flecs::world &ecs);
};
}
#endif

View File

@@ -1,5 +1,6 @@
project(gamedata)
find_package(OGRE REQUIRED COMPONENTS Bites Bullet Paging Terrain Overlay CONFIG)
add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp LuaData.cpp WorldMapModule.cpp)
add_library(GameData STATIC GameData.cpp CharacterModule.cpp WaterModule.cpp SunModule.cpp TerrainModule.cpp GUIModule.cpp LuaData.cpp WorldMapModule.cpp
BoatModule.cpp EventTriggerModule.cpp)
target_link_libraries(GameData PUBLIC OgreMain OgreBites OgreBullet OgrePaging OgreTerrain OgreOverlay flecs::flecs_static lua)
target_include_directories(GameData PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@@ -15,16 +15,7 @@ CharacterModule::CharacterModule(flecs::world &ecs)
ecs.component<Player>();
ecs.component<CharacterBase>();
ecs.component<CharacterVelocity>();
ecs.component<CharacterBody>().on_add(
[](flecs::entity e, CharacterBody &body) {
e.set<CharacterVelocity>(
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
body.checkGround = false;
body.checkGroundResult = false;
body.mCollisionShape = nullptr;
body.mGhostObject = nullptr;
body.mController = nullptr;
});
ecs.component<CharacterBody>();
ecs.system<EngineData, CharacterBase>("UpdateTimer")
.kind(flecs::OnUpdate)
.each([this](EngineData &eng, CharacterBase &ch) {
@@ -211,15 +202,19 @@ CharacterModule::CharacterModule(flecs::world &ecs)
ch.is_submerged = false;
});
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
"HandleGravity")
"HandleGravityBouyanceWater")
.kind(flecs::OnUpdate)
.with<TerrainReady>()
.with<WaterReady>()
.with<InWater>()
.each([this](flecs::entity e, const EngineData &eng,
const CharacterBase &ch, CharacterVelocity &gr) {
Ogre::Vector3 gravity(0, -9.8f, 0);
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
if (e.has<InWater>()) {
Ogre::Vector3 v(0, 0, 0);
if (e.has<CharacterGravity>())
v += gravity;
if (e.has<CharacterBuoyancy>()) {
float volume = 2.0f * 0.5f * 0.5f;
float density = 900.0f;
float full_subm = 2.0f;
@@ -235,22 +230,39 @@ CharacterModule::CharacterModule(flecs::world &ecs)
Ogre::Vector3 b = -gravity * density * volume *
multiplier * current_subm /
full_subm / mass;
gr.gvelocity += (gravity + b) * eng.delta;
gr.gvelocity.y = Ogre::Math::Clamp(
gr.gvelocity.y, -2.5f, 2.5f);
} else {
gr.gvelocity += gravity * eng.delta;
if (pos.y < -1.2) {
gr.gvelocity.y = 0.0f;
}
v += b;
}
gr.gvelocity *= 0.99;
gr.gvelocity += v * eng.delta;
gr.gvelocity.y =
Ogre::Math::Clamp(gr.gvelocity.y, -2.5f, 1.5f);
gr.gvelocity *= (1.0 - eng.delta);
gr.velocity.y *= (1.0 - eng.delta);
});
ecs.system<const EngineData, const CharacterBase, CharacterVelocity>(
"HandleGravityNoWater")
.kind(flecs::OnUpdate)
.with<TerrainReady>()
.with<WaterReady>()
.without<InWater>()
.with<CharacterGravity>()
.each([this](flecs::entity e, const EngineData &eng,
const CharacterBase &ch, CharacterVelocity &gr) {
Ogre::Vector3 gravity(0, -9.8f, 0);
Ogre::Vector3 pos = ch.mBodyNode->getPosition();
gr.gvelocity += gravity * eng.delta;
if (pos.y < -1.2) {
gr.gvelocity.y = 0.0f;
}
gr.gvelocity *= (1.0 - eng.delta);
gr.velocity.y *= (1.0 - eng.delta);
});
ecs.system<const EngineData, const AnimationControl,
const CharacterBase, CharacterVelocity>("HandleSwimming")
.kind(flecs::OnUpdate)
.with<TerrainReady>()
.with<WaterReady>()
.with<InWater>()
.with<CharacterBuoyancy>()
.each([this](flecs::entity e, const EngineData &eng,
const AnimationControl &anim,
const CharacterBase &ch, CharacterVelocity &gr) {
@@ -479,65 +491,11 @@ CharacterModule::CharacterModule(flecs::world &ecs)
CharacterBody>("UpdateCharacterBase")
.kind(flecs::OnUpdate)
.with<Character>()
.with<CharacterBody>()
.with<CharacterBase>()
.each([](const EngineData &eng, CharacterLocation &loc,
CharacterBase &ch, CharacterBody &body) {
if (!ch.mBodyNode) {
body.mController = nullptr;
ch.mBodyEnt = eng.mScnMgr->createEntity(
"normal-male.glb");
ch.mBodyNode = eng.mScnMgr->getRootSceneNode()
->createChildSceneNode();
ch.mBodyNode->setOrientation(loc.orientation);
ch.mBodyNode->setPosition(loc.position);
ch.mBodyNode->attachObject(ch.mBodyEnt);
ch.mSkeleton = ch.mBodyEnt->getSkeleton();
body.mGhostObject =
new btPairCachingGhostObject();
body.mCollisionShape =
new btCompoundShape(false);
body.mGhostObject->setCollisionShape(
body.mCollisionShape);
{
btVector3 inertia(0, 0, 0);
// mCollisionShape = new btCompoundShape();
btScalar height = 1.0f;
btScalar radius = 0.3f;
btCapsuleShape *shape =
new btCapsuleShape(
radius,
2 * height -
2 * radius);
btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(0, 1, 0));
static_cast<btCompoundShape *>(
body.mCollisionShape)
->addChildShape(transform,
shape);
btScalar masses[1] = { 0 };
btTransform principal;
static_cast<btCompoundShape *>(
body.mCollisionShape)
->calculatePrincipalAxisTransform(
masses, principal,
inertia);
}
body.mGhostObject->setCollisionFlags(
btCollisionObject::CF_KINEMATIC_OBJECT /*|
btCollisionObject::CF_NO_CONTACT_RESPONSE */);
body.mGhostObject->setActivationState(
DISABLE_DEACTIVATION);
eng.mWorld->attachCollisionObject(
body.mGhostObject, ch.mBodyEnt, 1,
0x7FFFFFFF);
OgreAssert(body.mGhostObject,
"Need GhostObject");
OgreAssert(body.mCollisionShape,
"No collision shape");
OgreAssert(ch.mSkeleton->hasBone("Root"),
"No root bone");
ch.mRootBone = ch.mSkeleton->getBone("Root");
OgreAssert(ch.mRootBone, "No root bone");
} else {
loc.orientation =
ch.mBodyNode->_getDerivedOrientation();
@@ -545,6 +503,77 @@ CharacterModule::CharacterModule(flecs::world &ecs)
ch.mBodyNode->_getDerivedPosition();
}
});
ecs.system<const EngineData, const CharacterLocation,
const CharacterConf>("SetupCharacter")
.kind(flecs::OnUpdate)
.with<Character>()
.without<CharacterBase>()
.without<CharacterBody>()
.each([](flecs::entity e, const EngineData &eng,
const CharacterLocation &loc,
const CharacterConf &conf) {
CharacterBase &ch = e.ensure<CharacterBase>();
CharacterBody &body = e.ensure<CharacterBody>();
AnimationControl &anim = e.ensure<AnimationControl>();
ch.mBodyEnt = eng.mScnMgr->createEntity(conf.type);
ch.mBodyNode = eng.mScnMgr->getRootSceneNode()
->createChildSceneNode();
ch.mBodyNode->setOrientation(loc.orientation);
ch.mBodyNode->setPosition(loc.position);
ch.mBodyNode->attachObject(ch.mBodyEnt);
ch.mSkeleton = ch.mBodyEnt->getSkeleton();
OgreAssert(ch.mSkeleton->hasBone("Root"),
"No root bone");
ch.mRootBone = ch.mSkeleton->getBone("Root");
OgreAssert(ch.mRootBone, "No root bone");
body.mController = nullptr;
e.set<CharacterVelocity>(
{ { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } });
body.checkGround = false;
body.checkGroundResult = false;
body.mCollisionShape = nullptr;
body.mGhostObject = nullptr;
body.mController = nullptr;
body.mGhostObject = new btPairCachingGhostObject();
body.mCollisionShape = new btCompoundShape(false);
body.mGhostObject->setCollisionShape(
body.mCollisionShape);
{
btVector3 inertia(0, 0, 0);
// mCollisionShape = new btCompoundShape();
btScalar height = 1.0f;
btScalar radius = 0.3f;
btCapsuleShape *shape = new btCapsuleShape(
radius, 2 * height - 2 * radius);
btTransform transform;
transform.setIdentity();
transform.setOrigin(btVector3(0, 1, 0));
static_cast<btCompoundShape *>(
body.mCollisionShape)
->addChildShape(transform, shape);
btScalar masses[1] = { 0 };
btTransform principal;
static_cast<btCompoundShape *>(
body.mCollisionShape)
->calculatePrincipalAxisTransform(
masses, principal, inertia);
}
body.mGhostObject->setCollisionFlags(
btCollisionObject::CF_KINEMATIC_OBJECT /*|
btCollisionObject::CF_NO_CONTACT_RESPONSE */);
body.mGhostObject->setActivationState(
DISABLE_DEACTIVATION);
eng.mWorld->attachCollisionObject(
body.mGhostObject, ch.mBodyEnt, 1, 0x7FFFFFFF);
OgreAssert(body.mGhostObject, "Need GhostObject");
OgreAssert(body.mCollisionShape, "No collision shape");
e.add<CharacterGravity>();
e.add<CharacterBuoyancy>();
anim.currentAnim = AnimationControl::ANIM_NONE;
anim.nextAnim = AnimationControl::ANIM_NONE;
anim.reset = false;
anim.configured = false;
});
ecs.system<const EngineData, CharacterBase, CharacterBody>(
"UpdateCharacterPhysics")
.kind(flecs::OnUpdate)

View File

@@ -7,6 +7,8 @@ struct Camera;
/* character */
struct Character {}; /* tag */
struct Player {}; /* tag */
struct CharacterGravity {};
struct CharacterBuoyancy {};
struct CharacterBase {
Ogre::String type;
float mTimer;
@@ -22,6 +24,9 @@ struct CharacterLocation {
Ogre::Quaternion orientation;
Ogre::Vector3 position;
};
struct CharacterConf {
Ogre::String type;
};
struct CharacterBody {
btPairCachingGhostObject *mGhostObject;
btCompoundShape *mCollisionShape;

View File

@@ -0,0 +1,255 @@
#include <iostream>
#include <OgreBullet.h>
#include <OgreMeshManager.h>
#include "Components.h"
#include "GameData.h"
#include "LuaData.h"
#include "EventTriggerModule.h"
struct TriggerBody {
btPairCachingGhostObject *mBody;
btCylinderShape *shape;
Ogre::SceneNode *mSceneNode;
std::set<const btCollisionObject *> contactBodies;
};
struct DeepPenetrationContactResultCallback : public btManifoldResult {
DeepPenetrationContactResultCallback(
const btCollisionObjectWrapper *body0Wrap,
const btCollisionObjectWrapper *body1Wrap)
: btManifoldResult(body0Wrap, body1Wrap)
, mPenetrationDistance(0)
, mOtherIndex(0)
{
}
float mPenetrationDistance;
int mOtherIndex;
btVector3 mNormal, mPoint;
void reset()
{
mPenetrationDistance = 0.0f;
}
bool hasHit()
{
return mPenetrationDistance < 0.0f;
}
virtual void addContactPoint(const btVector3 &normalOnBInWorld,
const btVector3 &pointInWorldOnB,
btScalar depth)
{
#ifdef VDEBUG
std::cout
<< "contact: " << Ogre::Bullet::convert(pointInWorldOnB)
<< " " << Ogre::Bullet::convert(normalOnBInWorld)
<< "\n";
#endif
if (mPenetrationDistance > depth) { // Has penetration?
const bool isSwapped =
m_manifoldPtr->getBody0() !=
m_body0Wrap->getCollisionObject();
mPenetrationDistance = depth;
mOtherIndex = isSwapped ? m_index0 : m_index1;
mPoint = isSwapped ? (pointInWorldOnB +
(normalOnBInWorld * depth)) :
pointInWorldOnB;
mNormal = isSwapped ? normalOnBInWorld * -1 :
normalOnBInWorld;
}
}
};
ECS::EventTriggerModule::EventTriggerModule(flecs::world &ecs)
{
ecs.module<EventTriggerModule>();
ecs.component<EventTriggerExit>();
ecs.component<TriggerBody>().on_add([](flecs::entity e,
TriggerBody &body) {
bool kinematic = false;
if (e.get<EventTrigger>().parent) {
body.mSceneNode =
e.get<EventTrigger>()
.parent->createChildSceneNode(
e.get<EventTrigger>().position,
Ogre::Quaternion(0, 0, 0, 1));
kinematic = true;
} else {
body.mSceneNode =
ECS::get<EngineData>()
.mScnMgr->getRootSceneNode()
->createChildSceneNode(
e.get<EventTrigger>().position,
Ogre::Quaternion(0, 0, 0, 1));
}
Ogre::MeshPtr mesh =
Ogre::MeshManager::getSingleton().createManual(
"trigger", "General");
Ogre::Entity *ent =
ECS::get<EngineData>().mScnMgr->createEntity(mesh);
body.mSceneNode->attachObject(ent);
body.mBody = new btPairCachingGhostObject();
body.mBody->getWorldTransform().setOrigin(Ogre::Bullet::convert(
body.mSceneNode->_getDerivedPosition()));
float h = e.get<EventTrigger>().halfheight;
float r = e.get<EventTrigger>().radius;
Ogre::Vector3 position = e.get<EventTrigger>().position;
body.shape = new btCylinderShape(btVector3(r, h, r));
body.mBody->setCollisionShape(body.shape);
int flags = body.mBody->getCollisionFlags();
flags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
if (kinematic)
flags |= btCollisionObject::CF_STATIC_OBJECT;
body.mBody->setCollisionFlags(flags);
ECS::get<EngineData>().mWorld->attachCollisionObject(
body.mBody, ent, 16, 0x1);
});
ecs.component<EventTrigger>().on_set(
[](flecs::entity e, EventTrigger &ev) {
e.add<TriggerBody>();
});
ecs.system<const EngineData, const EventTrigger, TriggerBody>(
"CheckCollisions")
.kind(flecs::OnUpdate)
.each([](flecs::entity e, const EngineData &eng,
const EventTrigger &evt, TriggerBody &body) {
btDispatcher *dispatch =
eng.mWorld->getBtWorld()->getDispatcher();
btHashedOverlappingPairCache *cache =
body.mBody->getOverlappingPairCache();
int i;
int count = cache->getNumOverlappingPairs();
std::set<const btCollisionObject *> currentContactBodies;
if (count > 0) {
btManifoldArray contacts;
btBroadphasePairArray &collisionPairs =
cache->getOverlappingPairArray();
for (i = 0; i < count; i++) {
contacts.resize(0);
if (collisionPairs[i].m_algorithm) {
collisionPairs[i]
.m_algorithm
->getAllContactManifolds(
contacts);
OgreAssert(false,
"Not implemented");
} else {
const btBroadphasePair *collisionPairPtr =
eng.mWorld->getBtWorld()
->getBroadphase()
->getOverlappingPairCache()
->findPair(
collisionPairs[i]
.m_pProxy0,
collisionPairs[i]
.m_pProxy1);
if (collisionPairPtr) {
const btBroadphasePair
&collisionPair =
*collisionPairPtr;
const btCollisionObject *objA = static_cast<
btCollisionObject
*>(
collisionPair
.m_pProxy0
->m_clientObject);
const btCollisionObject *objB = static_cast<
btCollisionObject
*>(
collisionPair
.m_pProxy1
->m_clientObject);
const btCollisionObject
*me,
*other;
if (objA ==
static_cast<
btCollisionObject
*>(
body.mBody)) {
me = objA;
other = objB;
} else {
me = objB;
other = objA;
}
const btCollisionShape *my_shape =
me->getCollisionShape();
const btCollisionShape *other_shape =
other->getCollisionShape();
btCollisionObjectWrapper obA(
NULL, my_shape,
body.mBody,
body.mBody
->getWorldTransform(),
-1, i);
btCollisionObjectWrapper obB(
NULL,
other_shape,
other,
other->getWorldTransform(),
-1, 0);
btCollisionAlgorithm *algorithm =
dispatch->findAlgorithm(
&obA,
&obB,
NULL,
BT_CONTACT_POINT_ALGORITHMS);
DeepPenetrationContactResultCallback
contactPointResult(
&obA,
&obB);
algorithm->processCollision(
&obA, &obB,
eng.mWorld
->getBtWorld()
->getDispatchInfo(),
&contactPointResult);
algorithm
->~btCollisionAlgorithm();
dispatch->freeCollisionAlgorithm(
algorithm);
if (contactPointResult
.hasHit()) {
currentContactBodies
.insert(other);
if (body.contactBodies
.find(other) ==
body.contactBodies
.end()) {
body.contactBodies
.insert(other);
ECS::get<
LuaBase>()
.mLua
->call_handler(
evt.event);
}
}
}
}
}
}
std::set<const btCollisionObject *>::iterator it =
body.contactBodies.begin();
while (it != body.contactBodies.end()) {
if (currentContactBodies.find(*it) ==
currentContactBodies.end()) {
if (e.has<EventTriggerExit>()) {
const Ogre::String &exit_event =
ECS::get<
EventTriggerExit>()
.event;
ECS::get<LuaBase>()
.mLua->call_handler(
exit_event);
} else {
std::cout << "body exited"
<< std::endl;
}
body.contactBodies.erase(*it);
}
it++;
}
});
}

View File

@@ -0,0 +1,21 @@
#ifndef EVENT_TRIGGER_MODULE_H_
#define EVENT_TRIGGER_MODULE_H_
#include <flecs.h>
#include <Ogre.h>
namespace ECS
{
struct EventTrigger {
Ogre::SceneNode *parent;
Ogre::Vector3 position;
float halfheight;
float radius;
Ogre::String event;
};
struct EventTriggerExit {
Ogre::String event;
};
struct EventTriggerModule {
EventTriggerModule(flecs::world &ecs);
};
}
#endif

View File

@@ -9,6 +9,8 @@
#include "GUIModule.h"
#include "LuaData.h"
#include "WorldMapModule.h"
#include "BoatModule.h"
#include "EventTriggerModule.h"
namespace ECS
{
@@ -43,6 +45,9 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
ecs.import <LuaModule>();
ecs.import <WorldMapModule>();
ecs.import <LuaModule>();
ecs.import <BoatModule>();
ecs.import <EventTriggerModule>();
ecs.system<EngineData>("UpdateDelta")
.kind(flecs::OnUpdate)
.each([](EngineData &eng) {
@@ -95,19 +100,7 @@ void setup(Ogre::SceneManager *scnMgr, Ogre::Bullet::DynamicsWorld *world,
player = ecs.entity("player");
Ogre::Vector3 playerPos(0, 0, 4);
player.set<CharacterLocation>({ { 0, 0, 0, 1 }, playerPos });
player.set<AnimationControl>({ AnimationControl::ANIM_NONE,
AnimationControl::ANIM_NONE, false,
false });
player.set<CharacterBase>({ "normal-male.glb",
0.0f,
nullptr,
nullptr,
nullptr,
nullptr,
{ 0, 0, 0 },
{ 0, 0, 0 },
false });
player.set<CharacterBody>({ nullptr, nullptr, nullptr, false, false });
player.set<CharacterConf>({ "normal-male.glb" });
player.add<Character>();
player.add<Player>();
}

View File

@@ -2,6 +2,9 @@
#include "GameData.h"
#include "Components.h"
#include "GUIModule.h"
#include "CharacterModule.h"
#include "BoatModule.h"
#include "EventTriggerModule.h"
#include "LuaData.h"
extern "C" {
@@ -9,6 +12,32 @@ int luaopen_lpeg(lua_State *L);
}
namespace ECS
{
struct idmap {
std::unordered_map<int, flecs::entity> id2entity;
int next_id;
idmap()
: id2entity({})
, next_id(0)
{
}
int get_next_id()
{
next_id++;
return next_id;
}
int add_entity(flecs::entity e)
{
int id = get_next_id();
id2entity[id] = e;
return id;
}
flecs::entity get_entity(int id)
{
OgreAssert(id2entity[id].is_valid(), "Invalid entity");
return id2entity[id];
}
};
struct idmap idmap;
int LuaData::setup_handler()
{
@@ -161,9 +190,6 @@ LuaData::LuaData()
ECS::modified<GUI>();
std::cout << "narration ended\n";
} else if (message.length() > 0) {
std::replace(message.begin(), message.end(), '\n', ' ');
std::replace(message.begin(), message.end(), '\r', ' ');
ECS::get_mut<GUI>().enabled = true;
ECS::get_mut<GUI>().grab = false;
ECS::get_mut<GUI>().grabChanged = true;
@@ -191,6 +217,134 @@ LuaData::LuaData()
return 0;
});
lua_setglobal(L, "main_menu");
lua_pushcfunction(L, [](lua_State *L) -> int {
OgreAssert(lua_gettop(L) == 3, "Invalid parameters");
luaL_checktype(L, 1, LUA_TSTRING);
luaL_checktype(L, 2, LUA_TSTRING);
luaL_checktype(L, 3, LUA_TBOOLEAN);
bool enable = lua_toboolean(L, 3);
flecs::entity e = ECS::get().lookup(lua_tostring(L, 1));
Ogre::String what = lua_tostring(L, 2);
OgreAssert(e.is_valid(), "Invalid character");
OgreAssert(e.has<Character>(), "Not a character");
if (what == "gravity") {
/* clear momentum */
e.get_mut<CharacterVelocity>().gvelocity.y = 0.0f;
e.get_mut<CharacterVelocity>().velocity.y = 0.0f;
e.modified<CharacterVelocity>();
if (enable)
e.add<CharacterGravity>();
else
e.remove<CharacterGravity>();
} else if (what == "buoyancy") {
if (enable)
e.add<CharacterBuoyancy>();
else
e.remove<CharacterBuoyancy>();
} else
OgreAssert(false, "Bad parameter " + what);
return 0;
});
lua_setglobal(L, "ecs_character_params_set");
lua_pushcfunction(L, [](lua_State *L) -> int {
luaL_checktype(L, 1, LUA_TSTRING);
luaL_checktype(L, 2, LUA_TNUMBER);
luaL_checktype(L, 3, LUA_TNUMBER);
luaL_checktype(L, 4, LUA_TNUMBER);
luaL_checktype(L, 5, LUA_TNUMBER);
Ogre::String what = lua_tostring(L, 1);
if (what == "boat") {
float yaw = lua_tonumber(L, 5);
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
float z = lua_tonumber(L, 4);
flecs::entity e = ECS::get().entity();
Ogre::Quaternion orientation(Ogre::Radian(yaw),
Ogre::Vector3(0, 1, 0));
Ogre::Vector3 position(x, y, z);
e.set<BoatType>({ "boat.glb", position, orientation });
lua_pushinteger(L, idmap.add_entity(e));
return 1;
}
lua_pushinteger(L, -1);
return 1;
});
lua_setglobal(L, "ecs_vehicle_set");
lua_pushcfunction(L, [](lua_State *L) -> int {
OgreAssert(lua_gettop(L) == 6, "bad parameters");
luaL_checktype(L, 1, LUA_TSTRING); // event
luaL_checktype(L, 2, LUA_TNUMBER); // x
luaL_checktype(L, 3, LUA_TNUMBER); // y
luaL_checktype(L, 4, LUA_TNUMBER); // z
luaL_checktype(L, 5, LUA_TNUMBER); // halfh
luaL_checktype(L, 6, LUA_TNUMBER); // radius
flecs::entity e = ECS::get().entity();
Ogre::String event = lua_tostring(L, 1);
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
float z = lua_tonumber(L, 4);
float h = lua_tonumber(L, 5);
float r = lua_tonumber(L, 6);
Ogre::Vector3 position(x, y, z);
e.set<EventTrigger>({ nullptr, position, h, r, event });
lua_pushinteger(L, idmap.add_entity(e));
return 1;
});
lua_setglobal(L, "ecs_character_trigger");
lua_pushcfunction(L, [](lua_State *L) -> int {
OgreAssert(lua_gettop(L) == 7, "bad parameters");
luaL_checktype(L, 1, LUA_TNUMBER); // parent
luaL_checktype(L, 2, LUA_TSTRING); // event
luaL_checktype(L, 3, LUA_TNUMBER); // x
luaL_checktype(L, 4, LUA_TNUMBER); // y
luaL_checktype(L, 5, LUA_TNUMBER); // z
luaL_checktype(L, 6, LUA_TNUMBER); // halfh
luaL_checktype(L, 7, LUA_TNUMBER); // radius
int parent = lua_tointeger(L, 1);
flecs::entity parent_e = idmap.get_entity(parent);
Ogre::SceneNode *parentNode = nullptr;
if (parent_e.has<CharacterBase>())
parentNode = parent_e.get<CharacterBase>().mBodyNode;
else if (parent_e.has<BoatBase>())
parentNode = parent_e.get<BoatBase>().mNode;
flecs::entity e = ECS::get().entity().child_of(parent_e);
Ogre::String event = lua_tostring(L, 2);
float x = lua_tonumber(L, 3);
float y = lua_tonumber(L, 4);
float z = lua_tonumber(L, 5);
float h = lua_tonumber(L, 6);
float r = lua_tonumber(L, 7);
OgreAssert(parentNode, "bad parent");
Ogre::Vector3 position(x, y, z);
e.set<EventTrigger>({ parentNode, position, h, r, event });
lua_pushinteger(L, idmap.add_entity(e));
return 1;
});
lua_setglobal(L, "ecs_child_character_trigger");
lua_pushcfunction(L, [](lua_State *L) -> int {
OgreAssert(lua_gettop(L) == 5, "Invalid parameters");
luaL_checktype(L, 1, LUA_TSTRING); // type
luaL_checktype(L, 2, LUA_TNUMBER);
luaL_checktype(L, 3, LUA_TNUMBER);
luaL_checktype(L, 4, LUA_TNUMBER);
luaL_checktype(L, 5, LUA_TNUMBER);
Ogre::String type = lua_tostring(L, 1);
float yaw = lua_tonumber(L, 5);
float x = lua_tonumber(L, 2);
float y = lua_tonumber(L, 3);
float z = lua_tonumber(L, 4);
flecs::entity e = ECS::get().entity();
Ogre::Quaternion orientation(Ogre::Radian(yaw),
Ogre::Vector3(0, 1, 0));
Ogre::Vector3 npcPos(x, y, z);
e.set<CharacterLocation>({ orientation, npcPos });
e.set<CharacterConf>({ type });
e.add<Character>();
lua_pushinteger(L, idmap.add_entity(e));
return 1;
});
lua_setglobal(L, "ecs_npc_set");
}
LuaData::~LuaData()
@@ -200,6 +354,7 @@ LuaData::~LuaData()
void LuaData::lateSetup()
{
#if 0
Ogre::DataStreamList streams =
Ogre::ResourceGroupManager::getSingleton().openResources(
"*.lua", "LuaScripts");
@@ -212,6 +367,16 @@ void LuaData::lateSetup()
OgreAssert(false, "Script failure");
}
}
#endif
Ogre::DataStreamPtr stream =
Ogre::ResourceGroupManager::getSingleton().openResource(
"data.lua", "LuaScripts");
std::cout << "stream: " << stream->getAsString() << "\n";
if (luaL_dostring(L, stream->getAsString().c_str()) != LUA_OK) {
std::cout << "error: " << lua_tostring(L, -1) << "\n";
OgreAssert(false, "Script failure");
}
const char *lua_code = "\n\
function stuff()\n\
return 4\n\
@@ -226,8 +391,14 @@ void LuaData::lateSetup()
LuaModule::LuaModule(flecs::world &ecs)
{
ecs.component<LuaBase>().add(flecs::Singleton);
ecs.set<LuaBase>({ OGRE_NEW LuaData, false, false });
ecs.component<LuaBase>()
.on_add([](LuaBase &lua) {
lua.mLua = new LuaData;
lua.setup_called = false;
lua.startup_called = false;
})
.add(flecs::Singleton);
ecs.add<LuaBase>();
ecs.system<const EngineData, LuaBase>("LuaUpdate")
.kind(flecs::OnUpdate)
.each([](const EngineData &eng, LuaBase &lua) {

View File

@@ -17,7 +17,7 @@
#include "TerrainModule.h"
#define TERRAIN_SIZE 129
#define TERRAIN_WORLD_SIZE 4000.0f
#define TERRAIN_WORLD_SIZE 1000.0f
#define ENDLESS_TERRAIN_FILE_PREFIX Ogre::String("EndlessWorldTerrain")
#define ENDLESS_TERRAIN_FILE_SUFFIX Ogre::String("dat")
@@ -82,10 +82,11 @@ struct HeightData {
world_y + (int)img.getHeight() * BRUSH_SIZE / 2;
Ogre::ColourValue color, colorb1, colorb2;
// float d;
int map_img_x = world_img_x / (BRUSH_SIZE);
int map_img_y = world_img_y / (BRUSH_SIZE);
int brush_img_x = world_img_x % BRUSH_SIZE;
int brush_img_y = world_img_y % BRUSH_SIZE;
int div = 1;
int map_img_x = world_img_x / (BRUSH_SIZE) / div;
int map_img_y = world_img_y / (BRUSH_SIZE) / div;
int brush_img_x = (world_img_x / div) % BRUSH_SIZE;
int brush_img_y = (world_img_y / div) % BRUSH_SIZE;
if (world_img_x < 0 ||
world_img_x >= img.getWidth() * BRUSH_SIZE ||
world_img_y < 0 ||
@@ -316,6 +317,11 @@ public:
what->attachObject(ent);
what->setOrientation(item.rotation);
what->setPosition(item.position);
ECS::get<EngineData>()
.mWorld->addRigidBody(
0, ent,
Ogre::Bullet::CT_TRIMESH,
nullptr, 2, 0x7fffffff);
}
} else {
output.push_back(collider_queue.front());
@@ -367,6 +373,8 @@ struct TerrainPrivate {
TerrainModule::TerrainModule(flecs::world &ecs)
{
struct CanSetPlayerPosition {};
ecs.component<CanSetPlayerPosition>().add(flecs::Singleton);
ecs.component<Terrain>().add(flecs::Singleton);
ecs.component<TerrainPrivate>().add(flecs::Singleton);
ecs.set<TerrainPrivate>({ nullptr, {} });
@@ -528,8 +536,8 @@ TerrainModule::TerrainModule(flecs::world &ecs)
0);
item.position.y = height;
placement.altar_items.push_back(item);
for (i = -64000; i < 64000; i += 1000)
for (j = -64000; j < 64000; j += 1000) {
for (i = -64000; i < 64000; i += 2000)
for (j = -64000; j < 64000; j += 2000) {
if (i == 0 && j == 0)
continue;
Ogre::Vector3 position(i, 0, j);
@@ -566,6 +574,7 @@ TerrainModule::TerrainModule(flecs::world &ecs)
#endif
if (height > -9.0f)
continue;
#ifdef VDEBUG
std::cout << "worldSize: "
<< worldSize - 1
<< std::endl;
@@ -573,6 +582,7 @@ TerrainModule::TerrainModule(flecs::world &ecs)
<< " " << j << " "
<< height
<< std::endl;
#endif
item.entity = "altar.glb";
item.rotation =
Ogre::Quaternion(0, 0,
@@ -582,6 +592,7 @@ TerrainModule::TerrainModule(flecs::world &ecs)
placement.altar_items.push_back(
item);
}
#ifdef VDEBUG
for (i = 0; i < placement.altar_items.size();
i++) {
std::cout << "placement: " << i << " "
@@ -589,20 +600,38 @@ TerrainModule::TerrainModule(flecs::world &ecs)
.position
<< std::endl;
}
flecs::entity player = ECS::player;
CharacterLocation &loc =
player.get_mut<CharacterLocation>();
height = get_height(terrain.mTerrainGroup,
loc.position);
loc.position.y = height + 0.0f;
player.get<CharacterBase>()
.mBodyNode->setPosition(loc.position);
player.get<CharacterBase>()
.mBodyNode->setOrientation(
Ogre::Quaternion());
player.modified<CharacterLocation>();
#endif
ECS::get().add<CanSetPlayerPosition>();
}
});
ecs.system<const Terrain>("SetPlayerPosition")
.kind(flecs::OnUpdate)
.with<CanSetPlayerPosition>()
.each([this](const Terrain &terrain) {
flecs::entity player = ECS::player;
if (!player.is_valid())
return;
if (!player.has<CharacterLocation>())
return;
if (!player.has<CharacterBase>())
return;
if (!player.has<Player>())
return;
CharacterLocation &loc =
player.get_mut<CharacterLocation>();
const CharacterBase &ch = player.get<CharacterBase>();
if (!ch.mBodyNode) {
std::cout << "no player yet";
return;
}
float height =
get_height(terrain.mTerrainGroup, loc.position);
loc.position.y = height + 0.0f;
ch.mBodyNode->setPosition(loc.position);
ch.mBodyNode->setOrientation(Ogre::Quaternion());
player.modified<CharacterLocation>();
ECS::get().remove<CanSetPlayerPosition>();
});
}
float TerrainModule::get_height(Ogre::TerrainGroup *group,
const Ogre::Vector3 &position)

View File

@@ -349,7 +349,9 @@ WaterModule::WaterModule(flecs::world &ecs)
water.mReflectionCamera->setNearClipDistance(
camera.mCamera->getNearClipDistance());
water.mReflectionCamera->setFarClipDistance(
camera.mCamera->getFarClipDistance());
Ogre::Math::Clamp(
camera.mCamera->getFarClipDistance(),
10.0f, 10.0f));
water.mReflectionCamera->enableCustomNearClipPlane(
water.mReflectionClipPlaneAbove);
water.mReflectionCamera->enableReflection(
@@ -410,7 +412,9 @@ WaterModule::WaterModule(flecs::world &ecs)
water.mRefractionCamera->setNearClipDistance(
camera.mCamera->getNearClipDistance());
water.mRefractionCamera->setFarClipDistance(
camera.mCamera->getFarClipDistance());
Ogre::Math::Clamp(
camera.mCamera->getFarClipDistance(),
1.0f, 10.0f));
water.mRefractionCamera->enableCustomNearClipPlane(
water.mRefractionClipPlaneAbove);
@@ -507,14 +511,14 @@ WaterModule::WaterModule(flecs::world &ecs)
water.mWaterNode->translate(d * 3.0f * delta);
else
water.mWaterNode->translate(d);
water.mWaterEnt->setVisible(false);
// water.mWaterEnt->setVisible(false);
water.mViewports[0]->update();
water.mViewports[1]->update();
water.mRenderTargetListener.mInDepth = true;
water.mViewports[2]->update();
water.mViewports[3]->update();
water.mRenderTargetListener.mInDepth = false;
water.mWaterEnt->setVisible(true);
// water.mRenderTargetListener.mInDepth = true;
// water.mViewports[2]->update();
// water.mViewports[3]->update();
// water.mRenderTargetListener.mInDepth = false;
// water.mWaterEnt->setVisible(true);
});
ecs.system<const EngineData, const WaterSurface, WaterBody>(
"UpdateWaterBody")