Refactored the FSM so that it uses a generic registry of systems to do what it needs.
This commit is contained in:
parent
cbff127b40
commit
e742b8772d
7 changed files with 150 additions and 118 deletions
82
src/game/registry.hpp
Normal file
82
src/game/registry.hpp
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include "game/components.hpp"
|
||||||
|
|
||||||
|
namespace System {
|
||||||
|
using MovingFunc = std::function<void(components::Position& move_to)>;
|
||||||
|
using CombatFunc = std::function<void(int attack_id)>;
|
||||||
|
using RenderFunc = std::function<void()>;
|
||||||
|
using UpdateFunc = std::function<void()>;
|
||||||
|
using UseItemFunc = std::function<void(const std::string& slot_name)>;
|
||||||
|
using PickupFunc = std::function<void()>;
|
||||||
|
|
||||||
|
struct Registry {
|
||||||
|
std::vector<MovingFunc> $moving;
|
||||||
|
std::vector<CombatFunc> $combat;
|
||||||
|
std::vector<RenderFunc> $render;
|
||||||
|
std::vector<UpdateFunc> $update;
|
||||||
|
std::vector<UseItemFunc> $use_item;
|
||||||
|
std::vector<PickupFunc> $pickup;
|
||||||
|
|
||||||
|
void addMoving(MovingFunc action) {
|
||||||
|
$moving.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCombat(CombatFunc action) {
|
||||||
|
$combat.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addRender(RenderFunc action) {
|
||||||
|
$render.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addUpdate(UpdateFunc action) {
|
||||||
|
$update.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addUseItem(UseItemFunc action) {
|
||||||
|
$use_item.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPickup(PickupFunc action) {
|
||||||
|
$pickup.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void runMoving(components::Position move_to) {
|
||||||
|
for(auto func : $moving) {
|
||||||
|
func(move_to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runCombat(int attack_id) {
|
||||||
|
for(auto func : $combat) {
|
||||||
|
func(attack_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runRender() {
|
||||||
|
for(auto func : $render) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runUpdate() {
|
||||||
|
for(auto func : $update) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runUseItem(const std::string& slot_name) {
|
||||||
|
for(auto func : $use_item) {
|
||||||
|
func(slot_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runPickup() {
|
||||||
|
for(auto func : $pickup) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -474,14 +474,14 @@ bool System::inventory_occupied(Entity container_id, const std::string& name) {
|
||||||
return inventory.has(name);
|
return inventory.has(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::use_item(const string& slot_name) {
|
void System::use_item(const string& slot_name) {
|
||||||
auto& level = GameDB::current_level();
|
auto& level = GameDB::current_level();
|
||||||
auto& world = *level.world;
|
auto& world = *level.world;
|
||||||
auto& inventory = world.get<inventory::Model>(level.player);
|
auto& inventory = world.get<inventory::Model>(level.player);
|
||||||
auto& player_combat = world.get<Combat>(level.player);
|
auto& player_combat = world.get<Combat>(level.player);
|
||||||
|
|
||||||
if(player_combat.hp >= player_combat.max_hp) return false;
|
if(player_combat.hp >= player_combat.max_hp) return;
|
||||||
if(!inventory.has(slot_name)) return false;
|
if(!inventory.has(slot_name)) return;
|
||||||
|
|
||||||
auto what = inventory.get(slot_name);
|
auto what = inventory.get(slot_name);
|
||||||
|
|
||||||
|
|
@ -498,10 +498,8 @@ bool System::use_item(const string& slot_name) {
|
||||||
player_combat.hp));
|
player_combat.hp));
|
||||||
|
|
||||||
world.remove<Curative>(what);
|
world.remove<Curative>(what);
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
dbc::log($F("no usable item at {}", what));
|
dbc::log($F("no usable item at {}", what));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,3 +539,19 @@ void System::clear_attack() {
|
||||||
|
|
||||||
void System::spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy) {
|
void System::spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void System::init(Registry& reg) {
|
||||||
|
reg.addRender(System::clear_attack);
|
||||||
|
reg.addUseItem(System::use_item);
|
||||||
|
reg.addMoving(System::move_player);
|
||||||
|
reg.addCombat(System::combat);
|
||||||
|
reg.addPickup(System::pickup);
|
||||||
|
reg.addUpdate(System::generate_paths);
|
||||||
|
reg.addUpdate(System::enemy_ai_initialize);
|
||||||
|
reg.addUpdate(System::enemy_pathing);
|
||||||
|
reg.addUpdate(System::motion);
|
||||||
|
reg.addUpdate(System::collision);
|
||||||
|
reg.addUpdate(System::lighting);
|
||||||
|
reg.addUpdate(System::death);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@
|
||||||
#include "algos/spatialmap.hpp"
|
#include "algos/spatialmap.hpp"
|
||||||
#include "game/level.hpp"
|
#include "game/level.hpp"
|
||||||
#include "events.hpp"
|
#include "events.hpp"
|
||||||
|
#include "game/registry.hpp"
|
||||||
|
|
||||||
namespace System {
|
namespace System {
|
||||||
|
|
||||||
using namespace components;
|
using namespace components;
|
||||||
using namespace DinkyECS;
|
using namespace DinkyECS;
|
||||||
using std::string, matrix::Matrix;
|
using std::string, matrix::Matrix;
|
||||||
|
|
@ -32,15 +34,15 @@ namespace System {
|
||||||
|
|
||||||
void pickup();
|
void pickup();
|
||||||
|
|
||||||
|
// BUG: these might need to go somewhere else....
|
||||||
bool place_in_container(Entity cont_id, const string& name, Entity world_entity);
|
bool place_in_container(Entity cont_id, const string& name, Entity world_entity);
|
||||||
|
|
||||||
void remove_from_container(Entity cont_id, const std::string& name);
|
void remove_from_container(Entity cont_id, const std::string& name);
|
||||||
void remove_from_world(Entity entity);
|
void remove_from_world(Entity entity);
|
||||||
void inventory_swap(Entity container_id, const std::string& a_name, const std::string &b_name);
|
void inventory_swap(Entity container_id, const std::string& a_name, const std::string &b_name);
|
||||||
bool inventory_occupied(Entity container_id, const std::string& name);
|
bool inventory_occupied(Entity container_id, const std::string& name);
|
||||||
|
|
||||||
void set_position(DinkyECS::World& world, SpatialMap& collision, Entity entity, Position pos);
|
void set_position(DinkyECS::World& world, SpatialMap& collision, Entity entity, Position pos);
|
||||||
bool use_item(const std::string& slot_name);
|
void use_item(const std::string& slot_name);
|
||||||
|
|
||||||
game::Event shortest_rotate(Point player_at, Point aiming_at, Point turning_to);
|
game::Event shortest_rotate(Point player_at, Point aiming_at, Point turning_to);
|
||||||
|
|
||||||
|
|
@ -67,4 +69,6 @@ namespace System {
|
||||||
|
|
||||||
void clear_attack();
|
void clear_attack();
|
||||||
void spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy);
|
void spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy);
|
||||||
|
|
||||||
|
void init(Registry& reg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace gui {
|
||||||
void FSM::MOVING(Event ) {
|
void FSM::MOVING(Event ) {
|
||||||
// this should be an optional that returns a point
|
// this should be an optional that returns a point
|
||||||
if(auto move_to = $main_ui.play_move()) {
|
if(auto move_to = $main_ui.play_move()) {
|
||||||
System::move_player(*move_to);
|
$systems.runMoving(*move_to);
|
||||||
run_systems();
|
run_systems();
|
||||||
$main_ui.dirty();
|
$main_ui.dirty();
|
||||||
state(State::IDLE);
|
state(State::IDLE);
|
||||||
|
|
@ -70,7 +70,7 @@ namespace gui {
|
||||||
switch(ev) {
|
switch(ev) {
|
||||||
case TICK: {
|
case TICK: {
|
||||||
dbc::log("!!!!!! FIX System::combat(0) doesn't use any weapons, only first");
|
dbc::log("!!!!!! FIX System::combat(0) doesn't use any weapons, only first");
|
||||||
System::combat(0);
|
$systems.runCombat(0);
|
||||||
run_systems();
|
run_systems();
|
||||||
state(State::IN_COMBAT);
|
state(State::IN_COMBAT);
|
||||||
} break;
|
} break;
|
||||||
|
|
@ -79,7 +79,7 @@ namespace gui {
|
||||||
break;
|
break;
|
||||||
case ATTACK: {
|
case ATTACK: {
|
||||||
int attack_id = std::any_cast<int>(data);
|
int attack_id = std::any_cast<int>(data);
|
||||||
System::combat(attack_id);
|
$systems.runCombat(attack_id);
|
||||||
run_systems();
|
run_systems();
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -174,10 +174,8 @@ namespace gui {
|
||||||
case USE_ITEM: {
|
case USE_ITEM: {
|
||||||
auto gui_id = std::any_cast<guecs::Entity>(data);
|
auto gui_id = std::any_cast<guecs::Entity>(data);
|
||||||
auto& slot_name = $status_ui.$gui.name_for(gui_id);
|
auto& slot_name = $status_ui.$gui.name_for(gui_id);
|
||||||
|
$systems.runUseItem(slot_name);
|
||||||
if(System::use_item(slot_name)) {
|
|
||||||
$status_ui.update();
|
$status_ui.update();
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case MOUSE_CLICK:
|
case MOUSE_CLICK:
|
||||||
mouse_action(guecs::NO_MODS);
|
mouse_action(guecs::NO_MODS);
|
||||||
|
|
@ -186,7 +184,7 @@ namespace gui {
|
||||||
mouse_action({1 << guecs::ModBit::hover});
|
mouse_action({1 << guecs::ModBit::hover});
|
||||||
} break;
|
} break;
|
||||||
case AIM_CLICK:
|
case AIM_CLICK:
|
||||||
System::pickup();
|
$systems.runPickup();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break; // ignore everything else
|
break; // ignore everything else
|
||||||
|
|
@ -312,9 +310,6 @@ namespace gui {
|
||||||
$debug_ui.debug();
|
$debug_ui.debug();
|
||||||
shaders::reload();
|
shaders::reload();
|
||||||
break;
|
break;
|
||||||
case KEY::O:
|
|
||||||
autowalking = true;
|
|
||||||
break;
|
|
||||||
case KEY::L:
|
case KEY::L:
|
||||||
// This will go away as soon as containers work
|
// This will go away as soon as containers work
|
||||||
$loot_ui.set_target($loot_ui.$temp_loot);
|
$loot_ui.set_target($loot_ui.$temp_loot);
|
||||||
|
|
@ -360,10 +355,8 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSM::render() {
|
void FSM::render() {
|
||||||
$window.clear();
|
|
||||||
|
|
||||||
// this clears any attack animations, like fire
|
// this clears any attack animations, like fire
|
||||||
System::clear_attack();
|
$systems.runRender();
|
||||||
// BUG: this is the render for this class, and where I add an update
|
// BUG: this is the render for this class, and where I add an update
|
||||||
draw_gui();
|
draw_gui();
|
||||||
|
|
||||||
|
|
@ -371,13 +364,7 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSM::run_systems() {
|
void FSM::run_systems() {
|
||||||
System::generate_paths();
|
$systems.runUpdate();
|
||||||
System::enemy_ai_initialize();
|
|
||||||
System::enemy_pathing();
|
|
||||||
System::motion();
|
|
||||||
System::collision();
|
|
||||||
System::lighting();
|
|
||||||
System::death();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSM::active() {
|
bool FSM::active() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
|
#include "game/registry.hpp"
|
||||||
#include "algos/simplefsm.hpp"
|
#include "algos/simplefsm.hpp"
|
||||||
#include "gui/debug_ui.hpp"
|
#include "gui/debug_ui.hpp"
|
||||||
#include "gui/main_ui.hpp"
|
#include "gui/main_ui.hpp"
|
||||||
|
|
@ -35,12 +36,11 @@ namespace gui {
|
||||||
LootUI $loot_ui;
|
LootUI $loot_ui;
|
||||||
gui::routing::Router $router;
|
gui::routing::Router $router;
|
||||||
DNDLoot $dnd_loot;
|
DNDLoot $dnd_loot;
|
||||||
|
System::Registry $systems;
|
||||||
|
|
||||||
FSM();
|
FSM();
|
||||||
|
|
||||||
void event(game::Event ev, std::any data={});
|
void event(game::Event ev, std::any data={});
|
||||||
void autowalk();
|
|
||||||
void start_autowalk(double rot_speed);
|
|
||||||
|
|
||||||
void START(game::Event ev);
|
void START(game::Event ev);
|
||||||
void MOVING(game::Event ev);
|
void MOVING(game::Event ev);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "gui/backend.hpp"
|
#include "gui/backend.hpp"
|
||||||
#include "game/level.hpp"
|
#include "game/level.hpp"
|
||||||
#include "graphics/camera.hpp"
|
#include "graphics/camera.hpp"
|
||||||
|
#include "game/systems.hpp"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -21,6 +22,7 @@ int main(int argc, char* argv[]) {
|
||||||
sound::mute(true);
|
sound::mute(true);
|
||||||
|
|
||||||
gui::FSM main;
|
gui::FSM main;
|
||||||
|
System::init(main.$systems);
|
||||||
main.event(game::Event::START);
|
main.event(game::Event::START);
|
||||||
|
|
||||||
sound::play("ambient_1", true);
|
sound::play("ambient_1", true);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
#include "game/systems.hpp"
|
#include "game/systems.hpp"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
#include "game/registry.hpp"
|
||||||
|
|
||||||
|
using components::Position;
|
||||||
|
|
||||||
TEST_CASE("figure out best rotation direction", "[systems-rotate]") {
|
TEST_CASE("figure out best rotation direction", "[systems-rotate]") {
|
||||||
Matrix map = matrix::make(3, 3);
|
Matrix map = matrix::make(3, 3);
|
||||||
|
|
@ -35,104 +37,45 @@ TEST_CASE("figure out best rotation direction", "[systems-rotate]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using MovingFunc = std::function<void()>;
|
|
||||||
using CombatFunc = std::function<void(bool)>;
|
|
||||||
using RenderFunc = std::function<void()>;
|
|
||||||
using UpdateFunc = std::function<void()>;
|
|
||||||
using UseFunc = std::function<void()>;
|
|
||||||
using PickupFunc = std::function<void()>;
|
|
||||||
|
|
||||||
struct Engine {
|
void test_moving(Position& move_to) {
|
||||||
std::vector<MovingFunc> $moving;
|
fmt::println("MOVING: {},{}", move_to.location.x, move_to.location.y);
|
||||||
std::vector<CombatFunc> $combat;
|
|
||||||
std::vector<RenderFunc> $render;
|
|
||||||
std::vector<UpdateFunc> $update;
|
|
||||||
std::vector<UseFunc> $use;
|
|
||||||
std::vector<PickupFunc> $pickup;
|
|
||||||
|
|
||||||
void addMoving(MovingFunc action) {
|
|
||||||
$moving.emplace_back(action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCombat(CombatFunc action) {
|
void test_combat(int attack_id) {
|
||||||
$combat.emplace_back(action);
|
fmt::println("ATTACK: {}", attack_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addRender(RenderFunc action) {
|
void test_render() {
|
||||||
$render.emplace_back(action);
|
fmt::println("RENDER");
|
||||||
}
|
}
|
||||||
|
|
||||||
void addUpdate(UpdateFunc action) {
|
void test_update() {
|
||||||
$update.emplace_back(action);
|
fmt::println("UPDATE");
|
||||||
}
|
}
|
||||||
|
|
||||||
void addUse(UseFunc action) {
|
void test_use_item(const std::string& slot_name) {
|
||||||
$use.emplace_back(action);
|
fmt::println("USE ITEM {}", slot_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPickup(PickupFunc action) {
|
void test_pickup() {
|
||||||
$pickup.emplace_back(action);
|
fmt::println("PICKUP");
|
||||||
}
|
|
||||||
|
|
||||||
void runMoving() {
|
|
||||||
for(auto func : $moving) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runCombat(bool attr) {
|
|
||||||
for(auto func : $combat) {
|
|
||||||
func(attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runRender() {
|
|
||||||
for(auto func : $render) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runUpdate() {
|
|
||||||
for(auto func : $update) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runUse() {
|
|
||||||
for(auto func : $use) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runPickup() {
|
|
||||||
for(auto func : $pickup) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void test_system_1() {
|
|
||||||
fmt::println("TEST 1");
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_combat(bool what) {
|
|
||||||
fmt::println("TEST 2: {}", what);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("new system running engine thing", "[systems-engine]") {
|
TEST_CASE("new system running engine thing", "[systems-engine]") {
|
||||||
Engine systems;
|
System::Registry systems;
|
||||||
|
|
||||||
systems.addMoving(test_system_1);
|
systems.addMoving(test_moving);
|
||||||
systems.addCombat(test_combat);
|
systems.addCombat(test_combat);
|
||||||
systems.addRender(test_system_1);
|
systems.addRender(test_render);
|
||||||
systems.addUpdate(test_system_1);
|
systems.addUpdate(test_update);
|
||||||
systems.addUse(test_system_1);
|
systems.addUseItem(test_use_item);
|
||||||
systems.addPickup(test_system_1);
|
systems.addPickup(test_pickup);
|
||||||
|
|
||||||
systems.runCombat(false);
|
systems.runCombat(1);
|
||||||
systems.runMoving();
|
systems.runMoving({1,1});
|
||||||
systems.runRender();
|
systems.runRender();
|
||||||
systems.runUpdate();
|
systems.runUpdate();
|
||||||
systems.runUse();
|
systems.runUseItem("hand_l");
|
||||||
systems.runPickup();
|
systems.runPickup();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue