Inventory system basically works now but is in a alpha hack stage. Time to refactor.
This commit is contained in:
parent
b7f49aa719
commit
e0e7a1027c
11 changed files with 92 additions and 33 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
12
guecs.cpp
12
guecs.cpp
|
@ -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);
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
guecs.hpp
11
guecs.hpp
|
@ -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)) {
|
||||||
|
auto name = std::any_cast<std::string>(data);
|
||||||
|
$status_ui.log(fmt::format("NOOP EVENT! {},{} name={}", evt, entity, name));
|
||||||
|
}
|
||||||
$status_ui.update();
|
$status_ui.update();
|
||||||
break;
|
} 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…
Add table
Add a link
Reference in a new issue