pleasing the stages array haters

This commit is contained in:
Andrei "Akari" Alexeyev 2017-02-27 16:27:48 +02:00
parent cc2b33e11d
commit f61e77d351
28 changed files with 327 additions and 304 deletions

View file

@ -46,6 +46,8 @@ set(SRCs
matrix.c
video.c
transition.c
color.c
difficulty.c
menu/menu.c
menu/mainmenu.c
menu/options.c
@ -54,7 +56,7 @@ set(SRCs
menu/ingamemenu.c
menu/gameovermenu.c
menu/savereplay.c
menu/difficulty.c
menu/difficultyselect.c
menu/charselect.c
menu/spellpractice.c
menu/common.c

View file

@ -9,6 +9,7 @@
#define BOSS_H
#include "tscomplex.h"
#include "difficulty.h"
#include <resource/animation.h>
struct Boss;
@ -23,6 +24,24 @@ typedef enum AttackType {
} AttackType;
typedef struct AttackInfo {
/*
HOW TO SET UP THE IDMAP FOR DUMMIES
The idmap is used as a template to generate spellstage IDs in stage_init_array().
It looks like this:
{id_easy, id_normal, id_hard, id_lunatic}
Where each of those IDs are in range of 0-127, and are unique within each stage-specific AttackInfo array.
A special value of -1 can be used to not generate a spellstage for specific difficulties.
This is useful if your spell is only available on Hard and Lunatic, or has a difficulty-dependent name, etc.
Most importantly DO NOT CHANGE ENSTABILISHED IDs unless you absolutely must.
Doing so is going to break replays, progress files, and anything that stores stage IDs permanently.
Stage IDs are an internal detail invisible to the player, so they don't need to have any kind of fancy ordering.
*/
signed char idmap[NUM_SELECTABLE_DIFFICULTIES];
AttackType type;
char *name;
float timeout;
@ -31,7 +50,6 @@ typedef struct AttackInfo {
BossRule rule;
BossRule draw_rule;
// complex pos_spawn;
complex pos_dest;
} AttackInfo;

25
src/color.c Normal file
View file

@ -0,0 +1,25 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
*/
#include <stdlib.h>
#include "color.h"
Color *rgba(float r, float g, float b, float a) {
Color *clr = malloc(sizeof(Color));
clr->r = r;
clr->g = g;
clr->b = b;
clr->a = a;
return clr;
}
Color *rgb(float r, float g, float b) {
return rgba(r, g, b, 1.0);
}

22
src/color.h Normal file
View file

@ -0,0 +1,22 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
*/
#ifndef TSCOLOR_H
#define TSCOLOR_H
typedef struct {
float r;
float g;
float b;
float a;
} Color;
Color* rgba(float r, float g, float b, float a);
Color* rgb(float r, float g, float b);
#endif

31
src/difficulty.c Normal file
View file

@ -0,0 +1,31 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
*/
#include "difficulty.h"
const char* difficulty_name(Difficulty diff) {
switch(diff) {
case D_Easy: return "Easy"; break;
case D_Normal: return "Normal"; break;
case D_Hard: return "Hard"; break;
case D_Lunatic: return "Lunatic"; break;
case D_Extra: return "Extra"; break;
default: return "Unknown"; break;
}
}
void difficulty_color(Color *c, Difficulty diff) {
switch(diff) {
case D_Easy: c->r = 0.5; c->g = 1.0; c->b = 0.5; break;
case D_Normal: c->r = 0.5; c->g = 0.5; c->b = 1.0; break;
case D_Hard: c->r = 1.0; c->g = 0.5; c->b = 0.5; break;
case D_Lunatic: c->r = 1.0; c->g = 0.5; c->b = 1.0; break;
case D_Extra: c->r = 0.5; c->g = 1.0; c->b = 1.0; break;
default: c->r = 0.5; c->g = 0.5; c->b = 0.5; break;
}
}

30
src/difficulty.h Normal file
View file

@ -0,0 +1,30 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
*/
#ifndef DIFFICULTY_H
#define DIFFICULTY_H
#include "color.h"
struct Color;
typedef enum {
D_Any = 0,
D_Easy,
D_Normal,
D_Hard,
D_Lunatic,
D_Extra // reserved for later
} Difficulty;
#define NUM_SELECTABLE_DIFFICULTIES D_Lunatic
const char* difficulty_name(Difficulty diff);
void difficulty_color(Color *c, Difficulty diff);
#endif

View file

@ -243,28 +243,6 @@ bool strendswith(const char *s, const char *e) {
return true;
}
char* difficulty_name(Difficulty diff) {
switch(diff) {
case D_Easy: return "Easy"; break;
case D_Normal: return "Normal"; break;
case D_Hard: return "Hard"; break;
case D_Lunatic: return "Lunatic"; break;
case D_Extra: return "Extra"; break;
default: return "Unknown"; break;
}
}
void difficulty_color(Color *c, Difficulty diff) {
switch(diff) {
case D_Easy: c->r = 0.5; c->g = 1.0; c->b = 0.5; break;
case D_Normal: c->r = 0.5; c->g = 0.5; c->b = 1.0; break;
case D_Hard: c->r = 1.0; c->g = 0.5; c->b = 0.5; break;
case D_Lunatic: c->r = 1.0; c->g = 0.5; c->b = 1.0; break;
case D_Extra: c->r = 0.5; c->g = 1.0; c->b = 1.0; break;
default: c->r = 0.5; c->g = 0.5; c->b = 0.5; break;
}
}
void stralloc(char **dest, const char *src) {
free(*dest);

View file

@ -39,6 +39,8 @@
#include "replay.h"
#include "random.h"
#include "events.h"
#include "difficulty.h"
#include "color.h"
#include "taisei_err.h"
#include "rwops/all.h"
@ -157,8 +159,6 @@ double clamp(double, double, double);
double approach(double v, double t, double d);
double psin(double);
bool strendswith(const char *s, const char *e);
char* difficulty_name(Difficulty diff);
void difficulty_color(Color *c, Difficulty diff);
void stralloc(char **dest, const char *src);
bool gamekeypressed(KeyIndex key);
int getenvint(const char *v);

View file

@ -8,7 +8,7 @@
#include "global.h"
#include "menu.h"
#include "savereplay.h"
#include "difficulty.h"
#include "difficultyselect.h"
#include "charselect.h"
#include "ending.h"
#include "credits.h"

View file

@ -6,6 +6,7 @@
*/
#include "difficulty.h"
#include "difficultyselect.h"
#include "options.h"
#include "common.h"
#include "global.h"

View file

@ -5,8 +5,8 @@
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#ifndef DIFFICULTY_H
#define DIFFICULTY_H
#ifndef DIFFICULTYMENU_H
#define DIFFICULTYMENU_H
#include "menu.h"

View file

@ -51,9 +51,6 @@ typedef struct Projectile {
int grazed;
} Projectile;
Color *rgba(float r, float g, float b, float a);
Color *rgb(float r, float g, float b);
#define create_particle3c(n,p,c,d,r,a1,a2,a3) create_particle4c(n,p,c,d,r,a1,a2,a3,0)
#define create_particle2c(n,p,c,d,r,a1,a2) create_particle4c(n,p,c,d,r,a1,a2,0,0)
#define create_particle1c(n,p,c,d,r,a1) create_particle4c(n,p,c,d,r,a1,0,0,0)

View file

@ -10,6 +10,7 @@
#define TSRAND_H
#include <stdint.h>
#include <stdbool.h>
typedef struct RandomState {
uint32_t w;

View file

@ -15,20 +15,6 @@
#include "list.h"
#include "vbo.h"
Color *rgba(float r, float g, float b, float a) {
Color *clr = malloc(sizeof(Color));
clr->r = r;
clr->g = g;
clr->b = b;
clr->a = a;
return clr;
}
Color *rgb(float r, float g, float b) {
return rgba(r, g, b, 1.0);
}
Texture *get_tex(char *name) {
Texture *t, *res = NULL;
for(t = resources.textures; t; t = t->next) {

View file

@ -10,13 +10,7 @@
#include <SDL.h>
#include "taiseigl.h"
typedef struct {
float r;
float g;
float b;
float a;
} Color;
#include "color.h"
typedef struct Texture Texture;

View file

@ -21,233 +21,110 @@
#include "menu/gameovermenu.h"
#include "taisei_err.h"
StageInfo stages[] = {
//
// ids must be unique
// they don't necessarily have to be human-readable or ordered
// they're basically there just for replays, so don't change the already enstabilished ones unless you must
//
static size_t numstages = 0;
StageInfo *stages = NULL;
//
// Story stages
//
static void add_stage(uint16_t id, StageProcs *procs, StageType type, const char *title, const char *subtitle, AttackInfo *spell, Difficulty diff, Color *titleclr, Color *bosstitleclr) {
++numstages;
stages = realloc(stages, numstages * sizeof(StageInfo));
StageInfo *stg = stages + (numstages - 1);
memset(stg, 0, sizeof(StageInfo));
// id loop type title subtitle titleclr bosstitleclr spell difficulty
{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},
stg->id = id;
stg->procs = procs;
stg->type = type;
stralloc(&stg->title, title);
stralloc(&stg->subtitle, subtitle);
stg->spell = spell;
stg->difficulty = diff;
//
// Spell practice stages
//
// titles and subtitles for those are generated later by stage_init_array()
//
if(titleclr) {
memcpy(&stg->titleclr, titleclr, sizeof(Color));
}
#define S STAGE_SPELL_BIT
// Freeze Sign ~ Perfect Freeze
{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},
if(bosstitleclr) {
memcpy(&stg->bosstitleclr, titleclr, sizeof(Color));
}
// Freeze Sign ~ Crystal Rain
{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},
free(titleclr);
free(bosstitleclr);
// Doom Sign ~ Icicle Fall
{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},
#ifdef DEBUG
if(title && subtitle) {
fprintf(stderr, "Added stage 0x%04x: %s: %s\n", id, title, subtitle);
}
#endif
}
// Shard ~ Amulet of Harm
{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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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}
};
static void end_stages() {
add_stage(0, NULL, 0, NULL, NULL, NULL, 0, NULL, NULL);
}
void stage_init_array(void) {
int spellnum = 0;
for(int i = 0; stages[i].procs; ++i) {
// we will allocate this later on demand
stages[i].progress = NULL;
// id procs type title subtitle spells diff titleclr bosstitleclr
add_stage(1, &stage1_procs, STAGE_STORY, "Stage 1", "Misty Lake", stage1_spells, D_Any, rgb(1, 1, 1), rgb(1, 1, 1));
add_stage(2, &stage2_procs, STAGE_STORY, "Stage 2", "Walk Along the Border", stage2_spells, D_Any, rgb(1, 1, 1), rgb(1, 1, 1));
add_stage(3, &stage3_procs, STAGE_STORY, "Stage 3", "Through the Tunnel of Light", stage3_spells, D_Any, rgb(0, 0, 0), rgb(0, 0, 0));
add_stage(4, &stage4_procs, STAGE_STORY, "Stage 4", "Forgotten Mansion", stage4_spells, D_Any, rgb(0, 0, 0), rgb(1, 1, 1));
add_stage(5, &stage5_procs, STAGE_STORY, "Stage 5", "Climbing the Tower of Babel", stage5_spells, D_Any, rgb(1, 1, 1), rgb(1, 1, 1));
add_stage(6, &stage6_procs, STAGE_STORY, "Stage 6", "Roof of the World", stage6_spells, D_Any, rgb(1, 1, 1), rgb(1, 1, 1));
if(stages[i].type == STAGE_SPELL) {
char *s, title[10], *postfix = difficulty_name(stages[i].difficulty);
// generate spellpractice stages
snprintf(title, sizeof(title), "Spell %d", ++spellnum);
stralloc(&stages[i].title, title);
int mainstages = numstages;
stages[i].subtitle = s = malloc(strlen(postfix) + strlen(stages[i].spell->name) + 4);
strcpy(s, stages[i].spell->name);
strcat(s, " ~ ");
strcat(s, postfix);
for(int i = 0; i < mainstages; ++i) {
StageInfo *s = stages + i;
for(AttackInfo *a = s->spell; a->rule; ++a) {
for(Difficulty diff = D_Easy; diff < D_Easy + NUM_SELECTABLE_DIFFICULTIES; ++diff) {
if(a->idmap[diff - D_Easy] >= 0) {
uint16_t id = STAGE_SPELL_BIT | a->idmap[diff - D_Easy] | (s->id << 8);
char title[10];
const char *postfix = difficulty_name(diff);
snprintf(title, sizeof(title), "Spell %d", ++spellnum);
char subtitle[strlen(postfix) + strlen(a->name) + 4];
strcpy(subtitle, a->name);
strcat(subtitle, " ~ ");
strcat(subtitle, postfix);
add_stage(id, s->procs->spellpractice_procs, STAGE_SPELL, title, subtitle, a, diff, NULL, NULL);
s = stages + i; // stages just got realloc'd, so we must update the pointer
}
}
}
}
end_stages();
#ifdef DEBUG
for(int i = 0; stages[i].procs; ++i) {
if(stages[i].type == STAGE_SPELL && !(stages[i].id & STAGE_SPELL_BIT)) {
errx(-1, "Spell stage has an ID without the spell bit set: %u", stages[i].id);
errx(-1, "Spell stage has an ID without the spell bit set: 0x%04x", stages[i].id);
}
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);
errx(-1, "Duplicate ID 0x%04x in stages array, indices: %i, %i", stages[i].id, i, j);
}
}
#endif
}
#endif
}
void stage_free_array(void) {
for(StageInfo *stg = stages; stg->procs; ++stg) {
if(stg->type == STAGE_SPELL) {
free(stg->subtitle);
}
free(stg->title);
free(stg->subtitle);
free(stg->progress);
}
free(stages);
}
// NOTE: This returns the stage BY ID, not by the array index!
@ -460,7 +337,8 @@ void stage_input(void) {
void draw_hud(void) {
draw_texture(SCREEN_W/2.0, SCREEN_H/2.0, "hud");
char buf[16], *diff;
char buf[16];
const char *diff;
int i;
glPushMatrix();
@ -594,7 +472,8 @@ static void stage_draw(StageInfo *stage) {
if(global.dialog)
draw_dialog(global.dialog);
draw_stage_title(stage);
if(stage->type != STAGE_SPELL)
draw_stage_title(stage);
if(!config_get_int(CONFIG_NO_SHADER)) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);

View file

@ -8,6 +8,12 @@
#ifndef STAGE_H
#define STAGE_H
#include <stdbool.h>
#include "projectile.h"
#include "boss.h"
#include "progress.h"
#include "difficulty.h"
/* taisei's strange macro language.
*
* sorry, I guess it is bad style, but I hardcode everything and in that case
@ -17,22 +23,6 @@
*
*/
#include <stdbool.h>
#include "projectile.h"
#include "boss.h"
#include "progress.h"
typedef enum {
D_Any = 0,
D_Easy,
D_Normal,
D_Hard,
D_Lunatic,
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)))
@ -55,35 +45,34 @@ typedef enum StageType {
STAGE_SPELL,
} StageType;
typedef struct StageProcs {
typedef struct StageProcs StageProcs;
struct StageProcs {
StageProc begin;
StageProc end;
StageProc draw;
StageProc event;
ShaderRule *shader_rules;
} StageProcs;
StageProcs *spellpractice_procs;
};
typedef struct StageInfo {
//
// don't reorder these!
//
uint16_t id; // must match type of ReplayStage.stage in replay.h
StageProcs *procs;
StageType type;
char *title;
char *subtitle;
Color titleclr;
Color bosstitleclr;
AttackInfo *spell;
Difficulty difficulty;
Color titleclr;
Color bosstitleclr;
// 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[];
extern StageInfo *stages;
StageInfo* stage_get(uint16_t);
StageInfo* stage_get_by_spellcard(AttackInfo *spell, Difficulty diff);

View file

@ -18,10 +18,19 @@ void cirno_crystal_rain(Boss*, int);
void cirno_icicle_fall(Boss*, int);
void cirno_pfreeze_bg(Boss*, int);
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
*/
AttackInfo stage1_spells[] = {
{AT_Spellcard, "Freeze Sign ~ Perfect Freeze", 32, 20000, cirno_perfect_freeze, cirno_pfreeze_bg, VIEWPORT_W/2.0+100.0*I},
{AT_Spellcard, "Freeze Sign ~ Crystal Rain", 28, 28000, cirno_crystal_rain, cirno_pfreeze_bg, VIEWPORT_W/2.0+100.0*I},
{AT_Spellcard, "Doom Sign ~ Icicle Fall", 35, 40000, cirno_icicle_fall, cirno_pfreeze_bg, VIEWPORT_W/2.0+100.0*I},
{{ 0, 1, 2, 3}, AT_Spellcard, "Freeze Sign ~ Perfect Freeze", 32, 20000,
cirno_perfect_freeze, cirno_pfreeze_bg, VIEWPORT_W/2.0+100.0*I},
{{ 4, 5, 6, 7}, AT_Spellcard, "Freeze Sign ~ Crystal Rain", 28, 28000,
cirno_crystal_rain, cirno_pfreeze_bg, VIEWPORT_W/2.0+100.0*I},
{{ 8, 9, 10, 11}, AT_Spellcard, "Doom Sign ~ Icicle Fall", 35, 40000,
cirno_icicle_fall, cirno_pfreeze_bg, VIEWPORT_W/2.0+100.0*I},
{{0}}
};
Dialog *stage1_dialog(void) {
@ -712,6 +721,7 @@ StageProcs stage1_procs = {
.draw = stage1_draw,
.event = stage1_events,
.shader_rules = stage1_shaders,
.spellpractice_procs = &stage1_spell_procs,
};
StageProcs stage1_spell_procs = {

View file

@ -181,6 +181,7 @@ StageProcs stage2_procs = {
.draw = stage2_draw,
.event = stage2_events,
.shader_rules = stage2_shaders,
.spellpractice_procs = &stage2_spell_procs,
};
StageProcs stage2_spell_procs = {

View file

@ -15,10 +15,19 @@ void hina_amulet(Boss*, int);
void hina_bad_pick(Boss*, int);
void hina_wheel(Boss*, int);
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
*/
AttackInfo stage2_spells[] = {
{AT_Spellcard, "Shard ~ Amulet of Harm", 26, 25000, hina_amulet, hina_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Lottery Sign ~ Bad Pick", 30, 36000, hina_bad_pick, hina_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Lottery Sign ~ Wheel of Fortune", 20, 36000, hina_wheel, hina_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 0, 1, 2, 3}, AT_Spellcard, "Shard ~ Amulet of Harm", 26, 25000,
hina_amulet, hina_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 4, 5, 6, 7}, AT_Spellcard, "Lottery Sign ~ Bad Pick", 30, 36000,
hina_bad_pick, hina_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 8, 9, 10, 11}, AT_Spellcard, "Lottery Sign ~ Wheel of Fortune", 20, 36000,
hina_wheel, hina_spell_bg, BOSS_DEFAULT_GO_POS},
{{0}}
};
Dialog *stage2_dialog(void) {

View file

@ -307,6 +307,7 @@ StageProcs stage3_procs = {
.draw = stage3_draw,
.event = stage3_events,
.shader_rules = stage3_shaders,
.spellpractice_procs = &stage3_spell_procs,
};
StageProcs stage3_spell_procs = {

View file

@ -19,12 +19,23 @@ void stage3_boss_a1(Boss*, int t);
void stage3_boss_a2(Boss*, int t);
void stage3_boss_a3(Boss*, int t);
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
*/
AttackInfo stage3_spells[] = {
{AT_Spellcard, "Venom Sign ~ Deadly Dance", 25, 25000, stage3_mid_a1, stage3_mid_spellbg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Venom Sign ~ Acid Rain", 20, 23000, stage3_mid_a2, stage3_mid_spellbg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Firefly Sign ~ Moonlight Rocket", 30, 20000, stage3_boss_a1, stage3_boss_spellbg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Light Source ~ Wriggle Night Ignite", 25, 40000, stage3_boss_a2, stage3_boss_spellbg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Bug Sign ~ Phosphaenus Hemipterus", 35, 30000, stage3_boss_a3, stage3_boss_spellbg, BOSS_DEFAULT_GO_POS},
{{ 0, 1, 2, 3}, AT_Spellcard, "Venom Sign ~ Deadly Dance", 25, 25000,
stage3_mid_a1, stage3_mid_spellbg, BOSS_DEFAULT_GO_POS},
{{-1, -1, 4, 5}, AT_Spellcard, "Venom Sign ~ Acid Rain", 20, 23000,
stage3_mid_a2, stage3_mid_spellbg, BOSS_DEFAULT_GO_POS},
{{ 6, 7, 8, 9}, AT_Spellcard, "Firefly Sign ~ Moonlight Rocket", 30, 20000,
stage3_boss_a1, stage3_boss_spellbg, BOSS_DEFAULT_GO_POS},
{{10, 11, 12, 13}, AT_Spellcard, "Light Source ~ Wriggle Night Ignite", 25, 40000,
stage3_boss_a2, stage3_boss_spellbg, BOSS_DEFAULT_GO_POS},
{{14, 15, 16, 17}, AT_Spellcard, "Bug Sign ~ Phosphaenus Hemipterus", 35, 30000,
stage3_boss_a3, stage3_boss_spellbg, BOSS_DEFAULT_GO_POS},
{{0}}
};
Dialog *stage3_dialog(void) {

View file

@ -250,6 +250,7 @@ StageProcs stage4_procs = {
.draw = stage4_draw,
.event = stage4_events,
.shader_rules = stage4_shaders,
.spellpractice_procs = &stage4_spell_procs,
};
StageProcs stage4_spell_procs = {

View file

@ -18,14 +18,27 @@ void kurumi_aniwall(Boss*, int);
void kurumi_blowwall(Boss*, int);
void kurumi_danmaku(Boss*, int);
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
*/
AttackInfo stage4_spells[] = {
{AT_Spellcard, "Bloodless ~ Gate of Walachia", 25, 20000, kurumi_slaveburst, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Bloodless ~ Dry Fountain", 30, 30000, kurumi_redspike, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Bloodless ~ Red Spike", 30, 30000, kurumi_redspike, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Limit ~ Animate Wall", 30, 40000, kurumi_aniwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Summoning ~ Demon Wall", 30, 40000, kurumi_aniwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Power Sign ~ Blow the Walls", 30, 32000, kurumi_blowwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Fear Sign ~ Bloody Danmaku", 30, 32000, kurumi_danmaku, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 0, 1, 2, 3}, AT_Spellcard, "Bloodless ~ Gate of Walachia", 25, 20000,
kurumi_slaveburst, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 4, 5, -1, -1}, AT_Spellcard, "Bloodless ~ Dry Fountain", 30, 30000,
kurumi_redspike, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{-1, -1, 6, 7}, AT_Spellcard, "Bloodless ~ Red Spike", 30, 30000,
kurumi_redspike, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 8, 9, -1, -1}, AT_Spellcard, "Limit ~ Animate Wall", 30, 40000,
kurumi_aniwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{-1, -1, 10, 11}, AT_Spellcard, "Summoning ~ Demon Wall", 30, 40000,
kurumi_aniwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{12, 13, 14, 15}, AT_Spellcard, "Power Sign ~ Blow the Walls", 30, 32000,
kurumi_blowwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{-1, -1, 16, 17}, AT_Spellcard, "Fear Sign ~ Bloody Danmaku", 30, 32000,
kurumi_danmaku, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
{{0}}
};
Dialog *stage4_dialog(void) {

View file

@ -149,6 +149,7 @@ StageProcs stage5_procs = {
.draw = stage5_draw,
.event = stage5_events,
.shader_rules = stage5_shaders,
.spellpractice_procs = &stage5_spell_procs,
};
StageProcs stage5_spell_procs = {

View file

@ -15,11 +15,21 @@ void iku_lightning(Boss*, int);
void iku_cathode(Boss*, int);
void iku_induction(Boss*, int);
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
*/
AttackInfo stage5_spells[] = {
{AT_Spellcard, "High Voltage ~ Atmospheric Discharge", 30, 30000, iku_atmospheric, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Charge Sign ~ Artificial Lightning", 30, 35000, iku_lightning, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Spark Sign ~ Natural Cathode", 30, 35000, iku_cathode, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Current Sign ~ Induction", 30, 35000, iku_induction, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 0, 1, 2, 3}, AT_Spellcard, "High Voltage ~ Atmospheric Discharge", 30, 30000,
iku_atmospheric, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 4, 5, 6, 7}, AT_Spellcard, "Charge Sign ~ Artificial Lightning", 30, 35000,
iku_lightning, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{{ 8, 9, 10, 11}, AT_Spellcard, "Spark Sign ~ Natural Cathode", 30, 35000,
iku_cathode, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{{12, 13, 14, 15}, AT_Spellcard, "Current Sign ~ Induction", 30, 35000,
iku_induction, iku_spell_bg, BOSS_DEFAULT_GO_POS},
{{0}}
};
Dialog *stage5_post_mid_dialog(void) {

View file

@ -234,6 +234,7 @@ StageProcs stage6_procs = {
.draw = stage6_draw,
.event = stage6_events,
.shader_rules = stage6_shaders,
.spellpractice_procs = &stage6_spell_procs,
};
StageProcs stage6_spell_procs = {

View file

@ -18,13 +18,25 @@ void elly_ricci(Boss*, int);
void elly_lhc(Boss*, int);
void elly_theory(Boss*, int);
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
*/
AttackInfo stage6_spells[] = {
{AT_Spellcard, "Newton Sign ~ 2.5 Laws of Movement", 60, 40000, elly_newton, elly_spellbg_classic, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Maxwell Sign ~ Wave Theory", 25, 22000, elly_maxwell, elly_spellbg_classic, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Eigenstate ~ Many-World Interpretation", 60, 30000, elly_eigenstate, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "Ricci Sign ~ Space Time Curvature", 50, 40000, elly_ricci, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{AT_Spellcard, "LHC ~ Higgs Boson Uncovered", 60, 50000, elly_lhc, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{AT_SurvivalSpell, "Tower of Truth ~ Theory of Everything", 70, 40000, elly_theory, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{{ 0, 1, 2, 3}, AT_Spellcard, "Newton Sign ~ 2.5 Laws of Movement", 60, 40000,
elly_newton, elly_spellbg_classic, BOSS_DEFAULT_GO_POS},
{{ 4, 5, 6, 7}, AT_Spellcard, "Maxwell Sign ~ Wave Theory", 25, 22000,
elly_maxwell, elly_spellbg_classic, BOSS_DEFAULT_GO_POS},
{{ 8, 9, 10, 11}, AT_Spellcard, "Eigenstate ~ Many-World Interpretation", 60, 30000,
elly_eigenstate, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{{12, 13, 14, 15}, AT_Spellcard, "Ricci Sign ~ Space Time Curvature", 50, 40000,
elly_ricci, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{{16, 17, 18, 19}, AT_Spellcard, "LHC ~ Higgs Boson Uncovered", 60, 50000,
elly_lhc, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{{20, 21, 22, 23}, AT_SurvivalSpell, "Tower of Truth ~ Theory of Everything", 70, 40000,
elly_theory, elly_spellbg_modern, BOSS_DEFAULT_GO_POS},
{{0}}
};
Dialog *stage6_dialog(void) {