StageProgress API
This commit is contained in:
parent
2643c4df01
commit
b900263611
4 changed files with 67 additions and 7 deletions
|
@ -122,7 +122,10 @@ static void progress_read(SDL_RWops *file) {
|
|||
case PCMD_UNLOCK_STAGES:
|
||||
warnx("progress_read(): %i %i", cmd, cmdsize);
|
||||
while(cur < cmdsize) {
|
||||
stage_get(SDL_ReadLE16(vfile))->unlocked = true;
|
||||
StageProgress *p = stage_get_progress(SDL_ReadLE16(vfile), D_Any);
|
||||
if(p) {
|
||||
p->unlocked = true;
|
||||
}
|
||||
cur += 2;
|
||||
}
|
||||
break;
|
||||
|
@ -146,7 +149,8 @@ static void progress_write(SDL_RWops *file) {
|
|||
StageInfo *stg;
|
||||
|
||||
for(stg = stages; stg->loop; ++stg) {
|
||||
if(stg->unlocked) {
|
||||
StageProgress *p = stage_get_progress_from_info(stg, D_Any);
|
||||
if(p && p->unlocked) {
|
||||
++num_unlocked;
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +170,8 @@ static void progress_write(SDL_RWops *file) {
|
|||
SDL_WriteLE16(vfile, num_unlocked * 2);
|
||||
|
||||
for(stg = stages; stg->loop; ++stg) {
|
||||
if(stg->unlocked) {
|
||||
StageProgress *p = stage_get_progress_from_info(stg, D_Any);
|
||||
if(p && p->unlocked) {
|
||||
SDL_WriteLE16(vfile, stg->id);
|
||||
}
|
||||
}
|
||||
|
@ -189,7 +194,10 @@ static void progress_unlock_all(void) {
|
|||
StageInfo *stg;
|
||||
|
||||
for(stg = stages; stg->loop; ++stg) {
|
||||
stg->unlocked = true;
|
||||
StageProgress *p = stage_get_progress_from_info(stg, D_Any);
|
||||
if(p) {
|
||||
p->unlocked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
#ifndef PROGRESS_H
|
||||
#define PROGRESS_H
|
||||
|
||||
#include "global.h"
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#define PROGRESS_FILENAME "progress.dat"
|
||||
#define PROGRESS_MAXFILESIZE 4096
|
||||
|
@ -21,6 +22,15 @@ typedef enum ProgfileCommand {
|
|||
PCMD_UNLOCK_STAGES,
|
||||
} ProgfileCommand;
|
||||
|
||||
typedef struct StageProgress {
|
||||
// keep this struct small if you can, it leaks
|
||||
// see stage_get_progress_from_info() in stage.c for more information
|
||||
|
||||
bool unlocked;
|
||||
// short num_played;
|
||||
// short num_cleared;
|
||||
} StageProgress;
|
||||
|
||||
void progress_load(void);
|
||||
void progress_save(void);
|
||||
|
||||
|
|
37
src/stage.c
37
src/stage.c
|
@ -209,7 +209,8 @@ StageInfo stages[] = {
|
|||
|
||||
void stage_init_array(void) {
|
||||
for(int i = 0; stages[i].loop; ++i) {
|
||||
stages[i].unlocked = false;
|
||||
// we will allocate this later on demand
|
||||
stages[i].progress = NULL;
|
||||
|
||||
if(stages[i].type == STAGE_SPELL) {
|
||||
char *s, *postfix = difficulty_name(stages[i].difficulty);
|
||||
|
@ -254,6 +255,40 @@ StageInfo* stage_get_by_spellcard(AttackInfo *spell, Difficulty diff) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
StageProgress* stage_get_progress_from_info(StageInfo *stage, Difficulty diff) {
|
||||
// D_Any stages will have a separate StageProgress for every selectable difficulty.
|
||||
// Stages with a fixed difficulty setting (spellpractice, extra stage...) obviously get just one and the diff parameter is ignored.
|
||||
|
||||
// We never free anything we allocate here either. RAM's cheap right?
|
||||
// This stuff must stay around until progress_save(), which happens on shutdown.
|
||||
// So do NOT try to free any pointers this function returns, that will fuck everything up.
|
||||
|
||||
if(!stage) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool fixed_diff = (stage->difficulty != D_Any);
|
||||
|
||||
if(!fixed_diff && (diff < D_Easy || diff > D_Lunatic)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!stage->progress) {
|
||||
size_t allocsize = sizeof(StageProgress) * (fixed_diff ? 1 : NUM_SELECTABLE_DIFFICULTIES);
|
||||
stage->progress = malloc(allocsize);
|
||||
memset(stage->progress, 0, allocsize);
|
||||
#ifdef DEBUG
|
||||
printf("stage_get_progress_from_info(): allocated %lu bytes for stage %u (%s: %s)\n", allocsize, stage->id, stage->title, stage->subtitle);
|
||||
#endif
|
||||
}
|
||||
|
||||
return stage->progress + (fixed_diff ? 0 : diff - D_Easy);
|
||||
}
|
||||
|
||||
StageProgress* stage_get_progress(uint16_t id, Difficulty diff) {
|
||||
return stage_get_progress_from_info(stage_get(id), diff);
|
||||
}
|
||||
|
||||
void stage_start(void) {
|
||||
global.timer = 0;
|
||||
global.frames = 0;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <stdbool.h>
|
||||
#include "projectile.h"
|
||||
#include "boss.h"
|
||||
#include "progress.h"
|
||||
|
||||
typedef enum {
|
||||
D_Any = 0,
|
||||
|
@ -30,6 +31,8 @@ typedef enum {
|
|||
D_Extra // reserved for later
|
||||
} Difficulty;
|
||||
|
||||
#define NUM_SELECTABLE_DIFFICULTIES D_Lunatic
|
||||
|
||||
#define TIMER(ptr) int *__timep = ptr; int _i = 0, _ni = 0; _i = _ni = _i;
|
||||
#define AT(t) if(*__timep == t)
|
||||
#define FROM_TO(start,end,step) _ni = _ni; _i = (*__timep - (start))/(step); if(*__timep >= (start) && *__timep <= (end) && !((*__timep - (start)) % (step)))
|
||||
|
@ -67,12 +70,16 @@ typedef struct StageInfo {
|
|||
AttackInfo *spell;
|
||||
Difficulty difficulty;
|
||||
|
||||
bool unlocked;
|
||||
// Do NOT access this directly!
|
||||
// Use stage_get_progress or stage_get_progress_from_info, which will lazy-initialize it and pick the correct offset.
|
||||
StageProgress *progress;
|
||||
} StageInfo;
|
||||
|
||||
extern StageInfo stages[];
|
||||
StageInfo* stage_get(uint16_t);
|
||||
StageInfo* stage_get_by_spellcard(AttackInfo *spell, Difficulty diff);
|
||||
StageProgress* stage_get_progress(uint16_t id, Difficulty diff);
|
||||
StageProgress* stage_get_progress_from_info(StageInfo *stage, Difficulty diff);
|
||||
void stage_init_array(void);
|
||||
|
||||
void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event, ShaderRule *shaderrules, int endtime);
|
||||
|
|
Loading…
Reference in a new issue