#include "common/jscore.h" #include "common/utils.h" #include "const.h" #include "director.h" #include #include #include #include #include #ifndef _WIN32 #include #endif // Constructor Director::Director(int argc, char *argv[]) { // Inicializa variables section.name = PROG_SECTION_LOGO; // Inicializa las opciones del programa initOptions(); // Comprueba los parametros del programa checkProgramArguments(argc, argv); // Crea la carpeta del sistema donde guardar datos createSystemFolder("jailgames"); #ifndef DEBUG createSystemFolder("jailgames/coffee_crisis"); #else createSystemFolder("jailgames/coffee_crisis_debug"); #endif // Crea el objeto que controla los ficheros de recursos asset = new Asset(executablePath); asset->setVerbose(options->console); // Si falta algún fichero no inicia el programa if (!setFileList()) { exit(EXIT_FAILURE); } // Carga el fichero de configuración loadConfigFile(); // Inicializa SDL initSDL(); // Inicializa JailAudio initJailAudio(); // Crea los objetos lang = new Lang(asset); lang->setLang(options->language); input = new Input(asset->get("gamecontrollerdb.txt")); initInput(); screen = new Screen(window, renderer, asset, options); // Inicializa los servicios online initOnline(); } Director::~Director() { saveConfigFile(); delete asset; delete input; delete screen; delete lang; delete options; SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); } // Inicializa el objeto input void Director::initInput() { // Establece si ha de mostrar mensajes input->setVerbose(options->console); // Busca si hay un mando conectado input->discoverGameController(); // Teclado - Movimiento del jugador input->bindKey(input_up, SDL_SCANCODE_UP); input->bindKey(input_down, SDL_SCANCODE_DOWN); input->bindKey(input_left, SDL_SCANCODE_LEFT); input->bindKey(input_right, SDL_SCANCODE_RIGHT); input->bindKey(input_fire_left, SDL_SCANCODE_Q); input->bindKey(input_fire_center, SDL_SCANCODE_W); input->bindKey(input_fire_right, SDL_SCANCODE_E); // Teclado - Otros input->bindKey(input_accept, SDL_SCANCODE_RETURN); input->bindKey(input_cancel, SDL_SCANCODE_ESCAPE); input->bindKey(input_pause, SDL_SCANCODE_ESCAPE); input->bindKey(input_exit, SDL_SCANCODE_ESCAPE); input->bindKey(input_window_dec_size, SDL_SCANCODE_F1); input->bindKey(input_window_inc_size, SDL_SCANCODE_F2); input->bindKey(input_window_fullscreen, SDL_SCANCODE_F3); // Mando - Movimiento del jugador input->bindGameControllerButton(input_up, SDL_CONTROLLER_BUTTON_DPAD_UP); input->bindGameControllerButton(input_down, SDL_CONTROLLER_BUTTON_DPAD_DOWN); input->bindGameControllerButton(input_left, SDL_CONTROLLER_BUTTON_DPAD_LEFT); input->bindGameControllerButton(input_right, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); input->bindGameControllerButton(input_fire_left, SDL_CONTROLLER_BUTTON_X); input->bindGameControllerButton(input_fire_center, SDL_CONTROLLER_BUTTON_Y); input->bindGameControllerButton(input_fire_right, SDL_CONTROLLER_BUTTON_B); // Mando - Otros input->bindGameControllerButton(input_accept, SDL_CONTROLLER_BUTTON_B); input->bindGameControllerButton(input_cancel, SDL_CONTROLLER_BUTTON_A); #ifdef GAME_CONSOLE input->bindGameControllerButton(input_pause, SDL_CONTROLLER_BUTTON_BACK); input->bindGameControllerButton(input_exit, SDL_CONTROLLER_BUTTON_START); #else input->bindGameControllerButton(input_pause, SDL_CONTROLLER_BUTTON_START); input->bindGameControllerButton(input_exit, SDL_CONTROLLER_BUTTON_BACK); #endif } // Inicializa JailAudio void Director::initJailAudio() { JA_Init(48000, AUDIO_S16, 2); } // Arranca SDL y crea la ventana bool Director::initSDL() { // Indicador de éxito bool success = true; // Inicializa SDL if (SDL_Init(SDL_INIT_EVERYTHING) < 0) // if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) { if (options->console) { std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl; } success = false; } else { // Inicia el generador de numeros aleatorios std::srand(static_cast(SDL_GetTicks())); // Establece el filtro de la textura if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(options->filter).c_str())) { if (options->console) { std::cout << "Warning: Nearest texture filtering not enabled!\n"; } } // Crea la ventana int incW = 0; int incH = 0; if (options->borderEnabled) { incW = options->borderWidth * 2; incH = options->borderHeight * 2; } window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, (options->gameWidth + incW) * options->windowSize, (options->gameHeight + incH) * options->windowSize, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); if (window == nullptr) { if (options->console) { std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl; } success = false; } else { // Crea un renderizador para la ventana. El vsync se activa en funcion de las opciones if (options->vSync) { renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); } else { renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); } if (renderer == nullptr) { if (options->console) { std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl; } success = false; } else { // Inicializa el color de renderizado SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); // Establece el tamaño del buffer de renderizado SDL_RenderSetLogicalSize(renderer, options->gameWidth, options->gameHeight); // Establece el modo de mezcla SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); } } } if (options->console) { std::cout << std::endl; } return success; } // Crea el indice de ficheros bool Director::setFileList() { #ifdef MACOS_BUNDLE const std::string prefix = "/../Resources"; #else const std::string prefix = ""; #endif // Ficheros de configuración asset->add(systemFolder + "/config.txt", t_data, false, true); asset->add(systemFolder + "/score.bin", t_data, false, true); asset->add(prefix + "/data/config/demo.bin", t_data); asset->add(prefix + "/data/config/gamecontrollerdb.txt", t_data); // Notificaciones asset->add(prefix + "/data/notifications/notify.png", t_bitmap); // Musicas asset->add(prefix + "/data/music/intro.ogg", t_music); asset->add(prefix + "/data/music/playing.ogg", t_music); asset->add(prefix + "/data/music/title.ogg", t_music); // Sonidos asset->add(prefix + "/data/sound/balloon.wav", t_sound); asset->add(prefix + "/data/sound/bubble1.wav", t_sound); asset->add(prefix + "/data/sound/bubble2.wav", t_sound); asset->add(prefix + "/data/sound/bubble3.wav", t_sound); asset->add(prefix + "/data/sound/bubble4.wav", t_sound); asset->add(prefix + "/data/sound/bullet.wav", t_sound); asset->add(prefix + "/data/sound/coffeeout.wav", t_sound); asset->add(prefix + "/data/sound/hiscore.wav", t_sound); asset->add(prefix + "/data/sound/itemdrop.wav", t_sound); asset->add(prefix + "/data/sound/itempickup.wav", t_sound); asset->add(prefix + "/data/sound/menu_move.wav", t_sound); asset->add(prefix + "/data/sound/menu_select.wav", t_sound); asset->add(prefix + "/data/sound/player_collision.wav", t_sound); asset->add(prefix + "/data/sound/stage_change.wav", t_sound); asset->add(prefix + "/data/sound/title.wav", t_sound); asset->add(prefix + "/data/sound/clock.wav", t_sound); asset->add(prefix + "/data/sound/powerball.wav", t_sound); asset->add(prefix + "/data/sound/notify.wav", t_sound); // Texturas asset->add(prefix + "/data/gfx/balloon1.png", t_bitmap); asset->add(prefix + "/data/gfx/balloon1.ani", t_data); asset->add(prefix + "/data/gfx/balloon2.png", t_bitmap); asset->add(prefix + "/data/gfx/balloon2.ani", t_data); asset->add(prefix + "/data/gfx/balloon3.png", t_bitmap); asset->add(prefix + "/data/gfx/balloon3.ani", t_data); asset->add(prefix + "/data/gfx/balloon4.png", t_bitmap); asset->add(prefix + "/data/gfx/balloon4.ani", t_data); asset->add(prefix + "/data/gfx/bullet.png", t_bitmap); asset->add(prefix + "/data/gfx/game_buildings.png", t_bitmap); asset->add(prefix + "/data/gfx/game_clouds.png", t_bitmap); asset->add(prefix + "/data/gfx/game_grass.png", t_bitmap); asset->add(prefix + "/data/gfx/game_power_meter.png", t_bitmap); asset->add(prefix + "/data/gfx/game_sky_colors.png", t_bitmap); asset->add(prefix + "/data/gfx/game_text.png", t_bitmap); asset->add(prefix + "/data/gfx/intro.png", t_bitmap); asset->add(prefix + "/data/gfx/logo.png", t_bitmap); asset->add(prefix + "/data/gfx/menu_game_over.png", t_bitmap); asset->add(prefix + "/data/gfx/menu_game_over_end.png", t_bitmap); asset->add(prefix + "/data/gfx/item_points1_disk.png", t_bitmap); asset->add(prefix + "/data/gfx/item_points1_disk.ani", t_data); asset->add(prefix + "/data/gfx/item_points2_gavina.png", t_bitmap); asset->add(prefix + "/data/gfx/item_points2_gavina.ani", t_data); asset->add(prefix + "/data/gfx/item_points3_pacmar.png", t_bitmap); asset->add(prefix + "/data/gfx/item_points3_pacmar.ani", t_data); asset->add(prefix + "/data/gfx/item_clock.png", t_bitmap); asset->add(prefix + "/data/gfx/item_clock.ani", t_data); asset->add(prefix + "/data/gfx/item_coffee.png", t_bitmap); asset->add(prefix + "/data/gfx/item_coffee.ani", t_data); asset->add(prefix + "/data/gfx/item_coffee_machine.png", t_bitmap); asset->add(prefix + "/data/gfx/item_coffee_machine.ani", t_data); asset->add(prefix + "/data/gfx/title_bg_tile.png", t_bitmap); asset->add(prefix + "/data/gfx/title_coffee.png", t_bitmap); asset->add(prefix + "/data/gfx/title_crisis.png", t_bitmap); asset->add(prefix + "/data/gfx/title_dust.png", t_bitmap); asset->add(prefix + "/data/gfx/title_dust.ani", t_data); asset->add(prefix + "/data/gfx/title_gradient.png", t_bitmap); asset->add(prefix + "/data/gfx/player_head.ani", t_data); asset->add(prefix + "/data/gfx/player_body.ani", t_data); asset->add(prefix + "/data/gfx/player_legs.ani", t_data); asset->add(prefix + "/data/gfx/player_death.ani", t_data); asset->add(prefix + "/data/gfx/player_fire.ani", t_data); asset->add(prefix + "/data/gfx/player_bal1_head.png", t_bitmap); asset->add(prefix + "/data/gfx/player_bal1_body.png", t_bitmap); asset->add(prefix + "/data/gfx/player_bal1_legs.png", t_bitmap); asset->add(prefix + "/data/gfx/player_bal1_death.png", t_bitmap); asset->add(prefix + "/data/gfx/player_bal1_fire.png", t_bitmap); asset->add(prefix + "/data/gfx/player_arounder_head.png", t_bitmap); asset->add(prefix + "/data/gfx/player_arounder_body.png", t_bitmap); asset->add(prefix + "/data/gfx/player_arounder_legs.png", t_bitmap); asset->add(prefix + "/data/gfx/player_arounder_death.png", t_bitmap); asset->add(prefix + "/data/gfx/player_arounder_fire.png", t_bitmap); // Fuentes asset->add(prefix + "/data/font/8bithud.png", t_font); asset->add(prefix + "/data/font/8bithud.txt", t_font); asset->add(prefix + "/data/font/nokia.png", t_font); asset->add(prefix + "/data/font/nokia_big2.png", t_font); asset->add(prefix + "/data/font/nokia.txt", t_font); asset->add(prefix + "/data/font/nokia2.png", t_font); asset->add(prefix + "/data/font/nokia2.txt", t_font); asset->add(prefix + "/data/font/nokia_big2.txt", t_font); asset->add(prefix + "/data/font/smb2_big.png", t_font); asset->add(prefix + "/data/font/smb2_big.txt", t_font); asset->add(prefix + "/data/font/smb2.png", t_font); asset->add(prefix + "/data/font/smb2.txt", t_font); // Textos asset->add(prefix + "/data/lang/es_ES.txt", t_lang); asset->add(prefix + "/data/lang/en_UK.txt", t_lang); asset->add(prefix + "/data/lang/ba_BA.txt", t_lang); // Menus asset->add(prefix + "/data/menu/title.men", t_data); asset->add(prefix + "/data/menu/title_gc.men", t_data); asset->add(prefix + "/data/menu/options.men", t_data); asset->add(prefix + "/data/menu/options_gc.men", t_data); asset->add(prefix + "/data/menu/pause.men", t_data); asset->add(prefix + "/data/menu/gameover.men", t_data); asset->add(prefix + "/data/menu/player_select.men", t_data); return asset->check(); } // Inicializa las opciones del programa void Director::initOptions() { // Crea el puntero a la estructura de opciones options = new options_t; // Pone unos valores por defecto para las opciones de control options->input.clear(); input_t inp; inp.id = 0; inp.name = "KEYBOARD"; inp.deviceType = INPUT_USE_KEYBOARD; options->input.push_back(inp); inp.id = 0; inp.name = "GAME CONTROLLER"; inp.deviceType = INPUT_USE_GAMECONTROLLER; options->input.push_back(inp); // Opciones de video options->gameWidth = GAMECANVAS_WIDTH; options->gameHeight = GAMECANVAS_HEIGHT; options->videoMode = 0; options->windowSize = 3; options->filter = FILTER_NEAREST; options->vSync = true; options->integerScale = true; options->keepAspect = true; options->borderWidth = 0; options->borderHeight = 0; options->borderEnabled = false; // Opciones varios options->playerSelected = 0; options->difficulty = DIFFICULTY_NORMAL; options->language = ba_BA; options->console = false; // Opciones online options->online.enabled = false; options->online.server = "jaildoctor.duckdns.org"; options->online.port = 9911; #ifdef DEBUG options->online.gameID = "coffee_crisis_test2"; #else options->online.gameID = "coffee_crisis"; #endif options->online.jailerID = ""; options->online.score = 0; // Opciones de las notificaciones options->notifications.posV = pos_top; options->notifications.posH = pos_left; options->notifications.sound = true; options->notifications.color = {48, 48, 48}; } // Comprueba los parametros del programa void Director::checkProgramArguments(int argc, char *argv[]) { // Establece la ruta del programa executablePath = argv[0]; // Comprueba el resto de parametros for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--console") == 0) { options->console = true; } } } // Crea la carpeta del sistema donde guardar datos void Director::createSystemFolder(std::string folder) { #ifdef _WIN32 systemFolder = std::string(getenv("APPDATA")) + "/" + folder; #elif __APPLE__ struct passwd *pw = getpwuid(getuid()); const char *homedir = pw->pw_dir; systemFolder = std::string(homedir) + "/Library/Application Support" + "/" + folder; #elif __linux__ struct passwd *pw = getpwuid(getuid()); const char *homedir = pw->pw_dir; systemFolder = std::string(homedir) + "/." + folder; #endif struct stat st = {0}; if (stat(systemFolder.c_str(), &st) == -1) { errno = 0; #ifdef _WIN32 int ret = mkdir(systemFolder.c_str()); #else int ret = mkdir(systemFolder.c_str(), S_IRWXU); #endif if (ret == -1) { switch (errno) { case EACCES: printf("the parent directory does not allow write"); exit(EXIT_FAILURE); case EEXIST: printf("pathname already exists"); exit(EXIT_FAILURE); case ENAMETOOLONG: printf("pathname is too long"); exit(EXIT_FAILURE); default: perror("mkdir"); exit(EXIT_FAILURE); } } } } // Carga el fichero de configuración bool Director::loadConfigFile() { // Indicador de éxito en la carga bool success = true; // Variables para manejar el fichero const std::string filePath = "config.txt"; std::string line; std::ifstream file(asset->get(filePath)); // Si el fichero se puede abrir if (file.good()) { // Procesa el fichero linea a linea if (options->console) { std::cout << "Reading file " << filePath << std::endl; } while (std::getline(file, line)) { // Comprueba que la linea no sea un comentario if (line.substr(0, 1) != "#") { // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (!setOptions(options, line.substr(0, pos), line.substr(pos + 1, line.length()))) { if (options->console) { std::cout << "Warning: file " << filePath << std::endl; std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl; } success = false; } } } // Cierra el fichero if (options->console) { std::cout << "Closing file " << filePath << std::endl; } file.close(); } // El fichero no existe else { // Crea el fichero con los valores por defecto saveConfigFile(); } // Normaliza los valores const bool a = options->videoMode == 0; const bool b = options->videoMode == SDL_WINDOW_FULLSCREEN; const bool c = options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP; if (!(a || b || c)) { options->videoMode = 0; } if (options->windowSize < 1 || options->windowSize > 4) { options->windowSize = 3; } if (options->language < 0 || options->language > MAX_LANGUAGES) { options->language = en_UK; } return success; } // Guarda el fichero de configuración bool Director::saveConfigFile() { bool success = true; // Crea y abre el fichero de texto std::ofstream file(asset->get("config.txt")); if (file.good()) { if (options->console) { std::cout << asset->get("config.txt") << " open for writing" << std::endl; } } else { if (options->console) { std::cout << asset->get("config.txt") << " can't be opened" << std::endl; } } // Opciones g´raficas file << "## VISUAL OPTIONS\n"; if (options->videoMode == 0) { file << "videoMode=0\n"; } else if (options->videoMode == SDL_WINDOW_FULLSCREEN) { file << "fullScreenMode=SDL_WINDOW_FULLSCREEN\n"; } else if (options->videoMode == SDL_WINDOW_FULLSCREEN_DESKTOP) { file << "fullScreenMode=SDL_WINDOW_FULLSCREEN_DESKTOP\n"; } file << "windowSize=" + std::to_string(options->windowSize) + "\n"; if (options->filter == FILTER_NEAREST) { file << "filter=FILTER_NEAREST\n"; } else { file << "filter=FILTER_LINEAL\n"; } file << "vSync=" + boolToString(options->vSync) + "\n"; file << "integerScale=" + boolToString(options->integerScale) + "\n"; file << "keepAspect=" + boolToString(options->keepAspect) + "\n"; file << "borderEnabled=" + boolToString(options->borderEnabled) + "\n"; file << "borderWidth=" + std::to_string(options->borderWidth) + "\n"; file << "borderHeight=" + std::to_string(options->borderHeight) + "\n"; // Otras opciones del programa file << "\n## OTHER OPTIONS\n"; file << "language=" + std::to_string(options->language) + "\n"; file << "difficulty=" + std::to_string(options->difficulty) + "\n"; file << "input0=" + std::to_string(options->input[0].deviceType) + "\n"; file << "input1=" + std::to_string(options->input[1].deviceType) + "\n"; // Opciones sobre la conexión online file << "\n## ONLINE OPTIONS\n"; file << "enabled=" + boolToString(options->online.enabled) + "\n"; file << "server=" + options->online.server + "\n"; file << "port=" + std::to_string(options->online.port) + "\n"; file << "jailerID=" + options->online.jailerID + "\n"; // Opciones de las notificaciones file << "\n## NOTIFICATION OPTIONS\n"; file << "## notifications.posV = pos_top | pos_bottom\n"; if (options->notifications.posV == pos_top) { file << "notifications.posV=pos_top\n"; } else { file << "notifications.posV=pos_bottom\n"; } file << "## notifications.posH = pos_left | pos_middle | pos_right\n"; if (options->notifications.posH == pos_left) { file << "notifications.posH=pos_left\n"; } else if (options->notifications.posH == pos_middle) { file << "notifications.posH=pos_middle\n"; } else { file << "notifications.posH=pos_right\n"; } file << "notifications.sound=" + boolToString(options->notifications.sound) + "\n"; // Cierra el fichero file.close(); return success; } // Establece el valor de la variable void Director::setSection(section_t section) { this->section = section; } void Director::runLogo() { logo = new Logo(renderer, screen, asset, input); setSection(logo->run()); delete logo; } void Director::runIntro() { intro = new Intro(renderer, screen, asset, input, lang); setSection(intro->run()); delete intro; } void Director::runTitle() { title = new Title(renderer, screen, input, asset, options, lang, section); setSection(title->run()); delete title; } void Director::runGame() { const int numPlayers = section.subsection == GAME_SECTION_PLAY_1P ? 1 : 2; game = new Game(numPlayers, 0, renderer, screen, asset, lang, input, false, options); setSection(game->run()); delete game; } void Director::run() { // Bucle principal while (section.name != PROG_SECTION_QUIT) { switch (section.name) { case PROG_SECTION_LOGO: runLogo(); break; case PROG_SECTION_INTRO: runIntro(); break; case PROG_SECTION_TITLE: runTitle(); break; case PROG_SECTION_GAME: runGame(); break; } } } // Inicializa los servicios online void Director::initOnline() { if (options->online.sessionEnabled) { // Si ya ha iniciado la sesión, que no continue return; } if (options->online.jailerID == "") { // Jailer ID no definido options->online.enabled = false; } else { // Jailer ID iniciado options->online.enabled = options->online.sessionEnabled = true; // Establece el servidor y el puerto jscore::init(options->online.server, options->online.port); #ifdef DEBUG const std::string caption = options->online.jailerID + " (DEBUG)"; #else const std::string caption = options->online.jailerID; #endif screen->showNotification(caption, lang->getText(85), 12); if (options->console) { std::cout << caption << std::endl; } // Obtiene la información de puntuaciones online if (!jscore::initOnlineScore(options->online.gameID)) { screen->showNotification(lang->getText(80), options->online.server); if (options->console) { std::cout << "Can't connect to " << options->online.server << std::endl; } options->online.enabled = false; return; } // Obten la puntuación online para el jailerID const int points = jscore::getUserPoints(options->online.gameID, options->online.jailerID); if (points == 0) { // Fallo de conexión o no hay registros screen->showNotification(lang->getText(81), lang->getText(82)); if (options->console) { std::cout << "Can't get online scores" << std::endl; } } else { options->online.score = points; } } } // Asigna variables a partir de dos cadenas bool Director::setOptions(options_t *options, std::string var, std::string value) { // Indicador de éxito en la asignación bool success = true; // Opciones de video if (var == "videoMode") { if (value == "SDL_WINDOW_FULLSCREEN_DESKTOP") { options->videoMode = SDL_WINDOW_FULLSCREEN_DESKTOP; } else if (value == "SDL_WINDOW_FULLSCREEN") { options->videoMode = SDL_WINDOW_FULLSCREEN; } else { options->videoMode = 0; } } else if (var == "windowSize") { options->windowSize = std::stoi(value); if ((options->windowSize < 1) || (options->windowSize > 4)) { options->windowSize = 3; } } else if (var == "filter") { if (value == "FILTER_LINEAL") { options->filter = FILTER_LINEAL; } else { options->filter = FILTER_NEAREST; } } else if (var == "vSync") { options->vSync = stringToBool(value); } else if (var == "integerScale") { options->integerScale = stringToBool(value); } else if (var == "keepAspect") { options->keepAspect = stringToBool(value); } else if (var == "borderEnabled") { options->borderEnabled = stringToBool(value); } else if (var == "borderWidth") { options->borderWidth = std::stoi(value); } else if (var == "borderHeight") { options->borderHeight = std::stoi(value); } // Opciones varias else if (var == "language") { options->language = std::stoi(value); } else if (var == "difficulty") { options->difficulty = std::stoi(value); } else if (var == "input0") { options->input[0].deviceType = std::stoi(value); } else if (var == "input1") { options->input[1].deviceType = std::stoi(value); } // Opciones onlince else if (var == "enabled") { options->online.enabled = stringToBool(value); } else if (var == "server") { options->online.server = value; } else if (var == "port") { if (value == "") { value = "0"; } options->online.port = std::stoi(value); } else if (var == "jailerID") { options->online.jailerID = toLower(value); } // Opciones de notificaciones else if (var == "notifications.posH") { if (value == "pos_left") { options->notifications.posH = pos_left; } else if (value == "pos_middle") { options->notifications.posH = pos_middle; } else { options->notifications.posH = pos_right; } } else if (var == "notifications.posV") { if (value == "pos_top") { options->notifications.posV = pos_top; } else { options->notifications.posV = pos_bottom; } } else if (var == "notifications.sound") { options->notifications.sound = stringToBool(value); } // Lineas vacias o que empiezan por comentario else if (var == "" || var.substr(0, 1) == "#") { } else { success = false; } return success; }