Skip to content

Commit 0c68f38

Browse files
committed
[ADD] Revamp of save
1 parent b410a24 commit 0c68f38

1 file changed

Lines changed: 170 additions & 19 deletions

File tree

src/utils.c

Lines changed: 170 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,42 +61,189 @@ void afficherVictoire(Vaisseau *joueur) {
6161

6262
void attendreJoueur() {
6363
printf(COLOR_CYAN "\n[ Appuyez sur ENTREE pour continuer ]" COLOR_RESET);
64+
int c;
65+
while ((c = getchar()) != '\n' && c != EOF); // Nettoie le buffer
6466
getchar();
6567
}
6668

6769
// Sauvegarde et chargement
6870

71+
// Version du format de sauvegarde — à incrémenter à chaque ajout de champ
72+
#define SAVE_VERSION 4
73+
6974
void sauvegarderPartie(Vaisseau *v) {
70-
FILE *fichier = fopen("savegame.dat", "wb"); // 'wb' pour Write Binary
71-
if (fichier == NULL) {
75+
FILE *f = fopen("savegame.sav", "w");
76+
if (f == NULL) {
7277
printf("\n" COLOR_RED "[ERREUR] Impossible de créer le fichier de sauvegarde." COLOR_RESET "\n");
7378
return;
7479
}
7580

76-
// On écrit toute la structure d'un coup
77-
fwrite(v, sizeof(Vaisseau), 1, fichier);
78-
79-
fclose(fichier);
81+
// --- EN-TÊTE ---
82+
fprintf(f, "VERSION %d\n", SAVE_VERSION);
83+
84+
// --- STATS DE BASE ---
85+
fprintf(f, "nom %s\n", v->nom);
86+
fprintf(f, "coque %d\n", v->coque);
87+
fprintf(f, "coqueMax %d\n", v->coqueMax);
88+
fprintf(f, "ferraille %d\n", v->ferraille);
89+
fprintf(f, "carburant %d\n", v->carburant);
90+
fprintf(f, "missiles %d\n", v->missiles);
91+
fprintf(f, "moteurs %d\n", v->moteurs);
92+
fprintf(f, "precision %d\n", v->precision);
93+
fprintf(f, "bouclierActuel %d\n", v->bouclierActuel);
94+
fprintf(f, "debuffArme %d\n", v->debuffArme);
95+
fprintf(f, "debuffMoteur %d\n", v->debuffMoteur);
96+
97+
// --- NAVIGATION ---
98+
fprintf(f, "distanceParcourue %d\n", v->distanceParcourue);
99+
fprintf(f, "distanceObjectif %d\n", v->distanceObjectif);
100+
fprintf(f, "secteurActuel %s\n", v->secteurActuel);
101+
fprintf(f, "seedSecteur %u\n", v->seedSecteur);
102+
fprintf(f, "explorationActuelle %d\n",v->explorationActuelle);
103+
fprintf(f, "explorationMax %d\n", v->explorationMax);
104+
105+
// --- ÉTAT COMBAT ---
106+
fprintf(f, "ennemiPresent %d\n", v->ennemiPresent);
107+
fprintf(f, "ennemiCoqueActuelle %d\n", v->ennemiCoqueActuelle);
108+
fprintf(f, "chargeFTL %d\n", v->chargeFTL);
109+
fprintf(f, "maxchargeFTL %d\n", v->maxchargeFTL);
110+
111+
// --- COMPOSANTS (nom rang efficacite) ---
112+
fprintf(f, "ARME %s|%d|%d\n",
113+
v->systemeArme.nom, v->systemeArme.rang, v->systemeArme.efficacite);
114+
fprintf(f, "BOUCLIER %s|%d|%d\n",
115+
v->systemeBouclier.nom, v->systemeBouclier.rang, v->systemeBouclier.efficacite);
116+
117+
// --- ÉQUIPAGE (nom|role|pv|pvMax|estVivant|xp|niveau) ---
118+
fprintf(f, "nbMembres %d\n", v->nbMembres);
119+
for (int i = 0; i < 3; i++) {
120+
Membre *m = &v->equipage[i];
121+
fprintf(f, "MEMBRE_%d %s|%d|%d|%d|%d|%d|%d\n",
122+
i, m->nom, (int)m->role, m->pv, m->pvMax,
123+
m->estVivant, m->xp, m->niveau);
124+
}
125+
126+
fclose(f);
80127
printf("\n" COLOR_GREEN "💾 Progression synchronisée avec les serveurs de la Fédération." COLOR_RESET "\n");
81128
}
82129

83130
int chargerPartie(Vaisseau *v) {
84-
FILE *fichier = fopen("savegame.dat", "rb"); // 'rb' pour Read Binary
85-
if (fichier == NULL) {
86-
return 0; // Pas de sauvegarde trouvée
131+
FILE *f = fopen("savegame.sav", "r");
132+
if (f == NULL) return 0; // Pas de sauvegarde
133+
134+
// --- Vérification de version ---
135+
int version = 0;
136+
if (fscanf(f, "VERSION %d\n", &version) != 1) {
137+
fclose(f);
138+
printf(COLOR_RED "[SAVE] Fichier de sauvegarde illisible. Nouvelle partie.\n" COLOR_RESET);
139+
return 0;
140+
}
141+
142+
if (version < SAVE_VERSION) {
143+
fclose(f);
144+
printf(COLOR_YELLOW "[SAVE] Sauvegarde ancienne version (v%d → v%d). "
145+
"Impossible de charger.\n" COLOR_RESET, version, SAVE_VERSION);
146+
printf("Appuyez sur ENTREE pour démarrer une nouvelle partie...\n");
147+
getchar();
148+
return 0;
149+
}
150+
151+
// --- Lecture ligne par ligne ---
152+
char clef[64];
153+
char valeur[256];
154+
155+
while (fscanf(f, "%63s", clef) == 1) {
156+
157+
// Stats de base
158+
if (strcmp(clef, "nom") == 0)
159+
{ fscanf(f, " %49[^\n]", v->nom); }
160+
else if (strcmp(clef, "coque") == 0)
161+
{ fscanf(f, "%d", &v->coque); }
162+
else if (strcmp(clef, "coqueMax") == 0)
163+
{ fscanf(f, "%d", &v->coqueMax); }
164+
else if (strcmp(clef, "ferraille") == 0)
165+
{ fscanf(f, "%d", &v->ferraille); }
166+
else if (strcmp(clef, "carburant") == 0)
167+
{ fscanf(f, "%d", &v->carburant); }
168+
else if (strcmp(clef, "missiles") == 0)
169+
{ fscanf(f, "%d", &v->missiles); }
170+
else if (strcmp(clef, "moteurs") == 0)
171+
{ fscanf(f, "%d", &v->moteurs); }
172+
else if (strcmp(clef, "precision") == 0)
173+
{ fscanf(f, "%d", &v->precision); }
174+
else if (strcmp(clef, "bouclierActuel") == 0)
175+
{ fscanf(f, "%d", &v->bouclierActuel); }
176+
else if (strcmp(clef, "debuffArme") == 0)
177+
{ fscanf(f, "%d", &v->debuffArme); }
178+
else if (strcmp(clef, "debuffMoteur") == 0)
179+
{ fscanf(f, "%d", &v->debuffMoteur); }
180+
181+
// Navigation
182+
else if (strcmp(clef, "distanceParcourue") == 0)
183+
{ fscanf(f, "%d", &v->distanceParcourue); }
184+
else if (strcmp(clef, "distanceObjectif") == 0)
185+
{ fscanf(f, "%d", &v->distanceObjectif); }
186+
else if (strcmp(clef, "secteurActuel") == 0)
187+
{ fscanf(f, " %49[^\n]", v->secteurActuel); }
188+
else if (strcmp(clef, "seedSecteur") == 0)
189+
{ fscanf(f, "%u", &v->seedSecteur); }
190+
else if (strcmp(clef, "explorationActuelle") == 0)
191+
{ fscanf(f, "%d", &v->explorationActuelle); }
192+
else if (strcmp(clef, "explorationMax") == 0)
193+
{ fscanf(f, "%d", &v->explorationMax); }
194+
195+
// État combat
196+
else if (strcmp(clef, "ennemiPresent") == 0)
197+
{ fscanf(f, "%d", &v->ennemiPresent); }
198+
else if (strcmp(clef, "ennemiCoqueActuelle") == 0)
199+
{ fscanf(f, "%d", &v->ennemiCoqueActuelle); }
200+
else if (strcmp(clef, "chargeFTL") == 0)
201+
{ fscanf(f, "%d", &v->chargeFTL); }
202+
else if (strcmp(clef, "maxchargeFTL") == 0)
203+
{ fscanf(f, "%d", &v->maxchargeFTL); }
204+
205+
// Composants (format: NOM|rang|efficacite)
206+
else if (strcmp(clef, "ARME") == 0) {
207+
fscanf(f, " %255[^\n]", valeur);
208+
sscanf(valeur, "%29[^|]|%d|%d",
209+
v->systemeArme.nom, &v->systemeArme.rang, &v->systemeArme.efficacite);
210+
}
211+
else if (strcmp(clef, "BOUCLIER") == 0) {
212+
fscanf(f, " %255[^\n]", valeur);
213+
sscanf(valeur, "%29[^|]|%d|%d",
214+
v->systemeBouclier.nom, &v->systemeBouclier.rang, &v->systemeBouclier.efficacite);
215+
}
216+
217+
// Équipage
218+
else if (strcmp(clef, "nbMembres") == 0)
219+
{ fscanf(f, "%d", &v->nbMembres); }
220+
else if (strncmp(clef, "MEMBRE_", 7) == 0) {
221+
int idx = atoi(clef + 7);
222+
if (idx >= 0 && idx < 3) {
223+
fscanf(f, " %255[^\n]", valeur);
224+
int role;
225+
sscanf(valeur, "%29[^|]|%d|%d|%d|%d|%d|%d",
226+
v->equipage[idx].nom, &role,
227+
&v->equipage[idx].pv, &v->equipage[idx].pvMax,
228+
&v->equipage[idx].estVivant,
229+
&v->equipage[idx].xp, &v->equipage[idx].niveau);
230+
v->equipage[idx].role = (TypeRole)role;
231+
}
232+
}
233+
234+
// Clef inconnue (nouveau champ d'une version future) → on ignore
235+
else {
236+
fgets(valeur, sizeof(valeur), f);
237+
}
87238
}
88239

89-
fread(v, sizeof(Vaisseau), 1, fichier);
90-
fclose(fichier);
91-
return 1; // Chargement réussi
240+
fclose(f);
241+
return 1;
92242
}
93243

94244
void supprimerSauvegarde() {
95-
// On vérifie si le fichier existe avant de tenter de le supprimer
96-
if (remove("savegame.dat") == 0) {
245+
if (remove("savegame.sav") == 0) {
97246
printf(COLOR_RED "\n[SYSTEME] Données de vol effacées. Fin de transmission.\n" COLOR_RESET);
98-
} else {
99-
// Le fichier n'existait probablement pas, rien à faire
100247
}
101248
}
102249

@@ -110,17 +257,22 @@ void finaliserEvenement(Vaisseau *joueur) {
110257
// Fonction utilitaire pour lire un entier de manière robuste
111258
int lireEntierSecurise(int min, int max) {
112259
int valeur;
113-
char buffer[100];
260+
char buffer[100]; // On lit une ligne de texte pour éviter les bugs de scanf
114261

115262
while (1) {
263+
// On lit toute la ligne (jusqu'à Entrée)
116264
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
265+
// On essaie de convertir le texte en nombre
266+
// %d capture le nombre, le reste est ignoré
117267
if (sscanf(buffer, "%d", &valeur) == 1) {
268+
// Si c'est un nombre valide, on vérifie les bornes
118269
if (valeur >= min && valeur <= max) {
119-
return valeur;
270+
return valeur; // C'est gagné, on renvoie la valeur
120271
}
121272
}
122273
}
123274

275+
// Si on arrive ici, c'est que l'entrée était mauvaise
124276
printf(COLOR_RED "⚠ Entrée invalide. Veuillez taper un nombre entre %d et %d : " COLOR_RESET, min, max);
125277
printf(COLOR_YELLOW "> " COLOR_RESET);
126278
}
@@ -135,7 +287,6 @@ int lireChoix(int defaut) {
135287
int c; while ((c = getchar()) != '\n' && c != EOF);
136288
return defaut;
137289
}
138-
int c; while ((c = getchar()) != '\n' && c != EOF); // vide le \n après succès
139290
return choix;
140291
}
141292

0 commit comments

Comments
 (0)