preserve game settings across restarts
this includes last picked difficulty, character, and shot mode
This commit is contained in:
parent
501b7d1199
commit
06a9874898
6 changed files with 65 additions and 15 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue