From 3b9525cca4038d4da303191c8ebc822971d95935 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 19 Feb 2025 23:18:33 -0500 Subject: [PATCH] Enemies now turn into a lootable device witha grave_stone sprite so you know they died. Need to implement noclipping on items with collision. --- assets/config.json | 2 +- assets/devices.json | 5 +- events.hpp | 2 +- gui.cpp | 12 ++-- raycaster.cpp | 6 ++ raycaster.hpp | 1 + systems.cpp | 132 +++++++++++++++++++++++--------------------- systems.hpp | 2 +- 8 files changed, 90 insertions(+), 72 deletions(-) diff --git a/assets/config.json b/assets/config.json index 25d52c9..90d30b7 100644 --- a/assets/config.json +++ b/assets/config.json @@ -30,7 +30,7 @@ "player": { }, "worldgen": { - "enemy_probability": 40, + "enemy_probability": 90, "empty_room_probability": 10, "device_probability": 20 } diff --git a/assets/devices.json b/assets/devices.json index 012ade7..ad294d4 100644 --- a/assets/devices.json +++ b/assets/devices.json @@ -60,9 +60,8 @@ "foreground": [32, 123, 164], "background": [24, 205, 189] }, - {"_type": "Device", - "config": {"test": true}, - "events": []}, + {"_type": "LightSource", "strength": 50, "radius": 0.5}, + {"_type": "Device", "config": {"test": true}, "events": []}, {"_type": "Sprite", "name": "grave_stone"} ] } diff --git a/events.hpp b/events.hpp index 537845e..a561c13 100644 --- a/events.hpp +++ b/events.hpp @@ -3,7 +3,7 @@ namespace Events { enum GUI { START, COMBAT, LOOT, DEATH, STAIRS_UP, STAIRS_DOWN, TRAP, - COMBAT_START, NO_NEIGHBORS, ATTACK, NOOP + COMBAT_START, NO_NEIGHBORS, ATTACK, UPDATE_SPRITE, NOOP }; struct Combat { diff --git a/gui.cpp b/gui.cpp index b0211af..a29eb54 100644 --- a/gui.cpp +++ b/gui.cpp @@ -372,7 +372,7 @@ namespace gui { System::collision($level); System::motion($level); System::lighting($level); - System::death($level); + System::death($level, $levels.$components); } bool FSM::active() { @@ -385,16 +385,14 @@ namespace gui { while(world.has_event()) { auto [evt, entity, data] = world.recv(); + auto player = world.get_the(); switch(evt) { case eGUI::COMBAT: { auto &damage = std::any_cast(data); - auto enemy_combat = world.get(entity); if(damage.enemy_did > 0) { $status_view.log(fmt::format("Enemy HIT YOU for {} damage!", damage.enemy_did)); - $status_view.log(fmt::format("-- Enemy has {} HP left.", enemy_combat.hp)); - auto player = world.get_the(); auto player_combat = world.get(player.entity); $combat_view.set_damage(float(player_combat.hp) / float(player_combat.max_hp)); } else { @@ -425,6 +423,12 @@ namespace gui { $rotation = 0; event(Event::ATTACK); break; + case eGUI::DEATH: { + if(entity != player.entity) { + auto &sprite = $level.world->get(entity); + $rayview.update_sprite(entity, sprite); + } + } break; case eGUI::NOOP: $status_view.log(fmt::format("NOOP EVENT! {},{}", evt, entity)); break; diff --git a/raycaster.cpp b/raycaster.cpp index 47eadd6..1619835 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -342,6 +342,12 @@ void Raycaster::draw(sf::RenderTarget& target) { sprite_casting(target); } +void Raycaster::update_sprite(DinkyECS::Entity ent, components::Sprite& sprite) { + fmt::println("entity UPDATE SPRITE {} will have sprite named {}", ent, sprite.name); + auto sprite_txt = $textures.get(sprite.name); + $sprites.insert_or_assign(ent, sprite_txt); +} + void Raycaster::set_level(GameLevel level) { $level = level; auto& tiles = $level.map->tiles(); diff --git a/raycaster.hpp b/raycaster.hpp index 50626b5..3442e36 100644 --- a/raycaster.hpp +++ b/raycaster.hpp @@ -58,5 +58,6 @@ struct Raycaster { } void set_level(GameLevel level); + void update_sprite(DinkyECS::Entity ent, components::Sprite& sprite); void init_shaders(); }; diff --git a/systems.cpp b/systems.cpp index 7a586b5..8e619b2 100644 --- a/systems.cpp +++ b/systems.cpp @@ -104,35 +104,37 @@ void System::motion(GameLevel &level) { }); } -void System::death(GameLevel &level) { +void System::death(GameLevel &level, components::ComponentMap& components) { auto &world = *level.world; - auto &collider = *level.collision; auto player = world.get_the(); + auto& config = world.get_the(); + std::vector dead_things; - // BUG: this is where entities can die on top of - // BUG: eachother and overlap their corpse - // BUG: maybe that can be allowed and looting just shows - // BUG: all dead things there? - world.query([&](auto ent, auto &position, auto &combat) { + world.query([&](auto ent, auto &combat) { // bring out yer dead if(combat.hp <= 0 && !combat.dead) { - fmt::println("DIE! entity {} died", ent); combat.dead = true; - // take them out of collision map - collider.remove(position.location); - - if(ent == player.entity) { - world.send(Events::GUI::DEATH, ent, {}); - } else { - // remove their motion so they're dead - // CHANGE: this needs to remove the enemies that are - // dead and then replace them at that position with - // a gave_stone device. And then that makes it so you - // can loot their dead bodies. - world.remove(ent); + if(ent != player.entity) { + // we won't change out the player's components later + dead_things.push_back(ent); } + // we need to send this event for everything that dies + world.send(Events::GUI::DEATH, ent, {}); } }); + + // this goes through everything that died and changes them to a gravestone + // NOTE: this could be a separate system but also could be a function in + // components:: + for(auto ent : dead_things) { + // remove their enemy setting + world.remove(ent); + world.remove(ent); + world.remove(ent); + + auto entity_data = config.devices["GRAVE_STONE"]; + components::configure_entity(components, world, ent, entity_data["components"]); + } } void System::combat(GameLevel &level) { @@ -173,54 +175,60 @@ void System::collision(GameLevel &level) { // this is guaranteed to not return the given position auto [found, nearby] = collider.neighbors(player_position.location); - - if(found) { - for(auto entity : nearby) { - if(world.has(entity)) { + int combat_count = 0; + + // BUG: this logic is garbage, needs a refactor + for(auto entity : nearby) { + if(world.has(entity)) { + auto combat = world.get(entity); + if(!combat.dead) { + combat_count++; world.send(Events::GUI::COMBAT_START, entity, entity); - } else if(world.has(entity)) { - auto item = world.get(entity); - auto& item_pos = world.get(entity); - auto& inventory = world.get(player.entity); - - if(world.has(entity)) { - inventory.add(item); - auto &new_light = world.get(entity); - world.set(player.entity, new_light); - inventory.light = new_light; - world.remove(entity); - } - - if(world.has(entity)) { - inventory.add(item); - auto &weapon = world.get(entity); - player_combat.damage = weapon.damage; - world.remove(entity); - } + } + } else if(world.has(entity)) { + auto item = world.get(entity); + auto& item_pos = world.get(entity); + auto& inventory = world.get(player.entity); + + if(world.has(entity)) { + inventory.add(item); + auto &new_light = world.get(entity); + world.set(player.entity, new_light); + inventory.light = new_light; + world.remove(entity); + } - if(world.has(entity)) { - auto &loot = world.get(entity); - inventory.gold += loot.amount; - world.remove(entity); - } + if(world.has(entity)) { + inventory.add(item); + auto &weapon = world.get(entity); + player_combat.damage = weapon.damage; + world.remove(entity); + } - if(world.has(entity)) { - auto& cure = world.get(entity); - player_combat.hp = std::min(player_combat.hp + cure.hp, player_combat.max_hp); - world.remove(entity); - } + if(world.has(entity)) { + auto &loot = world.get(entity); + inventory.gold += loot.amount; + world.remove(entity); + } - collider.remove(item_pos.location); - world.remove(entity); - world.remove(entity); - world.send(Events::GUI::LOOT, entity, item); - } else if(world.has(entity)) { - System::device(world, player.entity, entity); - } else { - println("UNKNOWN COLLISION TYPE {}", entity); + if(world.has(entity)) { + auto& cure = world.get(entity); + player_combat.hp = std::min(player_combat.hp + cure.hp, player_combat.max_hp); + world.remove(entity); } + + collider.remove(item_pos.location); + world.remove(entity); + world.remove(entity); + world.send(Events::GUI::LOOT, entity, item); + } else if(world.has(entity)) { + System::device(world, player.entity, entity); + } else { + println("UNKNOWN COLLISION TYPE {}", entity); } - } else { + } + + if(combat_count == 0) { world.send(Events::GUI::NO_NEIGHBORS, player.entity, player.entity); } } diff --git a/systems.hpp b/systems.hpp index d0e4460..2395ea6 100644 --- a/systems.hpp +++ b/systems.hpp @@ -10,7 +10,7 @@ namespace System { void lighting(GameLevel &level); void motion(GameLevel &level); void collision(GameLevel &level); - void death(GameLevel &level); + void death(GameLevel &level, components::ComponentMap& components); void enemy_pathing(GameLevel &level); void init_positions(DinkyECS::World &world, SpatialMap &collider);