diff --git a/source/game/game_control.hpp b/source/game/game_control.hpp new file mode 100644 index 0000000..6046bf1 --- /dev/null +++ b/source/game/game_control.hpp @@ -0,0 +1,14 @@ +#pragma once +#ifdef _DEBUG +#include +#include + +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() — hace toggle del modo debug (equivale a tecla 0) + inline std::function toggle_debug_mode; +} +#endif diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index c1c711e..13963f8 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -32,6 +32,7 @@ #ifdef _DEBUG #include "core/system/debug.hpp" // Para Debug +#include "game/game_control.hpp" // Para GameControl #endif // Constructor @@ -58,12 +59,31 @@ Game::Game(Mode mode) Cheevos::get()->enable(!Options::cheats.enabled()); // Deshabilita los logros si hay trucos activados Cheevos::get()->clearUnobtainableState(); +#ifdef _DEBUG + GameControl::change_room = [this](const std::string& r) -> bool { return this->changeRoom(r); }; + GameControl::refresh_player_color = [this]() -> void { player_->setColor(); }; + GameControl::toggle_debug_mode = [this]() -> void { + Debug::get()->toggleEnabled(); + room_->redrawMap(); + Options::cheats.invincible = static_cast(Debug::get()->isEnabled()); + player_->setColor(); + scoreboard_data_->music = !Debug::get()->isEnabled(); + scoreboard_data_->music ? Audio::get()->resumeMusic() : Audio::get()->pauseMusic(); + }; +#endif + SceneManager::current = (mode_ == Mode::GAME) ? SceneManager::Scene::GAME : SceneManager::Scene::DEMO; SceneManager::options = SceneManager::Options::NONE; } Game::~Game() { ItemTracker::destroy(); + +#ifdef _DEBUG + GameControl::change_room = nullptr; + GameControl::refresh_player_color = nullptr; + GameControl::toggle_debug_mode = nullptr; +#endif } // Comprueba los eventos de la cola diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index 4ed5992..247db58 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -18,6 +18,11 @@ #include "game/scene_manager.hpp" // Para SceneManager #include "game/ui/notifier.hpp" // Para Notifier +#ifdef _DEBUG +#include "core/system/debug.hpp" // Para Debug +#include "game/game_control.hpp" // Para GameControl +#endif + // ── Sistema de comandos ──────────────────────────────────────────────────────── struct ConsoleCommand { @@ -81,6 +86,11 @@ static void printHelp() { SDL_Log(" PALETTE [NEXT|PREV] Color palette (F5/F6)"); #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)"); #endif SDL_Log(" AUDIO [ON|OFF|VOL <0-100>] Audio master"); SDL_Log(" MUSIC [ON|OFF|VOL <0-100>] Music volume"); @@ -88,7 +98,8 @@ static void printHelp() { SDL_Log(" SCENE [LOGO|LOADING|TITLE|CREDITS|GAME|ENDING|ENDING2|RESTART]"); SDL_Log(" KIOSK [ON] Enable kiosk mode"); SDL_Log(" EXIT / QUIT Quit application"); - SDL_Log(" SHOW NOTIFICATION Show a test notification"); + SDL_Log(" SHOW [FPS|INFO|NOTIFICATION] Show debug overlay or test notification"); + SDL_Log(" HIDE [FPS|INFO] Hide debug overlay"); SDL_Log(" HELP/? Show this help in terminal"); } @@ -296,25 +307,117 @@ static const std::vector COMMANDS = { }}, #ifdef _DEBUG - // DEBUG [ON|OFF] — Overlay de debug (F12, solo en builds debug) - {.keyword = "DEBUG", .execute = BOOL_TOGGLE_CMD("Debug overlay", RenderInfo::get()->isActive(), RenderInfo::get()->toggle())}, + // DEBUG [ON|OFF] — Activa/desactiva el modo debug del juego (tecla 0); solo en escena GAME + {.keyword = "DEBUG", .execute = [](const std::vector& args) -> std::string { + if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } + if (!GameControl::toggle_debug_mode) { return "Game not initialized"; } + const bool ENABLED = Debug::get()->isEnabled(); + if (!args.empty() && args[0] == "ON") { + if (ENABLED) { return "Debug mode already ON"; } + GameControl::toggle_debug_mode(); + return "Debug mode ON"; + } + if (!args.empty() && args[0] == "OFF") { + if (!ENABLED) { return "Debug mode already OFF"; } + GameControl::toggle_debug_mode(); + return "Debug mode OFF"; + } + if (!args.empty()) { return "Usage: DEBUG [ON|OFF]"; } + GameControl::toggle_debug_mode(); + return std::string("Debug mode ") + (Debug::get()->isEnabled() ? "ON" : "OFF"); + }}, - // SHOW FPS / SHOW NOTIFICATION / HIDE FPS + // SHOW FPS / SHOW INFO / SHOW NOTIFICATION / HIDE FPS / HIDE INFO {.keyword = "SHOW", .execute = [](const std::vector& args) -> std::string { if (!args.empty() && args[0] == "NOTIFICATION") { Notifier::get()->show({"NOTIFICATION"}); return "Notification shown"; } - if (args.empty() || args[0] != "FPS") { return "Usage: SHOW [FPS|NOTIFICATION]"; } - if (RenderInfo::get()->isActive()) { return "Debug overlay already ON"; } + if (args.empty() || (args[0] != "FPS" && args[0] != "INFO")) { return "Usage: SHOW [FPS|INFO|NOTIFICATION]"; } + if (RenderInfo::get()->isActive()) { return "Info overlay already ON"; } RenderInfo::get()->toggle(); - return "Debug overlay ON"; + return "Info overlay ON"; }}, {.keyword = "HIDE", .execute = [](const std::vector& args) -> std::string { - if (args.empty() || args[0] != "FPS") { return "Usage: HIDE FPS"; } - if (!RenderInfo::get()->isActive()) { return "Debug overlay already OFF"; } + if (args.empty() || (args[0] != "FPS" && args[0] != "INFO")) { return "Usage: HIDE [FPS|INFO]"; } + if (!RenderInfo::get()->isActive()) { return "Info overlay already OFF"; } RenderInfo::get()->toggle(); - return "Debug overlay OFF"; + return "Info overlay OFF"; + }}, + + // ROOM — Cambia a la habitación indicada (1-60); solo en escena GAME + {.keyword = "ROOM", .execute = [](const std::vector& args) -> std::string { + if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } + if (args.empty()) { return "Usage: ROOM <1-60>"; } + int num = 0; + try { num = std::stoi(args[0]); } catch (...) { return "Usage: ROOM <1-60>"; } + if (num < 1 || num > 60) { return "Room must be between 1 and 60"; } + char buf[16]; + std::snprintf(buf, sizeof(buf), "%02d.yaml", num); + if (GameControl::change_room && GameControl::change_room(buf)) { + return std::string("Room: ") + buf; + } + 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