YoumuA bomb tweaks

This commit is contained in:
Andrei Alexeyev 2019-01-10 01:56:33 +02:00
parent 69079f245a
commit 88931ab316
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
7 changed files with 84 additions and 17 deletions

View file

@ -176,15 +176,24 @@ DamageResult ent_damage(EntityInterface *ent, const DamageInfo *damage) {
return res;
}
void ent_area_damage(complex origin, float radius, const DamageInfo *damage) {
void ent_area_damage(complex origin, float radius, const DamageInfo *damage, EntityAreaDamageCallback callback, void *callback_arg) {
for(Enemy *e = global.enemies.first; e; e = e->next) {
if(cabs(origin - e->pos) < radius) {
ent_damage(&e->ent, damage);
if(
cabs(origin - e->pos) < radius &&
ent_damage(&e->ent, damage) == DMG_RESULT_OK &&
callback != NULL
) {
callback(&e->entity_interface, e->pos, callback_arg);
}
}
if(global.boss && cabs(origin - global.boss->pos) < radius) {
ent_damage(&global.boss->ent, damage);
if(
global.boss != NULL &&
cabs(origin - global.boss->pos) < radius &&
ent_damage(&global.boss->ent, damage) == DMG_RESULT_OK &&
callback != NULL
) {
callback(&global.boss->entity_interface, global.boss->pos, callback_arg);
}
}

View file

@ -72,6 +72,7 @@ typedef void (*EntityDrawFunc)(EntityInterface *ent);
typedef bool (*EntityPredicate)(EntityInterface *ent);
typedef DamageResult (*EntityDamageFunc)(EntityInterface *target, const DamageInfo *damage);
typedef void (*EntityDrawHookCallback)(EntityInterface *ent, void *arg);
typedef void (*EntityAreaDamageCallback)(EntityInterface *ent, complex ent_origin, void *arg);
#define ENTITY_INTERFACE_BASE(typename) struct { \
OBJECT_INTERFACE(typename); \
@ -134,7 +135,7 @@ void ent_register(EntityInterface *ent, EntityType type) attr_nonnull(1);
void ent_unregister(EntityInterface *ent) attr_nonnull(1);
void ent_draw(EntityPredicate predicate);
DamageResult ent_damage(EntityInterface *ent, const DamageInfo *damage) attr_nonnull(1, 2);
void ent_area_damage(complex origin, float radius, const DamageInfo *damage) attr_nonnull(3);
void ent_area_damage(complex origin, float radius, const DamageInfo *damage, EntityAreaDamageCallback callback, void *callback_arg) attr_nonnull(3);
void ent_hook_pre_draw(EntityDrawHookCallback callback, void *arg);
void ent_unhook_pre_draw(EntityDrawHookCallback callback);

View file

@ -243,7 +243,7 @@ static int reimu_spirit_bomb_orb(Projectile *p, int t) {
double damage = 2000;
double range = 300;
ent_area_damage(p->pos, range, &(DamageInfo){damage, DMG_PLAYER_BOMB});
ent_area_damage(p->pos, range, &(DamageInfo){damage, DMG_PLAYER_BOMB}, NULL, NULL);
stage_clear_hazards_at(p->pos, range, CLEAR_HAZARDS_ALL | CLEAR_HAZARDS_NOW);
int count = 21;

View file

@ -83,7 +83,7 @@ static int reimu_dream_gap_bomb_projectile(Projectile *p, int t) {
// Yes, I know, this is inefficient as hell, but I'm too lazy to write a
// stage_clear_hazards_inside_rectangle function.
stage_clear_hazards_at(p->pos, range, CLEAR_HAZARDS_ALL | CLEAR_HAZARDS_NOW);
ent_area_damage(p->pos, range, &(DamageInfo) { damage, DMG_PLAYER_BOMB });
ent_area_damage(p->pos, range, &(DamageInfo) { damage, DMG_PLAYER_BOMB }, NULL, NULL);
}
return ACTION_NONE;

View file

@ -354,12 +354,45 @@ static void youmu_mirror_shot(Player *plr) {
}
}
static int youmu_split(Enemy *e, int t) {
if(t == EVENT_DEATH) {
return ACTION_ACK;
static void youmu_mirror_bomb_damage_callback(EntityInterface *victim, complex victim_origin, void *arg) {
victim_origin += cexp(I*M_PI*2*frand()) * 15 * frand();
PARTICLE(
.sprite = "blast_huge_halo",
.pos = victim_origin,
.color = RGBA(0.6 + 0.1 * frand(), 0.8, 0.7 + 0.075 * frand(), 0.5 * frand()),
.timeout = 30,
.draw_rule = ScaleFade,
.args = { 0, 0, (0.0 + 0.5*I) },
.layer = LAYER_PARTICLE_HIGH | 0x4,
.angle = frand() * 2 * M_PI,
.flags = PFLAG_REQUIREDPARTICLE,
);
if(global.frames & 2) {
return;
}
if(t == EVENT_DEATH) {
float t = frand();
PARTICLE(
.sprite = "petal",
.pos = victim_origin,
.rule = asymptotic,
.draw_rule = Petal,
.color = RGBA(sin(5*t) * t, cos(5*t) * t, 0.5 * t, 0),
.args = {
sign(nfrand())*(3+t*5*frand())*cexp(I*M_PI*8*t),
5+I,
frand() + frand()*I,
frand() + 360.0*I*frand()
},
.layer = LAYER_PARTICLE_PETAL,
);
}
static int youmu_mirror_bomb_controller(Enemy *e, int t) {
if(t == EVENT_DEATH || t == EVENT_BIRTH) {
return ACTION_ACK;
}
@ -412,17 +445,21 @@ static int youmu_split(Enemy *e, int t) {
);
}
float range = 200;
ent_area_damage(myonpos, range, &(DamageInfo){250, DMG_PLAYER_BOMB});
// roughly matches the shader effect
float bombtime = player_get_bomb_progress(&global.plr, 0);
float envelope = bombtime * (1 - bombtime);
float range = 200 / (1 + pow(0.08 / envelope, 5));
ent_area_damage(myonpos, range, &(DamageInfo) { 200, DMG_PLAYER_BOMB }, youmu_mirror_bomb_damage_callback, e);
stage_clear_hazards_at(myonpos, range, CLEAR_HAZARDS_ALL | CLEAR_HAZARDS_NOW);
return 1;
return ACTION_NONE;
}
static void youmu_mirror_shader(Framebuffer *fb) {
ShaderProgram *shader = r_shader_get("youmua_bomb");
double t = player_get_bomb_progress(&global.plr,0);
double t = player_get_bomb_progress(&global.plr, 0);
r_shader_ptr(shader);
r_uniform_float("tbomb", t);
@ -437,7 +474,7 @@ static void youmu_mirror_shader(Framebuffer *fb) {
static void youmu_mirror_bomb(Player *plr) {
play_sound("bomb_youmu_b");
create_enemy_p(&plr->slaves, MYON->pos, ENEMY_BOMB, NULL, youmu_split, -cexp(I*carg(MYON->args[0])) * 30, 0, 0, 0);
create_enemy_p(&plr->slaves, MYON->pos, ENEMY_BOMB, NULL, youmu_mirror_bomb_controller, -cexp(I*carg(MYON->args[0])) * 30, 0, 0, 0);
}
static void youmu_mirror_init(Player *plr) {

View file

@ -65,6 +65,14 @@ float fapproach_asymptotic(float val, float target, float rate, float epsilon) {
return val + (target - val) * rate;
}
complex capproach_asymptotic(complex val, complex target, double rate, double epsilon) {
if(cabs(val - target) < epsilon || rate >= 1) {
return target;
}
return val + (target - val) * rate;
}
void approach_asymptotic_p(double *val, double target, double rate, double epsilon) {
*val = approach_asymptotic(*val, target, rate, epsilon);
}
@ -73,6 +81,10 @@ void fapproach_asymptotic_p(float *val, float target, float rate, float epsilon)
*val = fapproach_asymptotic(*val, target, rate, epsilon);
}
void capproach_asymptotic_p(complex *val, complex target, double rate, double epsilon) {
*val = capproach_asymptotic(*val, target, rate, epsilon);
}
double psin(double x) {
return 0.5 + 0.5 * sin(x);
}
@ -121,6 +133,11 @@ intmax_t iclamp(intmax_t f, intmax_t lower, intmax_t upper) {
return f;
}
double smoothstep(double edge0, double edge1, double x) {
x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return x * x * (3 - 2 * x);
}
int sign(double x) {
return (x > 0) - (x < 0);
}

View file

@ -18,14 +18,17 @@ intmax_t iclamp(intmax_t, intmax_t, intmax_t) attr_const;
double min(double, double) attr_const;
double max(double, double) attr_const;
double clamp(double, double, double) attr_const;
double smoothstep(double edge0, double edge1, double x) attr_const;
double approach(double v, double t, double d) attr_const;
float fapproach(float v, float t, float d) attr_const;
void approach_p(double *v, double t, double d);
void fapproach_p(float *v, float t, float d);
double approach_asymptotic(double val, double target, double rate, double epsilon) attr_const;
float fapproach_asymptotic(float val, float target, float rate, float epsilon) attr_const;
complex capproach_asymptotic(complex val, complex target, double rate, double epsilon) attr_const;
void approach_asymptotic_p(double *val, double target, double rate, double epsilon);
void fapproach_asymptotic_p(float *val, float target, float rate, float epsilon);
void capproach_asymptotic_p(complex *val, complex target, double rate, double epsilon);
double psin(double) attr_const;
int sign(double) attr_const;
double swing(double x, double s) attr_const;