preserve game settings across restarts

this includes last picked difficulty, character, and shot mode
This commit is contained in:
Andrei Alexeyev 2017-10-10 08:09:16 +03:00
parent 501b7d1199
commit 06a9874898
6 changed files with 65 additions and 15 deletions

View file

@ -11,16 +11,12 @@
#include "common.h"
#include "global.h"
// static to preserve between menu restarts
static CharacterID selected_charid;
static ShotModeID selected_shotid;
void set_player(MenuData *m, void *p) {
selected_charid = (CharacterID)(uintptr_t)p;
progress.game_settings.character = (CharacterID)(uintptr_t)p;
}
void set_shotmode(MenuData *m, void *p) {
selected_shotid = (ShotModeID)(uintptr_t)p;
progress.game_settings.shotmode = (ShotModeID)(uintptr_t)p;
}
void create_shottype_menu(MenuData *m) {
@ -30,8 +26,9 @@ void create_shottype_menu(MenuData *m) {
for(uintptr_t i = 0; i < NUM_SHOT_MODES_PER_CHARACTER; ++i) {
add_menu_entry(m, NULL, set_shotmode, (void*)i);
if(i == selected_shotid) {
if(i == progress.game_settings.shotmode) {
m->cursor = i;
break;
}
}
}
@ -53,8 +50,9 @@ void create_char_menu(MenuData *m) {
for(uintptr_t i = 0; i < NUM_CHARACTERS; ++i) {
add_menu_entry(m, NULL, set_player, (void*)i)->transition = TransFadeBlack;
if(i == selected_charid) {
if(i == progress.game_settings.character) {
m->cursor = i;
break;
}
}
}
@ -200,7 +198,6 @@ void char_menu_input(MenuData *menu) {
}
void free_char_menu(MenuData *menu) {
global.plr.mode = plrmode_find(selected_charid, selected_shotid);
MenuData *mod = menu->context;
destroy_menu(mod);
free(mod);

View file

@ -32,6 +32,10 @@ static void start_game_internal(MenuData *menu, StageInfo *info, bool difficulty
if(menu_loop(&m) == -1) {
return;
}
global.diff = progress.game_settings.difficulty;
} else {
// assume global.diff is set up beforehand
}
} else {
global.diff = stagediff;
@ -47,6 +51,13 @@ static void start_game_internal(MenuData *menu, StageInfo *info, bool difficulty
}
} while(restart);
global.plr.mode = plrmode_find(
progress.game_settings.character,
progress.game_settings.shotmode
);
assert(global.plr.mode != NULL);
global.replay_stage = NULL;
replay_init(&global.replay);
PlayerMode *mode = global.plr.mode;

View file

@ -13,7 +13,7 @@
#include "global.h"
void set_difficulty(MenuData *m, void *d) {
global.diff = (Difficulty) (uintptr_t) d;
progress.game_settings.difficulty = (Difficulty)(uintptr_t)d;
}
void create_difficulty_menu(MenuData *m) {
@ -30,7 +30,7 @@ void create_difficulty_menu(MenuData *m) {
for(int i = 0; i < m->ecount; ++i) {
Difficulty d = (Difficulty)(uintptr_t)m->entries[i].arg;
if(global.diff == d) {
if(d == progress.game_settings.difficulty) {
m->cursor = i;
break;
}

View file

@ -58,6 +58,7 @@ void enter_stagepractice(MenuData *menu, void *arg) {
return;
}
global.diff = progress.game_settings.difficulty;
create_stgpract_menu(&m, global.diff);
menu_loop(&m);
} while(m.selected < 0 || m.selected == m.ecount - 1);

View file

@ -45,6 +45,9 @@
- PCMD_ENDINGS
Sets the the number of times an ending was achieved for a list of endings
- PCMD_GAME_SETTINGS
Sets the last picked difficulty, character and shot mode
*/
/*
@ -52,7 +55,8 @@
Now in case you wonder why I decided to do it this way instead of stuffing everything in the config file, here are a couple of reasons:
- The config module, as of the time of writting, is messy enough and probably needs refactoring.
I don't want to mix user preferences with things that are not supposed to be directly edited on top of that.
- I don't want to mix user preferences with things that are not supposed to be directly edited.
- I don't want someone to accidentally lose progress after deleting the config file because they wanted to restore the default settings.
@ -201,8 +205,23 @@ static void progress_read(SDL_RWops *file) {
}
break;
case PCMD_GAME_SETTINGS:
if(cmdsize == sizeof(uint8_t) * 3) {
progress.game_settings.difficulty = SDL_ReadU8(vfile);
progress.game_settings.character = SDL_ReadU8(vfile);
progress.game_settings.shotmode = SDL_ReadU8(vfile);
} else {
log_warn("Command %x with bad size %u ignored", cmd, cmdsize);
while(cur < cmdsize) {
SDL_ReadU8(vfile);
cur += sizeof(uint8_t);
}
}
break;
default:
log_warn("Unknown command %i (%u bytes). Will preserve as-is and not interpret.", cmd, cmdsize);
log_warn("Unknown command %x (%u bytes). Will preserve as-is and not interpret", cmd, cmdsize);
UnknownCmd *c = create_element((void**)&progress.unknown, sizeof(UnknownCmd));
c->cmd = cmd;
@ -459,6 +478,22 @@ static void progress_write_cmd_endings(SDL_RWops *vfile, void **arg) {
}
}
//
// PCMD_GAME_SETTINGS
//
static void progress_prepare_cmd_game_settings(size_t *bufsize, void **arg) {
*bufsize += CMD_HEADER_SIZE + sizeof(uint8_t) * 3;
}
static void progress_write_cmd_game_settings(SDL_RWops *vfile, void **arg) {
SDL_WriteU8(vfile, PCMD_GAME_SETTINGS);
SDL_WriteLE16(vfile, sizeof(uint8_t) * 3);
SDL_WriteU8(vfile, progress.game_settings.difficulty);
SDL_WriteU8(vfile, progress.game_settings.character);
SDL_WriteU8(vfile, progress.game_settings.shotmode);
}
//
// Copy unhandled commands from the original file
//
@ -501,6 +536,7 @@ static void progress_write(SDL_RWops *file) {
{progress_prepare_cmd_hiscore, progress_write_cmd_hiscore, NULL},
{progress_prepare_cmd_stage_playinfo, progress_write_cmd_stage_playinfo, NULL},
{progress_prepare_cmd_endings, progress_write_cmd_endings, NULL},
{progress_prepare_cmd_game_settings, progress_write_cmd_game_settings, NULL},
// {progress_prepare_cmd_test, progress_write_cmd_test, NULL},
{progress_prepare_cmd_unknown, progress_write_cmd_unknown, NULL},
{NULL}

View file

@ -27,6 +27,7 @@ typedef enum ProgfileCommand {
PCMD_HISCORE = 0x02,
PCMD_STAGE_PLAYINFO = 0x03,
PCMD_ENDINGS = 0x04,
PCMD_GAME_SETTINGS = 0x05,
} ProgfileCommand;
typedef struct StageProgress {
@ -45,6 +46,12 @@ typedef struct GlobalProgress {
uint32_t hiscore;
uint32_t achieved_endings[NUM_ENDINGS];
struct UnknownCmd *unknown;
struct {
uint8_t difficulty;
uint8_t character;
uint8_t shotmode;
} game_settings;
} GlobalProgress;
extern GlobalProgress progress;
@ -52,5 +59,3 @@ extern GlobalProgress progress;
void progress_load(void);
void progress_save(void);
void progress_unload(void);