Inventory system is mostly working and I can pick up everything and use it.

main
Zed A. Shaw 2 years ago
parent aaa6d9f9f3
commit 14b3ea7676
  1. 6
      assets/items.json
  2. 30
      gui.cpp
  3. 1
      gui.hpp
  4. 34
      inventory.cpp
  5. 8
      inventory.hpp
  6. 10
      main.cpp
  7. 4
      systems.cpp
  8. 10
      tests/inventory.cpp

@ -4,7 +4,7 @@
"name": "Crappy Torch", "name": "Crappy Torch",
"foreground": [24, 205, 189], "foreground": [24, 205, 189],
"background": [230, 20, 120], "background": [230, 20, 120],
"description": "Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. Summus brains sit​​, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris. Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium.", "description": "A torch that barely lights the way. You wonder if it'd be better to not see the person who murders you.",
"display": "\u0f08" "display": "\u0f08"
}, },
"SWORD_RUSTY": { "SWORD_RUSTY": {
@ -12,7 +12,7 @@
"name": "Rusty Junk Sword", "name": "Rusty Junk Sword",
"foreground": [24, 205, 189], "foreground": [24, 205, 189],
"background": [24, 205, 189], "background": [24, 205, 189],
"description": "Shoreditch pickled readymade tousled tumeric. Chicharrones same jawn irony woke echo park jianbing artisan ethical praxis grailed portland. Banjo solarpunk yes plz, offal Brooklyn beard bushwick letterpress celiac sartorial.", "description": "A sword left to rot in a deep hole where it acquired a patina of dirt and tetanus. You aren't sure if it's more deadly for you to hold it or for the people you stab with it.",
"display":"\u1e37" "display":"\u1e37"
}, },
"CHEST_SMALL": { "CHEST_SMALL": {
@ -21,7 +21,7 @@
"foreground": [24, 205, 189], "foreground": [24, 205, 189],
"background": [24, 205, 189], "background": [24, 205, 189],
"display":"\uaaea", "display":"\uaaea",
"description": "Tote bag sustainable crucifix gentrify kombucha. Try-hard single-origin coffee meh pork belly cliche aesthetic scenester disrupt banjo af." "description": "A small chest of gold. You wonder who would leave something like this around."
}, },
"WALL_TORCH": { "WALL_TORCH": {
"id": "WALL_TORCH", "id": "WALL_TORCH",

@ -31,14 +31,14 @@ using namespace ftxui;
using namespace components; using namespace components;
void InventoryUI::create_render() { void InventoryUI::create_render() {
auto inventory_render = Renderer([&] { MenuOption option;
$inventory_box = Menu(&$menu_list, &$selected, option);
$inventory_render = Renderer([&] {
auto &player = $world.get_the<Player>(); auto &player = $world.get_the<Player>();
auto &inventory = $world.get<Inventory>(player.entity); auto &inventory = $world.get<Inventory>(player.entity);
update_menu_list(inventory); update_menu_list(inventory);
MenuOption option;
$inventory_box = Menu(&$menu_list, &$selected, option);
return hbox({ return hbox({
$inventory_box->Render() | frame | size(WIDTH, EQUAL, 35) | yflex_grow, $inventory_box->Render() | frame | size(WIDTH, EQUAL, 35) | yflex_grow,
separator() | yflex_grow, separator() | yflex_grow,
@ -48,26 +48,22 @@ void InventoryUI::create_render() {
}) | border | flex; }) | border | flex;
}); });
set_renderer(inventory_render); set_renderer($inventory_render);
add($inventory_box);
} }
void InventoryUI::update_menu_list(Inventory& inventory) { void InventoryUI::update_menu_list(Inventory& inventory) {
// BUG: probably need to have a dirty marker on inventory
// so we don't update this all the damn time
$menu_list.clear(); $menu_list.clear();
int i = 0; // SOOOOO BADDDDD for(size_t i = 0; i < inventory.count(); i++) {
for(auto& [key, val] : inventory.items) { auto& item = inventory.get(i);
$menu_list.push_back(fmt::format("{} {} ({})", $menu_list.push_back(fmt::format("{} {} ({})",
string(val.data["display"]), string(item.data["display"]),
string(val.data["name"]), string(item.data["name"]),
val.count)); item.count));
// GARBAGE HOT if($selected == int(i)) {
if($selected == i) { $item_text = item.data["description"];
$item_text = val.data["description"];
} }
i++;
} }
} }

@ -53,6 +53,7 @@ class InventoryUI : public Panel {
int $selected = 0; int $selected = 0;
Component $inventory_box; Component $inventory_box;
Component $inventory_render;
Component $inventory_table; Component $inventory_table;
DinkyECS::World& $world; DinkyECS::World& $world;
std::vector<std::string> $menu_list; std::vector<std::string> $menu_list;

@ -2,31 +2,31 @@
namespace components { namespace components {
void Inventory::add(InventoryItem item) { void Inventory::add(InventoryItem new_item) {
std::string id = item.data["id"]; for(auto &slot : items) {
if(new_item.data["id"] == slot.data["id"]) {
if(items.contains(id)) { slot.count += new_item.count;
auto &slot = items[id]; return;
slot.count += item.count; }
} else {
items[id] = item;
} }
items.push_back(new_item);
} }
InventoryItem& Inventory::get(std::string id) { InventoryItem& Inventory::get(size_t at) {
dbc::check(items.contains(id), fmt::format("item id {} is not in inventory", id)); dbc::check(at < items.size(), fmt::format("inventory index {} too big", at));
return items[id]; return items[at];
} }
bool Inventory::decrease(std::string id, int count) { bool Inventory::decrease(size_t at, int count) {
dbc::check(items.contains(id), fmt::format("item id {} is not in inventory", id)); dbc::check(at < items.size(), fmt::format("inventory index {} too big", at));
auto &slot = items[id]; auto &slot = items[at];
slot.count -= count; slot.count -= count;
return slot.count > 0; return slot.count > 0;
} }
void Inventory::remove_all(std::string id) { void Inventory::erase_item(size_t at) {
dbc::check(items.contains(id), fmt::format("item id {} is not in inventory", id)); dbc::check(at < items.size(), fmt::format("inventory index {} too big", at));
items.erase(id); items.erase(items.begin() + at);
} }
} }

@ -16,16 +16,16 @@ namespace components {
struct Inventory { struct Inventory {
int gold; int gold;
LightSource light; LightSource light;
std::unordered_map<std::string, InventoryItem> items; std::vector<InventoryItem> items;
size_t count() { return items.size(); } size_t count() { return items.size(); }
void add(InventoryItem item); void add(InventoryItem item);
bool decrease(std::string id, int count); bool decrease(size_t at, int count);
InventoryItem& get(std::string id); InventoryItem& get(size_t at);
void remove_all(std::string id); void erase_item(size_t at);
}; };
} }

@ -34,7 +34,7 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
world.set<Motion>(player.entity, {0, 0}); world.set<Motion>(player.entity, {0, 0});
world.set<Combat>(player.entity, {100, 10}); world.set<Combat>(player.entity, {100, 10});
world.set<Tile>(player.entity, {config.enemies["PLAYER_TILE"]["display"]}); world.set<Tile>(player.entity, {config.enemies["PLAYER_TILE"]["display"]});
world.set<LightSource>(player.entity, {70,1.0}); world.set<LightSource>(player.entity, {50,1.0});
world.set<Inventory>(player.entity, {5}); world.set<Inventory>(player.entity, {5});
auto sword = world.entity(); auto sword = world.entity();
@ -44,6 +44,13 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
world.set<InventoryItem>(sword, {1, config.items["SWORD_RUSTY"]}); world.set<InventoryItem>(sword, {1, config.items["SWORD_RUSTY"]});
world.set<Weapon>(sword, {20}); world.set<Weapon>(sword, {20});
auto torch = world.entity();
pos = game_map.place_entity(2);
world.set<Position>(torch, {pos.x+1, pos.y+1});
world.set<Tile>(torch, {config.items["TORCH_BAD"]["display"]});
world.set<InventoryItem>(torch, {1, config.items["TORCH_BAD"]});
world.set<LightSource>(torch, {70,2.0f});
auto enemy = world.entity(); auto enemy = world.entity();
world.set<Position>(enemy, {game_map.place_entity(1)}); world.set<Position>(enemy, {game_map.place_entity(1)});
world.set<Motion>(enemy, {0,0}); world.set<Motion>(enemy, {0,0});
@ -61,6 +68,7 @@ void configure_world(DinkyECS::World &world, Map &game_map) {
world.set<Position>(gold, {game_map.place_entity(3)}); world.set<Position>(gold, {game_map.place_entity(3)});
world.set<Loot>(gold, {100}); world.set<Loot>(gold, {100});
world.set<Tile>(gold, {config.items["CHEST_SMALL"]["display"]}); world.set<Tile>(gold, {config.items["CHEST_SMALL"]["display"]});
world.set<InventoryItem>(gold, {1, config.items["CHEST_SMALL"]});
auto wall_torch = world.entity(); auto wall_torch = world.entity();
world.set<Position>(wall_torch, {game_map.place_entity(4)}); world.set<Position>(wall_torch, {game_map.place_entity(4)});

@ -150,6 +150,10 @@ void System::collision(DinkyECS::World &world, Player &player) {
auto &weapon = world.get<Weapon>(entity); auto &weapon = world.get<Weapon>(entity);
player_combat.damage = weapon.damage; player_combat.damage = weapon.damage;
world.remove<Weapon>(entity); world.remove<Weapon>(entity);
} else if(world.has<Loot>(entity)) {
auto &loot = world.get<Loot>(entity);
inventory.gold += loot.amount;
world.remove<Loot>(entity);
} }
collider.remove(item_pos.location); collider.remove(item_pos.location);

@ -37,7 +37,7 @@ TEST_CASE("basic inventory test", "[inventory]") {
System::pickup(world, player, sword); System::pickup(world, player, sword);
REQUIRE(inventory.count() == 1); REQUIRE(inventory.count() == 1);
// get the item and confirm there is 1 // get the item and confirm there is 1
auto &item1 = inventory.get("SWORD_RUSTY"); auto &item1 = inventory.get(0);
REQUIRE(item1.count == 1); REQUIRE(item1.count == 1);
System::pickup(world, player, sword); System::pickup(world, player, sword);
@ -46,16 +46,16 @@ TEST_CASE("basic inventory test", "[inventory]") {
REQUIRE(inventory.count() == 1); REQUIRE(inventory.count() == 1);
REQUIRE(item1.count == 4); REQUIRE(item1.count == 4);
inventory.decrease("SWORD_RUSTY", 1); inventory.decrease(0, 1);
REQUIRE(item1.count == 3); REQUIRE(item1.count == 3);
inventory.decrease("SWORD_RUSTY", 2); inventory.decrease(0, 2);
REQUIRE(item1.count == 1); REQUIRE(item1.count == 1);
bool active = inventory.decrease("SWORD_RUSTY", 1); bool active = inventory.decrease(0, 1);
REQUIRE(item1.count == 0); REQUIRE(item1.count == 0);
REQUIRE(active == false); REQUIRE(active == false);
inventory.remove_all("SWORD_RUSTY"); inventory.erase_item(0);
REQUIRE(inventory.count() == 0); REQUIRE(inventory.count() == 0);
} }