Refactored inventory some so that the UI is not so knowing of the internals.

master
Zed A. Shaw 10 months ago
parent e0e7a1027c
commit 0878a9e978
  1. 60
      components.hpp
  2. 48
      dinky_components.hpp
  3. 27
      inventory.cpp
  4. 3
      inventory.hpp
  5. 2
      levelmanager.hpp
  6. 31
      status_ui.cpp
  7. 10
      systems.cpp
  8. 1
      systems.hpp

@ -1,17 +1,23 @@
#pragma once
#include "dinkyecs.hpp"
#include "components.hpp"
#include "constants.hpp"
#include "config.hpp"
#include "dinky_components.hpp"
#include "constants.hpp"
#include "dinkyecs.hpp"
#include "point.hpp"
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/System/Vector2.hpp>
#include <functional>
#include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp>
#define ENROLL_COMPONENT(COMPONENT, ...) \
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \
template <> struct NameOf<COMPONENT> { \
static constexpr const char *name = #COMPONENT; \
};
namespace components {
struct Player {
DinkyECS::Entity entity;
};
using namespace nlohmann;
struct Position {
Point location;
@ -104,7 +110,7 @@ namespace components {
void step(sf::Vector2f& scale_out, sf::IntRect& rect_out);
};
void configure(ComponentMap& component_map);
template <typename T> struct NameOf;
// these need to be here if you're using components::convert outside of components.cpp
ENROLL_COMPONENT(Tile, display, foreground, background);
@ -113,4 +119,42 @@ namespace components {
ENROLL_COMPONENT(LightSource, strength, radius);
ENROLL_COMPONENT(Weapon, damage);
ENROLL_COMPONENT(Loot, amount);
using ReflFuncSignature = std::function<void(DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j)>;
using ComponentMap = std::unordered_map<std::string, ReflFuncSignature>;
struct Player {
DinkyECS::Entity entity;
};
template<typename COMPONENT> COMPONENT convert(nlohmann::json &data) {
COMPONENT result;
from_json(data, result);
return result;
}
template<typename COMPONENT> COMPONENT get(nlohmann::json &data) {
for (auto &i : data["components"]) {
if(i["_type"] == NameOf<COMPONENT>::name) {
COMPONENT result;
from_json(i, result);
return result;
}
}
return {};
}
template <typename COMPONENT> void enroll(ComponentMap &m) {
m[NameOf<COMPONENT>::name] = [](DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j) {
COMPONENT c;
from_json(j, c);
world.set<COMPONENT>(ent, c);
};
}
void configure(ComponentMap& component_map);
void configure_entity(const ComponentMap& component_map, DinkyECS::World& world, DinkyECS::Entity ent, json& data);
}

@ -1,48 +0,0 @@
#pragma once
#include <functional>
#include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp>
#include "dinkyecs.hpp"
#define ENROLL_COMPONENT(COMPONENT, ...) \
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \
template <> struct NameOf<COMPONENT> { \
static constexpr const char *name = #COMPONENT; \
};
namespace components {
using namespace nlohmann;
template <typename T> struct NameOf;
using ReflFuncSignature = std::function<void(DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j)>;
using ComponentMap = std::unordered_map<std::string, ReflFuncSignature>;
template<typename COMPONENT> COMPONENT convert(nlohmann::json &data) {
COMPONENT result;
from_json(data, result);
return result;
}
template<typename COMPONENT> COMPONENT get(nlohmann::json &data) {
for (auto &i : data["components"]) {
if(i["_type"] == NameOf<COMPONENT>::name) {
COMPONENT result;
from_json(i, result);
return result;
}
}
return {};
}
template <typename COMPONENT> void enroll(ComponentMap &m) {
m[NameOf<COMPONENT>::name] = [](DinkyECS::World& world, DinkyECS::Entity ent, nlohmann::json &j) {
COMPONENT c;
from_json(j, c);
world.set<COMPONENT>(ent, c);
};
}
void configure_entity(const ComponentMap& component_map, DinkyECS::World& world, DinkyECS::Entity ent, json& data);
}

@ -40,4 +40,31 @@ namespace components {
return -1;
}
std::pair<bool, std::string> Inventory::use(GameLevel &level, size_t at) {
auto& player_combat = level.world->get<components::Combat>(level.player);
auto& item = get(at);
if(item.count == 0) return {false, item.data["name"]};
if(item.data["id"] == "SWORD_RUSTY") {
auto weapon = components::get<components::Weapon>(item.data);
player_combat.damage = weapon.damage;
} else if(item.data["id"] == "POTION_HEALING_SMALL") {
auto cure = components::get<components::Curative>(item.data);
player_combat.hp = std::min(player_combat.hp + cure.hp, player_combat.max_hp);
} else if(item.data["id"] == "TORCH_BAD") {
auto new_light = components::get<components::LightSource>(item.data);
level.world->set<components::LightSource>(level.player, new_light);
light = new_light;
} else {
return {false, fmt::format("UNKNOWN ITEM: {}", (std::string)item.data["id"])};
}
decrease(at, 1);
return {true, item.data["name"]};
}
}

@ -1,6 +1,7 @@
#pragma once
#include "components.hpp"
#include <nlohmann/json.hpp>
#include "levelmanager.hpp"
namespace components {
using namespace nlohmann;
@ -26,5 +27,7 @@ namespace components {
int item_index(std::string id);
void erase_item(size_t at);
std::pair<bool, std::string> use(GameLevel &level, size_t at);
};
}

@ -6,7 +6,7 @@
#include <vector>
#include <memory>
#include "spatialmap.hpp"
#include "dinky_components.hpp"
#include "components.hpp"
using std::shared_ptr;

@ -47,34 +47,15 @@ namespace gui {
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);
auto [used, name] = inventory.use($level, 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;
if(used) {
log(fmt::format("Used item: {}", name));
} else {
log(fmt::format("You are out of {}.", name));
}
}
}

@ -141,6 +141,7 @@ void System::death(GameLevel &level, components::ComponentMap& components) {
auto entity_data = config.items["GRAVE_STONE"];
components::configure_entity(components, world, ent, entity_data["components"]);
if(entity_data["inventory_count"] > 0) {
// right here use a std::any that's already converted instead?
world.set<InventoryItem>(ent, {entity_data["inventory_count"], entity_data});
}
}
@ -248,15 +249,6 @@ void System::collision(GameLevel &level) {
}
}
void System::pickup(DinkyECS::World &world, DinkyECS::Entity actor, DinkyECS::Entity item) {
dbc::pre("System::pickup actor doesn't have inventory", world.has<Inventory>(actor));
dbc::pre("System::pickup item isn't configured with InventoryItem.", world.has<InventoryItem>(item));
auto& inventory = world.get<Inventory>(actor);
auto& invitem = world.get<InventoryItem>(item);
inventory.add(invitem);
}
void System::device(DinkyECS::World &world, DinkyECS::Entity actor, DinkyECS::Entity item) {
auto& device = world.get<Device>(item);

@ -14,7 +14,6 @@ namespace System {
void enemy_pathing(GameLevel &level);
void init_positions(DinkyECS::World &world, SpatialMap &collider);
void pickup(DinkyECS::World &world, DinkyECS::Entity actor, DinkyECS::Entity item);
void device(DinkyECS::World &world, DinkyECS::Entity actor, DinkyECS::Entity item);
void plan_motion(DinkyECS::World& world, Point move_to);
void draw_entities(DinkyECS::World &world, Map &map, const Matrix &lights, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y);