Tracked down the bug that was caused by picking up an item but not removing its Position in the world, so when you go to another level it gets brought back to life causing a dupe.

master
Zed A. Shaw 4 days ago
parent 2c6565c40a
commit e0588847fa
  1. 17
      dinkyecs.hpp
  2. 7
      gui/fsm.cpp
  3. 3
      gui/guecstra.cpp
  4. 5
      gui/loot_ui.cpp
  5. 11
      gui/status_ui.cpp
  6. 10
      levelmanager.cpp
  7. 14
      systems.cpp

@ -36,17 +36,22 @@ namespace DinkyECS
std::unordered_map<std::type_index, std::any> $facts; std::unordered_map<std::type_index, std::any> $facts;
std::unordered_map<std::type_index, EventQueue> $events; std::unordered_map<std::type_index, EventQueue> $events;
std::unordered_map<std::type_index, std::any> $component_storages; std::unordered_map<std::type_index, std::any> $component_storages;
std::vector<Entity> $constants; std::unordered_map<Entity, bool> $constants;
Entity entity() { return ++entity_count; } Entity entity() { return ++entity_count; }
void clone_into(DinkyECS::World &to_world) { void clone_into(DinkyECS::World &to_world) {
to_world.$constants = $constants; to_world.$constants = $constants;
to_world.$facts = $facts; to_world.$facts = $facts;
// BUG*10: entity IDs should be a global counter, not per world
to_world.entity_count = entity_count; to_world.entity_count = entity_count;
to_world.$component_storages = $component_storages; to_world.$component_storages = $component_storages;
for(auto eid : $constants) { for(auto [eid, is_set] : $constants) {
dbc::check(is_set == true, "is_set was not true? WHAT?!");
dbc::check(eid <= entity_count, fmt::format(
"eid {} is not less than entity_count {}", eid, entity_count));
for(const auto &[tid, eid_map] : $components) { for(const auto &[tid, eid_map] : $components) {
auto &their_map = to_world.$components[tid]; auto &their_map = to_world.$components[tid];
if(eid_map.contains(eid)) { if(eid_map.contains(eid)) {
@ -57,7 +62,13 @@ namespace DinkyECS
} }
void make_constant(DinkyECS::Entity entity) { void make_constant(DinkyECS::Entity entity) {
$constants.push_back(entity); fmt::println(">>> Entity {} is now constant", entity);
$constants.try_emplace(entity, true);
}
void not_constant(DinkyECS::Entity entity) {
fmt::println("<<< Entity {} is NOT constant", entity);
$constants.erase(entity);
} }
template <typename Comp> template <typename Comp>

@ -454,7 +454,7 @@ namespace gui {
break; break;
case eGUI::AIM_CLICK: case eGUI::AIM_CLICK:
if(auto aimed_at = $main_ui.camera_aim()) { if(auto aimed_at = $main_ui.camera_aim()) {
dbc::log("clicked on a thing"); fmt::println("clicked on a thing: {}", aimed_at);
System::pickup($level, aimed_at); System::pickup($level, aimed_at);
} else { } else {
dbc::log("there's no thing there!"); dbc::log("there's no thing there!");
@ -463,6 +463,7 @@ namespace gui {
case eGUI::LOOT_ITEM: { case eGUI::LOOT_ITEM: {
dbc::check(world.has<components::InventoryItem>(entity), dbc::check(world.has<components::InventoryItem>(entity),
"INVALID LOOT_ITEM, that entity has no InventoryItem"); "INVALID LOOT_ITEM, that entity has no InventoryItem");
fmt::println("in FSM LOOT_ITEM the entity is {}", entity);
System::place_in_container(*$level.world, $temp_loot, "item_0", entity); System::place_in_container(*$level.world, $temp_loot, "item_0", entity);
$loot_ui.set_target($temp_loot); $loot_ui.set_target($temp_loot);
$loot_ui.update(); $loot_ui.update();
@ -509,6 +510,10 @@ namespace gui {
$levels.create_level($level.world); $levels.create_level($level.world);
$level = $levels.next(); $level = $levels.next();
// this has to go away, but clear out the inventory
$temp_loot = $level.world->entity();
$level.world->set<inventory::Model>($temp_loot, {});
$status_ui.update_level($level); $status_ui.update_level($level);
$map_ui.update_level($level); $map_ui.update_level($level);
$mini_map.update_level($level); $mini_map.update_level($level);

@ -16,12 +16,15 @@ namespace guecs {
} }
DinkyECS::Entity GrabSource::grab() { DinkyECS::Entity GrabSource::grab() {
fmt::println("> Grab entity {}", world_entity);
return world_entity; return world_entity;
} }
void GrabSource::setSprite(guecs::UI& gui, guecs::Entity gui_id) { void GrabSource::setSprite(guecs::UI& gui, guecs::Entity gui_id) {
dbc::check(gui.has<guecs::Sprite>(gui_id), "GrabSource given sprite gui_id that doesn't exist"); dbc::check(gui.has<guecs::Sprite>(gui_id), "GrabSource given sprite gui_id that doesn't exist");
fmt::println("> Grabsource Set sprite entity {}", world_entity);
auto& sp = gui.get<guecs::Sprite>(gui_id); auto& sp = gui.get<guecs::Sprite>(gui_id);
sprite = sp.sprite; sprite = sp.sprite;
} }

@ -94,13 +94,16 @@ namespace gui {
} }
} }
void LootUI::remove_slot(DinkyECS::Entity slot_id) { void LootUI::remove_slot(guecs::Entity slot_id) {
auto& name = $slot_to_name.at(slot_id); auto& name = $slot_to_name.at(slot_id);
fmt::println("LootUI remove slot inv::Model id={} slot={}", $target, name);
System::remove_from_container(*$level.world, $target, name); System::remove_from_container(*$level.world, $target, name);
update(); update();
} }
bool LootUI::place_slot(guecs::Entity id, DinkyECS::Entity world_entity) { bool LootUI::place_slot(guecs::Entity id, DinkyECS::Entity world_entity) {
fmt::println("LootUI target={} placing world entity {} in slot id {}",
$target, id, world_entity);
auto& name = $slot_to_name.at(id); auto& name = $slot_to_name.at(id);
bool worked = System::place_in_container(*$level.world, $target, name, world_entity); bool worked = System::place_in_container(*$level.world, $target, name, world_entity);
if(worked) update(); if(worked) update();

@ -102,6 +102,16 @@ namespace gui {
bool StatusUI::place_slot(guecs::Entity gui_id, DinkyECS::Entity world_entity) { bool StatusUI::place_slot(guecs::Entity gui_id, DinkyECS::Entity world_entity) {
auto& slot_name = $slot_to_name.at(gui_id); auto& slot_name = $slot_to_name.at(gui_id);
auto& inventory = $level.world->get_the<inventory::Model>(); auto& inventory = $level.world->get_the<inventory::Model>();
for(auto [ent, slot] : inventory.by_entity) {
fmt::println("BY_ENTITY: ent={}, slot={}", ent, slot);
}
for(auto [slot, ent] : inventory.by_slot) {
fmt::println("BY_SLOT: ent={}, slot={}", ent, slot);
}
$level.world->make_constant(world_entity);
inventory.add(slot_name, world_entity); inventory.add(slot_name, world_entity);
update(); update();
return true; return true;
@ -109,6 +119,7 @@ namespace gui {
bool StatusUI::drop_item(DinkyECS::Entity item_id) { bool StatusUI::drop_item(DinkyECS::Entity item_id) {
bool dropped = System::drop_item($level, item_id); bool dropped = System::drop_item($level, item_id);
$level.world->not_constant(item_id);
if(dropped) update(); if(dropped) update();
return dropped; return dropped;
} }

@ -27,7 +27,16 @@ inline shared_ptr<DinkyECS::World> clone_load_world(shared_ptr<DinkyECS::World>
auto world = make_shared<DinkyECS::World>(); auto world = make_shared<DinkyECS::World>();
if(prev_world != nullptr) { if(prev_world != nullptr) {
fmt::println("############### NEW WORLD #################");
prev_world->clone_into(*world); prev_world->clone_into(*world);
fmt::println("new world entity_count={}, prev={}", world->entity_count, prev_world->entity_count);
for(auto [ent, is_set] : prev_world->$constants) {
if(world->has<components::Sprite>(ent)) {
fmt::println("#### Sprite {} copied to new world.", ent);
}
}
} else { } else {
save::load_configs(*world); save::load_configs(*world);
} }
@ -83,6 +92,7 @@ DinkyECS::Entity LevelManager::spawn_enemy(std::string named) {
size_t LevelManager::create_level(shared_ptr<DinkyECS::World> prev_world) { size_t LevelManager::create_level(shared_ptr<DinkyECS::World> prev_world) {
auto world = clone_load_world(prev_world); auto world = clone_load_world(prev_world);
auto scaling = scale_level(); auto scaling = scale_level();
auto map = make_shared<Map>(scaling.map_width, scaling.map_height); auto map = make_shared<Map>(scaling.map_width, scaling.map_height);

@ -102,6 +102,8 @@ void System::enemy_pathing(GameLevel &level) {
} }
void System::init_positions(World &world, SpatialMap &collider) { void System::init_positions(World &world, SpatialMap &collider) {
auto& inv = world.get_the<inventory::Model>();
world.query<Position>([&](auto ent, auto &pos) { world.query<Position>([&](auto ent, auto &pos) {
if(world.has<Combat>(ent)) { if(world.has<Combat>(ent)) {
const auto& combat = world.get<Combat>(ent); const auto& combat = world.get<Combat>(ent);
@ -109,6 +111,10 @@ void System::init_positions(World &world, SpatialMap &collider) {
collider.insert(pos.location, ent); collider.insert(pos.location, ent);
} }
} else { } else {
fmt::println("System::init_positions for ent={}", ent);
dbc::check(!inv.has(ent),
fmt::format("!!! Entity {} is in player inventory and _also_ has a position in the world.", ent));
collider.insert(pos.location, ent); collider.insert(pos.location, ent);
} }
}); });
@ -326,6 +332,9 @@ void System::pickup(GameLevel &level, Entity entity) {
auto& item_pos = world.get<Position>(entity); auto& item_pos = world.get<Position>(entity);
level.collision->remove(item_pos.location); level.collision->remove(item_pos.location);
world.remove<Tile>(entity); world.remove<Tile>(entity);
// if you don't do this you get the bug that you can pickup
// an item and it'll also be in your inventory
world.remove<Position>(entity);
if(world.has<ritual::JunkPile>(entity)) { if(world.has<ritual::JunkPile>(entity)) {
auto& pile = world.get<ritual::JunkPile>(entity); auto& pile = world.get<ritual::JunkPile>(entity);
@ -499,16 +508,21 @@ bool System::drop_item(GameLevel& level, Entity item) {
return false; return false;
} }
// NOTE: I tink pickup and this need to be different
bool System::place_in_container(World& world, Entity cont_id, const std::string& name, Entity world_entity) { bool System::place_in_container(World& world, Entity cont_id, const std::string& name, Entity world_entity) {
auto& container = world.get<inventory::Model>(cont_id); auto& container = world.get<inventory::Model>(cont_id);
if(container.has(world_entity)) { if(container.has(world_entity)) {
fmt::println("container {} already has entity {}, skip", cont_id, world_entity);
// NOTE: I think this would be a move?! // NOTE: I think this would be a move?!
return false; return false;
} else if(container.has(name)) { } else if(container.has(name)) {
// this is an already occupied slot // this is an already occupied slot
fmt::println("container {} already has SLOT {}, skip", cont_id, name);
return false; return false;
} else { } else {
// this should only apply to the player's inventory
fmt::println("adding {} entity to loot with name {}", world_entity, name);
container.add(name, world_entity); container.add(name, world_entity);
return true; return true;
} }

Loading…
Cancel
Save