Some stage-related refactoring

This commit is contained in:
Andrei "Akari" Alexeyev 2017-02-26 14:17:48 +02:00
parent da4f156c71
commit f2d385d147
32 changed files with 424 additions and 279 deletions

View file

@ -214,7 +214,7 @@ void credits_draw(void) {
credits_draw_entry(&(credits.entries[i]));
glPopMatrix();
draw_transition();
draw_and_update_transition();
}
void credits_finish(void *arg) {

View file

@ -118,7 +118,7 @@ void ending_draw(Ending *e) {
draw_text(AL_Center, SCREEN_W/2, SCREEN_H/5*4, e->entries[e->pos].msg, _fonts.standard);
glColor4f(1,1,1,1);
draw_transition();
draw_and_update_transition();
}
void ending_loop(void) {

View file

@ -80,8 +80,8 @@ enum {
GAMEOVER_DEFEAT = 1,
GAMEOVER_WIN,
GAMEOVER_ABORT,
GAMEOVER_REWATCH,
GAMEOVER_RESTART
GAMEOVER_RESTART,
GAMEOVER_TRANSITIONING = -1,
};
typedef struct {

View file

@ -84,7 +84,7 @@ int main(int argc, char **argv) {
if(argc >= 2 && argv[1] && !strcmp(argv[1], "dumpstages")) {
stage_init_array();
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
printf("%i %s: %s\n", stg->id, stg->title, stg->subtitle);
}
@ -185,8 +185,7 @@ int main(int argc, char **argv) {
do {
global.game_over = 0;
init_player(&global.plr);
global.stage = stg;
stg->loop();
stage_loop(stg);
} while(global.game_over == GAMEOVER_RESTART);
return 0;

View file

@ -48,12 +48,10 @@ troll:
troll2:
if(info) {
global.stage = info;
info->loop();
stage_loop(info);
} else {
for(int i = 0; stages[i].type == STAGE_STORY; ++i) {
global.stage = stages + i;
stages[i].loop();
for(StageInfo *s = stages; s->type == STAGE_STORY; ++s) {
stage_loop(s);
}
}

View file

@ -49,7 +49,7 @@ void main_menu_update_spellpractice(void) {
MenuEntry *e = spell_practice_entry;
e->action = NULL;
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
if(stg->type == STAGE_SPELL) {
StageProgress *p = stage_get_progress_from_info(stg, D_Any, false);
if(p && p->unlocked) {

View file

@ -158,7 +158,7 @@ int menu_loop(MenuData *menu) {
assert(menu->draw);
menu->draw(menu);
draw_transition();
draw_and_update_transition();
SDL_GL_SwapWindow(video.window);
frame_rate(&menu->lasttime);

View file

@ -26,7 +26,7 @@ void create_spell_menu(MenuData *m) {
m->flags = MF_Abortable;
m->transition = TransMenuDark;
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
if(stg->type != STAGE_SPELL) {
continue;
}

View file

@ -29,7 +29,7 @@ void create_stage_menu(MenuData *m) {
m->flags = MF_Abortable;
m->transition = TransMenuDark;
for(int i = 0; stages[i].loop; ++i) {
for(int i = 0; stages[i].procs; ++i) {
if(stages[i].difficulty < lastdiff || (stages[i].difficulty && !lastdiff)) {
add_menu_separator(m);
}

View file

@ -180,7 +180,7 @@ typedef struct cmd_writer_t {
static void progress_prepare_cmd_unlock_stages(size_t *bufsize, void **arg) {
int num_unlocked = 0;
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
StageProgress *p = stage_get_progress_from_info(stg, D_Any, false);
if(p && p->unlocked) {
++num_unlocked;
@ -205,7 +205,7 @@ static void progress_write_cmd_unlock_stages(SDL_RWops *vfile, void **arg) {
SDL_WriteU8(vfile, PCMD_UNLOCK_STAGES);
SDL_WriteLE16(vfile, num_unlocked * 2);
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
StageProgress *p = stage_get_progress_from_info(stg, D_Any, false);
if(p && p->unlocked) {
SDL_WriteLE16(vfile, stg->id);
@ -220,7 +220,7 @@ static void progress_write_cmd_unlock_stages(SDL_RWops *vfile, void **arg) {
static void progress_prepare_cmd_unlock_stages_with_difficulties(size_t *bufsize, void **arg) {
int num_unlocked = 0;
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
if(stg->difficulty)
continue;
@ -256,7 +256,7 @@ static void progress_write_cmd_unlock_stages_with_difficulties(SDL_RWops *vfile,
SDL_WriteU8(vfile, PCMD_UNLOCK_STAGES_WITH_DIFFICULTY);
SDL_WriteLE16(vfile, num_unlocked * 3);
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
if(stg->difficulty)
continue;
@ -325,7 +325,7 @@ static void progress_write(SDL_RWops *file) {
static void progress_unlock_all(void) {
StageInfo *stg;
for(stg = stages; stg->loop; ++stg) {
for(stg = stages; stg->procs; ++stg) {
for(Difficulty diff = D_Any; diff <= D_Lunatic; ++diff) {
StageProgress *p = stage_get_progress_from_info(stg, diff, true);
if(p) {

View file

@ -659,8 +659,7 @@ void replay_play(Replay *rpy, int firststage) {
continue;
}
global.stage = gstg;
gstg->loop();
stage_loop(gstg);
if(global.game_over == GAMEOVER_ABORT) {
break;

View file

@ -5,7 +5,7 @@
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#include <complex.h>
#include <assert.h>
#include "stage.h"
#include "tscomplex.h"
@ -33,12 +33,12 @@ StageInfo stages[] = {
//
// id loop type title subtitle titleclr bosstitleclr spell difficulty
{1, stage1_loop, STAGE_STORY, "Stage 1", "Misty Lake", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
{2, stage2_loop, STAGE_STORY, "Stage 2", "Walk Along the Border", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
{3, stage3_loop, STAGE_STORY, "Stage 3", "Through the Tunnel of Light", {0, 0, 0}, {0, 0, 0}, NULL, D_Any},
{4, stage4_loop, STAGE_STORY, "Stage 4", "Forgotten Mansion", {0, 0, 0}, {1, 1, 1}, NULL, D_Any},
{5, stage5_loop, STAGE_STORY, "Stage 5", "Climbing the Tower of Babel", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
{6, stage6_loop, STAGE_STORY, "Stage 6", "Roof of the World", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
{1, &stage1_procs, STAGE_STORY, "Stage 1", "Misty Lake", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
{2, &stage2_procs, STAGE_STORY, "Stage 2", "Walk Along the Border", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
{3, &stage3_procs, STAGE_STORY, "Stage 3", "Through the Tunnel of Light", {0, 0, 0}, {0, 0, 0}, NULL, D_Any},
{4, &stage4_procs, STAGE_STORY, "Stage 4", "Forgotten Mansion", {0, 0, 0}, {1, 1, 1}, NULL, D_Any},
{5, &stage5_procs, STAGE_STORY, "Stage 5", "Climbing the Tower of Babel", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
{6, &stage6_procs, STAGE_STORY, "Stage 6", "Roof of the World", {1, 1, 1}, {1, 1, 1}, NULL, D_Any},
//
// Spell practice stages
@ -48,160 +48,160 @@ StageInfo stages[] = {
#define S STAGE_SPELL_BIT
// Freeze Sign ~ Perfect Freeze
{S| 0, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Easy},
{S| 1, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Normal},
{S| 2, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Hard},
{S| 3, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Lunatic},
{S| 0, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Easy},
{S| 1, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Normal},
{S| 2, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Hard},
{S| 3, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+0, D_Lunatic},
// Freeze Sign ~ Crystal Rain
{S| 4, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Easy},
{S| 5, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Normal},
{S| 6, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Hard},
{S| 7, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Lunatic},
{S| 4, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Easy},
{S| 5, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Normal},
{S| 6, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Hard},
{S| 7, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+1, D_Lunatic},
// Doom Sign ~ Icicle Fall
{S| 8, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Easy},
{S| 9, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Normal},
{S| 10, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Hard},
{S| 11, stage1_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Lunatic},
{S| 8, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Easy},
{S| 9, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Normal},
{S| 10, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Hard},
{S| 11, &stage1_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage1_spells+2, D_Lunatic},
// Shard ~ Amulet of Harm
{S| 12, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Easy},
{S| 13, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Normal},
{S| 14, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Hard},
{S| 15, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Lunatic},
{S| 12, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Easy},
{S| 13, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Normal},
{S| 14, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Hard},
{S| 15, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+0, D_Lunatic},
// Lottery Sign ~ Bad Pick
{S| 16, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Easy},
{S| 17, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Normal},
{S| 18, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Hard},
{S| 19, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Lunatic},
{S| 16, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Easy},
{S| 17, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Normal},
{S| 18, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Hard},
{S| 19, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+1, D_Lunatic},
// Lottery Sign ~ Wheel of Fortune
{S| 20, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Easy},
{S| 21, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Normal},
{S| 22, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Hard},
{S| 23, stage2_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Lunatic},
{S| 20, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Easy},
{S| 21, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Normal},
{S| 22, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Hard},
{S| 23, &stage2_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage2_spells+2, D_Lunatic},
// Venom Sign ~ Deadly Dance
{S| 24, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Easy},
{S| 25, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Normal},
{S| 26, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Hard},
{S| 27, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Lunatic},
{S| 24, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Easy},
{S| 25, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Normal},
{S| 26, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Hard},
{S| 27, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+0, D_Lunatic},
// Venom Sign ~ Acid Rain
{S| 28, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+1, D_Hard},
{S| 29, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+1, D_Lunatic},
{S| 28, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+1, D_Hard},
{S| 29, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+1, D_Lunatic},
// Firefly Sign ~ Moonlight Rocket
{S| 30, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Easy},
{S| 31, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Normal},
{S| 32, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Hard},
{S| 33, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Lunatic},
{S| 30, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Easy},
{S| 31, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Normal},
{S| 32, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Hard},
{S| 33, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+2, D_Lunatic},
// Light Source ~ Wriggle Night Ignite
{S| 34, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Easy},
{S| 35, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Normal},
{S| 36, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Hard},
{S| 37, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Lunatic},
{S| 34, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Easy},
{S| 35, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Normal},
{S| 36, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Hard},
{S| 37, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+3, D_Lunatic},
// Bug Sign ~ Phosphaenus Hemipterus
{S| 38, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Easy},
{S| 39, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Normal},
{S| 40, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Hard},
{S| 41, stage3_spellpractice_loop, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Lunatic},
{S| 38, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Easy},
{S| 39, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Normal},
{S| 40, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Hard},
{S| 41, &stage3_spell_procs, STAGE_SPELL, NULL, NULL, {0, 0, 0}, {0, 0, 0}, stage3_spells+4, D_Lunatic},
// Bloodless ~ Gate of Walachia
{S| 42, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Easy},
{S| 43, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Normal},
{S| 44, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Hard},
{S| 45, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Lunatic},
{S| 42, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Easy},
{S| 43, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Normal},
{S| 44, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Hard},
{S| 45, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+0, D_Lunatic},
// Bloodless ~ Dry Fountain
{S| 46, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+1, D_Easy},
{S| 47, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+1, D_Normal},
{S| 46, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+1, D_Easy},
{S| 47, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+1, D_Normal},
// Bloodless ~ Red Spike
{S| 48, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+2, D_Hard},
{S| 49, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+2, D_Lunatic},
{S| 48, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+2, D_Hard},
{S| 49, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+2, D_Lunatic},
// Limit ~ Animate Wall
{S| 50, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+3, D_Easy},
{S| 51, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+3, D_Normal},
{S| 50, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+3, D_Easy},
{S| 51, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+3, D_Normal},
// Summoning ~ Demon Wall
{S| 52, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+4, D_Hard},
{S| 53, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+4, D_Lunatic},
{S| 52, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+4, D_Hard},
{S| 53, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+4, D_Lunatic},
// Power Sign ~ Blow the Walls
{S| 54, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Easy},
{S| 55, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Normal},
{S| 56, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Hard},
{S| 57, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Lunatic},
{S| 54, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Easy},
{S| 55, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Normal},
{S| 56, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Hard},
{S| 57, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+5, D_Lunatic},
// Fear Sign ~ Bloody Danmaku
{S| 58, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+6, D_Hard},
{S| 59, stage4_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+6, D_Lunatic},
{S| 58, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+6, D_Hard},
{S| 59, &stage4_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage4_spells+6, D_Lunatic},
// High Voltage ~ Atmospheric Discharge
{S| 60, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Easy},
{S| 61, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Normal},
{S| 62, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Hard},
{S| 63, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Lunatic},
{S| 60, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Easy},
{S| 61, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Normal},
{S| 62, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Hard},
{S| 63, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+0, D_Lunatic},
// Charge Sign ~ Artificial Lightning
{S| 64, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Easy},
{S| 65, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Normal},
{S| 66, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Hard},
{S| 67, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Lunatic},
{S| 64, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Easy},
{S| 65, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Normal},
{S| 66, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Hard},
{S| 67, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+1, D_Lunatic},
// Spark Sign ~ Natural Cathode
{S| 68, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Easy},
{S| 69, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Normal},
{S| 70, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Hard},
{S| 71, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Lunatic},
{S| 68, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Easy},
{S| 69, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Normal},
{S| 70, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Hard},
{S| 71, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+2, D_Lunatic},
// Current Sign ~ Induction
{S| 72, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Easy},
{S| 73, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Normal},
{S| 74, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Hard},
{S| 75, stage5_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Lunatic},
{S| 72, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Easy},
{S| 73, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Normal},
{S| 74, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Hard},
{S| 75, &stage5_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage5_spells+3, D_Lunatic},
// Newton Sign ~ 2.5 Laws of Movement
{S| 76, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Easy},
{S| 77, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Normal},
{S| 78, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Hard},
{S| 79, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Lunatic},
{S| 76, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Easy},
{S| 77, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Normal},
{S| 78, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Hard},
{S| 79, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+0, D_Lunatic},
// Maxwell Sign ~ Wave Theory
{S| 80, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Easy},
{S| 81, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Normal},
{S| 82, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Hard},
{S| 83, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Lunatic},
{S| 80, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Easy},
{S| 81, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Normal},
{S| 82, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Hard},
{S| 83, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+1, D_Lunatic},
// Eigenstate ~ Many-World Interpretation
{S| 84, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Easy},
{S| 85, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Normal},
{S| 86, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Hard},
{S| 87, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Lunatic},
{S| 84, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Easy},
{S| 85, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Normal},
{S| 86, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Hard},
{S| 87, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+2, D_Lunatic},
// Ricci Sign ~ Space Time Curvature
{S| 88, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Easy},
{S| 89, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Normal},
{S| 90, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Hard},
{S| 91, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Lunatic},
{S| 88, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Easy},
{S| 89, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Normal},
{S| 90, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Hard},
{S| 91, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+3, D_Lunatic},
// LHC ~ Higgs Boson Uncovered
{S| 92, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Easy},
{S| 93, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Normal},
{S| 94, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Hard},
{S| 95, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Lunatic},
{S| 92, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Easy},
{S| 93, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Normal},
{S| 94, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Hard},
{S| 95, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+4, D_Lunatic},
// Tower of Truth ~ Theory of Everything
{S| 96, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Easy},
{S| 97, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Normal},
{S| 98, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Hard},
{S| 99, stage6_spellpractice_loop, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Lunatic},
{S| 96, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Easy},
{S| 97, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Normal},
{S| 98, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Hard},
{S| 99, &stage6_spell_procs, STAGE_SPELL, NULL, NULL, {1, 1, 1}, {1, 1, 1}, stage6_spells+5, D_Lunatic},
#undef S
{0}
@ -210,7 +210,7 @@ StageInfo stages[] = {
void stage_init_array(void) {
int spellnum = 0;
for(int i = 0; stages[i].loop; ++i) {
for(int i = 0; stages[i].procs; ++i) {
// we will allocate this later on demand
stages[i].progress = NULL;
@ -231,7 +231,7 @@ void stage_init_array(void) {
errx(-1, "Spell stage has an ID without the spell bit set: %u", stages[i].id);
}
for(int j = 0; stages[j].loop; ++j) {
for(int j = 0; stages[j].procs; ++j) {
if(i != j && stages[i].id == stages[j].id) {
errx(-1, "Duplicate ID in stages array: %u", stages[i].id);
}
@ -241,7 +241,7 @@ void stage_init_array(void) {
}
void stage_free_array(void) {
for(StageInfo *stg = stages; stg->loop; ++stg) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
if(stg->type == STAGE_SPELL) {
free(stg->subtitle);
}
@ -252,7 +252,7 @@ void stage_free_array(void) {
// NOTE: This returns the stage BY ID, not by the array index!
StageInfo* stage_get(uint16_t n) {
for(StageInfo *stg = stages; stg->loop; ++stg)
for(StageInfo *stg = stages; stg->procs; ++stg)
if(stg->id == n)
return stg;
return NULL;
@ -262,7 +262,7 @@ StageInfo* stage_get_by_spellcard(AttackInfo *spell, Difficulty diff) {
if(!spell)
return NULL;
for(StageInfo *stg = stages; stg->loop; ++stg)
for(StageInfo *stg = stages; stg->procs; ++stg)
if(stg->spell == spell && stg->difficulty == diff)
return stg;
@ -306,7 +306,7 @@ StageProgress* stage_get_progress(uint16_t id, Difficulty diff, bool allocate) {
return stage_get_progress_from_info(stage_get(id), diff, allocate);
}
void stage_start(void) {
static void stage_start(StageInfo *stage) {
global.timer = 0;
global.frames = 0;
global.stageuiframes = 0;
@ -318,6 +318,11 @@ void stage_start(void) {
global.fps.fpstime = SDL_GetTicks();
prepare_player_for_next_stage(&global.plr);
if(stage->type == STAGE_SPELL) {
global.plr.lifes = 0;
global.plr.bombs = 0;
}
}
void stage_pause(void) {
@ -330,11 +335,20 @@ void stage_pause(void) {
void stage_gameover(void) {
MenuData menu;
save_bgm();
start_bgm("bgm_gameover");
create_gameover_menu(&menu);
bool interrupt_bgm = (global.stage->type != STAGE_SPELL);
if(interrupt_bgm) {
save_bgm();
start_bgm("bgm_gameover");
}
menu_loop(&menu);
restore_bgm();
if(interrupt_bgm) {
restore_bgm();
}
}
void stage_input_event(EventType type, int key, void *arg) {
@ -342,7 +356,7 @@ void stage_input_event(EventType type, int key, void *arg) {
case E_PlrKeyDown:
if(key == KEY_HAHAIWIN) {
#ifdef DEBUG
global.game_over = GAMEOVER_WIN;
stage_finish(GAMEOVER_WIN);
#endif
break;
}
@ -506,12 +520,15 @@ void draw_hud(void) {
draw_texture(VIEWPORT_X+creal(global.boss->pos), 590, "boss_indicator");
}
void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int time) {
static void apply_bg_shaders(ShaderRule *shaderrules);
static void draw_stage_title(StageInfo *info);
static void stage_draw(StageInfo *stage) {
if(!config_get_int(CONFIG_NO_SHADER)) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbg[0].fbo);
glViewport(0,0,SCREEN_W,SCREEN_H);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(-(VIEWPORT_X+VIEWPORT_W/2.0), -(VIEWPORT_Y+VIEWPORT_H/2.0),0);
@ -528,7 +545,7 @@ void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int
global.nostagebg = true;
if(!global.nostagebg)
bgdraw();
stage->procs->draw();
glPopMatrix();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -539,7 +556,7 @@ void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int
glTranslatef(VIEWPORT_X,VIEWPORT_Y,0);
if(!config_get_int(CONFIG_NO_SHADER))
apply_bg_shaders(shaderrules);
apply_bg_shaders(stage->procs->shader_rules);
if(global.boss) {
glPushMatrix();
@ -577,7 +594,7 @@ void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int
if(global.dialog)
draw_dialog(global.dialog);
draw_stage_title(info);
draw_stage_title(stage);
if(!config_get_int(CONFIG_NO_SHADER)) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -594,17 +611,13 @@ void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int
glPopMatrix();
draw_hud();
draw_transition();
}
int apply_shaderrules(ShaderRule *shaderrules, int fbonum) {
int i;
static int apply_shaderrules(ShaderRule *shaderrules, int fbonum) {
if(!global.nostagebg) {
for(i = 0; shaderrules != NULL && shaderrules[i] != NULL; i++) {
for(ShaderRule *rule = shaderrules; *rule; ++rule) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbg[!fbonum].fbo);
shaderrules[i](fbonum);
(*rule)(fbonum);
fbonum = !fbonum;
}
}
@ -612,7 +625,7 @@ int apply_shaderrules(ShaderRule *shaderrules, int fbonum) {
return fbonum;
}
void apply_bg_shaders(ShaderRule *shaderrules) {
static void apply_bg_shaders(ShaderRule *shaderrules) {
int fbonum = 0;
if(global.boss && global.boss->current && global.boss->current->draw_rule) {
@ -682,7 +695,7 @@ void apply_bg_shaders(ShaderRule *shaderrules) {
}
}
void stage_logic(int time) {
static void stage_logic(void) {
player_logic(&global.plr);
process_enemies(&global.enemies);
@ -706,18 +719,11 @@ void stage_logic(int time) {
if(!global.dialog && !global.boss)
global.timer++;
if(global.timer == time - FADE_TIME ||
(
global.replaymode == REPLAY_PLAY &&
global.frames == global.replay_stage->events[global.replay_stage->numevents-1].frame - FADE_TIME
)
) {
set_transition(TransFadeBlack, FADE_TIME, FADE_TIME*2);
if(global.frames == global.replay_stage->events[global.replay_stage->numevents-1].frame - FADE_TIME &&
global.game_over != GAMEOVER_TRANSITIONING) {
stage_finish(GAMEOVER_DEFEAT);
}
if(time && global.timer >= time)
global.game_over = GAMEOVER_WIN;
// BGM handling
if(global.dialog && global.dialog->messages[global.dialog->pos].side == BGM) {
start_bgm(global.dialog->messages[global.dialog->pos].msg);
@ -725,7 +731,7 @@ void stage_logic(int time) {
}
}
void stage_end(void) {
static void stage_free(void) {
delete_enemies(&global.enemies);
delete_items();
delete_lasers();
@ -744,7 +750,25 @@ void stage_end(void) {
}
}
void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event, ShaderRule *shaderrules, int endtime, char *bgmname) {
static void stage_finalize(void *arg) {
global.game_over = (intptr_t)arg;
}
void stage_finish(int gameover) {
assert(global.game_over != GAMEOVER_TRANSITIONING);
global.game_over = GAMEOVER_TRANSITIONING;
set_transition_callback(TransFadeBlack, FADE_TIME, FADE_TIME*2, stage_finalize, (void*)(intptr_t)gameover);
}
void stage_loop(StageInfo *stage) {
assert(stage);
assert(stage->procs);
assert(stage->procs->begin);
assert(stage->procs->end);
assert(stage->procs->draw);
assert(stage->procs->event);
assert(stage->procs->shader_rules);
if(global.game_over == GAMEOVER_WIN) {
global.game_over = 0;
} else if(global.game_over) {
@ -752,16 +776,16 @@ void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event,
}
// I really want to separate all of the game state from the global struct sometime
StageInfo *info = global.stage;
global.stage = stage;
uint32_t seed = (uint32_t)time(0);
tsrand_switch(&global.rand_game);
tsrand_seed_p(&global.rand_game, seed);
stage_start();
stage_start(stage);
if(global.replaymode == REPLAY_RECORD) {
if(config_get_int(CONFIG_SAVE_RPY)) {
global.replay_stage = replay_create_stage(&global.replay, info, seed, global.diff, global.plr.points, &global.plr);
global.replay_stage = replay_create_stage(&global.replay, stage, seed, global.diff, global.plr.points, &global.plr);
// make sure our player state is consistent with what goes into the replay
init_player(&global.plr);
@ -771,11 +795,6 @@ void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event,
}
printf("Random seed: %u\n", seed);
if(info->type == STAGE_SPELL) {
global.plr.lifes = 0;
global.plr.bombs = 0;
}
} else {
if(!global.replay_stage) {
errx(-1, "Attemped to replay a NULL stage");
@ -806,27 +825,35 @@ void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event,
player_set_power(&global.plr, power);
start();
start_bgm(bgmname);
stage->procs->begin();
if(info->type == STAGE_SPELL) {
endtime = 0;
}
int transition_delay = 0;
while(global.game_over <= 0) {
if(!global.boss && !global.dialog)
event();
if(global.game_over != GAMEOVER_TRANSITIONING) {
if(!global.boss && !global.dialog) {
stage->procs->event();
}
if(!endtime && info->type == STAGE_SPELL && !global.boss) {
endtime = global.timer + 60;
if(stage->type == STAGE_SPELL && !global.boss) {
stage_finish(GAMEOVER_WIN);
transition_delay = 60;
}
}
((global.replaymode == REPLAY_PLAY) ? replay_input : stage_input)();
replay_stage_check_desync(global.replay_stage, global.frames, (tsrand() ^ global.plr.points) & 0xFFFF, global.replaymode);
stage_logic(endtime);
stage_logic();
if(transition_delay) {
--transition_delay;
}
if(global.frameskip && global.frames % global.frameskip) {
if(!transition_delay) {
update_transition();
}
continue;
}
@ -834,11 +861,14 @@ void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event,
tsrand_lock(&global.rand_game);
tsrand_switch(&global.rand_visual);
stage_draw(info, draw, shaderrules, endtime);
stage_draw(stage);
tsrand_unlock(&global.rand_game);
tsrand_switch(&global.rand_game);
// print_state_checksum();
draw_transition();
if(!transition_delay) {
update_transition();
}
SDL_GL_SwapWindow(video.window);
@ -853,13 +883,12 @@ void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event,
replay_stage_event(global.replay_stage, global.frames, EV_OVER, 0);
}
end();
stage_end();
stage->procs->end();
stage_free();
tsrand_switch(&global.rand_visual);
global.stage = NULL;
}
void draw_title(int t, StageInfo *info, Alignment al, int x, int y, const char *text, TTF_Font *font, Color *color) {
static void draw_title(int t, StageInfo *info, Alignment al, int x, int y, const char *text, TTF_Font *font, Color *color) {
int i;
float f = 0;
if(t < 30 || t > 220)
@ -890,7 +919,7 @@ void draw_title(int t, StageInfo *info, Alignment al, int x, int y, const char *
glUseProgram(0);
}
void draw_stage_title(StageInfo *info) {
static void draw_stage_title(StageInfo *info) {
int t = global.stageuiframes;
draw_title(t, info, AL_Center, VIEWPORT_W/2, VIEWPORT_H/2-40, info->title, _fonts.mainmenu, &info->titleclr);

View file

@ -43,7 +43,7 @@ typedef enum {
#define GO_AT(obj, start, end, vel) if(*__timep >= (start) && *__timep <= (end)) (obj)->pos += (vel);
#define GO_TO(obj, p, f) (obj)->pos += (f)*((p) - (obj)->pos);
typedef void (*StageRule)(void);
typedef void (*StageProc)(void);
typedef void (*ShaderRule)(int);
// highest bit of uint16_t, WAY higher than the amount of spells in this game can ever possibly be
@ -55,13 +55,21 @@ typedef enum StageType {
STAGE_SPELL,
} StageType;
typedef struct StageProcs {
StageProc begin;
StageProc end;
StageProc draw;
StageProc event;
ShaderRule *shader_rules;
} StageProcs;
typedef struct StageInfo {
//
// don't reorder these!
//
uint16_t id; // must match type of ReplayStage.stage in replay.h
StageRule loop;
StageProcs *procs;
StageType type;
char *title;
char *subtitle;
@ -86,11 +94,9 @@ StageProgress* stage_get_progress_from_info(StageInfo *stage, Difficulty diff, b
void stage_init_array(void);
void stage_free_array(void);
void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event, ShaderRule *shaderrules, int endtime, char *bgmname);
void stage_loop(StageInfo *stage);
void stage_finish(int gameover);
void apply_bg_shaders(ShaderRule *shaderrules);
void draw_stage_title(StageInfo *info);
void draw_hud(void);
void stage_pause(void);

View file

@ -573,6 +573,10 @@ int stage1_tritoss(Enemy *e, int t) {
void stage1_events(void) {
TIMER(&global.timer);
AT(0) {
start_bgm("bgm_stage1");
}
/*
// graze testing
AT(0) {
@ -668,6 +672,9 @@ void stage1_events(void) {
AT(5000)
global.boss = create_cirno();
AT(5200 - FADE_TIME) {
stage_finish(GAMEOVER_WIN);
}
}
void stage1_start(void) {
@ -684,11 +691,6 @@ void stage1_end(void) {
free_stage3d(&bgcontext);
}
void stage1_loop(void) {
ShaderRule list[] = { stage1_fog, NULL };
stage_loop(stage1_start, stage1_end, stage1_draw, stage1_events, list, 5200, "bgm_stage1");
}
void stage1_spellpractice_events(void) {
TIMER(&global.timer);
@ -697,10 +699,25 @@ void stage1_spellpractice_events(void) {
boss_add_attack_from_info(cirno, global.stage->spell, true);
start_attack(cirno, cirno->attacks);
global.boss = cirno;
start_bgm("bgm_stage1boss");
}
}
void stage1_spellpractice_loop(void) {
ShaderRule list[] = { stage1_fog, NULL };
stage_loop(stage1_start, stage1_end, stage1_draw, stage1_spellpractice_events, list, 0, "bgm_stage1boss");
}
ShaderRule stage1_shaders[] = { stage1_fog, NULL };
StageProcs stage1_procs = {
.begin = stage1_start,
.end = stage1_end,
.draw = stage1_draw,
.event = stage1_events,
.shader_rules = stage1_shaders,
};
StageProcs stage1_spell_procs = {
.begin = stage1_start,
.end = stage1_end,
.draw = stage1_draw,
.event = stage1_spellpractice_events,
.shader_rules = stage1_shaders,
};

View file

@ -8,11 +8,10 @@
#ifndef STAGE1_H
#define STAGE1_H
#include "boss.h"
void stage1_loop(void);
void stage1_spellpractice_loop(void);
#include "stage.h"
extern StageProcs stage1_procs;
extern StageProcs stage1_spell_procs;
extern AttackInfo stage1_spells[];
#endif

View file

@ -158,11 +158,6 @@ void stage2_draw(void) {
}
void stage2_loop(void) {
ShaderRule shaderrules[] = { stage2_fog, stage2_bloom, NULL };
stage_loop(stage2_start, stage2_end, stage2_draw, stage2_events, shaderrules, 5240, "bgm_stage2");
}
void stage2_spellpractice_events(void) {
TIMER(&global.timer);
@ -173,10 +168,25 @@ void stage2_spellpractice_events(void) {
boss_add_attack_from_info(hina, global.stage->spell, true);
start_attack(hina, hina->attacks);
global.boss = hina;
start_bgm("bgm_stage2boss");
}
}
void stage2_spellpractice_loop(void) {
ShaderRule shaderrules[] = { stage2_fog, stage2_bloom, NULL };
stage_loop(stage2_start, stage2_end, stage2_draw, stage2_spellpractice_events, shaderrules, 0, "bgm_stage2boss");
}
ShaderRule stage2_shaders[] = { stage2_fog, stage2_bloom, NULL };
StageProcs stage2_procs = {
.begin = stage2_start,
.end = stage2_end,
.draw = stage2_draw,
.event = stage2_events,
.shader_rules = stage2_shaders,
};
StageProcs stage2_spell_procs = {
.begin = stage2_start,
.end = stage2_end,
.draw = stage2_draw,
.event = stage2_spellpractice_events,
.shader_rules = stage2_shaders,
};

View file

@ -8,11 +8,10 @@
#ifndef STAGE2_H
#define STAGE2_H
#include "boss.h"
void stage2_loop(void);
void stage2_spellpractice_loop(void);
#include "stage.h"
extern StageProcs stage2_procs;
extern StageProcs stage2_spell_procs;
extern AttackInfo stage2_spells[];
#endif

View file

@ -480,4 +480,8 @@ void stage2_events(void) {
AT(5180) {
global.dialog = stage2_post_dialog();
}
AT(5240 - FADE_TIME) {
stage_finish(GAMEOVER_WIN);
}
}

View file

@ -278,11 +278,6 @@ void stage3_draw(void) {
draw_stage3d(&bgcontext, 7000);
}
void stage3_loop(void) {
ShaderRule shaderrules[] = { stage3_fog, stage3_tunnel, NULL };
stage_loop(stage3_start, stage3_end, stage3_draw, stage3_events, shaderrules, 5700, "bgm_stage3");
}
void stage3_mid_spellbg(Boss*, int t);
void stage3_spellpractice_events(void) {
@ -299,10 +294,25 @@ void stage3_spellpractice_events(void) {
boss_add_attack_from_info(global.boss, global.stage->spell, true);
start_attack(global.boss, global.boss->attacks);
start_bgm("bgm_stage3boss");
}
}
void stage3_spellpractice_loop(void) {
ShaderRule shaderrules[] = { stage3_fog, stage3_tunnel, NULL };
stage_loop(stage3_start, stage3_end, stage3_draw, stage3_spellpractice_events,