diff --git a/source/core/system/debug.cpp b/source/core/system/debug.cpp index ddc98de..8f9a91e 100644 --- a/source/core/system/debug.cpp +++ b/source/core/system/debug.cpp @@ -92,6 +92,32 @@ void Debug::setDebugFile(const std::string& path) { debug_file_path_ = path; } +// Convierte string a SceneManager::Scene (para debug.yaml) +static auto sceneFromString(const std::string& s) -> SceneManager::Scene { + if (s == "LOGO") { return SceneManager::Scene::LOGO; } + if (s == "LOADING") { return SceneManager::Scene::LOADING_SCREEN; } + if (s == "TITLE") { return SceneManager::Scene::TITLE; } + if (s == "CREDITS") { return SceneManager::Scene::CREDITS; } + if (s == "DEMO") { return SceneManager::Scene::DEMO; } + if (s == "ENDING") { return SceneManager::Scene::ENDING; } + if (s == "ENDING2") { return SceneManager::Scene::ENDING2; } + return SceneManager::Scene::GAME; // Fallback seguro +} + +// Convierte SceneManager::Scene a string (para debug.yaml) +static auto sceneToString(SceneManager::Scene scene) -> std::string { + switch (scene) { + case SceneManager::Scene::LOGO: return "LOGO"; + case SceneManager::Scene::LOADING_SCREEN: return "LOADING"; + case SceneManager::Scene::TITLE: return "TITLE"; + case SceneManager::Scene::CREDITS: return "CREDITS"; + case SceneManager::Scene::DEMO: return "DEMO"; + case SceneManager::Scene::ENDING: return "ENDING"; + case SceneManager::Scene::ENDING2: return "ENDING2"; + default: return "GAME"; + } +} + // Carga la configuración de debug desde debug.yaml void Debug::loadFromFile() { // Inicializar con valores de release por defecto @@ -99,6 +125,7 @@ void Debug::loadFromFile() { spawn_settings_.spawn_x = Defaults::Game::Player::SPAWN_X; spawn_settings_.spawn_y = Defaults::Game::Player::SPAWN_Y; spawn_settings_.flip = Defaults::Game::Player::SPAWN_FLIP; + initial_scene_ = SceneManager::Scene::GAME; std::ifstream file(debug_file_path_); if (!file.good()) { @@ -124,12 +151,16 @@ void Debug::loadFromFile() { auto s = yaml["spawn_flip"].get_value(); spawn_settings_.flip = (s == "right") ? Flip::RIGHT : Flip::LEFT; } + if (yaml.contains("initial_scene")) { + initial_scene_ = sceneFromString(yaml["initial_scene"].get_value()); + } } catch (...) { // YAML inválido: resetear a defaults y sobreescribir spawn_settings_.room = Defaults::Game::Room::INITIAL; spawn_settings_.spawn_x = Defaults::Game::Player::SPAWN_X; spawn_settings_.spawn_y = Defaults::Game::Player::SPAWN_Y; spawn_settings_.flip = Defaults::Game::Player::SPAWN_FLIP; + initial_scene_ = SceneManager::Scene::GAME; saveToFile(); } } @@ -144,6 +175,7 @@ void Debug::saveToFile() const { file << "spawn_x: " << (spawn_settings_.spawn_x / Tile::SIZE) << " # en tiles\n"; file << "spawn_y: " << (spawn_settings_.spawn_y / Tile::SIZE) << " # en tiles\n"; file << "spawn_flip: " << ((spawn_settings_.flip == Flip::RIGHT) ? "right" : "left") << "\n"; + file << "initial_scene: " << sceneToString(initial_scene_) << "\n"; } #endif // _DEBUG \ No newline at end of file diff --git a/source/core/system/debug.hpp b/source/core/system/debug.hpp index 9c6fe88..e04e944 100644 --- a/source/core/system/debug.hpp +++ b/source/core/system/debug.hpp @@ -8,6 +8,8 @@ #include // Para string #include // Para vector +#include "game/scene_manager.hpp" // Para SceneManager::Scene + // Clase Debug class Debug { public: @@ -41,8 +43,10 @@ class Debug { void setDebugFile(const std::string& path); // Establece la ruta del archivo debug.yaml void loadFromFile(); // Carga la configuración de debug desde debug.yaml void saveToFile() const; // Guarda la configuración de debug en debug.yaml - [[nodiscard]] auto getSpawnSettings() const -> const SpawnSettings& { return spawn_settings_; } // Obtiene los valores de spawn - void setSpawnSettings(const SpawnSettings& s) { spawn_settings_ = s; } // Establece los valores de spawn + [[nodiscard]] auto getSpawnSettings() const -> const SpawnSettings& { return spawn_settings_; } // Obtiene los valores de spawn + void setSpawnSettings(const SpawnSettings& s) { spawn_settings_ = s; } // Establece los valores de spawn + [[nodiscard]] auto getInitialScene() const -> SceneManager::Scene { return initial_scene_; } // Obtiene la escena inicial de debug + void setInitialScene(SceneManager::Scene s) { initial_scene_ = s; } // Establece la escena inicial de debug private: static Debug* debug; // [SINGLETON] Objeto privado @@ -59,6 +63,7 @@ class Debug { bool enabled_ = false; // Indica si esta activo el modo debug std::string debug_file_path_; // Ruta del archivo debug.yaml SpawnSettings spawn_settings_; // Configuración de spawn para debug + SceneManager::Scene initial_scene_ = SceneManager::Scene::GAME; // Escena inicial en debug }; #endif // _DEBUG \ No newline at end of file diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 11889e5..3a90d70 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -171,6 +171,7 @@ Director::Director(std::vector const& args) { Debug::init(); Debug::get()->setDebugFile(Resource::List::get()->get("debug.yaml")); Debug::get()->loadFromFile(); + SceneManager::current = Debug::get()->getInitialScene(); #endif std::cout << "\n"; // Fin de inicialización de sistemas diff --git a/source/game/game_control.hpp b/source/game/game_control.hpp index c8e82f7..1c3dc1d 100644 --- a/source/game/game_control.hpp +++ b/source/game/game_control.hpp @@ -1,13 +1,18 @@ #pragma once -#ifdef _DEBUG #include #include +namespace GameControl { + // Disponible en todos los builds — refresca el color del jugador según cheats + inline std::function refresh_player_color; +} + +#ifdef _DEBUG namespace GameControl { // Registrada por Game::Game() — cambia la habitación activa inline std::function change_room; - // Registrada por Game::Game() — refresca el color del jugador según cheats - inline std::function refresh_player_color; + // Registrada por Game::Game() — fija el contador de items recogidos + inline std::function set_items; // Registrada por Game::Game() — hace toggle del modo debug (equivale a tecla 0) inline std::function toggle_debug_mode; // Registrada por Game::Game() — guarda la habitación actual como habitación de inicio en debug.yaml diff --git a/source/game/scene_manager.hpp b/source/game/scene_manager.hpp index 6f85134..b21b467 100644 --- a/source/game/scene_manager.hpp +++ b/source/game/scene_manager.hpp @@ -34,13 +34,8 @@ namespace SceneManager { }; // --- Variables de estado globales --- -#ifdef _DEBUG - inline Scene current = Scene::GAME; // Escena actual + inline Scene current = Scene::LOGO; // Escena actual (en _DEBUG sobrescrito por Director tras cargar debug.yaml) inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual -#else - inline Scene current = Scene::LOGO; // Escena actual - inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual -#endif - inline Scene scene_before_restart = Scene::LOGO; // escena a relanzar tras RESTART_CURRENT + inline Scene scene_before_restart = Scene::LOGO; // escena a relanzar tras RESTART_CURRENT } // namespace SceneManager diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 1569241..5d63eb9 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -64,9 +64,14 @@ Game::Game(Mode mode) Cheevos::get()->enable(!Options::cheats.enabled()); // Deshabilita los logros si hay trucos activados Cheevos::get()->clearUnobtainableState(); + GameControl::refresh_player_color = [this]() -> void { player_->setColor(); }; + #ifdef _DEBUG GameControl::change_room = [this](const std::string& r) -> bool { return this->changeRoom(r); }; - GameControl::refresh_player_color = [this]() -> void { player_->setColor(); }; + GameControl::set_items = [this](int count) -> void { + scoreboard_data_->items = count; + Options::stats.items = count; + }; GameControl::toggle_debug_mode = [this]() -> void { Debug::get()->toggleEnabled(); room_->redrawMap(); @@ -104,9 +109,11 @@ Game::Game(Mode mode) Game::~Game() { ItemTracker::destroy(); + GameControl::refresh_player_color = nullptr; + #ifdef _DEBUG GameControl::change_room = nullptr; - GameControl::refresh_player_color = nullptr; + GameControl::set_items = nullptr; GameControl::toggle_debug_mode = nullptr; GameControl::set_initial_room = nullptr; GameControl::set_initial_pos = nullptr; diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index ad2bb35..326a0e3 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -19,9 +19,10 @@ #include "game/scene_manager.hpp" // Para SceneManager #include "game/ui/notifier.hpp" // Para Notifier +#include "game/game_control.hpp" // Para GameControl (refresh_player_color) + #ifdef _DEBUG #include "core/system/debug.hpp" // Para Debug -#include "game/game_control.hpp" // Para GameControl #endif // ── Sistema de comandos ──────────────────────────────────────────────────────── @@ -89,11 +90,13 @@ static void printHelp() { #ifdef _DEBUG SDL_Log(" DEBUG Toggle debug overlay (F12)"); SDL_Log(" ROOM <1-60> Change to room number (GAME only)"); - SDL_Log(" INFINITE LIVES [ON|OFF] Infinite lives cheat (GAME only)"); - SDL_Log(" INVENCIBILITY [ON|OFF] Invincibility cheat (GAME only)"); - SDL_Log(" OPEN THE JAIL Open the jail (GAME only)"); - SDL_Log(" CLOSE THE JAIL Close the jail (GAME only)"); SDL_Log(" SET INITIAL [ROOM|POS] Set initial room/position from current state (GAME only)"); + SDL_Log(" SET INITIAL SCENE [] Set initial debug scene (GAME|LOGO|TITLE|LOADING|CREDITS|ENDING|ENDING2)"); + SDL_Log(" SET ITEMS <0-200> Set collected items count (GAME only)"); + SDL_Log(" CHEAT INFINITE LIVES [ON|OFF] Infinite lives (GAME only)"); + SDL_Log(" CHEAT INVINCIBILITY [ON|OFF] Invincibility (GAME only)"); + SDL_Log(" CHEAT OPEN THE JAIL Open the jail (GAME only)"); + SDL_Log(" CHEAT CLOSE THE JAIL Close the jail (GAME only)"); #endif SDL_Log(" AUDIO [ON|OFF|VOL <0-100>] Audio master"); SDL_Log(" MUSIC [ON|OFF|VOL <0-100>] Music volume"); @@ -408,70 +411,76 @@ static const std::vector COMMANDS = { return std::string("Room not found: ") + buf; }}, - // INFINITE LIVES [ON|OFF] — Truco vidas infinitas (tecla 1); solo en escena GAME - {.keyword = "INFINITE", .execute = [](const std::vector& args) -> std::string { - if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } - if (args.empty() || args[0] != "LIVES") { return "Usage: INFINITE LIVES [ON|OFF]"; } - auto& cheat = Options::cheats.infinite_lives; - using State = Options::Cheat::State; - const std::vector REST(args.begin() + 1, args.end()); - if (REST.empty()) { - cheat = (cheat == State::ENABLED) ? State::DISABLED : State::ENABLED; - } else if (REST[0] == "ON") { - if (cheat == State::ENABLED) { return "Infinite lives already ON"; } - cheat = State::ENABLED; - } else if (REST[0] == "OFF") { - if (cheat == State::DISABLED) { return "Infinite lives already OFF"; } - cheat = State::DISABLED; - } else { - return "Usage: INFINITE LIVES [ON|OFF]"; - } - if (GameControl::refresh_player_color) { GameControl::refresh_player_color(); } - return std::string("Infinite lives ") + (cheat == State::ENABLED ? "ON" : "OFF"); - }}, - - // INVENCIBILITY [ON|OFF] — Truco invencibilidad (tecla 2); solo en escena GAME - {.keyword = "INVENCIBILITY", .execute = [](const std::vector& args) -> std::string { - if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } - auto& cheat = Options::cheats.invincible; - using State = Options::Cheat::State; - if (args.empty()) { - cheat = (cheat == State::ENABLED) ? State::DISABLED : State::ENABLED; - } else if (args[0] == "ON") { - if (cheat == State::ENABLED) { return "Invencibility already ON"; } - cheat = State::ENABLED; - } else if (args[0] == "OFF") { - if (cheat == State::DISABLED) { return "Invencibility already OFF"; } - cheat = State::DISABLED; - } else { - return "Usage: INVENCIBILITY [ON|OFF]"; - } - if (GameControl::refresh_player_color) { GameControl::refresh_player_color(); } - return std::string("Invencibility ") + (cheat == State::ENABLED ? "ON" : "OFF"); - }}, - - // OPEN THE JAIL — Abre la jail (tecla 3 → ON); solo en escena GAME - {.keyword = "OPEN", .execute = [](const std::vector& args) -> std::string { - if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } - if (args.size() < 2 || args[0] != "THE" || args[1] != "JAIL") { return "Usage: OPEN THE JAIL"; } - if (Options::cheats.jail_is_open == Options::Cheat::State::ENABLED) { return "Jail already open"; } - Options::cheats.jail_is_open = Options::Cheat::State::ENABLED; - return "Jail opened"; - }}, - - // CLOSE THE JAIL — Cierra la jail (tecla 3 → OFF); solo en escena GAME - {.keyword = "CLOSE", .execute = [](const std::vector& args) -> std::string { - if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } - if (args.size() < 2 || args[0] != "THE" || args[1] != "JAIL") { return "Usage: CLOSE THE JAIL"; } - if (Options::cheats.jail_is_open == Options::Cheat::State::DISABLED) { return "Jail already closed"; } - Options::cheats.jail_is_open = Options::Cheat::State::DISABLED; - return "Jail closed"; - }}, - #endif - // SET SHADER [POSTFX|CRTPI] — Activa un shader concreto (disponible en todos los builds) - // SET INITIAL [ROOM|POS] — Guarda habitación/posición actual como inicio (solo _DEBUG, GAME) + // CHEAT — Trucos de juego; solo en escena GAME; no aparece en ayuda en builds Release + {.keyword = "CHEAT", .execute = [](const std::vector& args) -> std::string { + if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } + if (args.empty()) { return "Usage: CHEAT [INFINITE LIVES|INVINCIBILITY|OPEN THE JAIL|CLOSE THE JAIL]"; } + + // CHEAT INFINITE LIVES [ON|OFF] + if (args[0] == "INFINITE") { + if (args.size() < 2 || args[1] != "LIVES") { return "Usage: CHEAT INFINITE LIVES [ON|OFF]"; } + auto& cheat = Options::cheats.infinite_lives; + using State = Options::Cheat::State; + const std::vector REST(args.begin() + 2, args.end()); + if (REST.empty()) { + cheat = (cheat == State::ENABLED) ? State::DISABLED : State::ENABLED; + } else if (REST[0] == "ON") { + if (cheat == State::ENABLED) { return "Infinite lives already ON"; } + cheat = State::ENABLED; + } else if (REST[0] == "OFF") { + if (cheat == State::DISABLED) { return "Infinite lives already OFF"; } + cheat = State::DISABLED; + } else { + return "Usage: CHEAT INFINITE LIVES [ON|OFF]"; + } + if (GameControl::refresh_player_color) { GameControl::refresh_player_color(); } + return std::string("Infinite lives ") + (cheat == State::ENABLED ? "ON" : "OFF"); + } + + // CHEAT INVINCIBILITY [ON|OFF] + if (args[0] == "INVINCIBILITY" || args[0] == "INVENCIBILITY") { + auto& cheat = Options::cheats.invincible; + using State = Options::Cheat::State; + if (args.size() == 1) { + cheat = (cheat == State::ENABLED) ? State::DISABLED : State::ENABLED; + } else if (args[1] == "ON") { + if (cheat == State::ENABLED) { return "Invincibility already ON"; } + cheat = State::ENABLED; + } else if (args[1] == "OFF") { + if (cheat == State::DISABLED) { return "Invincibility already OFF"; } + cheat = State::DISABLED; + } else { + return "Usage: CHEAT INVINCIBILITY [ON|OFF]"; + } + if (GameControl::refresh_player_color) { GameControl::refresh_player_color(); } + return std::string("Invincibility ") + (cheat == State::ENABLED ? "ON" : "OFF"); + } + + // CHEAT OPEN THE JAIL + if (args[0] == "OPEN") { + if (args.size() < 3 || args[1] != "THE" || args[2] != "JAIL") { return "Usage: CHEAT OPEN THE JAIL"; } + if (Options::cheats.jail_is_open == Options::Cheat::State::ENABLED) { return "Jail already open"; } + Options::cheats.jail_is_open = Options::Cheat::State::ENABLED; + return "Jail opened"; + } + + // CHEAT CLOSE THE JAIL + if (args[0] == "CLOSE") { + if (args.size() < 3 || args[1] != "THE" || args[2] != "JAIL") { return "Usage: CHEAT CLOSE THE JAIL"; } + if (Options::cheats.jail_is_open == Options::Cheat::State::DISABLED) { return "Jail already closed"; } + Options::cheats.jail_is_open = Options::Cheat::State::DISABLED; + return "Jail closed"; + } + + return "Usage: CHEAT [INFINITE LIVES|INVINCIBILITY|OPEN THE JAIL|CLOSE THE JAIL]"; + }}, + + // SET SHADER [POSTFX|CRTPI] — Activa un shader concreto (disponible en todos los builds) + // SET INITIAL [ROOM|POS] — Guarda habitación/posición actual como inicio (solo _DEBUG, GAME) + // SET INITIAL SCENE [] — Guarda escena como escena inicial de debug (solo _DEBUG) + // SET ITEMS <0-200> — Fija el contador de items recogidos (solo _DEBUG, GAME) {.keyword = "SET", .execute = [](const std::vector& args) -> std::string { if (!args.empty() && args[0] == "SHADER") { if (args.size() < 2) { return "Usage: SET SHADER [POSTFX|CRTPI]"; } @@ -486,13 +495,46 @@ static const std::vector COMMANDS = { return "Usage: SET SHADER [POSTFX|CRTPI]"; } #ifdef _DEBUG + // SET INITIAL SCENE [] — disponible desde cualquier escena + if (args.size() >= 2 && args[0] == "INITIAL" && args[1] == "SCENE") { + SceneManager::Scene target = SceneManager::current; + std::string name = "current"; + if (args.size() >= 3) { + if (args[2] == "GAME") { target = SceneManager::Scene::GAME; name = "GAME"; } + else if (args[2] == "LOGO") { target = SceneManager::Scene::LOGO; name = "LOGO"; } + else if (args[2] == "LOADING") { target = SceneManager::Scene::LOADING_SCREEN; name = "LOADING"; } + else if (args[2] == "TITLE") { target = SceneManager::Scene::TITLE; name = "TITLE"; } + else if (args[2] == "CREDITS") { target = SceneManager::Scene::CREDITS; name = "CREDITS"; } + else if (args[2] == "ENDING") { target = SceneManager::Scene::ENDING; name = "ENDING"; } + else if (args[2] == "ENDING2") { target = SceneManager::Scene::ENDING2; name = "ENDING2"; } + else { return "Unknown scene: " + args[2]; } + } + Debug::get()->setInitialScene(target); + Debug::get()->saveToFile(); + return "Initial scene set to: " + name; + } + if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } - if (args.empty() || args[0] != "INITIAL") { return "Usage: SET INITIAL [ROOM|POS] | SET SHADER [POSTFX|CRTPI]"; } + + // SET ITEMS <0-200> — Fija el contador de items recogidos + if (args[0] == "ITEMS") { + if (args.size() < 2) { return "Usage: SET ITEMS <0-200>"; } + int count = 0; + try { + count = std::stoi(args[1]); + } catch (...) { return "Usage: SET ITEMS <0-200>"; } + if (count < 0 || count > 200) { return "Items must be between 0 and 200"; } + if (!GameControl::set_items) { return "Game not initialized"; } + GameControl::set_items(count); + return "Items: " + std::to_string(count); + } + + if (args.empty() || args[0] != "INITIAL") { return "Usage: SET INITIAL [ROOM|POS|SCENE] | SET ITEMS <0-200> | SET SHADER [POSTFX|CRTPI]"; } const bool DO_ROOM = args.size() == 1 || (args.size() >= 2 && args[1] == "ROOM"); const bool DO_POS = args.size() == 1 || (args.size() >= 2 && args[1] == "POS"); - if (!DO_ROOM && !DO_POS) { return "Usage: SET INITIAL [ROOM|POS]"; } + if (!DO_ROOM && !DO_POS) { return "Usage: SET INITIAL [ROOM|POS|SCENE]"; } if (!GameControl::set_initial_room || !GameControl::set_initial_pos) { return "Game not initialized"; } std::string result;