stage3: redesign scuttle's spell

This commit is contained in:
Andrei Alexeyev 2023-05-29 05:06:45 +02:00
parent cf8015c784
commit 736e659bab
No known key found for this signature in database
GPG key ID: 72D26128040B9690
5 changed files with 112 additions and 131 deletions

View file

@ -5,9 +5,9 @@ stage3_src = files(
'draw.c',
'nonspells/boss_nonspells.c',
'nonspells/midboss_nonspell_1.c',
'spells/deadly_dance.c',
'spells/firefly_storm.c',
'spells/light_singularity.c',
'spells/logic_bomb.c',
'spells/moonlight_rocket.c',
'spells/night_ignite.c',
'stage3.c',

View file

@ -1,127 +0,0 @@
/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "taisei.h"
#include "spells.h"
#include "../scuttle.h"
#include "common_tasks.h"
#include "global.h"
TASK(spawner_proj, { cmplx pos; MoveParams move; Color *color; int t; int i; }) {
Projectile *p = TASK_BIND(PROJECTILE(
.proto = pp_wave,
.pos = ARGS.pos,
.color = ARGS.color,
.move = ARGS.move,
));
int t = ARGS.t;
int i = ARGS.i;
WAIT(150);
real a = (M_PI/(5 + global.diff) * i * 2);
play_sfx("redirect");
PROJECTILE(
.proto = rng_chance(0.5) ? pp_thickrice : pp_rice,
.pos = p->pos,
.color = RGB(0.3, 0.7 + 0.3 * psin(a/3.0 + t/20.0), 0.3),
.move = move_accelerated(0, 0.005 * cdir((M_TAU * sin(a / 5.0 + t / 20.0))))
);
}
TASK(spawners, { BoxedBoss boss; real tfactor; }) {
Boss *boss = TASK_BIND(ARGS.boss);
int count = difficulty_value(15, 18, 21, 24);
real tfactor = ARGS.tfactor;
for(int time = 0;; time += WAIT(70)) {
real angle_ofs = rng_angle();
play_sfx("shot_special1");
for(int i = 0; i < count; ++i) {
real a = (M_PI/(5 + global.diff) * i * 2);
INVOKE_TASK(spawner_proj,
.pos = boss->pos,
.color = RGB(0.3, 0.3 + 0.7 * psin((M_PI/(5 + global.diff) * i * 2) * 3 + time/50.0), 0.3),
.move = move_accelerated(0, 0.02 * cdir(angle_ofs + a + time/10.0)),
.t = time * tfactor,
.i = i,
);
}
}
}
TASK(balls, { BoxedBoss boss; }) {
Boss *boss = TASK_BIND(ARGS.boss);
int count = difficulty_value(2, 4, 6, 8);
for(int time = 0;; time += WAIT(35)) {
real angle_ofs = rng_angle();
play_sfx("shot1");
for(int i = 0; i < count; ++i) {
PROJECTILE(
.proto = pp_ball,
.pos = boss->pos,
.color = RGB(1.0, 1.0, 0.3),
.move = move_asymptotic_simple(
(0.5 + 3 * psin(time + M_PI / 3 * 2 * i)) * cdir(angle_ofs + time / 20.0 + M_PI / count * i * 2),
1.5
)
);
}
}
}
TASK(limiters, { BoxedBoss boss; }) {
Boss *boss = TASK_BIND(ARGS.boss);
for(int time = 0;; time += WAIT(3)) {
play_sfx_loop("shot1_loop");
for(int i = -1; i < 2; i += 2) {
real c = psin(time/10.0);
cmplx aim = cnormalize(global.plr.pos - boss->pos);
cmplx v = 10 * (aim + (M_PI/4.0 * i * (1 - time / 2500.0)) * (1 - 0.5 * psin(time / 15.0)));
PROJECTILE(
.proto = pp_crystal,
.pos = boss->pos,
.color = RGBA_MUL_ALPHA(0.3 + c * 0.7, 0.6 - c * 0.3, 0.3, 0.7),
.move = move_linear(v),
);
}
}
}
DEFINE_EXTERN_TASK(stage3_spell_deadly_dance) {
STAGE_BOOKMARK(dance);
Boss *boss = INIT_BOSS_ATTACK(&ARGS);
boss->move = move_from_towards(boss->pos, VIEWPORT_W/2 + VIEWPORT_H*I/2, 0.08);
BEGIN_BOSS_ATTACK(&ARGS);
boss->move.attraction = 0;
aniplayer_queue(&boss->ani, "dance", 0);
real tfactor = difficulty_value(1.05, 1.5, 1.95, 2.4);
INVOKE_SUBTASK(limiters, ENT_BOX(boss));
INVOKE_SUBTASK(spawners, ENT_BOX(boss), .tfactor = tfactor);
if(global.diff > D_Easy) {
INVOKE_SUBTASK(balls, ENT_BOX(boss));
}
for(int time = 0;; ++time, YIELD) {
real t = time * tfactor;
real moverad = fmin(160, time/2.7);
boss->pos = VIEWPORT_W/2 + VIEWPORT_H*I/2 + sin(t/50.0) * moverad * cdir(M_PI/2 * t/100.0);
}
}

View file

@ -0,0 +1,108 @@
/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
*/
#include "taisei.h"
#include "spells.h"
#include "../scuttle.h"
#include "common_tasks.h"
#include "global.h"
#define SHOT_OFS1 CMPLX(20, 8)
#define SHOT_OFS2 CMPLX(-14, -42)
TASK(limiters, { BoxedBoss boss; }) {
Boss *boss = TASK_BIND(ARGS.boss);
real angle = 3*M_PI/2;
real final_angle = M_PI/16;
for(int time = 0;; time += WAIT(3)) {
play_sfx_loop("shot1_loop");
for(int i = -1; i < 2; i += 2) {
real c = psin(time/10.0);
cmplx aim = cnormalize(global.plr.pos - boss->pos);
cmplx v = 8 * aim * cdir(i * angle);
PROJECTILE(
.proto = pp_crystal,
.pos = boss->pos + SHOT_OFS2,
.color = RGBA_MUL_ALPHA(0.3 + c * 0.7, 0.6 - c * 0.3, 0.3, 0.7),
.move = move_linear(v),
);
}
angle = lerp(angle, final_angle, 0.02);
}
}
TASK(recursive_ball, { cmplx origin; cmplx dir; real angle; ProjFlags flags; }) {
auto p = TASK_BIND(PROJECTILE(
.proto = pp_ball,
.pos = ARGS.origin,
.color = RGB(1.0, 1.0, 0.3),
.move = move_asymptotic_halflife(3 * ARGS.dir, 0, 13),
.flags = ARGS.flags,
));
WAIT(difficulty_value(60, 60, 60, 50));
cmplx r = cdir(ARGS.angle);
play_sfx("redirect");
real a = ARGS.angle * 0.75;
if(a > M_PI/32) {
INVOKE_TASK(recursive_ball, p->pos, ARGS.dir * r, a);
INVOKE_TASK(recursive_ball, p->pos, ARGS.dir / r, a, PFLAG_NOSPAWNFLARE);
} else {
spawn_projectile_highlight_effect(p);
}
if(global.diff > D_Easy) {
p->color.r = 0;
projectile_set_prototype(p, pp_thickrice);
WAIT(difficulty_value(0, 120, 120, 100));
spawn_projectile_highlight_effect(p);
}
kill_projectile(p);
}
TASK(recursive_balls, { BoxedBoss boss; }) {
auto boss = TASK_BIND(ARGS.boss);
int delay = difficulty_value(120, 120, 60, 50);
for(;;WAIT(delay)) {
cmplx o = boss->pos + boss_get_sprite_offset(boss) + SHOT_OFS2;
cmplx d = cnormalize(global.plr.pos - o + 32 * rng_dir());
play_sfx("shot_special1");
INVOKE_TASK(recursive_ball, o, d, M_PI/2);
}
}
DEFINE_EXTERN_TASK(stage3_spell_logic_bomb) {
Boss *boss = INIT_BOSS_ATTACK(&ARGS);
boss->move = move_from_towards(boss->pos, VIEWPORT_W/2 + VIEWPORT_H*I/2, 0.08);
BEGIN_BOSS_ATTACK(&ARGS);
boss->move.attraction = 0;
aniplayer_queue(&boss->ani, "dance", 0);
INVOKE_SUBTASK(limiters, ENT_BOX(boss));
INVOKE_SUBTASK_DELAYED(20, recursive_balls, ENT_BOX(boss));
for(int time = 0;; ++time, YIELD) {
real t = time * 1.5;
real moverad = fmin(160, time/2.7);
boss->pos = VIEWPORT_W/2 + VIEWPORT_H*I/2 + sin(t/50.0) * moverad * cdir(M_PI/2 * t/100.0);
}
}

View file

@ -15,4 +15,4 @@ DECLARE_EXTERN_TASK_WITH_INTERFACE(stage3_spell_firefly_storm, BossAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage3_spell_light_singularity, BossAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage3_spell_moonlight_rocket, BossAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage3_spell_night_ignite, BossAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage3_spell_deadly_dance, BossAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage3_spell_logic_bomb, BossAttack);

View file

@ -28,8 +28,8 @@
struct stage3_spells_s stage3_spells = {
.mid = {
.deadly_dance = {
{ 0, 1, 2, 3}, AT_SurvivalSpell, "Venom Sign “Deadly Dance", 14, 40000,
TASK_INDIRECT_INIT(BossAttack, stage3_spell_deadly_dance),
{ 0, 1, 2, 3}, AT_SurvivalSpell, "Disruption “Logic Bomb", 14, 40000,
TASK_INDIRECT_INIT(BossAttack, stage3_spell_logic_bomb),
stage3_draw_scuttle_spellbg, VIEWPORT_W/2.0+100*I, 3,
},
},