109 lines
2.8 KiB
C
109 lines
2.8 KiB
C
/*
|
|
* This software is licensed under the terms of the MIT License.
|
|
* See COPYING for further information.
|
|
* ---
|
|
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
|
|
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
|
|
*/
|
|
|
|
#include "spells.h"
|
|
|
|
TASK(crystal_wall) {
|
|
int num_crystals = difficulty_value(18, 21, 24, 27);
|
|
real spacing = VIEWPORT_W / (real)(num_crystals - 1);
|
|
real ofs = rng_real() - 1;
|
|
|
|
for(int i = 0; i < 30; ++i) {
|
|
play_sfx("shot1");
|
|
|
|
for(int c = 0; c < num_crystals; ++c) {
|
|
cmplx accel = 0.02*I + 0.01*I * ((c % 2) ? 1 : -1) * sin((c * 3 + global.frames) / 30.0);
|
|
PROJECTILE(
|
|
.proto = pp_crystal,
|
|
.pos = (ofs + c) * spacing + 20,
|
|
.color = (c % 2) ? RGB(0.2, 0.2, 0.4) : RGB(0.5, 0.5, 0.5),
|
|
.move = move_accelerated(0, accel),
|
|
.max_viewport_dist = 16,
|
|
);
|
|
}
|
|
|
|
WAIT(10);
|
|
}
|
|
}
|
|
|
|
TASK(cirno_frostbolt_trail, { BoxedProjectile proj; }) {
|
|
Projectile *p = TASK_BIND(ARGS.proj);
|
|
int period = 12;
|
|
|
|
WAIT(rng_irange(0, period + 1));
|
|
|
|
for(;;) {
|
|
stage1_spawn_stain(p->pos, rng_f32_angle(), 20);
|
|
WAIT(period);
|
|
}
|
|
}
|
|
|
|
TASK(cirno_frostbolt, { cmplx pos; cmplx vel; }) {
|
|
Projectile *p = TASK_BIND(PROJECTILE(
|
|
.proto = pp_wave,
|
|
.pos = ARGS.pos,
|
|
.color = RGBA(0.2, 0.2, 0.4, 0.0),
|
|
.move = move_asymptotic_simple(ARGS.vel, 5),
|
|
));
|
|
|
|
INVOKE_TASK(cirno_frostbolt_trail, ENT_BOX(p));
|
|
WAIT(difficulty_value(200, 300, 400, 500));
|
|
p->move.retention = 1.03;
|
|
}
|
|
|
|
DEFINE_EXTERN_TASK(stage1_spell_crystal_blizzard) {
|
|
Boss *boss = INIT_BOSS_ATTACK(&ARGS);
|
|
boss->move = move_from_towards(boss->pos, VIEWPORT_W / 2.0 + 300 * I, 0.1);
|
|
BEGIN_BOSS_ATTACK(&ARGS);
|
|
|
|
int frostbolt_period = difficulty_value(4, 3, 2, 1);
|
|
|
|
for(;;) {
|
|
INVOKE_SUBTASK_DELAYED(60, crystal_wall);
|
|
|
|
int charge_time = 120;
|
|
|
|
WAIT(330 - charge_time);
|
|
aniplayer_queue(&boss->ani, "(9)" ,0);
|
|
INVOKE_SUBTASK(common_charge, boss->pos, RGBA(0.5, 0.6, 2.0, 0.0), charge_time, .sound = COMMON_CHARGE_SOUNDS);
|
|
WAIT(charge_time);
|
|
|
|
boss->move = move_towards_exp(boss->move.velocity, global.plr.pos, 1, 0.1);
|
|
|
|
for(int t = 0; t < 370; ++t) {
|
|
play_sfx_loop("shot1_loop");
|
|
boss->move.attraction_point = global.plr.pos;
|
|
|
|
if(!(t % frostbolt_period)) {
|
|
cmplx aim = cnormalize(global.plr.pos - boss->pos) * cdir(rng_sreal() * 0.2);
|
|
cmplx vel = rng_range(0.01, 4) * aim;
|
|
INVOKE_TASK(cirno_frostbolt, boss->pos, vel);
|
|
}
|
|
|
|
if(!(t % 7)) {
|
|
play_sfx("shot1");
|
|
int cnt = global.diff - 1;
|
|
for(int i = 0; i < cnt; ++i) {
|
|
PROJECTILE(
|
|
.proto = pp_ball,
|
|
.pos = boss->pos,
|
|
.color = RGBA(0.1, 0.1, 0.5, 0.0),
|
|
.move = move_accelerated(0, 0.01 * cdir(global.frames/20.0 + i*M_TAU/cnt)),
|
|
);
|
|
}
|
|
}
|
|
|
|
WAIT(1);
|
|
}
|
|
|
|
boss->move.attraction_point = 0;
|
|
boss->move.attraction = 0;
|
|
boss->move.retention = 0.8;
|
|
aniplayer_queue(&boss->ani, "main" ,0);
|
|
}
|
|
}
|