wip: ricci

This commit is contained in:
laochailan 2021-09-22 16:53:42 +02:00 committed by Andrei Alexeyev
parent 96d6e4499c
commit 6c2129607a
No known key found for this signature in database
GPG key ID: 72D26128040B9690
3 changed files with 192 additions and 178 deletions

View file

@ -12,245 +12,259 @@
#include "common_tasks.h"
MODERNIZE_THIS_FILE_AND_REMOVE_ME
/* !!! You are entering Akari danmaku code !!! */
/* !!! You are entering Akari danmaku code !!! (rejuvenated by lao) */
#define SAFE_RADIUS_DELAY 300
#define SAFE_RADIUS_BASE 100
#define SAFE_RADIUS_STRETCH 100
#define SAFE_RADIUS_MIN 60
#define SAFE_RADIUS_MAX 150
#define SAFE_RADIUS_SPEED 0.015
#define SAFE_RADIUS_PHASE_VELOCITY 0.015
#define SAFE_RADIUS_PHASE 3*M_PI/2
#define SAFE_RADIUS_PHASE_FUNC(o) ((int)(creal(e->args[2])+0.5) * M_PI/3 + SAFE_RADIUS_PHASE + fmax(0, time - SAFE_RADIUS_DELAY) * SAFE_RADIUS_SPEED)
//#define SAFE_RADIUS_PHASE_FUNC(o) ((int)(creal(e->args[2])+0.5) * M_PI/3 + SAFE_RADIUS_PHASE + fmax(0, time - SAFE_RADIUS_DELAY) * SAFE_RADIUS_SPEED)
#define SAFE_RADIUS_PHASE_NORMALIZED(o) (fmod(SAFE_RADIUS_PHASE_FUNC(o) - SAFE_RADIUS_PHASE, 2*M_PI) / (2*M_PI))
#define SAFE_RADIUS_PHASE_NUM(o) ((int)((SAFE_RADIUS_PHASE_FUNC(o) - SAFE_RADIUS_PHASE) / (2*M_PI)))
#define SAFE_RADIUS(o) smoothreclamp(SAFE_RADIUS_BASE + SAFE_RADIUS_STRETCH * sin(SAFE_RADIUS_PHASE_FUNC(o)), SAFE_RADIUS_BASE - SAFE_RADIUS_STRETCH, SAFE_RADIUS_BASE + SAFE_RADIUS_STRETCH, SAFE_RADIUS_MIN, SAFE_RADIUS_MAX)
static void ricci_laser_logic(Laser *l, int t) {
if(t == EVENT_BIRTH) {
// remember maximum radius, start at 0 actual radius
l->args[1] = 0 + creal(l->args[1]) * I;
l->width = 0;
return;
}
if(t == EVENT_DEATH) {
free_ref(l->args[2]);
return;
}
Enemy *e = (Enemy*)REF(l->args[2]);
if(e) {
// attach to baryon
l->pos = e->pos + l->args[3];
}
if(t > 0) {
// expand then shrink radius
l->args[1] = cimag(l->args[1]) * (I + sin(M_PI * t / (l->deathtime + l->timespan)));
l->width = clamp(t / 4.0, 0, 10);
}
return;
static real safe_radius_phase(int time, int baryon_idx) {
return baryon_idx * M_PI / 3 + SAFE_RADIUS_PHASE + fmax(0, time - SAFE_RADIUS_DELAY) * SAFE_RADIUS_PHASE_VELOCITY;
}
static int ricci_proj2(Projectile *p, int t) {
TIMER(&t);
static int phase_num(real phase) {
return (int)((phase - SAFE_RADIUS_PHASE) / M_TAU);
}
AT(EVENT_BIRTH) {
play_sfx("shot3");
}
static real safe_radius(real phase) {
real base = 0.5 * (SAFE_RADIUS_MAX + SAFE_RADIUS_MIN);
real stretch = 0.5 * (SAFE_RADIUS_MAX - SAFE_RADIUS_MIN);
AT(EVENT_DEATH) {
Enemy *e = (Enemy*)REF(p->args[1]);
return base + stretch * 2 * (smooth(0.5 * sin(phase) + 0.5) - 0.5);
}
if(!e) {
return ACTION_ACK;
TASK(ricci_laser, { BoxedEllyBaryons baryons; int baryon_idx; cmplx offset; Color color; int turn_speed; int timespan; }) {
Laser *l = TASK_BIND(create_laser(100+100*I, ARGS.timespan, 60, &ARGS.color, las_circle, NULL, ARGS.turn_speed, 100, 0, 0));
double radius = SAFE_RADIUS_MAX * difficulty_value(0.4, 0.47, 0.53, 0.6);
for(int t = 0; t < l->deathtime + l->timespan; t++) {
EllyBaryons *baryons = ENT_UNBOX(ARGS.baryons);
if(baryons == NULL) {
return;
}
//l->pos = baryons->poss[ARGS.baryon_idx] + ARGS.offset;
l->args[1] = radius ;//* sin(M_PI * t / (real)(l->deathtime + l->timespan));
l->width = 10;//clamp(t / 4.0, 0, 10);
// play_sound_ex("shot3",8, false);
play_sfx("shot_special1");
YIELD;
}
}
double rad = SAFE_RADIUS_MAX * (0.6 - 0.2 * (double)(D_Lunatic - global.diff) / 3);
TASK(ricci_baryon_laser_spawner, { BoxedEllyBaryons baryons; int baryon_idx; cmplx dir; }) {
play_sfx("shot3");
create_laser(p->pos, 12, 60, RGBA(0.2, 1, 0.5, 0), las_circle, ricci_laser_logic, 6*M_PI + 0*I, rad, add_ref(e), p->pos - e->pos);
create_laser(p->pos, 12, 60, RGBA(0.2, 0.4, 1, 0), las_circle, ricci_laser_logic, 6*M_PI + 30*I, rad, add_ref(e), p->pos - e->pos);
create_laser(p->pos, 1, 60, RGBA(1.0, 0.0, 0, 0), las_circle, ricci_laser_logic, -6*M_PI + 0*I, rad, add_ref(e), p->pos - e->pos);
create_laser(p->pos, 1, 60, RGBA(1.0, 0.0, 0, 0), las_circle, ricci_laser_logic, -6*M_PI + 30*I, rad, add_ref(e), p->pos - e->pos);
Projectile *p = TASK_BIND(PROJECTILE(
.proto = pp_ball,
.color = RGBA(0.0, 0.5, 0.1, 0.0),
.flags = PFLAG_NOCOLLISION,
));
free_ref(p->args[1]);
return ACTION_ACK;
int delay = 30;
cmplx offset = 15 * ARGS.dir;
for(int t = 0; t < delay; t++) {
p->pos = NOT_NULL(ENT_UNBOX(ARGS.baryons))->poss[ARGS.baryon_idx] + offset;
YIELD;
}
if(t < 0) {
return ACTION_ACK;
}
Enemy *e = (Enemy*)REF(p->args[1]);
// play_sound_ex("shot3",8, false);
play_sfx("shot_special1");
if(!e) {
return ACTION_DESTROY;
}
double turn_speed = 3*M_TAU/60;
p->pos = e->pos + p->pos0;
INVOKE_TASK(ricci_laser,
.baryons = ARGS.baryons,
.baryon_idx = ARGS.baryon_idx,
.offset = offset,
.color = *RGBA(0.2, 1, 0.5, 0),
.turn_speed = turn_speed,
.timespan = 12
);
INVOKE_TASK(ricci_laser,
.baryons = ARGS.baryons,
.baryon_idx = ARGS.baryon_idx,
.offset = offset,
.color = *RGBA(1, 0, 0, 0),
.turn_speed = -turn_speed,
.timespan = 1
);
if(t > 30)
return ACTION_DESTROY;
INVOKE_TASK_DELAYED(30, ricci_laser,
.baryons = ARGS.baryons,
.baryon_idx = ARGS.baryon_idx,
.offset = offset,
.color = *RGBA(0.2, 0.4, 1, 0),
.turn_speed = turn_speed,
.timespan = 12
);
INVOKE_TASK_DELAYED(30, ricci_laser,
.baryons = ARGS.baryons,
.baryon_idx = ARGS.baryon_idx,
.offset = offset,
.color = *RGBA(1, 0, 0, 0),
.turn_speed = -turn_speed,
.timespan = 1
);
return ACTION_NONE;
kill_projectile(p);
}
static int baryon_ricci(Enemy *e, int t) {
if(t < 0) {
return ACTION_ACK;
}
TASK(ricci_baryons_movement, { BoxedEllyBaryons baryons; BoxedBoss boss; }) {
EllyBaryons *baryons = TASK_BIND(ARGS.baryons);
real baryon_speed = difficulty_value(1.00, 1.25, 1.50, 1.75);
int num = creal(e->args[2])+0.5;
for(int t = 0;; t++) {
baryons->center_pos = NOT_NULL(ENT_UNBOX(ARGS.boss))->pos;
cmplx target = VIEWPORT_W / 2.0 + VIEWPORT_H * I * 2 / 3 + 100 * sin(baryon_speed * t / 200.0) + 25 * I * cos(baryon_speed * t * 3.0 / 500.0);
if(num % 2 == 1) {
GO_TO(e, global.boss->pos,0.1);
} else if(num == 0) {
if(t < 150) {
GO_TO(e, global.plr.pos, 0.1);
baryons->target_poss[0] = global.plr.pos;
} else {
float s = 1.00 + 0.25 * (global.diff - D_Easy);
cmplx d = e->pos - VIEWPORT_W/2-VIEWPORT_H*I*2/3 + 100*sin(s*t/200.)+25*I*cos(s*t*3./500.);
e->pos += -0.5*d/cabs(d);
baryons->target_poss[0] += 0.5 * cnormalize(target - baryons->target_poss[0]);
}
} else {
for(Enemy *reference = global.enemies.first; reference; reference = reference->next) {
if(reference->logic_rule == baryon_ricci && (int)(creal(reference->args[2])+0.5) == 0) {
e->pos = global.boss->pos+(reference->pos-global.boss->pos)*cexp(I*2*M_PI*(1./6*creal(e->args[2])));
for(int i = 1; i < NUM_BARYONS; i++) {
if(i % 2 == 1) {
baryons->target_poss[i] = baryons->center_pos;
} else {
baryons->target_poss[i] = baryons->center_pos + (baryons->poss[0] - baryons->center_pos) * cdir(M_TAU/NUM_BARYONS * i);
}
}
YIELD;
}
int time = global.frames - global.boss->current->starttime;
if(num % 2 == 0 && SAFE_RADIUS_PHASE_NUM(e) > 0) {
TIMER(&time);
float phase = SAFE_RADIUS_PHASE_NORMALIZED(e);
if(phase < 0.55 && phase > 0.15) {
FROM_TO(150,100000,10) {
int c = 3;
cmplx n = cexp(2*M_PI*I * (0.25 + 1.0/c*_i));
PROJECTILE(
.proto = pp_ball,
.pos = 15*n,
.color = RGBA(0.0, 0.5, 0.1, 0.0),
.rule = ricci_proj2,
.args = {
-n,
add_ref(e),
},
.flags = PFLAG_NOCOLLISION,
);
}
}
}
return 1;
}
static int ricci_proj(Projectile *p, int t) {
if(t < 0) {
return ACTION_ACK;
}
TASK(ricci_baryons, { BoxedEllyBaryons baryons; BoxedBoss boss; }) {
TASK_BIND(ARGS.baryons);
if(!global.boss) {
p->prevpos = p->pos;
return ACTION_DESTROY;
}
INVOKE_SUBTASK(ricci_baryons_movement, ARGS.baryons, ARGS.boss);
if(p->type == PROJ_DEAD) {
// p->pos += p->args[0];
p->prevpos = p->pos0 = p->pos;
p->birthtime = global.frames;
p->rule = asymptotic;
p->args[0] = cexp(I*M_PI*2*frand());
p->args[1] = 9;
return ACTION_NONE;
WAIT(150);
for(int t = 0;; t++) {
int time = global.frames - NOT_NULL(ENT_UNBOX(ARGS.boss))->current->starttime;
for(int i = 0; i < NUM_BARYONS; i += 2) {
real phase = safe_radius_phase(time, i);
int num = phase_num(phase);
real phase_norm = fmod(phase, M_TAU) / M_TAU;
if(num > 0 && phase_norm > 0.15 && phase_norm < 0.55) {
int count = 3;
cmplx dir = cdir(M_TAU * (0.25 + 1.0 / count * t));
INVOKE_TASK(ricci_baryon_laser_spawner, ARGS.baryons,
.baryon_idx = i,
.dir = dir
);
}
}
WAIT(10);
}
}
TASK(ricci_proj, { cmplx pos; cmplx velocity; BoxedEllyBaryons baryons; }) {
Projectile *p = TASK_BIND(PROJECTILE(
.proto = pp_ball,
.pos = ARGS.pos,
.color = RGBA(0, 0, 0, 0),
.flags = PFLAG_NOSPAWNEFFECTS | PFLAG_NOCLEAR,
.max_viewport_dist = SAFE_RADIUS_MAX,
));
int time = global.frames-global.boss->current->starttime;
cmplx shift = 0;
p->pos = p->pos0 + p->args[0]*t;
for(int t = 0;; t++) {
cmplx shift = 0;
p->pos = ARGS.pos + ARGS.velocity * t;
double influence = 0;
for(Enemy *e = global.enemies.first; e; e = e->next) {
if(e->logic_rule != baryon_ricci) {
continue;
EllyBaryons *baryons = ENT_UNBOX(ARGS.baryons);
if(baryons == NULL) {
return;
}
int num = creal(e->args[2])+0.5;
double influence = 0;
for(int i = 0; i < NUM_BARYONS; i += 2) {
real base_radius = safe_radius(safe_radius_phase(time, i));
if(num % 2 == 0) {
double radius = SAFE_RADIUS(e);
cmplx d = e->pos-p->pos;
float s = 1.00 + 0.25 * (global.diff - D_Easy);
int gaps = SAFE_RADIUS_PHASE_NUM(e) + 5;
double r = cabs(d)/(1.0-0.15*sin(gaps*carg(d)+0.01*s*time));
double range = 1/(exp((r-radius)/50)+1);
shift += -1.1*(radius-r)/r*d*range;
cmplx d = baryons->poss[i] - p->pos;
real angular_velocity = 0.01 * difficulty_value(1.0, 1.25, 1.5, 1.75);
int gaps = phase_num(safe_radius_phase(time, i)) + 5;
real radius= cabs(d) / (1.0 - 0.15 * sin(gaps * carg(d) + angular_velocity * time));
double range = 1 / (exp((radius - base_radius) / 50) + 1);
shift += -1.1 * (base_radius - radius) / radius * d * range;
influence += range;
}
if(p->type == PROJ_DEAD) {
p->move = move_asymptotic_simple(rng_dir(), 9);
return;
}
p->pos = ARGS.pos + ARGS.velocity * t + shift;
float a = 0.5 + 0.5 * fmax(0, tanh((time - 80) / 100.)) * clamp(influence, 0.2, 1);
a *= fmin(1, t / 20.0f);
p->color.r = 0.5;
p->color.g = 0;
p->color.b = cabs(shift)/20.0;
p->color.a = 0;
p->opacity = a;
YIELD;
}
p->pos = p->pos0 + p->args[0]*t+shift;
p->angle = carg(p->args[0]);
p->prevpos = p->pos;
float a = 0.5 + 0.5 * fmax(0,tanh((time-80)/100.))*clamp(influence,0.2,1);
a *= fmin(1, t / 20.0f);
p->color.r = 0.5;
p->color.g = 0;
p->color.b = cabs(shift)/20.0;
p->color.a = 0;
p->opacity = a;
return ACTION_NONE;
}
void elly_ricci(Boss *b, int t) {
TIMER(&t);
AT(0)
set_baryon_rule(baryon_ricci);
AT(EVENT_DEATH)
set_baryon_rule(baryon_reset);
DEFINE_EXTERN_TASK(stage6_spell_ricci) {
Boss *boss = stage6_elly_init_baryons_attack(&ARGS);
BEGIN_BOSS_ATTACK(&ARGS.base);
int c = 15;
float v = 3;
INVOKE_SUBTASK(ricci_baryons, ARGS.baryons, ENT_BOX(boss));
boss->move = move_towards(BOSS_DEFAULT_GO_POS, 0.03);
int count = 15;
real speed = 3;
int interval = 5;
for(int t = 0;; t++) {
real offset = -VIEWPORT_W/(real)count;
real w = VIEWPORT_W * (1 + 2.0 / count);
GO_TO(b, BOSS_DEFAULT_GO_POS, 0.03);
for(int i = 0; i < count; i++) {
cmplx pos = offset + fmod((i + 0.5 * t) / count, 1) * w + (VIEWPORT_H + 10) * I;
FROM_TO(30, 100000, interval) {
float w = VIEWPORT_W;
float ofs = -1 * w/(float)c;
w *= (1 + 2.0 / c);
for(int i = 0; i < c; i++) {
cmplx pos = ofs + fmod(w/(float)c*(i+0.5*_i),w) + (VIEWPORT_H+10)*I;
PROJECTILE(
.proto = pp_ball,
.pos = pos,
.color = RGBA(0, 0, 0, 0),
.rule = ricci_proj,
.args = { -v*I },
.flags = PFLAG_NOSPAWNEFFECTS | PFLAG_NOCLEAR,
.max_viewport_dist = SAFE_RADIUS_MAX,
);
INVOKE_TASK(ricci_proj, pos, -speed * I, ARGS.baryons);
}
WAIT(interval);
}
}
/* Thank you for visiting Akari danmaku code (tm) */
/* Thank you for visiting Akari danmaku code (tm) rejuvenated by lao */

View file

@ -21,10 +21,10 @@ DECLARE_EXTERN_TASK_WITH_INTERFACE(stage6_spell_kepler, ScytheAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage6_spell_maxwell, ScytheAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage6_spell_eigenstate, BaryonsAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage6_spell_broglie, BaryonsAttack);
DECLARE_EXTERN_TASK_WITH_INTERFACE(stage6_spell_ricci, BaryonsAttack);
void elly_spellbg_toe(Boss*, int);
void elly_curvature(Boss*, int);
void elly_lhc(Boss*, int);
void elly_ricci(Boss*, int);
void elly_theory(Boss*, int);

View file

@ -53,7 +53,7 @@ struct stage6_spells_s stage6_spells = {
},
.spacetime_curvature = {
{12, 13, 14, 15}, AT_Spellcard, "Ricci Sign “Spacetime Curvature”", 50, 80000,
elly_ricci, elly_spellbg_modern, BOSS_DEFAULT_GO_POS, 7
NULL, elly_spellbg_modern, BOSS_DEFAULT_GO_POS, 7, TASK_INDIRECT_INIT(BossAttack, stage6_spell_ricci),
},
.higgs_boson_uncovered = {
{16, 17, 18, 19}, AT_Spellcard, "LHC “Higgs Boson Uncovered”", 75, 60000,