Lots of updates - lua, narrator, logic, models
This commit is contained in:
@@ -195,6 +195,12 @@ endif()
|
||||
|
||||
add_dependencies(TerrainTest stage_lua_scripts stage_files)
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/stories
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/lua-scripts/stories ${CMAKE_BINARY_DIR}/stories
|
||||
DEPENDS ${CMAKE_BINARY_DIR}/lua-scripts/stories
|
||||
)
|
||||
add_custom_target(stage_stories ALL DEPENDS stage_lua_scripts ${CMAKE_BINARY_DIR}/stories)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/resources.cfg
|
||||
COMMAND cp ${CMAKE_SOURCE_DIR}/resources.cfg ${CMAKE_BINARY_DIR}/resources.cfg
|
||||
|
||||
19
Game.cpp
19
Game.cpp
@@ -282,10 +282,6 @@ public:
|
||||
control &= ~256;
|
||||
return false;
|
||||
}
|
||||
void update(float delta)
|
||||
{
|
||||
return;
|
||||
}
|
||||
void frameRendered(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
@@ -432,18 +428,22 @@ public:
|
||||
}
|
||||
void updateWorld(float delta)
|
||||
{
|
||||
mDynWorld->getBtWorld()->stepSimulation(delta, 4);
|
||||
mDynWorld->getBtWorld()->stepSimulation(delta, 3);
|
||||
if (!ECS::get().has<ECS::GUI>())
|
||||
return;
|
||||
/* Update window grab */
|
||||
if (ECS::get().has<ECS::GUI>() &&
|
||||
ECS::get().get<ECS::GUI>().grabChanged) {
|
||||
setWindowGrab(ECS::get().get<ECS::GUI>().grab);
|
||||
ECS::get().get_mut<ECS::GUI>().grabChanged = false;
|
||||
ECS::GUI &gui = ECS::get().get_mut<ECS::GUI>();
|
||||
if (gui.grabChanged) {
|
||||
setWindowGrab(gui.grab);
|
||||
gui.grabChanged = false;
|
||||
ECS::get().modified<ECS::GUI>();
|
||||
}
|
||||
ECS::update(delta);
|
||||
|
||||
/*
|
||||
if (enabldDbgDraw)
|
||||
mDbgDraw->update();
|
||||
*/
|
||||
}
|
||||
class InputListenerChainFlexible : public OgreBites::InputListener {
|
||||
protected:
|
||||
@@ -761,7 +761,6 @@ void KeyboardListener::frameRendered(const Ogre::FrameEvent &evt)
|
||||
<< "\n";
|
||||
fps_timer.reset();
|
||||
}
|
||||
update(evt.timeSinceLastFrame);
|
||||
if (!isGuiEnabled() ||
|
||||
(isGuiEnabled() && ECS::get<ECS::GUI>().narrationBox)) {
|
||||
mApp->updateWorld(evt.timeSinceLastFrame);
|
||||
|
||||
BIN
assets/blender/edited-normal-male.blend
(Stored with Git LFS)
BIN
assets/blender/edited-normal-male.blend
(Stored with Git LFS)
Binary file not shown.
@@ -54,6 +54,20 @@ class ExportMappingMale:
|
||||
self.files.append({"name": fobj})
|
||||
|
||||
class ExportMappingMaleEdited:
|
||||
blend_path = "assets/blender/" + "edited-normal-male.blend"
|
||||
gltf_path = "characters/male/normal-male.gltf"
|
||||
ogre_scene = "characters/male/vroid-normal-male.scene"
|
||||
inner_path = "Object"
|
||||
objs = ["male", "Body", "Hair", "Face", "BackHair"]
|
||||
armature_name = "male"
|
||||
outfile = "tmp-male.blend"
|
||||
default_action = 'default'
|
||||
def __init__(self):
|
||||
self.files = []
|
||||
for fobj in self.objs:
|
||||
self.files.append({"name": fobj})
|
||||
|
||||
class ExportMappingMaleClothedEdited:
|
||||
blend_path = "assets/blender/" + "edited-normal-male.blend"
|
||||
gltf_path = "characters/male/normal-male.gltf"
|
||||
ogre_scene = "characters/male/vroid-normal-male.scene"
|
||||
|
||||
BIN
assets/blender/vehicles/boat-sails.blend
(Stored with Git LFS)
Normal file
BIN
assets/blender/vehicles/boat-sails.blend
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/blender/vehicles/boat.blend
(Stored with Git LFS)
BIN
assets/blender/vehicles/boat.blend
(Stored with Git LFS)
Binary file not shown.
@@ -63,15 +63,6 @@ dropped you into the sea. Last thing you heard before you hit the water was happ
|
||||
]]--
|
||||
local narrator = require('narrator.narrator')
|
||||
|
||||
-- Parse a book from the Ink file.
|
||||
local book = narrator.parse_file('stories.game')
|
||||
|
||||
-- Init a story from the book
|
||||
local story = narrator.init_story(book)
|
||||
|
||||
-- Begin the story
|
||||
story:begin()
|
||||
|
||||
function dump(o)
|
||||
if type(o) == 'table' then
|
||||
local s = '{ '
|
||||
@@ -85,26 +76,45 @@ function dump(o)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
function _narration()
|
||||
local ret = ""
|
||||
local choices = {}
|
||||
if story:can_continue() then
|
||||
local paragraphs = story:continue()
|
||||
for _, paragraph in ipairs(paragraphs) do
|
||||
local text = paragraph.text
|
||||
if paragraph.tags then
|
||||
text = text .. ' #' .. table.concat(paragraph.tags, ' #')
|
||||
print("can continue")
|
||||
local paragraph = story:continue(1)
|
||||
print(dump(paragraph))
|
||||
local text = paragraph.text
|
||||
if paragraph.tags then
|
||||
text = text .. ' #' .. table.concat(paragraph.tags, ' #')
|
||||
for i, tag in ipairs(paragraph.tags) do
|
||||
if tag == "mc_is_free" then
|
||||
ecs_character_set("player", "gravity", true)
|
||||
ecs_character_set("player", "buoyancy", true)
|
||||
end
|
||||
end
|
||||
ret = ret .. text
|
||||
end
|
||||
ret = text
|
||||
if story:can_choose() then
|
||||
local ch = story:get_choices()
|
||||
for i, choice in ipairs(ch) do
|
||||
table.insert(choices, choice.text)
|
||||
print(i, dump(choice))
|
||||
end
|
||||
if #choices == 1 and choices[1] == "Ascend" then
|
||||
story:choose(1)
|
||||
choices = {}
|
||||
end
|
||||
if #choices == 1 and choices[1] == "Continue" then
|
||||
story:choose(1)
|
||||
choices = {}
|
||||
end
|
||||
end
|
||||
else
|
||||
print("can NOT continue")
|
||||
end
|
||||
print(ret)
|
||||
if (#choices > 0) then
|
||||
print("choices!!!")
|
||||
narrate(ret, choices)
|
||||
@@ -112,9 +122,134 @@ function _narration()
|
||||
narrate(ret)
|
||||
end
|
||||
end
|
||||
]]--
|
||||
function Quest(name, book)
|
||||
local quest = {
|
||||
name = name,
|
||||
active = false,
|
||||
activate = function(this)
|
||||
this.active = true
|
||||
this.story:begin()
|
||||
this:_narration()
|
||||
end,
|
||||
event = function(this, event)
|
||||
if not this.active then
|
||||
return
|
||||
end
|
||||
if event == "narration_progress" then
|
||||
this:_narration()
|
||||
elseif event == "narration_answered" then
|
||||
local answer = narration_get_answer()
|
||||
this.story:choose(answer)
|
||||
print("answered:", answer)
|
||||
this:_narration()
|
||||
end
|
||||
end,
|
||||
_handle_tag = function(this, tag)
|
||||
if tag == "mc_is_free" then
|
||||
ecs_character_set("player", "gravity", true)
|
||||
ecs_character_set("player", "buoyancy", true)
|
||||
end
|
||||
end,
|
||||
_narration = function(this)
|
||||
local ret = ""
|
||||
local choices = {}
|
||||
local have_choice = false
|
||||
local have_paragraph = false
|
||||
if not this.active then
|
||||
return
|
||||
end
|
||||
if this.story:can_continue() then
|
||||
print("can continue")
|
||||
have_paragraph = true
|
||||
local paragraph = this.story:continue(1)
|
||||
print(dump(paragraph))
|
||||
local text = paragraph.text
|
||||
if paragraph.tags then
|
||||
text = text .. ' #' .. table.concat(paragraph.tags, ' #')
|
||||
for i, tag in ipairs(paragraph.tags) do
|
||||
this:_handle_tag(tag)
|
||||
end
|
||||
end
|
||||
ret = text
|
||||
if this.story:can_choose() then
|
||||
have_choice = true
|
||||
local ch = this.story:get_choices()
|
||||
for i, choice in ipairs(ch) do
|
||||
table.insert(choices, choice.text)
|
||||
print(i, dump(choice))
|
||||
end
|
||||
if #choices == 1 and choices[1] == "Ascend" then
|
||||
this.story:choose(1)
|
||||
choices = {}
|
||||
end
|
||||
if #choices == 1 and choices[1] == "Continue" then
|
||||
this.story:choose(1)
|
||||
choices = {}
|
||||
end
|
||||
end
|
||||
else
|
||||
print("can NOT continue")
|
||||
end
|
||||
if not have_choice and not have_paragraph then
|
||||
this:complete()
|
||||
this.active = false
|
||||
end
|
||||
print(ret)
|
||||
if (#choices > 0) then
|
||||
print("choices!!!")
|
||||
narrate(ret, choices)
|
||||
else
|
||||
narrate(ret)
|
||||
end
|
||||
end,
|
||||
complete = function(this)
|
||||
print(this.name .. 'complete')
|
||||
end,
|
||||
story = narrator.init_story(book)
|
||||
}
|
||||
|
||||
-- Begin the story
|
||||
|
||||
return quest
|
||||
end
|
||||
function StartGameQuest()
|
||||
-- Parse a book from the Ink file.
|
||||
local book = narrator.parse_file('stories.initiation')
|
||||
local quest = Quest('start game', book)
|
||||
quest.base = {}
|
||||
quest.base.activate = quest.activate
|
||||
quest.base.complete = quest.complete
|
||||
quest.boat = false
|
||||
quest.activate = function(this)
|
||||
print('activate...')
|
||||
local mc_is_free = function()
|
||||
ecs_character_params_set("player", "gravity", true)
|
||||
ecs_character_params_set("player", "buoyancy", true)
|
||||
end
|
||||
this.story:bind('mc_is_free', mc_is_free)
|
||||
this.base.activate(this)
|
||||
end
|
||||
quest.complete = function(this)
|
||||
this.base.complete(this)
|
||||
this.active = false
|
||||
if not this.boat then
|
||||
local boat = ecs_vehicle_set("boat", 0, 0, -20, 1.75)
|
||||
local trigger = ecs_child_character_trigger(boat, "entered_boat", 0, 0, 0, 3, 3)
|
||||
local npc = ecs_npc_set("normal-female.glb", 0, 2, -20, 1.75)
|
||||
this.boat = true
|
||||
end
|
||||
end
|
||||
return quest
|
||||
end
|
||||
quests = {}
|
||||
setup_handler(function(event)
|
||||
print(event)
|
||||
for k, v in pairs(quests) do
|
||||
if v.active then
|
||||
v:event(event)
|
||||
end
|
||||
end
|
||||
if event == "startup" then
|
||||
main_menu()
|
||||
elseif event == "narration_progress" then
|
||||
@@ -122,12 +257,16 @@ setup_handler(function(event)
|
||||
elseif event == "narration_answered" then
|
||||
local answer = narration_get_answer()
|
||||
story:choose(answer)
|
||||
print("answered:", answer)
|
||||
_narration()
|
||||
elseif event == "new_game" then
|
||||
local ret = ""
|
||||
story = narrator.init_story(book)
|
||||
story:begin()
|
||||
_narration()
|
||||
ecs_character_params_set("player", "gravity", true)
|
||||
ecs_character_params_set("player", "buoyancy", false)
|
||||
local quest = StartGameQuest()
|
||||
quests[quest.name] = quest
|
||||
for k, v in pairs(quests) do
|
||||
print(k, v.active)
|
||||
end
|
||||
quest:activate()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
35
lua-scripts/stories/initiation.ink
Normal file
35
lua-scripts/stories/initiation.ink
Normal file
@@ -0,0 +1,35 @@
|
||||
- The party was hot, girls were sexy the wine, beer and whisky were in <>
|
||||
enormous numbers. It was anniversary since you set sail with your friends.
|
||||
The sea was calm and everything promised you another great night. <>
|
||||
The whole year with your friends on your ship over vast seas of the world in decay was almost over. <>
|
||||
It was so good year full of adventure, romance, indecency and luxury.
|
||||
You did not know what future had for you and you never thought much about it. However <>
|
||||
you had zero insights on what to follow even if you cared enough about it. You thought you could not <>
|
||||
wish for brigher future far away from troubles of this world.
|
||||
One day (a few days ago) your trusted friends decided that you have too much, they have too much of you and you owe them a lot.<>
|
||||
They waited for opportunity to get rid of you. You totally missed the point when people started conspiring against you<>
|
||||
and the following events came at total surprize.
|
||||
They found you drunk in your room and moved to the deck and used ropes to <>
|
||||
restrain you and attach a bucket of stones or something else heavy to your body. <>
|
||||
They left you lying on the deck while were checking your room, looking for papers and something of value.
|
||||
After a few hours passed two strong people pulled you to the side and <>
|
||||
dropped you into the sea. You did not see their faces. Last thing you heard before you hit the water was happy laugher...
|
||||
Suddenly next you found yourself under water out of breath in agony. You did not know nor care about time and place, you just cared for <>
|
||||
last air leaving your body. All you wished for was quick end.
|
||||
Suddenly the suffering stopped and your mind cleared. Some impactful presence <>
|
||||
subdued everything in your mind leaving you with question. The only thing you could see was a strange altar for some ancient deity nearby.
|
||||
You had very bad feeling about this.
|
||||
'You have just a few seconds, so be quick' - the voice sounded directly somewhere inside your head.
|
||||
'WILL you serve me?' Something told me my life depends on the answer.
|
||||
* Sure
|
||||
Of course you will.
|
||||
* Do I have a choice?
|
||||
You have or you have not. That depends on what you expect.
|
||||
* I will
|
||||
I know.
|
||||
- An abrupt silence.
|
||||
Then I feel my restraints removed and I started rising to the surface. 'We'll talk again soon enough' - the voice in my head told me.
|
||||
'Your service will be rewarded. Go enjoy your new life.'
|
||||
* [Ascend]
|
||||
~ mc_is_free()
|
||||
- ->END
|
||||
35
src/gamedata/BoatModule.cpp
Normal file
35
src/gamedata/BoatModule.cpp
Normal 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
28
src/gamedata/BoatModule.h
Normal 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
|
||||
@@ -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})
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
255
src/gamedata/EventTriggerModule.cpp
Normal file
255
src/gamedata/EventTriggerModule.cpp
Normal 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++;
|
||||
}
|
||||
});
|
||||
}
|
||||
21
src/gamedata/EventTriggerModule.h
Normal file
21
src/gamedata/EventTriggerModule.h
Normal 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
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user