diff --git a/data/console/commands.yaml b/data/console/commands.yaml index dc8126b..baf2e13 100644 --- a/data/console/commands.yaml +++ b/data/console/commands.yaml @@ -182,7 +182,8 @@ categories: - keyword: HELP handler: cmd_help description: "Show this help" - usage: "HELP / ?" + usage: "HELP []" + dynamic_completions: true - keyword: "?" handler: cmd_help @@ -271,6 +272,7 @@ categories: description: "Game cheats (GAME only)" usage: "CHEAT [INFINITE LIVES|INVINCIBILITY|OPEN THE JAIL|CLOSE THE JAIL]" hidden: true + help_hidden: true completions: CHEAT: [INFINITE, INVINCIBILITY, OPEN, CLOSE] CHEAT INFINITE: [LIVES] @@ -282,3 +284,4 @@ categories: CHEAT CLOSE THE: [JAIL] debug_extras: hidden: false + help_hidden: false diff --git a/source/game/editor/map_editor.cpp b/source/game/editor/map_editor.cpp index 489b2ff..82385e2 100644 --- a/source/game/editor/map_editor.cpp +++ b/source/game/editor/map_editor.cpp @@ -18,9 +18,9 @@ #include "core/resources/resource_list.hpp" // Para Resource::List #include "core/resources/resource_types.hpp" // Para RoomResource #include "game/editor/editor_statusbar.hpp" // Para EditorStatusBar -#include "game/game_control.hpp" // Para GameControl #include "game/editor/room_saver.hpp" // Para RoomSaver #include "game/entities/player.hpp" // Para Player +#include "game/game_control.hpp" // Para GameControl #include "game/gameplay/enemy_manager.hpp" // Para EnemyManager #include "game/gameplay/item_manager.hpp" // Para ItemManager #include "game/gameplay/room.hpp" // Para Room @@ -69,12 +69,18 @@ void MapEditor::loadSettings() { if (yaml.contains("grid")) { settings_.grid = yaml["grid"].get_value(); } if (yaml.contains("show_render_info")) { settings_.show_render_info = yaml["show_render_info"].get_value(); } if (yaml.contains("minimap_bg")) { - if (yaml["minimap_bg"].is_string()) { settings_.minimap_bg = yaml["minimap_bg"].get_value(); } - else if (yaml["minimap_bg"].is_integer()) { settings_.minimap_bg = std::to_string(yaml["minimap_bg"].get_value()); } + if (yaml["minimap_bg"].is_string()) { + settings_.minimap_bg = yaml["minimap_bg"].get_value(); + } else if (yaml["minimap_bg"].is_integer()) { + settings_.minimap_bg = std::to_string(yaml["minimap_bg"].get_value()); + } } if (yaml.contains("minimap_conn")) { - if (yaml["minimap_conn"].is_string()) { settings_.minimap_conn = yaml["minimap_conn"].get_value(); } - else if (yaml["minimap_conn"].is_integer()) { settings_.minimap_conn = std::to_string(yaml["minimap_conn"].get_value()); } + if (yaml["minimap_conn"].is_string()) { + settings_.minimap_conn = yaml["minimap_conn"].get_value(); + } else if (yaml["minimap_conn"].is_integer()) { + settings_.minimap_conn = std::to_string(yaml["minimap_conn"].get_value()); + } } } catch (...) { // Fichero corrupto o vacío, usar defaults @@ -116,8 +122,9 @@ auto MapEditor::showGrid(bool show) -> std::string { // Parsea un color por nombre o índice numérico static auto parseColor(const std::string& value) -> Uint8 { - try { return static_cast(std::stoi(value)); } - catch (...) { return stringToColor(value); } + try { + return static_cast(std::stoi(value)); + } catch (...) { return stringToColor(value); } } void MapEditor::toggleMiniMap() { @@ -243,7 +250,7 @@ void MapEditor::exit() { // Restaurar prompt y scope de la consola selected_enemy_ = -1; Console::get()->setPrompt("> "); - Console::get()->setScope(""); + Console::get()->setScope("debug"); drag_ = {}; statusbar_.reset(); room_.reset(); @@ -421,14 +428,13 @@ void MapEditor::handleEvent(const SDL_Event& event) { // Tile bajo el cursor como tile actual del picker int tile_index = mouse_tile_y_ * 32 + mouse_tile_x_; int current = (tile_index >= 0 && tile_index < static_cast(room_data_.tile_map.size())) - ? room_data_.tile_map[tile_index] - : -1; + ? room_data_.tile_map[tile_index] + : -1; tile_picker_.on_select = [this](int tile) { brush_tile_ = tile; }; - tile_picker_.open(room_->getTileSetFile(), current, - stringToColor(room_data_.bg_color)); + tile_picker_.open(room_->getTileSetFile(), current, stringToColor(room_data_.bg_color)); return; } @@ -1178,19 +1184,36 @@ auto MapEditor::setRoomProperty(const std::string& property, const std::string& // Dirección opuesta para la conexión recíproca std::string opposite; std::string* our_field = nullptr; - if (property == "UP") { opposite = "lower_room"; our_field = &room_data_.upper_room; } - if (property == "DOWN") { opposite = "upper_room"; our_field = &room_data_.lower_room; } - if (property == "LEFT") { opposite = "right_room"; our_field = &room_data_.left_room; } - if (property == "RIGHT") { opposite = "left_room"; our_field = &room_data_.right_room; } + if (property == "UP") { + opposite = "lower_room"; + our_field = &room_data_.upper_room; + } + if (property == "DOWN") { + opposite = "upper_room"; + our_field = &room_data_.lower_room; + } + if (property == "LEFT") { + opposite = "right_room"; + our_field = &room_data_.left_room; + } + if (property == "RIGHT") { + opposite = "left_room"; + our_field = &room_data_.right_room; + } // Si había una conexión anterior, romper la recíproca de la otra room if (our_field != nullptr && *our_field != "0" && !our_field->empty()) { auto old_other = Resource::Cache::get()->getRoom(*our_field); if (old_other) { - if (opposite == "upper_room") { old_other->upper_room = "0"; } - else if (opposite == "lower_room") { old_other->lower_room = "0"; } - else if (opposite == "left_room") { old_other->left_room = "0"; } - else if (opposite == "right_room") { old_other->right_room = "0"; } + if (opposite == "upper_room") { + old_other->upper_room = "0"; + } else if (opposite == "lower_room") { + old_other->lower_room = "0"; + } else if (opposite == "left_room") { + old_other->left_room = "0"; + } else if (opposite == "right_room") { + old_other->right_room = "0"; + } // Guardar la otra room std::string other_path = Resource::List::get()->get(*our_field); if (!other_path.empty()) { @@ -1207,10 +1230,15 @@ auto MapEditor::setRoomProperty(const std::string& property, const std::string& if (connection != "0") { auto other = Resource::Cache::get()->getRoom(connection); if (other) { - if (opposite == "upper_room") { other->upper_room = room_path_; } - else if (opposite == "lower_room") { other->lower_room = room_path_; } - else if (opposite == "left_room") { other->left_room = room_path_; } - else if (opposite == "right_room") { other->right_room = room_path_; } + if (opposite == "upper_room") { + other->upper_room = room_path_; + } else if (opposite == "lower_room") { + other->lower_room = room_path_; + } else if (opposite == "left_room") { + other->left_room = room_path_; + } else if (opposite == "right_room") { + other->right_room = room_path_; + } std::string other_path = Resource::List::get()->get(connection); if (!other_path.empty()) { auto other_yaml = RoomSaver::loadYAML(other_path); @@ -1306,10 +1334,15 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { // Comprobar que no hay ya una room en esa dirección if (!direction.empty()) { std::string* existing = nullptr; - if (direction == "UP") { existing = &room_data_.upper_room; } - else if (direction == "DOWN") { existing = &room_data_.lower_room; } - else if (direction == "LEFT") { existing = &room_data_.left_room; } - else if (direction == "RIGHT") { existing = &room_data_.right_room; } + if (direction == "UP") { + existing = &room_data_.upper_room; + } else if (direction == "DOWN") { + existing = &room_data_.lower_room; + } else if (direction == "LEFT") { + existing = &room_data_.left_room; + } else if (direction == "RIGHT") { + existing = &room_data_.right_room; + } if (existing != nullptr && *existing != "0" && !existing->empty()) { return "Already connected " + toLower(direction) + ": " + *existing; } @@ -1319,8 +1352,9 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { auto& rooms = Resource::Cache::get()->getRooms(); std::set used; for (const auto& r : rooms) { - try { used.insert(std::stoi(r.name.substr(0, r.name.find('.')))); } - catch (...) {} + try { + used.insert(std::stoi(r.name.substr(0, r.name.find('.')))); + } catch (...) {} } int new_num = 1; while (used.contains(new_num)) { ++new_num; } @@ -1351,10 +1385,15 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { new_room.tile_map.resize(32 * 16, -1); // Conexión recíproca: la nueva room conecta de vuelta a la actual - if (direction == "UP") { new_room.lower_room = room_path_; } - else if (direction == "DOWN") { new_room.upper_room = room_path_; } - else if (direction == "LEFT") { new_room.right_room = room_path_; } - else if (direction == "RIGHT") { new_room.left_room = room_path_; } + if (direction == "UP") { + new_room.lower_room = room_path_; + } else if (direction == "DOWN") { + new_room.upper_room = room_path_; + } else if (direction == "LEFT") { + new_room.right_room = room_path_; + } else if (direction == "RIGHT") { + new_room.left_room = room_path_; + } // Conexiones del YAML auto connStr = [](const std::string& c) -> std::string { return (c == "0") ? "null" : c; }; @@ -1400,10 +1439,15 @@ auto MapEditor::createNewRoom(const std::string& direction) -> std::string { addRoomToAssetsYaml(new_name); // Conectar la room actual con la nueva (recíproco: ya hecho arriba para la nueva) - if (direction == "UP") { room_data_.upper_room = new_name; } - else if (direction == "DOWN") { room_data_.lower_room = new_name; } - else if (direction == "LEFT") { room_data_.left_room = new_name; } - else if (direction == "RIGHT") { room_data_.right_room = new_name; } + if (direction == "UP") { + room_data_.upper_room = new_name; + } else if (direction == "DOWN") { + room_data_.lower_room = new_name; + } else if (direction == "LEFT") { + room_data_.left_room = new_name; + } else if (direction == "RIGHT") { + room_data_.right_room = new_name; + } if (!direction.empty()) { autosave(); } @@ -1425,15 +1469,23 @@ auto MapEditor::deleteRoom() -> std::string { // Buscar una room vecina a la que navegar después de borrar std::string target = "0"; - if (room_data_.upper_room != "0" && !room_data_.upper_room.empty()) { target = room_data_.upper_room; } - else if (room_data_.lower_room != "0" && !room_data_.lower_room.empty()) { target = room_data_.lower_room; } - else if (room_data_.left_room != "0" && !room_data_.left_room.empty()) { target = room_data_.left_room; } - else if (room_data_.right_room != "0" && !room_data_.right_room.empty()) { target = room_data_.right_room; } + if (room_data_.upper_room != "0" && !room_data_.upper_room.empty()) { + target = room_data_.upper_room; + } else if (room_data_.lower_room != "0" && !room_data_.lower_room.empty()) { + target = room_data_.lower_room; + } else if (room_data_.left_room != "0" && !room_data_.left_room.empty()) { + target = room_data_.left_room; + } else if (room_data_.right_room != "0" && !room_data_.right_room.empty()) { + target = room_data_.right_room; + } if (target == "0") { // Buscar la primera room que no sea esta for (const auto& r : Resource::Cache::get()->getRooms()) { - if (r.name != deleted_name) { target = r.name; break; } + if (r.name != deleted_name) { + target = r.name; + break; + } } } if (target == "0") { return "Cannot delete: no other room to navigate to"; } @@ -1443,10 +1495,15 @@ auto MapEditor::deleteRoom() -> std::string { if (neighbor == "0" || neighbor.empty()) { return; } auto other = Resource::Cache::get()->getRoom(neighbor); if (!other) { return; } - if (field_name == "upper_room") { other->upper_room = "0"; } - else if (field_name == "lower_room") { other->lower_room = "0"; } - else if (field_name == "left_room") { other->left_room = "0"; } - else if (field_name == "right_room") { other->right_room = "0"; } + if (field_name == "upper_room") { + other->upper_room = "0"; + } else if (field_name == "lower_room") { + other->lower_room = "0"; + } else if (field_name == "left_room") { + other->left_room = "0"; + } else if (field_name == "right_room") { + other->right_room = "0"; + } // Guardar la otra room std::string other_path = Resource::List::get()->get(neighbor); if (!other_path.empty()) { @@ -1474,8 +1531,7 @@ auto MapEditor::deleteRoom() -> std::string { // Quitar del cache auto& cache_rooms = Resource::Cache::get()->getRooms(); cache_rooms.erase( - std::remove_if(cache_rooms.begin(), cache_rooms.end(), - [&](const RoomResource& r) { return r.name == deleted_name; }), + std::remove_if(cache_rooms.begin(), cache_rooms.end(), [&](const RoomResource& r) { return r.name == deleted_name; }), cache_rooms.end()); // Quitar de assets.yaml diff --git a/source/game/editor/map_editor.hpp b/source/game/editor/map_editor.hpp index 83ed6cd..e016baf 100644 --- a/source/game/editor/map_editor.hpp +++ b/source/game/editor/map_editor.hpp @@ -118,12 +118,12 @@ class MapEditor { // Estado del editor bool active_{false}; DragState drag_; - int selected_enemy_{-1}; // Índice del enemigo seleccionado (-1 = ninguno) - int selected_item_{-1}; // Índice del item seleccionado (-1 = ninguno) - static constexpr int NO_BRUSH = -2; // Sin brush activo - static constexpr int ERASER_BRUSH = -1; // Brush borrador (pinta tile vacío = -1) - int brush_tile_{NO_BRUSH}; // Tile activo para pintar - bool painting_{false}; // true mientras se está pintando con click izquierdo mantenido + int selected_enemy_{-1}; // Índice del enemigo seleccionado (-1 = ninguno) + int selected_item_{-1}; // Índice del item seleccionado (-1 = ninguno) + static constexpr int NO_BRUSH = -2; // Sin brush activo + static constexpr int ERASER_BRUSH = -1; // Brush borrador (pinta tile vacío = -1) + int brush_tile_{NO_BRUSH}; // Tile activo para pintar + bool painting_{false}; // true mientras se está pintando con click izquierdo mantenido // Datos de la habitación Room::Data room_data_; diff --git a/source/game/editor/mini_map.cpp b/source/game/editor/mini_map.cpp index 8b83a48..d6db693 100644 --- a/source/game/editor/mini_map.cpp +++ b/source/game/editor/mini_map.cpp @@ -3,8 +3,8 @@ #include "game/editor/mini_map.hpp" #include // Para std::max, std::min -#include // Para std::floor #include // Para std::array +#include // Para std::floor #include // Para cout #include // Para std::map #include // Para queue (BFS) @@ -18,7 +18,9 @@ #include "utils/utils.hpp" // Para stringToColor // Constructor: construye todo el minimapa -MiniMap::MiniMap(Uint8 bg_color, Uint8 conn_color) : bg_color_(bg_color), conn_color_(conn_color) { +MiniMap::MiniMap(Uint8 bg_color, Uint8 conn_color) + : bg_color_(bg_color), + conn_color_(conn_color) { buildTileColorTable("standard.gif"); layoutRooms(); buildRoomSurfaces(); @@ -217,8 +219,7 @@ void MiniMap::composeFinalSurface() { if (!mini.surface) { continue; } int px = cellPixelX(mini.pos.x) + SHADOW_OFFSET; int py = cellPixelY(mini.pos.y) + SHADOW_OFFSET; - SDL_FRect shadow = {.x = static_cast(px), .y = static_cast(py), - .w = static_cast(CELL_W), .h = static_cast(CELL_H)}; + SDL_FRect shadow = {.x = static_cast(px), .y = static_cast(py), .w = static_cast(CELL_W), .h = static_cast(CELL_H)}; map_surface_->fillRect(&shadow, COLOR_SHADOW); } @@ -229,13 +230,11 @@ void MiniMap::composeFinalSurface() { int py = cellPixelY(mini.pos.y); // Borde negro (la celda entera) - SDL_FRect cell = {.x = static_cast(px), .y = static_cast(py), - .w = static_cast(CELL_W), .h = static_cast(CELL_H)}; + SDL_FRect cell = {.x = static_cast(px), .y = static_cast(py), .w = static_cast(CELL_W), .h = static_cast(CELL_H)}; map_surface_->fillRect(&cell, COLOR_ROOM_BORDER); // Miniroom dentro del borde - SDL_FRect dst = {.x = static_cast(px + BORDER), .y = static_cast(py + BORDER), - .w = static_cast(ROOM_W), .h = static_cast(ROOM_H)}; + SDL_FRect dst = {.x = static_cast(px + BORDER), .y = static_cast(py + BORDER), .w = static_cast(ROOM_W), .h = static_cast(ROOM_H)}; mini.surface->render(nullptr, &dst); } @@ -255,8 +254,7 @@ void MiniMap::drawConnections() { if (room_data->right_room != "0" && !room_data->right_room.empty() && room_positions_.contains(room_data->right_room)) { int x1 = px + CELL_W; int y_mid = py + CELL_H / 2 - 1; - SDL_FRect line = {.x = static_cast(x1), .y = static_cast(y_mid), - .w = static_cast(GAP), .h = 3.0F}; + SDL_FRect line = {.x = static_cast(x1), .y = static_cast(y_mid), .w = static_cast(GAP), .h = 3.0F}; map_surface_->fillRect(&line, conn_color_); } @@ -264,8 +262,7 @@ void MiniMap::drawConnections() { if (room_data->lower_room != "0" && !room_data->lower_room.empty() && room_positions_.contains(room_data->lower_room)) { int x_mid = px + CELL_W / 2 - 1; int y1 = py + CELL_H; - SDL_FRect line = {.x = static_cast(x_mid), .y = static_cast(y1), - .w = 3.0F, .h = static_cast(GAP)}; + SDL_FRect line = {.x = static_cast(x_mid), .y = static_cast(y1), .w = 3.0F, .h = static_cast(GAP)}; map_surface_->fillRect(&line, conn_color_); } } @@ -309,8 +306,7 @@ void MiniMap::render(const std::string& current_room) { // Renderizar la surface del minimapa con el viewport actual (alineado a pixel) float vx = std::floor(view_x_); float vy = std::floor(view_y_); - SDL_FRect dst = {.x = vx, .y = vy, - .w = static_cast(map_width_ + SHADOW_OFFSET), .h = static_cast(map_height_ + SHADOW_OFFSET)}; + SDL_FRect dst = {.x = vx, .y = vy, .w = static_cast(map_width_ + SHADOW_OFFSET), .h = static_cast(map_height_ + SHADOW_OFFSET)}; map_surface_->render(nullptr, &dst); // Highlight de la room actual (solo si está completamente visible en el play area) diff --git a/source/game/editor/mini_map.hpp b/source/game/editor/mini_map.hpp index 2ac156e..704e7b7 100644 --- a/source/game/editor/mini_map.hpp +++ b/source/game/editor/mini_map.hpp @@ -4,11 +4,11 @@ #include -#include // Para function -#include // Para shared_ptr -#include // Para string -#include // Para unordered_map -#include // Para vector +#include // Para function +#include // Para shared_ptr +#include // Para string +#include // Para unordered_map +#include // Para vector class Surface; @@ -58,9 +58,9 @@ class MiniMap { auto cellPixelY(int grid_y) const -> int { return PADDING + (grid_y - min_grid_y_) * (CELL_H + GAP); } // Tabla de color predominante por tile index - std::vector tile_colors_; // tile_index → palette color index - int tileset_width_{0}; // Ancho del tileset en tiles - Uint8 tileset_transparent_{16}; // Color transparente del tileset + std::vector tile_colors_; // tile_index → palette color index + int tileset_width_{0}; // Ancho del tileset en tiles + Uint8 tileset_transparent_{16}; // Color transparente del tileset // Rooms renderizadas y posicionadas std::unordered_map room_positions_; @@ -84,20 +84,20 @@ class MiniMap { float view_start_y_{0.0F}; // Constantes - static constexpr int ROOM_W = 32; // Ancho de una room en pixels del minimapa - static constexpr int ROOM_H = 16; // Alto de una room en pixels del minimapa - static constexpr int BORDER = 1; // Borde alrededor de cada room + static constexpr int ROOM_W = 32; // Ancho de una room en pixels del minimapa + static constexpr int ROOM_H = 16; // Alto de una room en pixels del minimapa + static constexpr int BORDER = 1; // Borde alrededor de cada room static constexpr int CELL_W = ROOM_W + BORDER * 2; // Room + borde static constexpr int CELL_H = ROOM_H + BORDER * 2; - static constexpr int GAP = 4; // Separación entre celdas - static constexpr int SHADOW_OFFSET = 1; // Desplazamiento de la sombra - static constexpr int PADDING = 4; // Padding alrededor del minimapa + static constexpr int GAP = 4; // Separación entre celdas + static constexpr int SHADOW_OFFSET = 1; // Desplazamiento de la sombra + static constexpr int PADDING = 4; // Padding alrededor del minimapa // Colores del minimapa (índices de paleta) - Uint8 bg_color_{2}; // Fondo general (configurable) - Uint8 conn_color_{14}; // Líneas de conexión (configurable) + Uint8 bg_color_{2}; // Fondo general (configurable) + Uint8 conn_color_{14}; // Líneas de conexión (configurable) static constexpr Uint8 COLOR_ROOM_BORDER = 0; // Borde de cada miniroom - static constexpr Uint8 COLOR_SHADOW = 1; // Sombra de cada miniroom + static constexpr Uint8 COLOR_SHADOW = 1; // Sombra de cada miniroom }; #endif // _DEBUG diff --git a/source/game/editor/tile_picker.cpp b/source/game/editor/tile_picker.cpp index f013886..aeebef4 100644 --- a/source/game/editor/tile_picker.cpp +++ b/source/game/editor/tile_picker.cpp @@ -14,9 +14,7 @@ static constexpr int BORDER_PAD = 3; // Abre el picker con un tileset -void TilePicker::open(const std::string& tileset_name, int current_tile, - int bg_color, int source_color, int target_color, - int tile_spacing_in, int tile_spacing_out) { +void TilePicker::open(const std::string& tileset_name, int current_tile, int bg_color, int source_color, int target_color, int tile_spacing_in, int tile_spacing_out) { tileset_ = Resource::Cache::get()->getSurface(tileset_name); if (!tileset_) { open_ = false; @@ -70,16 +68,15 @@ void TilePicker::open(const std::string& tileset_name, int current_tile, SDL_FRect src = { .x = static_cast(col * src_cell), .y = static_cast(row * src_cell), - .w = TS, .h = TS}; + .w = TS, + .h = TS}; // Destino: posición en el frame con spacing de salida int dst_x = BORDER_PAD + col * out_cell; int dst_y = BORDER_PAD + row * out_cell; if (source_color >= 0 && target_color >= 0) { - tileset_->renderWithColorReplace(dst_x, dst_y, - static_cast(source_color), - static_cast(target_color), &src); + tileset_->renderWithColorReplace(dst_x, dst_y, static_cast(source_color), static_cast(target_color), &src); } else { SDL_FRect dst = {.x = static_cast(dst_x), .y = static_cast(dst_y), .w = TS, .h = TS}; tileset_->render(&src, &dst); @@ -97,8 +94,7 @@ void TilePicker::open(const std::string& tileset_name, int current_tile, visible_height_ = PlayArea::HEIGHT; - frame_dst_ = {.x = static_cast(offset_x_), .y = static_cast(offset_y), - .w = static_cast(frame_w), .h = static_cast(frame_h)}; + frame_dst_ = {.x = static_cast(offset_x_), .y = static_cast(offset_y), .w = static_cast(frame_w), .h = static_cast(frame_h)}; // Si el frame es más alto que el play area, necesitará scroll if (frame_h > visible_height_) { @@ -138,8 +134,7 @@ void TilePicker::render() { int max_scroll = frame_h - visible_height_; scroll_y_ = std::clamp(scroll_y_, 0, max_scroll); - SDL_FRect src = {.x = 0, .y = static_cast(scroll_y_), - .w = frame_dst_.w, .h = static_cast(visible_height_)}; + SDL_FRect src = {.x = 0, .y = static_cast(scroll_y_), .w = frame_dst_.w, .h = static_cast(visible_height_)}; SDL_FRect dst = {.x = frame_dst_.x, .y = 0, .w = frame_dst_.w, .h = static_cast(visible_height_)}; frame_surface_->render(&src, &dst); } diff --git a/source/game/editor/tile_picker.hpp b/source/game/editor/tile_picker.hpp index e4f0ee4..bb9b886 100644 --- a/source/game/editor/tile_picker.hpp +++ b/source/game/editor/tile_picker.hpp @@ -29,9 +29,7 @@ class TilePicker { // source_color/target_color: sustitución de color (-1 = sin sustitución) // tile_spacing_in: pixels de separación entre tiles en el fichero fuente // tile_spacing_out: pixels de separación visual entre tiles al mostrar - void open(const std::string& tileset_name, int current_tile = -1, - int bg_color = -1, int source_color = -1, int target_color = -1, - int tile_spacing_in = 0, int tile_spacing_out = 1); + void open(const std::string& tileset_name, int current_tile = -1, int bg_color = -1, int source_color = -1, int target_color = -1, int tile_spacing_in = 0, int tile_spacing_out = 1); void close(); [[nodiscard]] auto isOpen() const -> bool { return open_; } @@ -54,8 +52,8 @@ class TilePicker { int hover_tile_{-1}; // Tile bajo el cursor // Spacing - int spacing_in_{0}; // Spacing en el fichero fuente - int spacing_out_{1}; // Spacing visual al mostrar + int spacing_in_{0}; // Spacing en el fichero fuente + int spacing_out_{1}; // Spacing visual al mostrar // Scroll y posicionamiento int scroll_y_{0}; // Scroll vertical en pixels diff --git a/source/game/gameplay/tilemap_renderer.cpp b/source/game/gameplay/tilemap_renderer.cpp index b317ba0..1b21658 100644 --- a/source/game/gameplay/tilemap_renderer.cpp +++ b/source/game/gameplay/tilemap_renderer.cpp @@ -114,8 +114,7 @@ void TilemapRenderer::setTile(int index, int tile_value) { Screen::get()->setRendererSurface(map_surface_); // Borrar la celda con el color de fondo - SDL_FRect cell = {.x = static_cast(col * TILE_SIZE), .y = static_cast(row * TILE_SIZE), - .w = static_cast(TILE_SIZE), .h = static_cast(TILE_SIZE)}; + SDL_FRect cell = {.x = static_cast(col * TILE_SIZE), .y = static_cast(row * TILE_SIZE), .w = static_cast(TILE_SIZE), .h = static_cast(TILE_SIZE)}; map_surface_->fillRect(&cell, stringToColor(bg_color_)); // Dibujar el nuevo tile (si no es vacío ni animado) @@ -123,8 +122,9 @@ void TilemapRenderer::setTile(int index, int tile_value) { const bool IS_ANIMATED = (tile_value >= 18 * tile_set_width_) && (tile_value < 19 * tile_set_width_); if (!IS_ANIMATED) { SDL_FRect clip = {.x = static_cast((tile_value % tile_set_width_) * TILE_SIZE), - .y = static_cast((tile_value / tile_set_width_) * TILE_SIZE), - .w = static_cast(TILE_SIZE), .h = static_cast(TILE_SIZE)}; + .y = static_cast((tile_value / tile_set_width_) * TILE_SIZE), + .w = static_cast(TILE_SIZE), + .h = static_cast(TILE_SIZE)}; tileset_surface_->render(col * TILE_SIZE, row * TILE_SIZE, &clip); } } diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 573c45e..a78f0e4 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -79,6 +79,11 @@ Game::Game(Mode mode) Cheevos::get()->enable(!Options::cheats.enabled()); // Deshabilita los logros si hay trucos activados Cheevos::get()->clearUnobtainableState(); +#ifdef _DEBUG + Console::get()->setScope("debug"); +#else + Console::get()->setScope("game"); +#endif Console::get()->on_toggle = [this](bool open) { player_->setIgnoreInput(open); }; if (Console::get()->isActive()) { player_->setIgnoreInput(true); } GameControl::change_player_skin = [this](const std::string& skin_name) -> void { diff --git a/source/game/ui/console.hpp b/source/game/ui/console.hpp index e9415c0..987a938 100644 --- a/source/game/ui/console.hpp +++ b/source/game/ui/console.hpp @@ -58,7 +58,7 @@ class Console { // Constantes de consola static constexpr std::string_view CONSOLE_NAME = "JDD Console"; - static constexpr std::string_view CONSOLE_VERSION = "v2.1"; + static constexpr std::string_view CONSOLE_VERSION = "v2.2"; static constexpr int MAX_LINE_CHARS = 32; static constexpr int MAX_HISTORY_SIZE = 20; static constexpr float CURSOR_ON_TIME = 0.5F; diff --git a/source/game/ui/console_commands.cpp b/source/game/ui/console_commands.cpp index 3d8ce51..99f4983 100644 --- a/source/game/ui/console_commands.cpp +++ b/source/game/ui/console_commands.cpp @@ -1032,6 +1032,11 @@ void CommandRegistry::registerHandlers() { dynamic_providers_["SET BGCOLOR"] = color_provider; dynamic_providers_["EDIT MAPBG"] = color_provider; dynamic_providers_["EDIT MAPCONN"] = color_provider; + + // HELP: lista de comandos visibles en el scope activo + dynamic_providers_["HELP"] = [this]() -> std::vector { + return getVisibleKeywords(); + }; dynamic_providers_["SET BORDER"] = color_provider; dynamic_providers_["SET ITEMCOLOR1"] = color_provider; dynamic_providers_["SET ITEMCOLOR2"] = color_provider; @@ -1151,6 +1156,7 @@ void CommandRegistry::load(const std::string& yaml_path) { if (extras.contains("description")) { def.description = extras["description"].get_value(); } if (extras.contains("usage")) { def.usage = extras["usage"].get_value(); } if (extras.contains("hidden")) { def.hidden = extras["hidden"].get_value(); } + if (extras.contains("help_hidden")) { def.help_hidden = extras["help_hidden"].get_value(); } if (extras.contains("completions")) { def.completions.clear(); auto extras_completions = extras["completions"]; @@ -1176,7 +1182,29 @@ void CommandRegistry::load(const std::string& yaml_path) { } // Registrar el handler de HELP (captura this) - handlers_["cmd_help"] = [this](const std::vector&) -> std::string { + handlers_["cmd_help"] = [this](const std::vector& args) -> std::string { + if (!args.empty()) { + // HELP : mostrar ayuda detallada de un comando + const auto* cmd = findCommand(args[0]); + if (cmd != nullptr) { + std::string kw_lower = cmd->keyword; + std::ranges::transform(kw_lower, kw_lower.begin(), ::tolower); + std::string result = kw_lower + ": " + cmd->description + "\n" + cmd->usage; + + // Listar subcomandos/opciones si hay completions + auto opts = getCompletions(cmd->keyword); + if (!opts.empty()) { + result += "\noptions:"; + for (const auto& opt : opts) { + std::string opt_lower = opt; + std::ranges::transform(opt_lower, opt_lower.begin(), ::tolower); + result += " " + opt_lower; + } + } + return result; + } + return "Unknown command: " + args[0]; + } std::cout << generateTerminalHelp(); return generateConsoleHelp(); }; @@ -1288,6 +1316,15 @@ auto CommandRegistry::generateConsoleHelp() const -> std::string { } auto CommandRegistry::getCompletions(const std::string& path) const -> std::vector { + // Verificar que el comando raíz es visible en el scope activo + if (!active_scope_.empty()) { + std::string root = path; + auto space = root.find(' '); + if (space != std::string::npos) { root = root.substr(0, space); } + const auto* cmd = findCommand(root); + if (cmd != nullptr && !isCommandVisible(*cmd)) { return {}; } + } + // Primero: buscar proveedor dinámico (tiene prioridad si existe) const auto dyn_it = dynamic_providers_.find(path); if (dyn_it != dynamic_providers_.end()) {