void ai_spur_trail(Object *o) { if (++o->timer > 20) { o->frame++; if (o->frame >= sprites[o->sprite].nframes) { o->Delete(); return; } } // keep dealing "damage" even once we are dealing 0 damage, // so that the enemy keeps making noise and shaking for as long // as it remains in the beam. if (damage_enemies(o, FLAG_INVULNERABLE)) { o->shot.damage = 0; } }
void aftermove_blade_slash(Object *o) { ANIMATE_FWD(2); if (o->frame >= 4) { o->Delete(); return; } o->x += (o->dir == LEFT) ? -0x400 : 0x400; o->y += 0x400; static const int damage_for_frames[] = { 0, 1, 2, 2, 2 }; o->shot.damage = damage_for_frames[o->frame]; // deal damage to anything we touch. Object *enemy = damage_enemies(o); if (enemy && (enemy->flags & FLAG_INVULNERABLE)) o->Delete(); }
void ai_spur_shot(Object *o) { if (IsBlockedInShotDir(o)) { if (!shot_destroy_blocks(o)) { sound(SND_SHOT_HIT); shot_spawn_effect(o, EFFECT_FISHY); shot_spawn_effect(o, EFFECT_SPUR_HIT); o->Delete(); return; } } Object *enemy; if ((enemy = damage_enemies(o))) { o->shot.damage--; if (o->shot.damage <= 0 || (enemy->flags & FLAG_INVULNERABLE)) { o->Delete(); return; } } if (--o->shot.ttl < 0) { shot_spawn_effect(o, EFFECT_STARPOOF); o->Delete(); return; } spur_spawn_trail(o); }
void ai_missile_shot(Object *o) { int index = o->shot.level + ((o->type == OBJ_SUPERMISSILE_SHOT) ? 3 : 0); MissileSettings *settings = &missile_settings[index]; if (o->state == 0) { o->shot.damage = settings->damage; if (o->shot.level == 2) { // initilize wavey effect if (o->shot.dir == LEFT || o->shot.dir == RIGHT) o->ymark = -0x20; else o->xmark = -0x20; // don't let it explode until the "recoil" effect is over. o->state = STATE_WAIT_RECOIL_OVER; // record position we were fired at (we won't explode until we pass it) o->xmark2 = player->x; o->ymark2 = player->y; } else { o->state = STATE_MISSILE_CAN_EXPLODE; } } // accelerate according to current type and level of missile // don't use LIMITX here as it can mess up recoil of level 3 super missiles switch(o->shot.dir) { case RIGHT: o->xinertia += settings->accel; if (o->xinertia > settings->maxspeed) o->xinertia = settings->maxspeed; break; case LEFT: o->xinertia -= settings->accel; if (o->xinertia < -settings->maxspeed) o->xinertia = -settings->maxspeed; break; case UP: o->yinertia -= settings->accel; if (o->yinertia < -settings->maxspeed) o->yinertia = -settings->maxspeed; break; case DOWN: o->yinertia += settings->accel; if (o->yinertia > settings->maxspeed) o->yinertia = settings->maxspeed; break; } // wavey effect for level 3 // (markx/y is used as a "speed" value here) if (o->shot.level == 2) { if (o->shot.dir == LEFT || o->shot.dir == RIGHT) { o->yinertia += o->ymark; if (o->ymark > 0 && o->yinertia > 0x100) o->ymark = -o->ymark; if (o->ymark < 0 && o->yinertia < -0x100) o->ymark = -o->ymark; } else { o->xinertia += o->xmark; if (o->xmark > 0 && o->xinertia > 0x100) o->xmark = -o->xmark; if (o->xmark < 0 && o->xinertia < -0x100) o->xmark = -o->xmark; } } // check if we hit an enemy // level 3 missiles can not blow up while they are "recoiling" // what we do is first wait until they're traveling in the direction // they're pointing, then wait till they pass the player's original position. switch(o->state) { case STATE_WAIT_RECOIL_OVER: switch(o->shot.dir) { case LEFT: if (o->xinertia <= 0) o->state = STATE_RECOIL_OVER; break; case RIGHT: if (o->xinertia >= 0) o->state = STATE_RECOIL_OVER; break; case UP: if (o->yinertia <= 0) o->state = STATE_RECOIL_OVER; break; case DOWN: if (o->yinertia >= 0) o->state = STATE_RECOIL_OVER; break; } if (o->state != STATE_RECOIL_OVER) break; case STATE_RECOIL_OVER: switch(o->shot.dir) { case LEFT: if (o->x <= o->xmark2-(2<<CSF)) o->state = STATE_MISSILE_CAN_EXPLODE; break; case RIGHT: if (o->x >= o->xmark2+(2<<CSF)) o->state = STATE_MISSILE_CAN_EXPLODE; break; case UP: if (o->y <= o->ymark2-(2<<CSF)) o->state = STATE_MISSILE_CAN_EXPLODE; break; case DOWN: if (o->y >= o->ymark2+(2<<CSF)) o->state = STATE_MISSILE_CAN_EXPLODE; break; } if (o->state != STATE_MISSILE_CAN_EXPLODE) break; case STATE_MISSILE_CAN_EXPLODE: { bool blow_up = false; if (damage_enemies(o)) { blow_up = true; } else { // check if we hit a wall if (o->shot.dir==LEFT && o->blockl) blow_up = true; else if (o->shot.dir==RIGHT && o->blockr) blow_up = true; else if (o->shot.dir==UP && o->blocku) blow_up = true; else if (o->shot.dir==DOWN && o->blockd) blow_up = true; } if (blow_up) { sound(SND_MISSILE_HIT); // create the boom-spawner object for the flashes, smoke, and AoE damage Object *sp = CreateObject(o->CenterX(), o->CenterY(), OBJ_MISSILE_BOOM_SPAWNER); sp->shot.boomspawner.range = settings->boomrange; sp->shot.boomspawner.booms_left = settings->num_booms; sp->shot.damage = settings->boomdamage; o->Delete(); return; } } break; } if (--o->shot.ttl < 0) shot_dissipate(o, EFFECT_STARPOOF); // smoke trails if (++o->timer > 2) { o->timer = 0; Caret *trail = effect(o->CenterX() - o->xinertia, \ o->CenterY() - o->yinertia, EFFECT_SMOKETRAIL); const int trailspd = 0x400; switch(o->shot.dir) { case LEFT: trail->xinertia = trailspd; trail->y -= (2<<CSF); break; case RIGHT: trail->xinertia = -trailspd; trail->y -= (2<<CSF); break; case UP: trail->yinertia = trailspd; trail->x -= (1<<CSF); break; case DOWN: trail->yinertia = -trailspd; trail->x -= (1<<CSF); break; } } }
void ai_blade_l3_shot(Object *o) { switch(o->state) { case STATE_FLYING: { if ((++o->timer % 4) == 1) { Object *slash = CreateObject(o->x, o->y - (12 << CSF), OBJ_BLADE_SLASH); if (++o->timer2 & 1) { slash->dir = LEFT; slash->x += (10 << CSF); } else { slash->dir = RIGHT; slash->x -= (10 << CSF); } sound(SND_SLASH); } if (++o->timer2 > o->shot.ttl) { shot_dissipate(o); return; } // damage enemies and hit walls if (o->timer2 >= 5) { Object *enemy; if ((enemy = damage_enemies(o))) { if (enemy->flags & FLAG_INVULNERABLE) { shot_spawn_effect(o, EFFECT_STARSOLID); sound(SND_SHOT_HIT); o->Delete(); } else { o->x += o->xinertia; o->y += o->yinertia; o->xinertia = 0; o->yinertia = 0; o->state = STATE_AOE; o->frame = 1; o->timer = 0; } } else if (IsBlockedInShotDir(o)) { if (!shot_destroy_blocks(o)) sound(SND_SHOT_HIT); shot_spawn_effect(o, EFFECT_STARSOLID); o->Delete(); } } } break; case STATE_AOE: { if (!random(0, 2)) { Object *slash = CreateObject(o->x + random(-BLADE_AOE, BLADE_AOE), o->y + random(-BLADE_AOE, BLADE_AOE), OBJ_BLADE_SLASH); slash->dir = random(0, 1) ? LEFT : RIGHT; sound(SND_SLASH); } if (++o->timer > 50) o->Delete(); } break; } o->invisible = (o->timer & 1); }