From 8a828fbd31e5dfb6c662989222f9d434f2cd4303 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 24 Sep 2025 14:22:24 -0400 Subject: [PATCH] Boss fight now reuses the combat_ui.cpp to do the combat panel, so next is making it work with the mechanics I want but no art. --- autowalker.cpp | 6 ++--- boss/ui.cpp | 30 +++++++++++------------- boss/ui.hpp | 2 ++ gui/combat_ui.cpp | 56 ++++++++++++++++++++++++++++----------------- gui/combat_ui.hpp | 7 +++--- gui/fsm.cpp | 57 +++++++++++++++++++++++----------------------- gui/fsm.hpp | 6 ++--- gui/fsm_events.hpp | 29 +++++++++++------------ inventory.hpp | 1 + main.cpp | 2 +- rituals.hpp | 2 +- 11 files changed, 107 insertions(+), 91 deletions(-) diff --git a/autowalker.cpp b/autowalker.cpp index 9f5ac9d..5cb33e5 100644 --- a/autowalker.cpp +++ b/autowalker.cpp @@ -101,7 +101,7 @@ void Autowalker::path_fail(const std::string& msg, Matrix& bad_paths, Point pos) status(L"PATH FAIL"); matrix::dump("MOVE FAIL PATHS", bad_paths, pos.x, pos.y); log(L"Autowalk failed to find a path."); - send_event(gui::Event::STAIRS_DOWN); + send_event(gui::Event::BOSS_START); } bool Autowalker::path_player(Pathing& paths, Point& target_out) { @@ -176,9 +176,9 @@ void Autowalker::update_state(ai::EntityAI& player_ai) { void Autowalker::handle_boss_fight() { // skip the boss fight for now - if(fsm.in_state(gui::State::NEXT_LEVEL)) { + if(fsm.in_state(gui::State::BOSS_FIGHT)) { // eventually we'll have AI handle this too - send_event(gui::Event::STAIRS_DOWN); + send_event(gui::Event::BOSS_END); face_enemy(); } } diff --git a/boss/ui.cpp b/boss/ui.cpp index 0ad6174..7d877f8 100644 --- a/boss/ui.cpp +++ b/boss/ui.cpp @@ -7,6 +7,7 @@ namespace boss { UI::UI(shared_ptr world, Entity boss_id) : $world(world), $boss_id(boss_id), + $combat_ui(true), $boss_sprite(textures::get_sprite("test_boss")), $player_sprite(textures::get_sprite("test_player")), $floor_sprite(textures::get_sprite("test_floor")) @@ -30,33 +31,27 @@ namespace boss { position_sprite($boss_sprite, "boss2", 0.7, true); position_sprite($player_sprite, "player1", 0.5, true); - position_sprite($floor_sprite, "floor2", 1.0, false); + position_sprite($floor_sprite, "floor1", 1.0, false); $arena.init(); $actions.position(0,0, SCREEN_WIDTH-BOSS_VIEW_WIDTH, SCREEN_HEIGHT); $actions.layout( - "[action1|action2]" - "[action3|action4]" - "[action5|action6]" - "[*(200)dodge]" + "[*(200,400)combat|_]" + "[_|_]" + "[_|_]" + "[_|_]" "[*(200,300)stats]" "[_]" "[_]"); - - for(auto& [name, cell] : $actions.cells()) { - auto id = $actions.entity(name); - $actions.set(id, {}); - $actions.set(id, {guecs::to_wstring(name)}); - - if(name != "stats") { - $actions.set(id, { - [name](auto){ fmt::println("clicked {}", name); } - }); - } - } + auto stats = $actions.entity("stats"); + $actions.set(stats, {}); + $actions.set(stats, {L"stats"}); $actions.init(); + + auto& cell = $actions.cell_for("combat"); + $combat_ui.init(cell.x, cell.y, cell.w, cell.h); } void UI::position_sprite(textures::SpriteTexture& st, const std::string& name, float scale, bool at_mid) { @@ -71,6 +66,7 @@ namespace boss { void UI::render(sf::RenderWindow& window) { $arena.render(window); $actions.render(window); + $combat_ui.render(window); window.draw(*$floor_sprite.sprite); window.draw(*$boss_sprite.sprite); window.draw(*$player_sprite.sprite); diff --git a/boss/ui.hpp b/boss/ui.hpp index 20ab6ee..41ea682 100644 --- a/boss/ui.hpp +++ b/boss/ui.hpp @@ -4,6 +4,7 @@ #include #include #include "textures.hpp" +#include "gui/combat_ui.hpp" namespace boss { using std::shared_ptr; @@ -13,6 +14,7 @@ namespace boss { struct UI { shared_ptr $world = nullptr; Entity $boss_id = NONE; + gui::CombatUI $combat_ui; SpriteTexture $boss_sprite; SpriteTexture $player_sprite; SpriteTexture $floor_sprite; diff --git a/gui/combat_ui.cpp b/gui/combat_ui.cpp index 1f351fc..4dac579 100644 --- a/gui/combat_ui.cpp +++ b/gui/combat_ui.cpp @@ -1,32 +1,27 @@ -#include "gui/combat_ui.hpp" #include "constants.hpp" #include "rituals.hpp" #include #include "gui/guecstra.hpp" -#include "inventory.hpp" #include "game_level.hpp" +#include "gui/combat_ui.hpp" namespace gui { + using guecs::THEME; using namespace guecs; - CombatUI::CombatUI() + CombatUI::CombatUI(bool boss_style) : + $boss_style(boss_style) { - $gui.position(COMBAT_UI_X, COMBAT_UI_Y, COMBAT_UI_WIDTH, COMBAT_UI_HEIGHT); - $gui.layout( - "[button_0 | button_1 | button_2 | button_3" - "|button_4 | button_5 | button_6 | =healing_button | =hp_gauge ]" - ); } guecs::Entity CombatUI::make_button( - std::string name, + guecs::Entity button, Events::GUI event, int action, const std::string &icon_name, const std::string &sound, const std::string &effect_name) { - auto button = $gui.entity(name); $gui.set(button, {icon_name}); $gui.set(button, {sound}); $gui.set(button, {.duration=0.5f, .name=effect_name}); @@ -36,49 +31,68 @@ namespace gui { return button; } - void CombatUI::init() { + void CombatUI::init(int x, int y, int w, int h) { + $gui.position(x, y, w, h); + + if($boss_style) { + $gui.layout( + "[action0|action1]" + "[action2|action3]" + "[action4|action5]" + "[action6|action7]"); + } else { + $gui.layout( + "[action0 | action1 | action2 | action3" + "|action4 | action5 | action6 | action7 | =hp_gauge ]"); + } + auto world = GameDB::current_world(); - using guecs::THEME; $gui.set($gui.MAIN, {$gui.$parser, THEME.DARK_MID}); auto& the_belt = world->get_the(); for(int slot = 0; slot < the_belt.max_slots; slot++) { + fmt::println("combat ui belt slot {}", slot); if(the_belt.has(slot)) { - std::string name = fmt::format("button_{}", slot); + auto button = $gui.entity("action", slot); + fmt::println("combat ui has belt slot {} with id {}", slot, button); + auto& ritual = the_belt.get(slot); using enum ritual::Element; switch(ritual.element) { case FIRE: - make_button(name, Events::GUI::ATTACK, + make_button(button, Events::GUI::ATTACK, slot, "broken_yoyo", "fireball_01", "flame"); break; case LIGHTNING: - make_button(name, Events::GUI::ATTACK, + make_button(button, Events::GUI::ATTACK, slot, "pocket_watch", "electric_shock_01", "lightning"); break; default: - make_button(name, Events::GUI::ATTACK, + make_button(button, Events::GUI::ATTACK, slot, "severed_finger", "punch_cartoony", "ui_shader"); } } } - auto hp_gauge = $gui.entity("hp_gauge"); - $gui.set(hp_gauge, {"stone_doll_cursed"}); - $gui.set(hp_gauge, - guecs::make_action(hp_gauge, Events::GUI::HP_STATUS, {})); + if(!$boss_style) { + auto hp_gauge = $gui.entity("hp_gauge"); + $gui.set(hp_gauge, {"stone_doll_cursed"}); + $gui.set(hp_gauge, + guecs::make_action(hp_gauge, Events::GUI::HP_STATUS, {})); + } $gui.init(); } void CombatUI::render(sf::RenderWindow& window) { $gui.render(window); + // $gui.debug_layout(window); } void CombatUI::update_level() { - init(); + init(COMBAT_UI_X, COMBAT_UI_Y, COMBAT_UI_WIDTH, COMBAT_UI_HEIGHT); } bool CombatUI::mouse(float x, float y, guecs::Modifiers mods) { diff --git a/gui/combat_ui.hpp b/gui/combat_ui.hpp index c14898d..89ad6b3 100644 --- a/gui/combat_ui.hpp +++ b/gui/combat_ui.hpp @@ -7,15 +7,16 @@ namespace gui { class CombatUI { public: + bool $boss_style; guecs::UI $gui; - CombatUI(); + CombatUI(bool boss_style); - void init(); + void init(int x, int y, int w, int h); void render(sf::RenderWindow& window); void update_level(); bool mouse(float x, float y, guecs::Modifiers mods); - guecs::Entity make_button(std::string name, Events::GUI event, + guecs::Entity make_button(guecs::Entity button, Events::GUI event, int action, const std::string &icon_name, const std::string &sound, const std::string &effect_name); }; diff --git a/gui/fsm.cpp b/gui/fsm.cpp index 35dae80..2bee864 100644 --- a/gui/fsm.cpp +++ b/gui/fsm.cpp @@ -20,6 +20,7 @@ namespace gui { FSM::FSM() : $window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Zed's Raycaster Thing"), $main_ui($window), + $combat_ui(false), $font{FONT_FILE_NAME}, $dnd_loot($status_ui, $loot_ui, $window, $router) { @@ -35,7 +36,7 @@ namespace gui { FSM_STATE(State, IDLE, ev, data); FSM_STATE(State, IN_COMBAT, ev); FSM_STATE(State, COMBAT_ROTATE, ev); - FSM_STATE(State, NEXT_LEVEL, ev); + FSM_STATE(State, BOSS_FIGHT, ev); FSM_STATE(State, END, ev); FSM_STATE(State, LOOTING, ev, data); } @@ -50,12 +51,8 @@ namespace gui { auto cell = $main_ui.overlay_cell("left"); $debug_ui.init(cell); - $combat_ui.init(); + $combat_ui.init(COMBAT_UI_X, COMBAT_UI_Y, COMBAT_UI_WIDTH, COMBAT_UI_HEIGHT); $status_ui.init(); - - $boss_fight_ui = GameDB::create_bossfight(); - $boss_fight_ui->init(); - $map_ui.init(); $map_ui.log(L"Welcome to the game!"); @@ -169,9 +166,10 @@ namespace gui { case CLOSE: dbc::log("Nothing to close."); break; - case STAIRS_DOWN: + case BOSS_START: sound::stop("ambient"); - state(State::NEXT_LEVEL); + next_level(true); + state(State::BOSS_FIGHT); break; case LOOT_ITEM: $dnd_loot.event(Event::LOOT_ITEM); @@ -207,13 +205,16 @@ namespace gui { } } - void FSM::NEXT_LEVEL(Event ev) { + void FSM::BOSS_FIGHT(Event ev) { + dbc::check($boss_fight_ui != nullptr, "$boss_fight_ui not initialized"); using enum Event; switch(ev) { - case STAIRS_DOWN: + // this is only if using the debug X key to skip it + case BOSS_START: + case BOSS_END: sound::play("ambient"); - next_level(); + next_level(false); state(State::IDLE); break; case MOUSE_CLICK: { @@ -221,7 +222,7 @@ namespace gui { $boss_fight_ui->mouse(pos.x, pos.y, guecs::NO_MODS); if($boss_fight_ui->boss_dead()) { - event(Event::STAIRS_DOWN); + event(Event::BOSS_END); } } break; default: @@ -362,7 +363,7 @@ namespace gui { $main_ui.toggle_mind_reading(); break; case KEY::X: - event(Event::STAIRS_DOWN); + event(Event::BOSS_START); break; case KEY::F5: take_screenshot(); @@ -384,7 +385,7 @@ namespace gui { } void FSM::draw_gui() { - if(in_state(State::NEXT_LEVEL)) { + if(in_state(State::BOSS_FIGHT)) { $boss_fight_ui->render($window); } else { if($debug_ui.active) { @@ -406,7 +407,7 @@ namespace gui { } void FSM::render() { - if(in_state(State::NEXT_LEVEL)) { + if(in_state(State::BOSS_FIGHT)) { $window.clear(); $boss_fight_ui->render($window); } else { @@ -502,14 +503,14 @@ namespace gui { System::player_status(); break; case eGUI::NEW_RITUAL: - $combat_ui.init(); + $combat_ui.init(COMBAT_UI_X, COMBAT_UI_Y, COMBAT_UI_WIDTH, COMBAT_UI_HEIGHT); break; case eGUI::ATTACK: $temp_attack_id = std::any_cast(data); event(Event::ATTACK); break; case eGUI::STAIRS_DOWN: - event(Event::STAIRS_DOWN); + event(Event::BOSS_START); break; case eGUI::DEATH: { $status_ui.update(); @@ -541,17 +542,17 @@ namespace gui { dbc::check(worked, "Failed to write screenshot.png"); } - void FSM::next_level() { - dbc::log("current_level: Yep, next is called..."); - GameDB::create_level(); - - $status_ui.update_level(); - $combat_ui.update_level(); - $main_ui.update_level(); - $loot_ui.update_level(); - - $boss_fight_ui = GameDB::create_bossfight(); - $boss_fight_ui->init(); + void FSM::next_level(bool bossfight) { + if(bossfight) { + $boss_fight_ui = GameDB::create_bossfight(); + $boss_fight_ui->init(); + } else { + GameDB::create_level(); + $status_ui.update_level(); + $combat_ui.update_level(); + $main_ui.update_level(); + $loot_ui.update_level(); + } run_systems(); } diff --git a/gui/fsm.hpp b/gui/fsm.hpp index bba7002..22c3bd4 100644 --- a/gui/fsm.hpp +++ b/gui/fsm.hpp @@ -21,7 +21,7 @@ namespace gui { COMBAT_ROTATE=3, ATTACKING=4, ROTATING=5, - NEXT_LEVEL=6, + BOSS_FIGHT=6, LOOTING=7, IDLE=8, END=9 @@ -59,7 +59,7 @@ namespace gui { void IDLE(Event ev, std::any data); void IN_COMBAT(Event ev); void COMBAT_ROTATE(Event ev); - void NEXT_LEVEL(Event ev); + void BOSS_FIGHT(Event ev); void LOOTING(Event ev, std::any data); void END(Event ev); @@ -72,7 +72,7 @@ namespace gui { bool active(); void run_systems(); void handle_world_events(); - void next_level(); + void next_level(bool bossfight); void debug_render(); void take_screenshot(); }; diff --git a/gui/fsm_events.hpp b/gui/fsm_events.hpp index 6d6940a..d451fd0 100644 --- a/gui/fsm_events.hpp +++ b/gui/fsm_events.hpp @@ -15,19 +15,20 @@ namespace gui { ATTACK = 10, START_COMBAT = 11, STOP_COMBAT = 12, - STAIRS_DOWN = 13, - LOOT_OPEN=14, - LOOT_ITEM=15, - LOOT_SELECT=16, - INV_SELECT=17, - USE_ITEM=18, - QUIT = 19, - MOUSE_CLICK=20, - MOUSE_MOVE=21, - MOUSE_DRAG=22, - MOUSE_DRAG_START=23, - MOUSE_DROP=24, - KEY_PRESS=25, - AIM_CLICK=26 + BOSS_START = 13, + BOSS_END = 14, + LOOT_OPEN=15, + LOOT_ITEM=16, + LOOT_SELECT=17, + INV_SELECT=18, + USE_ITEM=19, + QUIT = 20, + MOUSE_CLICK=21, + MOUSE_MOVE=22, + MOUSE_DRAG=23, + MOUSE_DRAG_START=24, + MOUSE_DROP=25, + KEY_PRESS=26, + AIM_CLICK=27 }; } diff --git a/inventory.hpp b/inventory.hpp index 50e8734..e67ebcd 100644 --- a/inventory.hpp +++ b/inventory.hpp @@ -1,3 +1,4 @@ +#pragma once #include "dinkyecs.hpp" #include diff --git a/main.cpp b/main.cpp index b403ebc..e30fb33 100644 --- a/main.cpp +++ b/main.cpp @@ -35,7 +35,7 @@ int main(int argc, char* argv[]) { // BUG: need to sort out how to deal with this in the FSM if(main.in_state(gui::State::IDLE) - || main.in_state(gui::State::NEXT_LEVEL) + || main.in_state(gui::State::BOSS_FIGHT) || main.in_state(gui::State::LOOTING) || main.in_state(gui::State::IN_COMBAT)) { diff --git a/rituals.hpp b/rituals.hpp index 197fa82..1ad0f5e 100644 --- a/rituals.hpp +++ b/rituals.hpp @@ -71,7 +71,7 @@ namespace ritual { struct Belt { int next_slot = 0; - int max_slots = 6; + int max_slots = 8; std::unordered_map equipped; Action& get(int index);