difficulty: mogut desde options a un fitxer propi

This commit is contained in:
2025-07-23 19:52:57 +02:00
parent e21839e478
commit d33c1f5dc5
10 changed files with 319 additions and 146 deletions

39
source/difficulty.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "difficulty.h"
#include <vector> // Para vector
namespace Difficulty {
static std::vector<Info> difficulties_list;
void init() {
difficulties_list = {
{Code::EASY, "Easy"},
{Code::NORMAL, "Normal"},
{Code::HARD, "Hard"}
};
}
auto getDifficulties() -> std::vector<Info>& {
return difficulties_list;
}
auto getNameFromCode(Code code) -> std::string {
for (const auto& difficulty : difficulties_list) {
if (difficulty.code == code) {
return difficulty.name;
}
}
return !difficulties_list.empty() ? difficulties_list.front().name : "Unknown";
}
auto getCodeFromName(const std::string& name) -> Code {
for (const auto& difficulty : difficulties_list) {
if (difficulty.name == name) {
return difficulty.code;
}
}
return !difficulties_list.empty() ? difficulties_list.front().code : Code::NORMAL;
}
} // namespace Difficulty

52
source/difficulty.h Normal file
View File

@@ -0,0 +1,52 @@
#pragma once
#include <string>
#include <vector>
namespace Difficulty {
/**
* @brief Códigos que identifican unívocamente cada nivel de dificultad.
*/
enum class Code {
EASY = 0,
NORMAL = 1,
HARD = 2,
};
/**
* @brief Estructura que asocia un código de dificultad con su nombre traducible.
*/
struct Info {
Code code;
std::string name;
};
// --- Interfaz Pública ---
/**
* @brief Inicializa la lista de dificultades con sus valores por defecto.
*/
void init();
/**
* @brief Devuelve una referencia al vector de todas las dificultades para su lectura o modificación.
* @return Referencia a `std::vector<Info>&`.
*/
auto getDifficulties() -> std::vector<Info>&;
/**
* @brief Obtiene el nombre de una dificultad a partir de su código.
* @param code El código de la dificultad.
* @return El nombre de la dificultad.
*/
auto getNameFromCode(Code code) -> std::string;
/**
* @brief Obtiene el código de una dificultad a partir de su nombre.
* @param name El nombre de la dificultad.
* @return El código de la dificultad.
*/
auto getCodeFromName(const std::string& name) -> Code;
} // namespace Difficulty

View File

@@ -82,11 +82,12 @@ Director::~Director() {
// Inicializa todo
void Director::init() {
// Configuración inicial de recursos
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
setFileList(); // Crea el índice de archivos
Options::loadFromFile(); // Carga el archivo de configuración
loadParams(); // Carga los parámetros del programa
loadScoreFile(); // Carga el archivo de puntuaciones
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
setFileList(); // Crea el índice de archivos
Options::setFile(Asset::get()->get("config.txt")); // Establece el fichero de configuración
Options::loadFromFile(); // Carga el archivo de configuración
loadParams(); // Carga los parámetros del programa
loadScoreFile(); // Carga el archivo de puntuaciones
// Inicialización de subsistemas principales
Lang::setLanguage(Options::settings.language); // Carga el archivo de idioma

View File

@@ -8,8 +8,9 @@
#include <vector> // Para vector
#include "asset.h" // Para Asset
#include "difficulty.h" // Para Difficulty
#include "external/json.hpp" // Para basic_json, iteration_proxy_value, oper...
#include "options.h" // Para Difficulty, DifficultyCode, SettingsOpt...
#include "options.h" // Para SettingsOpt...
using json = nlohmann::json;
@@ -121,19 +122,21 @@ void updateLanguageNames() {
// Actualiza los nombres de las dificultades
void updateDifficultyNames() {
for (auto &difficulty : Options::difficulties) {
switch (difficulty.code) {
case Options::DifficultyCode::EASY:
difficulty.name = Lang::getText("[SERVICE_MENU] EASY");
// 1. Pide una referencia MODIFICABLE a la lista de dificultades
auto &difficulties = Difficulty::getDifficulties();
// 2. Recorre la lista
for (auto &difficulty_info : difficulties) {
// 3. Para cada dificultad, usa su código para obtener el texto traducido y actualizar su nombre
switch (difficulty_info.code) {
case Difficulty::Code::EASY:
difficulty_info.name = Lang::getText("[SERVICE_MENU] EASY");
break;
case Options::DifficultyCode::NORMAL:
difficulty.name = Lang::getText("[SERVICE_MENU] NORMAL");
case Difficulty::Code::NORMAL:
difficulty_info.name = Lang::getText("[SERVICE_MENU] NORMAL");
break;
case Options::DifficultyCode::HARD:
difficulty.name = Lang::getText("[SERVICE_MENU] HARD");
break;
default:
difficulty.name = "Unknown";
case Difficulty::Code::HARD:
difficulty_info.name = Lang::getText("[SERVICE_MENU] HARD");
break;
}
}

View File

@@ -4,19 +4,18 @@
#include <algorithm> // Para clamp, max
#include <fstream> // Para basic_ostream, operator<<, basic_ostream::operator<<, basic_ofstream, basic_istream, basic_ifstream, ifstream, ofstream
#include <utility> // Para swap
#include <vector> // Para vector
#include <functional>
#include <map>
#include <stdexcept> // Para excepciones de std::stoi
#include <string>
#include <utility> // Para swap
#include <vector> // Para vector
#include "asset.h" // Para Asset
#include "difficulty.h" // Para Difficulty
#include "input.h" // Para InputDevice
#include "lang.h" // Para Code
#include "utils.h" // Para boolToString, stringToBool, getFileName
#include <string>
#include <functional>
#include <map>
#include <stdexcept> // Para excepciones de std::stoi
namespace Options {
// --- Variables globales ---
WindowOptions window; // Opciones de la ventana
@@ -26,19 +25,16 @@ AudioOptions audio; // Opciones de audio
std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
PendingChanges pending_changes; // Opciones que se aplican al cerrar
// Vector con las dificultades
std::vector<Difficulty> difficulties = {
{DifficultyCode::EASY, "Easy"},
{DifficultyCode::NORMAL, "Normal"},
{DifficultyCode::HARD, "Hard"}};
// Declaraciones
auto set(const std::string &var, const std::string &value) -> bool;
auto set(const std::string& var, const std::string& value) -> bool;
// Establece el fichero de configuración
void setFile(const std::string& file_path) { settings.config_file = file_path; };
// Inicializa las opciones del programa
void init() {
// Settings
settings.config_file = Asset::get()->get("config.txt");
// Dificultades
Difficulty::init();
// Opciones de control
controllers.clear();
@@ -143,7 +139,7 @@ auto saveToFile() -> bool {
// Opciones del juego
file << "\n\n## GAME\n";
file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
file << "## game.difficulty [" << static_cast<int>(DifficultyCode::EASY) << ": easy, " << static_cast<int>(DifficultyCode::NORMAL) << ": normal, " << static_cast<int>(DifficultyCode::HARD) << ": hard]\n";
file << "## game.difficulty [" << static_cast<int>(Difficulty::Code::EASY) << ": easy, " << static_cast<int>(Difficulty::Code::NORMAL) << ": normal, " << static_cast<int>(Difficulty::Code::HARD) << ": hard]\n";
file << "\n";
file << "game.language=" << static_cast<int>(settings.language) << "\n";
@@ -155,7 +151,7 @@ auto saveToFile() -> bool {
file << "\n\n## CONTROLLERS\n";
int controller_index = 0;
for (const auto &controller : controllers) {
for (const auto& controller : controllers) {
file << "\n";
file << "controller." << controller_index << ".name=" << controller.name << "\n";
file << "controller." << controller_index << ".player=" << controller.player_id << "\n";
@@ -177,7 +173,7 @@ auto saveToFile() -> bool {
}
// Función auxiliar para analizar la configuración del mando y reducir duplicación
void parseAndSetController(const std::string &var, const std::string &value) {
void parseAndSetController(const std::string& var, const std::string& value) {
// Lógica básica de análisis (puede hacerse más robusta)
size_t first_dot = var.find('.');
size_t second_dot = var.find('.', first_dot + 1);
@@ -206,7 +202,7 @@ void parseAndSetController(const std::string &var, const std::string &value) {
}
}
auto set(const std::string &var, const std::string &value) -> bool {
auto set(const std::string& var, const std::string& value) -> bool {
// Clausula de protección: ignora líneas vacías o comentarios
if (var.empty() || var.starts_with("#")) {
return false;
@@ -215,32 +211,31 @@ auto set(const std::string &var, const std::string &value) -> bool {
// Un mapa estático asegura que se inicializa solo una vez
static const std::map<std::string, std::function<void(const std::string&)>> settings_map = {
// Ventana
{"window.zoom", [](const auto& val){ window.zoom = std::stoi(val); }},
{"window.zoom", [](const auto& val) { window.zoom = std::stoi(val); }},
// Vídeo
{"video.fullscreen", [](const auto& val){ video.fullscreen = stringToBool(val); }},
{"video.scale_mode", [](const auto& val){ video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(val)); }},
{"video.shaders", [](const auto& val){ video.shaders = stringToBool(val); }},
{"video.integer_scale", [](const auto& val){ video.integer_scale = stringToBool(val); }},
{"video.vsync", [](const auto& val){ video.vsync = stringToBool(val); }},
{"video.fullscreen", [](const auto& val) { video.fullscreen = stringToBool(val); }},
{"video.scale_mode", [](const auto& val) { video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(val)); }},
{"video.shaders", [](const auto& val) { video.shaders = stringToBool(val); }},
{"video.integer_scale", [](const auto& val) { video.integer_scale = stringToBool(val); }},
{"video.vsync", [](const auto& val) { video.vsync = stringToBool(val); }},
// Audio
{"audio.enabled", [](const auto& val){ audio.enabled = stringToBool(val); }},
{"audio.volume", [](const auto& val){ audio.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.music.enabled", [](const auto& val){ audio.music.enabled = stringToBool(val); }},
{"audio.music.volume", [](const auto& val){ audio.music.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.sound.enabled", [](const auto& val){ audio.sound.enabled = stringToBool(val); }},
{"audio.sound.volume", [](const auto& val){ audio.sound.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.enabled", [](const auto& val) { audio.enabled = stringToBool(val); }},
{"audio.volume", [](const auto& val) { audio.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.music.enabled", [](const auto& val) { audio.music.enabled = stringToBool(val); }},
{"audio.music.volume", [](const auto& val) { audio.music.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.sound.enabled", [](const auto& val) { audio.sound.enabled = stringToBool(val); }},
{"audio.sound.volume", [](const auto& val) { audio.sound.volume = std::clamp(std::stoi(val), 0, 100); }},
// Juego
{"game.language", [](const auto& val){
settings.language = static_cast<Lang::Code>(std::stoi(val));
pending_changes.new_language = settings.language;
}},
{"game.difficulty", [](const auto& val){
settings.difficulty = static_cast<DifficultyCode>(std::stoi(val));
pending_changes.new_difficulty = settings.difficulty;
}},
{"game.autofire", [](const auto& val){ settings.autofire = stringToBool(val); }},
{"game.shutdown_enabled", [](const auto& val){ settings.shutdown_enabled = stringToBool(val); }}
};
{"game.language", [](const auto& val) {
settings.language = static_cast<Lang::Code>(std::stoi(val));
pending_changes.new_language = settings.language;
}},
{"game.difficulty", [](const auto& val) {
settings.difficulty = static_cast<Difficulty::Code>(std::stoi(val));
pending_changes.new_difficulty = settings.difficulty;
}},
{"game.autofire", [](const auto& val) { settings.autofire = stringToBool(val); }},
{"game.shutdown_enabled", [](const auto& val) { settings.shutdown_enabled = stringToBool(val); }}};
// Maneja por separado la configuración general de los mandos
if (var.starts_with("controller.")) {
@@ -249,7 +244,7 @@ auto set(const std::string &var, const std::string &value) -> bool {
return true;
} catch (const std::out_of_range& e) {
// Error: por ejemplo, índice de mando fuera de rango
return false;
return false;
} catch (const std::invalid_argument& e) {
// Error: por ejemplo, fallo en std::stoi
return false;
@@ -267,15 +262,14 @@ auto set(const std::string &var, const std::string &value) -> bool {
return false;
}
}
// Si la clave no se encontró en el mapa ni en la lógica de mandos
return false;
}
// Asigna el teclado al jugador
void setKeyboardToPlayer(int player_id) {
for (auto &controller : controllers) {
for (auto& controller : controllers) {
if (controller.player_id == player_id) {
controller.type = InputDevice::ANY;
} else {
@@ -297,7 +291,7 @@ void swapControllers() {
// Averigua quien está usando el teclado
auto getPlayerWhoUsesKeyboard() -> int {
for (const auto &controller : controllers) {
for (const auto& controller : controllers) {
if (controller.type == InputDevice::ANY) {
return controller.player_id;
}
@@ -318,24 +312,4 @@ void checkPendingChanges() {
pending_changes.has_pending_changes = settings.language != pending_changes.new_language ||
settings.difficulty != pending_changes.new_difficulty;
}
auto getDifficultyCodeFromName(const std::string &name) -> DifficultyCode {
for (const auto &difficulty : difficulties) {
if (difficulty.name == name) {
return difficulty.code;
}
}
// Si no se encuentra, devuelve el primero por defecto
return difficulties[0].code;
}
auto getDifficultyNameFromCode(DifficultyCode code) -> std::string {
for (const auto &difficulty : difficulties) {
if (difficulty.code == code) {
return difficulty.name;
}
}
// Si no se encuentra, devuelve el nombre del primero por defecto
return difficulties[0].name;
}
} // namespace Options

View File

@@ -7,6 +7,7 @@
#include <utility> // Para move
#include <vector> // Para vector
#include "difficulty.h" //Para Difficulty
#include "input.h" // Para InputAction, InputDevice
#include "lang.h" // Para Code
#include "manage_hiscore_table.h" // Para HiScoreEntry
@@ -14,22 +15,6 @@
static constexpr int INVALID_INDEX = -1;
namespace Options {
// --- Dificultad del juego ---
enum class DifficultyCode {
EASY = 0,
NORMAL = 1,
HARD = 2,
};
// --- Estructura que representa un nivel de dificultad
struct Difficulty {
DifficultyCode code; // Código que identifica la dificultad
std::string name; // Nombre que identifica la dificultad
Difficulty(DifficultyCode c, std::string n)
: code(c), name(std::move(n)) {}
};
// --- Opciones de ventana ---
struct WindowOptions {
std::string caption; // Texto que aparece en la barra de título de la ventana
@@ -85,7 +70,7 @@ struct AudioOptions {
// --- Opciones de configuración ---
struct SettingsOptions {
DifficultyCode difficulty{DifficultyCode::NORMAL}; // Dificultad del juego
Difficulty::Code difficulty{Difficulty::Code::NORMAL}; // Dificultad del juego
Lang::Code language{Lang::Code::VALENCIAN}; // Idioma usado en el juego
bool autofire{true}; // Indicador de autofire
bool shutdown_enabled{false}; // Especifica si se puede apagar el sistema
@@ -135,7 +120,7 @@ struct GamepadOptions {
// --- Opciones pendientes de aplicar ---
struct PendingChanges {
Lang::Code new_language{Lang::Code::VALENCIAN}; // Idioma en espera de aplicar
DifficultyCode new_difficulty{DifficultyCode::NORMAL}; // Dificultad en espera de aplicar
Difficulty::Code new_difficulty{Difficulty::Code::NORMAL}; // Dificultad en espera de aplicar
bool has_pending_changes{false}; // Indica si hay cambios pendientes
// Constructor por defecto con valores iniciales
@@ -149,18 +134,16 @@ extern VideoOptions video; // Opciones de vídeo
extern AudioOptions audio; // Opciones de audio
extern std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
extern std::vector<Difficulty> difficulties; // Lista de los diferentes tipos de dificultad
// --- Funciones de configuración ---
void init(); // Inicializa las opciones del programa
auto loadFromFile() -> bool; // Carga el fichero de configuración
auto saveToFile() -> bool; // Guarda el fichero de configuración
void setKeyboardToPlayer(int player_id); // Asigna el teclado al jugador
void swapKeyboard(); // Intercambia el teclado de jugador
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
auto getPlayerWhoUsesKeyboard() -> int; // Averigua quién está usando el teclado
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
void checkPendingChanges(); // Verifica si hay cambios pendientes
auto getDifficultyCodeFromName(const std::string &name) -> DifficultyCode; // Obtiene el código de dificultad a partir del nombre
auto getDifficultyNameFromCode(DifficultyCode code) -> std::string; // Obtiene el nombre de la dificultad a partir del código
void init(); // Inicializa las opciones del programa
void setFile(const std::string &file_path); // Establece el fichero de configuración
auto loadFromFile() -> bool; // Carga el fichero de configuración
auto saveToFile() -> bool; // Guarda el fichero de configuración
void setKeyboardToPlayer(int player_id); // Asigna el teclado al jugador
void swapKeyboard(); // Intercambia el teclado de jugador
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
auto getPlayerWhoUsesKeyboard() -> int; // Averigua quién está usando el teclado
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
void checkPendingChanges(); // Verifica si hay cambios pendientes
} // namespace Options

View File

@@ -1537,21 +1537,21 @@ void Game::initScoreboard() {
void Game::initDifficultyVars() {
// Variables relacionadas con la dificultad
switch (difficulty_) {
case Options::DifficultyCode::EASY: {
case Difficulty::Code::EASY: {
balloon_manager_->setDefaultBalloonSpeed(BALLOON_SPEED[0]);
difficulty_score_multiplier_ = 0.5F;
scoreboard_->setColor(param.scoreboard.easy_color);
break;
}
case Options::DifficultyCode::NORMAL: {
case Difficulty::Code::NORMAL: {
balloon_manager_->setDefaultBalloonSpeed(BALLOON_SPEED[0]);
difficulty_score_multiplier_ = 1.0F;
scoreboard_->setColor(param.scoreboard.normal_color);
break;
}
case Options::DifficultyCode::HARD: {
case Difficulty::Code::HARD: {
balloon_manager_->setDefaultBalloonSpeed(BALLOON_SPEED[4]);
difficulty_score_multiplier_ = 1.5F;
scoreboard_->setColor(param.scoreboard.hard_color);
@@ -1759,7 +1759,7 @@ void Game::evaluateAndSetMenace() {
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void Game::checkAndUpdateBalloonSpeed() {
if (difficulty_ != Options::DifficultyCode::NORMAL) {
if (difficulty_ != Difficulty::Code::NORMAL) {
return;
}

View File

@@ -6,6 +6,7 @@
#include <string> // Para string
#include <vector> // Para vector
#include "difficulty.h" // Para Difficulty
#include "item.h" // Para Item, ItemType
#include "manage_hiscore_table.h" // Para HiScoreEntry
#include "options.h" // Para SettingsOptions, settings, DifficultyCode (ptr only)
@@ -129,7 +130,7 @@ class Game {
Options::settings.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
Demo demo_; // Variable con todas las variables relacionadas con el modo demo
Options::DifficultyCode difficulty_ = Options::settings.difficulty; // Dificultad del juego
Difficulty::Code difficulty_ = Options::settings.difficulty; // Dificultad del juego
Helper helper_; // Variable para gestionar las ayudas
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego

View File

@@ -3,6 +3,7 @@
#include <algorithm> // Para max
#include "audio.h" // Para Audio
#include "difficulty.h" // Para Difficulty
#include "lang.h" // Para getText, getCodeFromName, getNameFromCode
#include "menu_option.h" // Para MenuOption, BoolOption, ActionOption, IntOption, FolderOption, ListOption
#include "menu_renderer.h" // Para MenuRenderer
@@ -238,36 +239,154 @@ auto ServiceMenu::countOptionsInGroup(SettingsGroup group) const -> size_t {
void ServiceMenu::initializeOptions() {
options_.clear();
// --- Video ---
options_.push_back(std::make_unique<BoolOption>(Lang::getText("[SERVICE_MENU] FULLSCREEN"), SettingsGroup::VIDEO, &Options::video.fullscreen));
options_.push_back(std::make_unique<IntOption>(Lang::getText("[SERVICE_MENU] WINDOW_SIZE"), SettingsGroup::VIDEO, &Options::window.zoom, 1, Options::window.max_zoom, 1));
options_.push_back(std::make_unique<BoolOption>(Lang::getText("[SERVICE_MENU] SHADERS"), SettingsGroup::VIDEO, &Options::video.shaders));
options_.push_back(std::make_unique<BoolOption>(Lang::getText("[SERVICE_MENU] VSYNC"), SettingsGroup::VIDEO, &Options::video.vsync));
options_.push_back(std::make_unique<BoolOption>(Lang::getText("[SERVICE_MENU] INTEGER_SCALE"), SettingsGroup::VIDEO, &Options::video.integer_scale));
// VIDEO
options_.push_back(std::make_unique<BoolOption>(
Lang::getText("[SERVICE_MENU] FULLSCREEN"),
SettingsGroup::VIDEO,
&Options::video.fullscreen));
// --- Audio ---
options_.push_back(std::make_unique<BoolOption>(Lang::getText("[SERVICE_MENU] AUDIO"), SettingsGroup::AUDIO, &Options::audio.enabled));
options_.push_back(std::make_unique<IntOption>(Lang::getText("[SERVICE_MENU] MAIN_VOLUME"), SettingsGroup::AUDIO, &Options::audio.volume, 0, 100, 5));
options_.push_back(std::make_unique<IntOption>(Lang::getText("[SERVICE_MENU] MUSIC_VOLUME"), SettingsGroup::AUDIO, &Options::audio.music.volume, 0, 100, 5));
options_.push_back(std::make_unique<IntOption>(Lang::getText("[SERVICE_MENU] SFX_VOLUME"), SettingsGroup::AUDIO, &Options::audio.sound.volume, 0, 100, 5));
options_.push_back(std::make_unique<IntOption>(
Lang::getText("[SERVICE_MENU] WINDOW_SIZE"),
SettingsGroup::VIDEO,
&Options::window.zoom,
1,
Options::window.max_zoom,
1));
// --- Settings ---
options_.push_back(std::make_unique<BoolOption>(Lang::getText("[SERVICE_MENU] AUTOFIRE"), SettingsGroup::SETTINGS, &Options::settings.autofire));
options_.push_back(std::make_unique<ListOption>(Lang::getText("[SERVICE_MENU] LANGUAGE"), SettingsGroup::SETTINGS, std::vector<std::string>{Lang::getText("[SERVICE_MENU] LANG_ES"), Lang::getText("[SERVICE_MENU] LANG_BA"), Lang::getText("[SERVICE_MENU] LANG_EN")}, []() { return Lang::getNameFromCode(Options::pending_changes.new_language); }, [](const std::string &val) { Options::pending_changes.new_language = Lang::getCodeFromName(val); Options::checkPendingChanges(); }));
options_.push_back(std::make_unique<ListOption>(Lang::getText("[SERVICE_MENU] DIFFICULTY"), SettingsGroup::SETTINGS, std::vector<std::string>{Lang::getText("[SERVICE_MENU] EASY"), Lang::getText("[SERVICE_MENU] NORMAL"), Lang::getText("[SERVICE_MENU] HARD")}, []() { return Options::getDifficultyNameFromCode(Options::pending_changes.new_difficulty); }, [](const std::string &val) { Options::pending_changes.new_difficulty = Options::getDifficultyCodeFromName(val); Options::checkPendingChanges(); }));
options_.push_back(std::make_unique<BoolOption>(Lang::getText("[SERVICE_MENU] ENABLE_SHUTDOWN"), SettingsGroup::SETTINGS, &Options::settings.shutdown_enabled));
options_.push_back(std::make_unique<BoolOption>(
Lang::getText("[SERVICE_MENU] SHADERS"),
SettingsGroup::VIDEO,
&Options::video.shaders));
// --- System ---
options_.push_back(std::make_unique<ActionOption>(Lang::getText("[SERVICE_MENU] RESET"), SettingsGroup::SYSTEM, [this]() { Section::name = Section::Name::RESET; toggle(); }));
options_.push_back(std::make_unique<ActionOption>(Lang::getText("[SERVICE_MENU] QUIT"), SettingsGroup::SYSTEM, []() { Section::name = Section::Name::QUIT; Section::options = Section::Options::NONE; }));
options_.push_back(std::make_unique<ActionOption>(Lang::getText("[SERVICE_MENU] SHUTDOWN"), SettingsGroup::SYSTEM, []() { Section::name = Section::Name::QUIT; Section::options = Section::Options::SHUTDOWN; }, !Options::settings.shutdown_enabled));
options_.push_back(std::make_unique<BoolOption>(
Lang::getText("[SERVICE_MENU] VSYNC"),
SettingsGroup::VIDEO,
&Options::video.vsync));
// --- Main Menu ---
options_.push_back(std::make_unique<FolderOption>(Lang::getText("[SERVICE_MENU] VIDEO"), SettingsGroup::MAIN, SettingsGroup::VIDEO));
options_.push_back(std::make_unique<FolderOption>(Lang::getText("[SERVICE_MENU] AUDIO"), SettingsGroup::MAIN, SettingsGroup::AUDIO));
options_.push_back(std::make_unique<FolderOption>(Lang::getText("[SERVICE_MENU] SETTINGS"), SettingsGroup::MAIN, SettingsGroup::SETTINGS));
options_.push_back(std::make_unique<FolderOption>(Lang::getText("[SERVICE_MENU] SYSTEM"), SettingsGroup::MAIN, SettingsGroup::SYSTEM));
options_.push_back(std::make_unique<BoolOption>(
Lang::getText("[SERVICE_MENU] INTEGER_SCALE"),
SettingsGroup::VIDEO,
&Options::video.integer_scale));
// AUDIO
options_.push_back(std::make_unique<BoolOption>(
Lang::getText("[SERVICE_MENU] AUDIO"),
SettingsGroup::AUDIO,
&Options::audio.enabled));
options_.push_back(std::make_unique<IntOption>(
Lang::getText("[SERVICE_MENU] MAIN_VOLUME"),
SettingsGroup::AUDIO,
&Options::audio.volume,
0,
100,
5));
options_.push_back(std::make_unique<IntOption>(
Lang::getText("[SERVICE_MENU] MUSIC_VOLUME"),
SettingsGroup::AUDIO,
&Options::audio.music.volume,
0,
100,
5));
options_.push_back(std::make_unique<IntOption>(
Lang::getText("[SERVICE_MENU] SFX_VOLUME"),
SettingsGroup::AUDIO,
&Options::audio.sound.volume,
0,
100,
5));
// SETTINGS
options_.push_back(std::make_unique<BoolOption>(
Lang::getText("[SERVICE_MENU] AUTOFIRE"),
SettingsGroup::SETTINGS,
&Options::settings.autofire));
options_.push_back(std::make_unique<ListOption>(
Lang::getText("[SERVICE_MENU] LANGUAGE"),
SettingsGroup::SETTINGS,
std::vector<std::string>{
Lang::getText("[SERVICE_MENU] LANG_ES"),
Lang::getText("[SERVICE_MENU] LANG_BA"),
Lang::getText("[SERVICE_MENU] LANG_EN")},
[]() {
return Lang::getNameFromCode(Options::pending_changes.new_language);
},
[](const std::string &val) {
Options::pending_changes.new_language = Lang::getCodeFromName(val);
Options::checkPendingChanges();
}));
options_.push_back(std::make_unique<ListOption>(
Lang::getText("[SERVICE_MENU] DIFFICULTY"),
SettingsGroup::SETTINGS,
std::vector<std::string>{
Lang::getText("[SERVICE_MENU] EASY"),
Lang::getText("[SERVICE_MENU] NORMAL"),
Lang::getText("[SERVICE_MENU] HARD")},
[]() {
return Difficulty::getNameFromCode(Options::pending_changes.new_difficulty);
},
[](const std::string &val) {
Options::pending_changes.new_difficulty = Difficulty::getCodeFromName(val);
Options::checkPendingChanges();
}));
options_.push_back(std::make_unique<BoolOption>(
Lang::getText("[SERVICE_MENU] ENABLE_SHUTDOWN"),
SettingsGroup::SETTINGS,
&Options::settings.shutdown_enabled));
// SYSTEM
options_.push_back(std::make_unique<ActionOption>(
Lang::getText("[SERVICE_MENU] RESET"),
SettingsGroup::SYSTEM,
[this]() {
Section::name = Section::Name::RESET;
toggle();
}));
options_.push_back(std::make_unique<ActionOption>(
Lang::getText("[SERVICE_MENU] QUIT"),
SettingsGroup::SYSTEM,
[]() {
Section::name = Section::Name::QUIT;
Section::options = Section::Options::NONE;
}));
options_.push_back(std::make_unique<ActionOption>(
Lang::getText("[SERVICE_MENU] SHUTDOWN"),
SettingsGroup::SYSTEM,
[]() {
Section::name = Section::Name::QUIT;
Section::options = Section::Options::SHUTDOWN;
},
!Options::settings.shutdown_enabled));
// MAIN MENU
options_.push_back(std::make_unique<FolderOption>(
Lang::getText("[SERVICE_MENU] VIDEO"),
SettingsGroup::MAIN,
SettingsGroup::VIDEO));
options_.push_back(std::make_unique<FolderOption>(
Lang::getText("[SERVICE_MENU] AUDIO"),
SettingsGroup::MAIN,
SettingsGroup::AUDIO));
options_.push_back(std::make_unique<FolderOption>(
Lang::getText("[SERVICE_MENU] SETTINGS"),
SettingsGroup::MAIN,
SettingsGroup::SETTINGS));
options_.push_back(std::make_unique<FolderOption>(
Lang::getText("[SERVICE_MENU] SYSTEM"),
SettingsGroup::MAIN,
SettingsGroup::SYSTEM));
// Oculta opciones según configuración
setHiddenOptions();
}