void ondeath_omega_body(Object *o) { o->flags &= ~FLAG_SHOOTABLE; KillObjectsOfType(OBJ_OMEGA_SHOT); game.stageboss.SetState(OMG_EXPLODING); }
// defeated states--they're all run by the ondeath script. static void run_defeated(Object *o) { // these states are all script-triggered and must be constant. switch (o->state) { // defeated! "gaah" in air case 1000: { o->flags &= ~FLAG_SHOOTABLE; KillObjectsOfType(OBJ_MISERY_RING); SmokeClouds(o, 3, 2, 2); o->xinertia = 0; o->yinertia = 0; o->state = 1001; o->timer = 0; o->frame = 4; o->xmark = o->x; } case 1001: // shake until script tells us otherwise { o->x = o->xmark; if (++o->timer & 2) o->x += (1 * CSFI); } break; case 1010: // fall to ground and do defeated frame: "ergh" { o->yinertia += 10; if (o->blockd) { o->frame = 7; o->state = 1011; } } break; } }
void XBoss::Run() { Object *o = mainobject; int i; if (!mainobject) return; if (o->state == 0 || (!X.initilized && o->state != STATE_X_APPEAR)) { o->hp = 1; o->x = -(Graphics::SCREEN_WIDTH << CSF); return; } switch(o->state) { // script triggered us to initilize/appear // (there is a hvtrigger, right before player first walks by us // and sees us inactive, which sends us this ANP). case STATE_X_APPEAR: { if (!X.initilized) { Init(); X.initilized = true; } } break; // script has triggered the fight to begin case STATE_X_FIGHT_BEGIN: { o->timer = 0; o->state++; } case STATE_X_FIGHT_BEGIN+1: { if (++o->timer > 100) { FACEPLAYER; o->timer = 0; o->state = STATE_X_TRAVEL; } } break; // starts the treads and moves us in the currently-facing direction case STATE_X_TRAVEL: { // count number of times we've traveled, we brake // and attack every third time. o->timer2++; o->timer = 0; o->state++; } case STATE_X_TRAVEL+1: { o->timer++; // trigger the treads to start moving, // and put them slightly out of sync with each-other. for(int i=0;i<4;i++) { if (o->timer == tread_turnon_times[i]) { treads[i]->state = STATE_TREAD_RUN; treads[i]->dir = o->dir; } } if (o->timer > 120) { // time to attack? we attack every 3rd travel // if so skid to a stop, that's the first step. if (o->timer2 >= 3) { o->timer2 = 0; o->dir ^= 1; o->state = STATE_X_BRAKE; o->timer = 0; } else { // passed player? skid and turn around. if ((o->dir == RIGHT && o->x > player->x) || \ (o->dir == LEFT && o->x < player->x)) { o->dir ^= 1; o->state = STATE_X_TRAVEL; } } } } break; // skidding to a stop in preparation to attack case STATE_X_BRAKE: { o->timer = 0; o->state++; } case STATE_X_BRAKE+1: { o->timer++; // trigger the treads to start braking, // and put them slightly out of sync with each-other. for(int i=0;i<4;i++) { if (o->timer == tread_turnon_times[i]) { treads[i]->state = STATE_TREAD_BRAKE; treads[i]->dir = o->dir; } } if (o->timer > 50) { o->state = STATE_X_OPEN_DOORS; o->timer = 0; } } break; // doors opening to attack case STATE_X_OPEN_DOORS: { o->timer = 0; o->savedhp = o->hp; // select type of attack depending on where we are in the battle if (!AllTargetsDestroyed()) { SetStates(doors, 2, STATE_DOOR_OPENING); o->state = STATE_X_FIRE_TARGETS; } else { SetStates(doors, 2, STATE_DOOR_OPENING_PARTIAL); o->state = STATE_X_FIRE_FISHIES; } } break; // firing targets (early battle) case STATE_X_FIRE_TARGETS: { if (doors[0]->state == STATE_DOOR_FINISHED) { doors[0]->state = 0; SetStates(targets, 4, STATE_TARGET_FIRE); } if (++o->timer > 300 || AllTargetsDestroyed()) { o->state = STATE_X_CLOSE_DOORS; o->timer = 0; } } break; // firing fishy missiles (late battle) case STATE_X_FIRE_FISHIES: { if (doors[0]->state == STATE_DOOR_FINISHED) { doors[0]->state = 0; SetStates(fishspawners, 4, STATE_FISHSPAWNER_FIRE); internals->flags |= FLAG_SHOOTABLE; } if (++o->timer > 300 || (o->savedhp - o->hp) > 200) { o->state = STATE_X_CLOSE_DOORS; o->timer = 0; } } break; // doors closing after attack case STATE_X_CLOSE_DOORS: { o->timer = 0; o->state++; SetStates(doors, 2, STATE_DOOR_CLOSING); } case STATE_X_CLOSE_DOORS+1: { if (doors[0]->state == STATE_DOOR_FINISHED) { doors[0]->state = 0; // just turn off everything for both types of attacks; // turning off the attack type that wasn't enabled isn't harmful. SetStates(targets, 4, 0); SetStates(fishspawners, 4, 0); internals->flags &= ~FLAG_SHOOTABLE; } if (++o->timer > 50) { FACEPLAYER; o->state = STATE_X_TRAVEL; o->timer = 0; } } break; // exploding case STATE_X_EXPLODING: { SetStates(fishspawners, 4, 0); KillObjectsOfType(OBJ_X_FISHY_MISSILE); StartScript(1000); o->timer = 0; o->state++; } case STATE_X_EXPLODING+1: { game.quaketime = 2; o->timer++; if ((o->timer % 8) == 0) sound(SND_ENEMY_HURT_BIG); SmokePuff(o->CenterX() + (random(-72, 72) << CSF), o->CenterY() + (random(-64, 64) << CSF)); if (o->timer > 100) { starflash.Start(o->CenterX(), o->CenterY()); sound(SND_EXPLOSION1); o->timer = 0; o->state++; } } break; case STATE_X_EXPLODING+2: { game.quaketime = 40; if (++o->timer > 50) { CreateObject(o->x, o->y - (24 << CSF), OBJ_X_DEFEATED); DeleteMonster(); return; } } break; } // call AI for all tread pieces for(i=0;i<4;i++) { run_tread(i); run_fishy_spawner(i); } }
void ai_ma_pignon(Object *o) { /*debug("state: %d", o->state); debug("timer: %d", o->timer); debug("timer2: %d", o->timer2); debug("timer3: %d", o->timer3); debug("xinertia: %d", o->xinertia); debug("yinertia: %d", o->yinertia); debug("frame: %d", o->frame); */ switch(o->state) { case 0: { o->SnapToGround(); o->state = 1; } case 1: { FACEPLAYER; o->frame = 0; randblink(o); } break; case MP_Fight_Start: // set by script { o->state = MP_BaseState; o->timer = 0; o->timer2 = 0; o->flags |= FLAG_SHOOTABLE; } case MP_BaseState: { FACEPLAYER; o->damage = 1; o->frame = 0; if (++o->timer > 4) { o->timer = 0; o->state = MP_Jump; if (++o->timer3 > 12) { o->timer3 = 0; o->state = MP_CloneAttack; } } } break; case MP_Jump: // pause a moment and jump { o->frame = 2; if (++o->timer > 4) { o->state = MP_In_Air; o->frame = 3; o->xinertia = random(-0x400, 0x400); o->yinertia = -0x800; sound(SND_ENEMY_JUMP); o->timer2++; } } break; case MP_In_Air: // jumping or falling after clone attack { o->yinertia += 0x80; // for when falling back onscreen after clone attack if (o->y > (8 * TILE_H) << CSF) o->flags &= ~FLAG_IGNORE_SOLID; else o->blockd = false; // bounce off walls if ((o->blockl && o->xinertia < 0) || \ (o->blockr && o->xinertia > 0)) { o->xinertia = -o->xinertia; } FACEPLAYER; // select frame if (o->yinertia < -0x200) { o->frame = 3; } else if (o->yinertia > 0x200) { o->frame = 4; } else { o->frame = 0; } if (o->blockd && o->yinertia > 0) { o->state = MP_Landed; o->timer = 0; o->frame = 2; o->xinertia = 0; } if (o->timer2 > 4) { if (player->y < (o->y + 0x800)) { o->state = MP_ChargeAttack; o->timer = 0; o->xinertia = 0; o->yinertia = 0; } } } break; case MP_Landed: { o->frame = 2; if (++o->timer > 4) { o->state = MP_BaseState; } } break; case MP_ChargeAttack: // charge attack { o->frame = 5; if (++o->timer > 10) { o->state = MP_ChargeAttack+1; o->frame = 6; XMOVE(0x5ff); sound(SND_FUNNY_EXPLODE); o->flags &= ~FLAG_SHOOTABLE; o->flags |= FLAG_INVULNERABLE; o->damage = 10; } } break; case MP_ChargeAttack+1: // in-air during charge attack { ANIMATE(0, 6, 7); if ((o->xinertia < 0 && o->blockl) || \ (o->xinertia > 0 && o->blockr)) { o->state = MP_Hit_Wall; } } break; case MP_Hit_Wall: // hit wall { o->state++; o->timer = 0; quake(16); } case MP_Hit_Wall+1: { o->damage = 4; ANIMATE(0, 6, 7); if ((++o->timer % 6) == 0) { int x = (random(4, 16) * TILE_W) << CSF; CreateObject(x, (16 << CSF), OBJ_MA_PIGNON_ROCK); } if (o->timer > 30) { o->timer2 = 0; o->state = MP_In_Air; o->flags |= FLAG_SHOOTABLE; o->flags &= ~FLAG_INVULNERABLE; o->damage = 3; } } break; case MP_CloneAttack: // begin clone-attack sequence { o->state++; o->frame = 9; FACEPLAYER; } case MP_CloneAttack+1: // walk at player before attack { ANIMATE(0, 9, 11); XMOVE(0x400); if (pdistlx(3 << CSF)) { o->state = MP_Fly_Up; o->timer = 0; o->frame = 2; o->xinertia = 0; } } break; case MP_Fly_Up: // jump and fly up for clone attack { o->frame = 2; if (++o->timer > 4) { o->state++; o->frame = 12; o->yinertia = -0x800; sound(SND_FUNNY_EXPLODE); o->flags |= FLAG_IGNORE_SOLID; o->flags &= ~FLAG_SHOOTABLE; o->flags |= FLAG_INVULNERABLE; o->damage = 10; } } break; case MP_Fly_Up+1: // flying up { ANIMATE(0, 12, 13); if (o->y < (16<<CSF)) o->state = MP_Spawn_Clones; } break; case MP_Spawn_Clones: // offscreen, spawning clones { o->yinertia = 0; o->state++; o->timer = 0; quake(10); } case MP_Spawn_Clones+1: { ANIMATE(0, 12, 13); if ((++o->timer % 6) == 0) { int x = (random(4, 16) * TILE_W) << CSF; CreateObject(x, (16 << CSF), OBJ_MA_PIGNON_CLONE); } if (o->timer > 30) { o->timer2 = 0; o->state = MP_In_Air; // fall back down to ground o->flags |= FLAG_SHOOTABLE; o->flags &= ~FLAG_INVULNERABLE; } } break; case MP_Defeated: // defeated -- set by script { KillObjectsOfType(OBJ_MA_PIGNON_CLONE); o->flags &= ~FLAG_SHOOTABLE; o->state++; o->timer = 0; o->frame = 8; o->damage = 0; } case MP_Defeated+1: { o->yinertia += 0x20; if (o->blockd) { o->xinertia *= 7; o->xinertia /= 8; } o->display_xoff = (++o->timer & 1); } break; } // ma pignon is invulnerable to missiles and Blade. if (o->state >= MP_Fight_Start && o->state < MP_Defeated) { // ....he's invulnerable anyway during these two states so don't mess with that. if (o->state != MP_ChargeAttack+1 && o->state != MP_Fly_Up+1) { bool found_weapons = false; if (o->type != OBJ_MA_PIGNON_CLONE) { Object *c; FOREACH_OBJECT(c) { if (c->type == OBJ_MISSILE_SHOT || \ c->type == OBJ_SUPERMISSILE_SHOT || \ c->type == OBJ_MISSILE_BOOM_SPAWNER || \ c->type == OBJ_BLADE12_SHOT || \ c->type == OBJ_BLADE3_SHOT || \ c->type == OBJ_BLADE_SLASH) { found_weapons = true; break; } } } if (found_weapons) { o->flags &= ~FLAG_SHOOTABLE; o->flags |= FLAG_INVULNERABLE; } else { o->flags |= FLAG_SHOOTABLE; o->flags &= ~FLAG_INVULNERABLE; } }
void IronheadBoss::Run(void) { if (!o) return; switch(o->state) { case IRONH_SPAWN_FISHIES: { o->timer = 0; o->state++; } case IRONH_SPAWN_FISHIES+1: // wave of fishies comes in { if (++o->timer > 50) { o->timer = 0; o->state = IRONH_SWIM; } if ((o->timer & 3)==0) { CreateObject((random(15, 18) * TILE_W) << CSF, \ (random(ARENA_TOP, ARENA_BOTTOM) * TILE_H) << CSF, \ OBJ_IRONH_FISHY); } } break; case IRONH_SWIM: // swimming attack { o->state++; if (o->dir==RIGHT) { // coming up on player from left o->x = 0x1e000; o->y = player->y; } else { // returning from right side of screen o->x = 0x5a000; o->y = (random(ARENA_TOP, ARENA_BOTTOM) * TILE_H) << CSF; } o->xmark = o->x; o->ymark = o->y; o->yinertia = random(-0x200, 0x200); o->xinertia = random(-0x200, 0x200); o->flags |= FLAG_SHOOTABLE; } case IRONH_SWIM+1: { ANIMATE(2, 0, 7); if (o->dir==RIGHT) { o->xmark += 0x400; } else { o->xmark -= 0x200; o->ymark += (o->ymark < player->y) ? 0x200: -0x200; } //debugXline(o->xmark, 255,0,0); //debugYline(o->ymark, 0,255,0); o->xinertia += (o->x > o->xmark) ? -8 : 8; o->yinertia += (o->y > o->ymark) ? -8 : 8; LIMITY(0x200); if (o->dir==RIGHT) { if (o->x > 0x5a000) { o->dir = LEFT; o->state = IRONH_SPAWN_FISHIES; } } else { if (o->x < 0x22000) { o->dir = RIGHT; o->state = IRONH_SPAWN_FISHIES; } } if (o->dir==LEFT) { // fire bullets at player when retreating switch(++o->timer) { case 300: case 310: case 320: { Object *shot = SpawnObjectAtActionPoint(o, OBJ_IRONH_SHOT); shot->xinertia = (random(-3, 0) << CSF); shot->yinertia = (random(-3, 3) << CSF); sound(SND_EM_FIRE); } break; } } } break; case IRONH_DEFEATED: { sound(SND_EXPL_SMALL); o->state = IRONH_DEFEATED+1; o->flags &= ~FLAG_SHOOTABLE; o->frame = 8; o->damage = 0; o->xmark = o->x; o->ymark = o->y; o->xinertia = o->yinertia = 0; o->timer = 0; KillObjectsOfType(OBJ_IRONH_FISHY); KillObjectsOfType(OBJ_IRONH_BRICK); KillObjectsOfType(OBJ_BRICK_SPAWNER); game.quaketime = 20; for(int i=0;i<32;i++) ironh_smokecloud(o); } case IRONH_DEFEATED+1: // retreat back to left... { o->xmark -= (1<<CSF); o->x = o->xmark + (random(-1, 1) << CSF); o->y = o->ymark + (random(-1, 1) << CSF); o->timer++; if ((o->timer & 3)==0) ironh_smokecloud(o); } break; } // show pink "hit" frame when he's taking damage o->sprite = SPR_IRONH; if (o->shaketime) { this->hittimer++; if (this->hittimer & 2) { o->sprite = SPR_IRONH_HURT; } } else { this->hittimer = 0; } }