#include "cheevos.h" #include // Para SDL_GetError #include // Para SDL_RWFromFile, SDL_RWclose, SDL_RWwrite #include // Para NULL #include // Para basic_ostream, operator<<, basic_ofstream #include // Para cout, cerr #include "notifier.h" // Para Notifier #include "options.h" // Para Options, options // [SINGLETON] Cheevos* Cheevos::cheevos_ = nullptr; // [SINGLETON] Crearemos el objeto con esta función estática void Cheevos::init(const std::string& file) { Cheevos::cheevos_ = new Cheevos(file); } // [SINGLETON] Destruiremos el objeto con esta función estática void Cheevos::destroy() { delete Cheevos::cheevos_; } // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él Cheevos* Cheevos::get() { return Cheevos::cheevos_; } // Constructor Cheevos::Cheevos(const std::string& file) : file_(file) { init(); loadFromFile(); } // Destructor Cheevos::~Cheevos() { saveToFile(); } // Inicializa los logros void Cheevos::init() { cheevos_list_.clear(); cheevos_list_.emplace_back(1, "SHINY THINGS", "Get 25% of the items", 2); cheevos_list_.emplace_back(2, "HALF THE WORK", "Get 50% of the items", 2); cheevos_list_.emplace_back(3, "GETTING THERE", "Get 75% of the items", 2); cheevos_list_.emplace_back(4, "THE COLLECTOR", "Get 100% of the items", 2); cheevos_list_.emplace_back(5, "WANDERING AROUND", "Visit 20 rooms", 2); cheevos_list_.emplace_back(6, "I GOT LOST", "Visit 40 rooms", 2); cheevos_list_.emplace_back(7, "I LIKE TO EXPLORE", "Visit all rooms", 2); cheevos_list_.emplace_back(8, "FINISH THE GAME", "Complete the game", 2); cheevos_list_.emplace_back(9, "I WAS SUCKED BY A HOLE", "Complete the game without entering the jail", 2); cheevos_list_.emplace_back(10, "MY LITTLE PROJECTS", "Complete the game with all items", 2); cheevos_list_.emplace_back(11, "I LIKE MY MULTICOLOURED FRIENDS", "Complete the game without dying", 2); cheevos_list_.emplace_back(12, "SHIT PROJECTS DONE FAST", "Complete the game in under 30 minutes", 2); } // Busca un logro por id y devuelve el indice int Cheevos::find(int id) { for (int i = 0; i < (int)cheevos_list_.size(); ++i) { if (cheevos_list_[i].id == id) { return i; } } return -1; } // Desbloquea un logro void Cheevos::unlock(int id) { const int INDEX = find(id); // Si el índice es inválido, el logro no es válido, ya está completado o el sistema de logros no está habilitado, no hacemos nada if (INDEX == -1 || !cheevos_list_.at(INDEX).obtainable || cheevos_list_.at(INDEX).completed || !enabled_) { return; } // Marcar el logro como completado cheevos_list_.at(INDEX).completed = true; // Mostrar notificación en la pantalla Notifier::get()->show({"ACHIEVEMENT UNLOCKED!", cheevos_list_.at(INDEX).caption}, NotificationText::CENTER, CHEEVO_NOTIFICATION_DURATION /*, cheevos_list_.at(INDEX).icon*/); // Guardar el estado de los logros saveToFile(); } // Invalida un logro void Cheevos::setUnobtainable(int id) { const int index = find(id); // Si el índice es válido, se invalida el logro if (index != -1) { cheevos_list_.at(index).obtainable = false; } } // Carga el estado de los logros desde un fichero void Cheevos::loadFromFile() { std::ifstream file(file_, std::ios::binary); // El fichero no existe if (!file) { if (options.console) { std::cout << "Warning: Unable to open " << file_ << "! Creating new file..." << std::endl; } // Crea el fichero en modo escritura (binario) std::ofstream newFile(file_, std::ios::binary); if (newFile) { if (options.console) { std::cout << "New " << file_ << " created!" << std::endl; } // Guarda la información for (const auto& cheevo : cheevos_list_) { newFile.write(reinterpret_cast(&cheevo.completed), sizeof(bool)); } } else { if (options.console) { std::cerr << "Error: Unable to create " << file_ << "!" << std::endl; } } } // El fichero existe else { if (options.console) { std::cout << "Reading " << file_ << std::endl; } // Carga los datos for (auto& cheevo : cheevos_list_) { file.read(reinterpret_cast(&cheevo.completed), sizeof(bool)); } } } // Guarda el estado de los logros en un fichero void Cheevos::saveToFile() { // Abre el fichero en modo escritura (binario) SDL_RWops* file = SDL_RWFromFile(this->file_.c_str(), "w+b"); if (file != NULL) { // Guarda la información for (int i = 0; i < (int)cheevos_list_.size(); ++i) { SDL_RWwrite(file, &cheevos_list_[i].completed, sizeof(bool), 1); } // Cierra el fichero SDL_RWclose(file); } else { if (options.console) { std::cout << "Error: Unable to save file! " << SDL_GetError() << std::endl; } } } // Devuelve el número total de logros desbloqueados int Cheevos::getTotalUnlockedAchievements() { int count = 0; for (const auto& cheevo : cheevos_list_) { if (cheevo.completed) { count++; } } return count; } // Elimina el estado "no obtenible" void Cheevos::clearUnobtainableState() { for (auto& cheevo : cheevos_list_) { cheevo.obtainable = true; } }