Inventory system basically works now but is in a alpha hack stage. Time to refactor.

master
Zed A. Shaw 2 weeks ago
parent b7f49aa719
commit e0e7a1027c
  1. 6
      assets/config.json
  2. 2
      assets/enemies.json
  3. 4
      components.cpp
  4. 4
      components.hpp
  5. 12
      guecs.cpp
  6. 11
      guecs.hpp
  7. 11
      gui_fsm.cpp
  8. 60
      status_ui.cpp
  9. 5
      status_ui.hpp
  10. 9
      systems.cpp
  11. 1
      worldbuilder.hpp

@ -38,8 +38,8 @@
"player": { "player": {
}, },
"worldgen": { "worldgen": {
"enemy_probability": 30, "enemy_probability": 10,
"empty_room_probability": 10, "empty_room_probability": 1,
"device_probability": 20 "device_probability": 10
} }
} }

@ -8,7 +8,7 @@
}, },
{"_type": "Combat", "hp": 200, "max_hp": 200, "damage": 50, "dead": false}, {"_type": "Combat", "hp": 200, "max_hp": 200, "damage": 50, "dead": false},
{"_type": "Motion", "dx": 0, "dy": 0, "random": false}, {"_type": "Motion", "dx": 0, "dy": 0, "random": false},
{"_type": "LightSource", "strength": 50, "radius": 1.0}, {"_type": "LightSource", "strength": 40, "radius": 1.5},
{"_type": "EnemyConfig", "hearing_distance": 5}, {"_type": "EnemyConfig", "hearing_distance": 5},
{"_type": "Animation", "scale": 0.1, "simple": true, "frames": 10, "speed": 1.0} {"_type": "Animation", "scale": 0.1, "simple": true, "frames": 10, "speed": 1.0}
] ]

@ -2,14 +2,10 @@
#include "point.hpp" #include "point.hpp"
namespace components { namespace components {
ENROLL_COMPONENT(Loot, amount);
ENROLL_COMPONENT(Position, location.x, location.y); ENROLL_COMPONENT(Position, location.x, location.y);
ENROLL_COMPONENT(Weapon, damage);
ENROLL_COMPONENT(Curative, hp);
ENROLL_COMPONENT(EnemyConfig, hearing_distance); ENROLL_COMPONENT(EnemyConfig, hearing_distance);
ENROLL_COMPONENT(Motion, dx, dy, random); ENROLL_COMPONENT(Motion, dx, dy, random);
ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead); ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead);
ENROLL_COMPONENT(LightSource, strength, radius);
ENROLL_COMPONENT(Device, config, events); ENROLL_COMPONENT(Device, config, events);
ENROLL_COMPONENT(Animation, scale, simple, frames, speed); ENROLL_COMPONENT(Animation, scale, simple, frames, speed);
ENROLL_COMPONENT(Sound, attack, death); ENROLL_COMPONENT(Sound, attack, death);

@ -109,4 +109,8 @@ namespace components {
// these need to be here if you're using components::convert outside of components.cpp // these need to be here if you're using components::convert outside of components.cpp
ENROLL_COMPONENT(Tile, display, foreground, background); ENROLL_COMPONENT(Tile, display, foreground, background);
ENROLL_COMPONENT(Sprite, name); ENROLL_COMPONENT(Sprite, name);
ENROLL_COMPONENT(Curative, hp);
ENROLL_COMPONENT(LightSource, strength, radius);
ENROLL_COMPONENT(Weapon, damage);
ENROLL_COMPONENT(Loot, amount);
} }

@ -103,15 +103,19 @@ namespace guecs {
if((x >= cell.x && x <= cell.x + cell.w) && if((x >= cell.x && x <= cell.x + cell.w) &&
(y >= cell.y && y <= cell.y + cell.h)) (y >= cell.y && y <= cell.y + cell.h))
{ {
auto& cn = $world.get<CellName>(ent); if(auto action_data = get_if<ActionData>(ent)) {
clicked.action(ent, cn.name); clicked.action(ent, action_data->data);
} else {
clicked.action(ent, {});
}
} }
}); });
} }
Clickable make_action(DinkyECS::World& target, Events::GUI event) { Clickable make_action(DinkyECS::World& target, Events::GUI event) {
return {[&, event](auto ent, auto&){ return {[&, event](auto ent, auto data){
target.send<Events::GUI>(event, ent, {}); // remember that ent is passed in from the UI::mouse handler
target.send<Events::GUI>(event, ent, data);
}}; }};
} }
} }

@ -10,6 +10,7 @@
#include "events.hpp" #include "events.hpp"
#include "constants.hpp" #include "constants.hpp"
#include "components.hpp" #include "components.hpp"
#include <any>
namespace guecs { namespace guecs {
using std::shared_ptr, std::make_shared; using std::shared_ptr, std::make_shared;
@ -50,7 +51,10 @@ namespace guecs {
}; };
struct Clickable { struct Clickable {
std::function<void(DinkyECS::Entity ent, std::string &name)> action; /* This is actually called by UI::mouse and passed the entity ID of the
* button pressed so you can interact with it in the event handler.
*/
std::function<void(DinkyECS::Entity ent, std::any data)> action;
}; };
struct Sprite { struct Sprite {
@ -95,6 +99,10 @@ namespace guecs {
} }
}; };
struct ActionData {
std::any data;
};
struct CellName { struct CellName {
std::string name; std::string name;
}; };
@ -157,6 +165,7 @@ namespace guecs {
template <typename Comp> template <typename Comp>
void set_init(DinkyECS::Entity ent, Comp val) { void set_init(DinkyECS::Entity ent, Comp val) {
dbc::check(has<lel::Cell>(ent),"WRONG! slot is missing its cell?!");
auto& cell = get<lel::Cell>(ent); auto& cell = get<lel::Cell>(ent);
val.init(cell); val.init(cell);
$world.set<Comp>(ent, val); $world.set<Comp>(ent, val);

@ -355,10 +355,13 @@ namespace gui {
$main_ui.dead_entity(entity); $main_ui.dead_entity(entity);
} }
} break; } break;
case eGUI::NOOP: case eGUI::NOOP: {
$status_ui.log(fmt::format("NOOP EVENT! {},{}", evt, entity)); if(data.type() == typeid(std::string)) {
$status_ui.update(); auto name = std::any_cast<std::string>(data);
break; $status_ui.log(fmt::format("NOOP EVENT! {},{} name={}", evt, entity, name));
}
$status_ui.update();
} break;
default: default:
$status_ui.log(fmt::format("INVALID EVENT! {},{}", evt, entity)); $status_ui.log(fmt::format("INVALID EVENT! {},{}", evt, entity));
$status_ui.update(); $status_ui.update();

@ -31,14 +31,58 @@ namespace gui {
auto button = $gui.entity(name); auto button = $gui.entity(name);
$gui.set<Rectangle>(button, {}); $gui.set<Rectangle>(button, {});
$gui.set<Textual>(button, {""}); $gui.set<Textual>(button, {""});
$gui.set<Clickable>(button, $gui.set<ActionData>(button, {std::make_any<std::string>(name)});
guecs::make_action(*$level.world, Events::GUI::NOOP)); $gui.set<Clickable>(button, {
[&](auto ent, auto data){ select_slot(ent, data); }
});
} }
} }
$gui.init(); $gui.init();
} }
void StatusUI::select_slot(DinkyECS::Entity ent, std::any) {
auto cn = $gui.get<CellName>(ent);
auto world = $level.world;
if(world->has<components::Inventory>($level.player)) {
auto& inventory = world->get<components::Inventory>($level.player);
for(size_t i = 0; i < inventory.count(); i++) {
if($slots[i] == cn.name) {
auto& player_combat = world->get<components::Combat>($level.player);
auto& item = inventory.get(i);
if(item.count == 0) continue;
if(item.data["id"] == "SWORD_RUSTY") {
auto weapon = components::get<components::Weapon>(item.data);
player_combat.damage = weapon.damage;
inventory.decrease(i, 1);
log("You equip a new sword.");
break;
} else if(item.data["id"] == "POTION_HEALING_SMALL") {
auto cure = components::get<components::Curative>(item.data);
int prev_hp = player_combat.hp;
player_combat.hp = std::min(player_combat.hp + cure.hp, player_combat.max_hp);
log(fmt::format("Healed player from {} to {}", prev_hp, player_combat.hp));
inventory.decrease(i, 1);
break;
} else if(item.data["id"] == "TORCH_BAD") {
auto new_light = components::get<components::LightSource>(item.data);
world->set<components::LightSource>($level.player, new_light);
inventory.light = new_light;
inventory.decrease(i, 1);
log("You are using a new torch.");
break;
}
}
}
update();
}
}
/* WARNING: This is really not the greatest way to do this. */ /* WARNING: This is really not the greatest way to do this. */
void StatusUI::update() { void StatusUI::update() {
if($gui.has<Textual>($log_to)) { if($gui.has<Textual>($log_to)) {
@ -62,11 +106,17 @@ namespace gui {
auto& item = inventory.get(i); auto& item = inventory.get(i);
auto comp_sprite = components::get<components::Sprite>(item.data); auto comp_sprite = components::get<components::Sprite>(item.data);
$gui.set_init<guecs::Sprite>(slot, {comp_sprite.name}); $gui.set_init<guecs::Sprite>(slot, {comp_sprite.name});
std::string count_label = fmt::format("{}", item.count);
std::string count_label = item.count > 1 ? fmt::format("{}", item.count): "";
auto& label = $gui.get<Textual>(slot); auto& label = $gui.get<Textual>(slot);
label.text->setString(count_label); label.text->setString(count_label);
auto& sprite = $gui.get<guecs::Sprite>(slot);
if(item.count == 0) {
sprite.sprite->setColor({125, 125, 125});
} else {
sprite.sprite->setColor({255, 255, 255});
}
} }
} }
} }

@ -11,14 +11,15 @@ namespace gui {
guecs::UI $gui; guecs::UI $gui;
DinkyECS::Entity $log_to; DinkyECS::Entity $log_to;
std::array<std::string, 9> $slots = { std::array<std::string, 9> $slots = {
"slot1", "slot2", "slot3" "slot1", "slot2", "slot3",
"slot4", "slot5", "slot6" "slot4", "slot5", "slot6",
"slot7", "slot8", "slot9" "slot7", "slot8", "slot9"
}; };
std::deque<std::string> $messages; std::deque<std::string> $messages;
GameLevel $level; GameLevel $level;
StatusUI(GameLevel level); StatusUI(GameLevel level);
void select_slot(DinkyECS::Entity ent, std::any data);
void update_level(GameLevel &level) { $level = level; } void update_level(GameLevel &level) { $level = level; }
void log(std::string msg); void log(std::string msg);
void render(); void render();

@ -189,7 +189,6 @@ void System::collision(GameLevel &level) {
auto player = world.get_the<Player>(); auto player = world.get_the<Player>();
const auto& player_position = world.get<Position>(player.entity); const auto& player_position = world.get<Position>(player.entity);
auto& player_combat = world.get<Combat>(player.entity);
// this is guaranteed to not return the given position // this is guaranteed to not return the given position
auto [found, nearby] = collider.neighbors(player_position.location); auto [found, nearby] = collider.neighbors(player_position.location);
@ -210,16 +209,11 @@ void System::collision(GameLevel &level) {
if(world.has<LightSource>(entity)) { if(world.has<LightSource>(entity)) {
inventory.add(item); inventory.add(item);
auto &new_light = world.get<LightSource>(entity);
world.set<LightSource>(player.entity, new_light);
inventory.light = new_light;
world.remove<LightSource>(entity); world.remove<LightSource>(entity);
} }
if(world.has<Weapon>(entity)) { if(world.has<Weapon>(entity)) {
inventory.add(item); inventory.add(item);
auto &weapon = world.get<Weapon>(entity);
player_combat.damage = weapon.damage;
world.remove<Weapon>(entity); world.remove<Weapon>(entity);
} }
@ -230,8 +224,7 @@ void System::collision(GameLevel &level) {
} }
if(world.has<Curative>(entity)) { if(world.has<Curative>(entity)) {
auto& cure = world.get<Curative>(entity); inventory.add(item);
player_combat.hp = std::min(player_combat.hp + cure.hp, player_combat.max_hp);
world.remove<Curative>(entity); world.remove<Curative>(entity);
} }

@ -28,7 +28,6 @@ class WorldBuilder {
DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, nlohmann::json &entity_data, int in_room); DinkyECS::Entity configure_entity_in_map(DinkyECS::World &world, nlohmann::json &entity_data, int in_room);
void place_entities(DinkyECS::World &world); void place_entities(DinkyECS::World &world);
void generate(DinkyECS::World &world); void generate(DinkyECS::World &world);
void random_entity(DinkyECS::World &world, components::GameConfig &config);
void randomize_entities(DinkyECS::World &world, components::GameConfig &config); void randomize_entities(DinkyECS::World &world, components::GameConfig &config);
void place_stairs(DinkyECS::World& world, components::GameConfig& config); void place_stairs(DinkyECS::World& world, components::GameConfig& config);
}; };

Loading…
Cancel
Save