YoumuA bomb tweaks
This commit is contained in:
parent
69079f245a
commit
88931ab316
7 changed files with 84 additions and 17 deletions
19
src/entity.c
19
src/entity.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue