diff --git a/assets-cg/skills/shock.aseprite b/assets-cg/skills/shock.aseprite index cb40bdb..0452b97 100644 Binary files a/assets-cg/skills/shock.aseprite and b/assets-cg/skills/shock.aseprite differ diff --git a/src/aoe.c b/src/aoe.c index 340a9b3..6a49554 100644 --- a/src/aoe.c +++ b/src/aoe.c @@ -69,7 +69,7 @@ entity_t *aoe_make_attack(uint16_t type, entity_t *origin, vec2 dir) } else if(type == AOE_SHOCK) { anim = &anims_skill_shock; - hitbox = (rect){ -fix(17)/16, fix(18)/16, -fix(17)/16, fix(18)/16 }; + hitbox = (rect){ -fix(23)/16, fix(24)/16, -fix(23)/16, fix(24)/16 }; distance = fix(0); rotate = false; plane = HORIZONTAL; @@ -116,7 +116,7 @@ entity_t *aoe_make_attack(uint16_t type, entity_t *origin, vec2 dir) else if(type == AOE_SHOCK) { aoe->data.shock.strength = f->ATK; aoe->data.shock.origin = physical_pos(origin); - aoe->repeat_delay = fix(0.1); + aoe->repeat_delay = fix(0.2); } else if(type == AOE_BULLET) { aoe->data.bullet.strength = f->ATK; @@ -157,6 +157,8 @@ static bool attack_apply(game_t *game, aoe_t *aoe, entity_t *target) if(!target_f) return false; + if(target_f->invulnerability_delay > 0) + return false; /* No friendly fire */ bool origin_is_monster = !aoe->origin ? true : @@ -195,7 +197,8 @@ static bool attack_apply(game_t *game, aoe_t *aoe, entity_t *target) dir.y = target_p->y - aoe->data.shock.origin.y; dir = fnormalize(dir); damage = aoe->data.shock.strength * 3 / 2; - r /= 2; + r /= 4; + fighter_stun(target, fix(0.1)); } else if(aoe->type == AOE_JUDGEMENT) { r = fix(0); diff --git a/src/comp/fighter.c b/src/comp/fighter.c index 26e9032..3da5f1d 100644 --- a/src/comp/fighter.c +++ b/src/comp/fighter.c @@ -4,6 +4,7 @@ #include "enemies.h" #include #include +#include static int instantiate_stat(fixed_t affinity, fixed_t multiplier, int level) { @@ -49,3 +50,15 @@ int fighter_damage(entity_t *e, int base_damage) return damage; } + +void fighter_stun(entity_t *e, fixed_t duration) +{ + fighter_t *f = getcomp(e, fighter); + f->stun_delay = max(f->stun_delay, duration); +} + +void fighter_invulnerability(entity_t *e, fixed_t duration) +{ + fighter_t *f = getcomp(e, fighter); + f->invulnerability_delay = max(f->invulnerability_delay, duration); +} diff --git a/src/comp/fighter.h b/src/comp/fighter.h index 1143780..dc826a4 100644 --- a/src/comp/fighter.h +++ b/src/comp/fighter.h @@ -46,6 +46,10 @@ typedef struct /* Cooldown; positive while waiting, zero when the skill/item is ready */ fixed_t actions_cooldown[5]; + /* Current status effects */ + fixed_t stun_delay; + fixed_t invulnerability_delay; + } fighter_t; /* Initialize fighter's stats by using the provided stat model */ @@ -55,3 +59,9 @@ void fighter_set_stats(fighter_t *f, fighter_stat_model_t const *model, /* Damage entity for that amount of raw strength. Returns actual damage after DES is subtracted, and randomization. */ int fighter_damage(entity_t *e, int base_damage); + +/* Stun the fighter for a specified duration. */ +void fighter_stun(entity_t *e, fixed_t duration); + +/* Make the fighter invulnerable for a specified duration. */ +void fighter_invulnerability(entity_t *e, fixed_t duration); diff --git a/src/comp/mechanical.c b/src/comp/mechanical.c index 02b9395..4558357 100644 --- a/src/comp/mechanical.c +++ b/src/comp/mechanical.c @@ -10,10 +10,13 @@ void mechanical_move(entity_t *e, vec2 direction, fixed_t dt, map_t const *map) { physical_t *p = getcomp(e, physical); mechanical_t *m = getcomp(e, mechanical); + fighter_t *f = getcomp(e, fighter); mechanical_limits_t const *limits = m->limits; direction = fnormalize(direction); + bool stunned = f && f->stun_delay > 0; + /* Determine facing */ int facing = -1; bool horz = abs(direction.x) >= abs(direction.y); @@ -32,7 +35,7 @@ void mechanical_move(entity_t *e, vec2 direction, fixed_t dt, map_t const *map) target.x += fmul(limits->dash_speed, dir.x); target.y += fmul(limits->dash_speed, dir.y); } - if(facing >= 0) { + if(facing >= 0 && !stunned) { /* Walking speed can be directed anywhere, anytime */ target.x += fmul(limits->max_speed, direction.x); target.y += fmul(limits->max_speed, direction.y); @@ -62,7 +65,6 @@ void mechanical_move(entity_t *e, vec2 direction, fixed_t dt, map_t const *map) // TODO ECS: New collision/ejection system based on teleports if(!map_collides(map, new_hitbox)) { - fighter_t *f = getcomp(e, fighter); if(f && f->current_attack && f->attack_follows_movement) { physical_t *attack = getcomp(f->current_attack, physical); attack->x += (new_x - p->x); diff --git a/src/game.c b/src/game.c index 333af90..f2d9a2d 100644 --- a/src/game.c +++ b/src/game.c @@ -376,6 +376,19 @@ void game_update_animations(game_t *g, fixed_t dt) anim_state_update(&g->hud_xp_anim, dt); } +void game_update_effects(game_t *g, fixed_t dt) +{ + for(int i = 0; i < g->entity_count; i++) { + entity_t *e = g->entities[i]; + fighter_t *f = getcomp(e, fighter); + if(!f) + continue; + + f->stun_delay = max(f->stun_delay - dt, fix(0)); + f->invulnerability_delay = max(f->invulnerability_delay - dt, fix(0)); + } +} + void game_update_aoes(game_t *g, fixed_t dt) { for(int i = 0; i < g->entity_count; i++) { diff --git a/src/game.h b/src/game.h index c0e0eac..24c27b5 100644 --- a/src/game.h +++ b/src/game.h @@ -111,6 +111,9 @@ void game_spawn_enemies(game_t *g); /* Update all entities' and effect areas' animations. */ void game_update_animations(game_t *g, fixed_t dt); +/* Update all entities' status ailments and temporary buffs/debuffs */ +void game_update_effects(game_t *g, fixed_t dt); + /* Update all effect areas and apply their effects. */ void game_update_aoes(game_t *g, fixed_t dt); diff --git a/src/main.c b/src/main.c index e4cfda5..cc9011d 100644 --- a/src/main.c +++ b/src/main.c @@ -540,6 +540,7 @@ int main(void) - Weaker but longer-lasting buffs */ game_update_animations(&game, dt); + game_update_effects(&game, dt); game_update_aoes(&game, dt); game_update_particles(&game, dt); // TODO: Kill out-of-bounds entities diff --git a/src/skills.c b/src/skills.c index b683c5d..5f42f96 100644 --- a/src/skills.c +++ b/src/skills.c @@ -1,3 +1,4 @@ +#include #include "skills.h" #include "comp/fighter.h" #include "comp/physical.h" @@ -50,6 +51,7 @@ void skill_use(game_t *game, entity_t *e, int slot, vec2 dir) f->current_attack = aoe; f->attack_follows_movement = true; + fighter_stun(e, fix(0.5)); game_shake(game, 5, fix(0.7)); } else if(skill == AOE_JUDGEMENT) {