175 lines
5.4 KiB
C++
175 lines
5.4 KiB
C++
#include "game/gameplay/cheevos.hpp"
|
|
|
|
#include <SDL3/SDL.h>
|
|
#include <stddef.h> // Para NULL
|
|
|
|
#include <fstream> // Para basic_ostream, operator<<, basic_ofstream
|
|
#include <iostream> // Para cout, cerr
|
|
|
|
#include "game/gameplay/options.hpp" // Para Options, options
|
|
#include "game/ui/notifier.hpp" // Para Notifier
|
|
|
|
// [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<const char*>(&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<char*>(&cheevo.completed), sizeof(bool));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Guarda el estado de los logros en un fichero
|
|
void Cheevos::saveToFile() {
|
|
// Abre el fichero en modo escritura (binario)
|
|
SDL_IOStream* file = SDL_IOFromFile(this->file_.c_str(), "w+b");
|
|
if (file != nullptr) {
|
|
// Guarda la información
|
|
for (int i = 0; i < (int)cheevos_list_.size(); ++i) {
|
|
SDL_WriteIO(file, &cheevos_list_[i].completed, sizeof(bool));
|
|
}
|
|
|
|
// Cierra el fichero
|
|
SDL_CloseIO(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;
|
|
}
|
|
} |