taisei/src/stages/stage4.c
2017-12-10 19:53:00 +01:00

326 lines
8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (c) 2011-2017, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2017, Andrei Alexeyev <akari@alienslab.net>.
*/
#include "stage4.h"
#include "stage4_events.h"
#include "global.h"
#include "stage.h"
#include "stageutils.h"
/*
* See the definition of AttackInfo in boss.h for information on how to set up the idmaps.
* To add, remove, or reorder spells, see this stage's header file.
*/
struct stage4_spells_s stage4_spells = {
.mid = {
.gate_of_walachia = {{ 0, 1, 2, 3}, AT_Spellcard, "Bloodless ~ Gate of Walachia", 25, 44000,
kurumi_slaveburst, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
.dry_fountain = {{ 4, 5, -1, -1}, AT_Spellcard, "Bloodless ~ Dry Fountain", 30, 44000,
kurumi_redspike, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
.red_spike = {{-1, -1, 6, 7}, AT_Spellcard, "Bloodless ~ Red Spike", 30, 46000,
kurumi_redspike, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
},
.boss = {
.animate_wall = {{ 8, 9, -1, -1}, AT_Spellcard, "Limit ~ Animate Wall", 30, 50000,
kurumi_aniwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
.demon_wall = {{-1, -1, 10, 11}, AT_Spellcard, "Summoning ~ Demon Wall", 30, 55000,
kurumi_aniwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
.blow_the_walls = {{12, 13, 14, 15}, AT_Spellcard, "Power Sign ~ Blow the Walls", 30, 55000,
kurumi_blowwall, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
.bloody_danmaku = {{18, 19, 16, 17}, AT_Spellcard, "Fear Sign ~ Bloody Danmaku", 30, 60000,
kurumi_danmaku, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
},
.extra.vlads_army = {{ 0, 1, 2, 3}, AT_ExtraSpell, "Blood Magic ~ Vlads Army", 60, 50000,
kurumi_extra, kurumi_spell_bg, BOSS_DEFAULT_GO_POS},
};
static void stage4_fog(FBO *fbo) {
Shader *shader = get_shader("zbuf_fog");
float f = 0;
int redtime = 5100 + STAGE4_MIDBOSS_MUSIC_TIME;
if(global.timer > redtime) {
float v = (global.timer-redtime)*0.0005;
f = v < 0.1 ? v : 0.1;
}
glUseProgram(shader->prog);
glUniform1i(uniloc(shader, "depth"),2);
glUniform4f(uniloc(shader, "fog_color"),10*f,0,0.1-f,1.0);
glUniform1f(uniloc(shader, "start"),0.4);
glUniform1f(uniloc(shader, "end"),0.8);
glUniform1f(uniloc(shader, "exponent"),4.0);
glUniform1f(uniloc(shader, "sphereness"),0);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, fbo->depth);
glActiveTexture(GL_TEXTURE0);
draw_fbo_viewport(fbo);
glUseProgram(0);
}
static Vector **stage4_fountain_pos(Vector pos, float maxrange) {
Vector p = {0, 400, 1500};
Vector r = {0, 0, 3000};
Vector **list = linear3dpos(pos, maxrange, p, r);
int i;
for(i = 0; list[i] != NULL; i++) {
if((*list[i])[2] > 0)
(*list[i])[2] = -9000;
}
return list;
}
static void stage4_fountain_draw(Vector pos) {
glBindTexture(GL_TEXTURE_2D, get_tex("stage2/border")->gltex);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glRotatef(-90, 1,0,0);
glScalef(1000,3010,1);
draw_quad();
glPopMatrix();
}
static Vector **stage4_lake_pos(Vector pos, float maxrange) {
Vector p = {0, 600, 0};
Vector d;
int i;
for(i = 0; i < 3; i++)
d[i] = p[i] - pos[i];
if(length(d) > maxrange) {
return NULL;
} else {
Vector **list = calloc(2, sizeof(Vector*));
list[0] = malloc(sizeof(Vector));
for(i = 0; i < 3; i++)
(*list[0])[i] = p[i];
list[1] = NULL;
return list;
}
}
static void stage4_lake_draw(Vector pos) {
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/lake")->gltex);
glPushMatrix();
glTranslatef(pos[0], pos[1]+140, pos[2]);
glScalef(15,15,15);
draw_model("lake");
glPopMatrix();
glPushMatrix();
glTranslatef(pos[0], pos[1]+944, pos[2]+50);
glScalef(30,30,30);
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/mansion")->gltex);
draw_model("mansion");
glPopMatrix();
}
static Vector **stage4_corridor_pos(Vector pos, float maxrange) {
Vector p = {0, 2400, 50};
Vector r = {0, 2000, 0};
Vector **list = linear3dpos(pos, maxrange, p, r);
int i;
for(i = 0; list[i] != NULL; i++) {
if((*list[i])[1] < p[1])
(*list[i])[1] = -9000;
}
return list;
}
static void stage4_corridor_draw(Vector pos) {
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/planks")->gltex);
glMatrixMode(GL_TEXTURE);
glScalef(1,2,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glPushMatrix();
glRotatef(180, 1,0,0);
glScalef(300,2000,1);
draw_quad();
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/wall")->gltex);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glRotatef(90,0,0,1);
glScalef(1,10,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(100,5,75);
glRotatef(90, 0,1,0);
glScalef(150,2000,1);
draw_quad();
glPopMatrix();
glPushMatrix();
glTranslatef(-100,5,75);
glRotatef(180,1,0,0);
glRotatef(-90, 0,1,0);
glScalef(150,2000,1);
draw_quad();
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_TEXTURE_2D);
glColor3f(0.01,0.01,0.01);
glPushMatrix();
glTranslatef(0,0,150);
glScalef(500,2000,1);
draw_quad();
glPopMatrix();
glPopMatrix();
glColor3f(1,1,1);
glEnable(GL_TEXTURE_2D);
}
static void stage4_start(void) {
init_stage3d(&stage_3d_context);
stage_3d_context.cx[2] = -10000;
stage_3d_context.cv[2] = 19.7;
stage_3d_context.crot[0] = 80;
// for testing
// stage_3d_context.cx[1] = 2000;
// stage_3d_context.cx[2] = 130;
// stage_3d_context.cv[1] = 10;
// stage_3d_context.crot[0] = 80;
add_model(&stage_3d_context, stage4_lake_draw, stage4_lake_pos);
add_model(&stage_3d_context, stage4_fountain_draw, stage4_fountain_pos);
add_model(&stage_3d_context, stage4_corridor_draw, stage4_corridor_pos);
}
static void stage4_preload(void) {
preload_resources(RES_BGM, RESF_OPTIONAL, "stage4", "stage4boss", NULL);
preload_resources(RES_TEXTURE, RESF_DEFAULT,
"stage2/border", // Stage 2 is intentional!
"stage4/kurumibg1",
"stage4/kurumibg2",
"stage4/lake",
"stage4/mansion",
"stage4/planks",
"stage4/wall",
"stage6/scythe", // Stage 6 is also intentional
"dialog/kurumi",
NULL);
preload_resources(RES_SHADER, RESF_DEFAULT,
"zbuf_fog",
NULL);
preload_resources(RES_ANIM, RESF_DEFAULT,
"kurumi",
NULL);
preload_resources(RES_MODEL, RESF_DEFAULT,
"mansion",
"lake",
NULL);
}
static void stage4_end(void) {
free_stage3d(&stage_3d_context);
}
static void stage4_draw(void) {
set_perspective(&stage_3d_context, 130, 3000);
draw_stage3d(&stage_3d_context, 4000);
}
static void stage4_update(void) {
update_stage3d(&stage_3d_context);
if(stage_3d_context.cx[2] >= -1000 && stage_3d_context.cv[2] > 0)
stage_3d_context.cv[2] -= 0.17;
if(stage_3d_context.cx[1] < 100 && stage_3d_context.cv[2] < 0)
stage_3d_context.cv[2] = 0;
if(stage_3d_context.cx[2] >= 0 && stage_3d_context.cx[2] <= 10)
stage_3d_context.cv[1] += 0.2;
if(stage_3d_context.cx[1] >= 1200 && stage_3d_context.cx[1] <= 2000)
stage_3d_context.cv[1] += 0.02;
}
static void stage4_spellpractice_events(void) {
TIMER(&global.timer);
AT(0) {
skip_background_anim(&stage_3d_context, stage4_update, 3200, &global.frames, NULL);
global.boss = stage4_spawn_kurumi(BOSS_DEFAULT_SPAWN_POS);
boss_add_attack_from_info(global.boss, global.stage->spell, true);
boss_start_attack(global.boss, global.boss->attacks);
start_bgm("stage4boss");
}
}
void stage4_skip(int t) {
skip_background_anim(&stage_3d_context, stage4_update, t, &global.timer, &global.frames);
audio_backend_music_set_position(global.timer / (double)FPS);
}
ShaderRule stage4_shaders[] = { stage4_fog, NULL };
StageProcs stage4_procs = {
.begin = stage4_start,
.preload = stage4_preload,
.end = stage4_end,
.draw = stage4_draw,
.update = stage4_update,
.event = stage4_events,
.shader_rules = stage4_shaders,
.spellpractice_procs = &stage4_spell_procs,
};
StageProcs stage4_spell_procs = {
.preload = stage4_preload,
.begin = stage4_start,
.end = stage4_end,
.draw = stage4_draw,
.update = stage4_update,
.event = stage4_spellpractice_events,
.shader_rules = stage4_shaders,
};