void ai_proximity_press_vert(Object *o) { switch(o->state) { case 0: { if (pdistlx(8<<CSF) && pdistly2(8<<CSF, 128<<CSF) && \ !o->blockd) { o->state = 10; o->animtimer = 0; o->frame = 1; } } break; case 10: { if (o->frame < 2) ANIMATE_FWD(2); if (o->blockd) { if (o->frame >= 2) // make sure eye fully open { SmokeSide(o, 4, DOWN); quake(10); } o->flags |= FLAG_SOLID_BRICK; o->damage = 0; o->state = 11; o->frame = 0; } else { if (player->Top() > o->CenterY()) { o->flags &= ~FLAG_SOLID_BRICK; o->damage = 127; } else { o->flags |= FLAG_SOLID_BRICK; o->damage = 0; } } } break; } if (o->state >= 5) { o->yinertia += 0x80; LIMITY(0x5ff); } }
void ai_press_vert(Object *o) { switch(o->state) { case 0: { o->state = 1; o->y -= (4 << CSF); if (pdistlx((8<<CSF)) && pdistly2((8<<CSF), (128<<CSF))) { o->state = 5; } } break; case 5: { if (o->blockd) { o->state = 10; o->animtimer = 0; o->frame = 1; } } break; case 10: { ANIMATE_FWD(2); if (o->frame > 2) o->frame = 2; if (player->y > o->y) o->flags |= FLAG_SOLID_BRICK; } break; } }
// used only for purple ones in maze void ai_critter_shooting_purple(Object *o) { switch(o->state) { case 0: o->state = STATE_IDLE; o->damage = CRITTER_DAMAGE; case STATE_IDLE: { o->frame = 0; // assume not at attention if (o->timer >= 8) { if (pdistlx(96<<CSF) && pdistly2(96<<CSF, 32<<CSF)) { FACEPLAYER; // close enough to attack? if (pdistlx(48<<CSF)) { o->state = STATE_PREPARE_JUMP; o->frame = 0; o->timer = 0; } else { // no, but stand at "attention" o->frame = 1; } } } else { o->timer++; } // also attack if shot if (o->shaketime) { o->state = STATE_PREPARE_JUMP; o->frame = 0; o->timer = 0; } } break; case STATE_PREPARE_JUMP: { o->frame = 1; if (++o->timer > 8) { FACEPLAYER; o->state = STATE_JUMP; o->timer = 0; o->frame = 2; sound(SND_ENEMY_JUMP); o->yinertia = -0x5ff; } } break; case STATE_JUMP: { if (o->yinertia > 0x100 || \ (o->blockd && ++o->timer > 16)) // failsafe { o->ymark = o->y; o->state = STATE_HOVER; o->frame = 3; o->timer = 0; o->CurlyTargetHere(60, 100); } } break; case STATE_HOVER: { // sinusoidal hover o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10; LIMITY(0x200); FACEPLAYER; ANIMATE(0, 3, 5); // time to end flight? if (++o->timer > 60 || o->blocku) { o->damage = CRITTER_FALL_DAMAGE; o->state = STATE_END_JUMP; o->frame = 2; break; } if ((o->timer % 4) == 1) sound(SND_CRITTER_FLY); if ((o->timer % 30) == 6) { EmFireAngledShot(o, OBJ_CRITTER_SHOT, 6, 0x600); sound(SND_EM_FIRE); } if (o->blockd) o->yinertia = -0x200; } break; case STATE_END_JUMP: { if (o->blockd) { o->damage = 2; o->xinertia = 0; o->timer = 0; o->frame = 0; o->state = 0; sound(SND_THUD); } } break; } if (o->state != STATE_HOVER) { o->yinertia += 0x20; LIMITY(0x5ff); } }
void ai_bute_sword(Object *o) { if (run_bute_defeated(o, BUTE_HP)) return; switch(o->state) { case 0: { o->flags |= (FLAG_SHOOTABLE | FLAG_INVULNERABLE); o->nxflags |= NXFLAG_FOLLOW_SLOPE; o->damage = 0; o->state = 1; } case 1: // lying in wait { FACEPLAYER; if (pdistlx(128<<CSF) && \ pdistly2(128<<CSF, 16<<CSF)) { o->state = 10; } } break; // wait a moment, then start running at player case 10: { o->flags |= FLAG_INVULNERABLE; o->damage = 0; o->frame = 0; o->state = 11; o->timer = 0; } case 11: { if (++o->timer > 30) { o->state = 20; o->timer = 0; } } break; // run at player and jump case 20: { o->flags &= ~FLAG_INVULNERABLE; o->state = 21; FACEPLAYER; } case 21: { ANIMATE(3, 0, 1); XMOVE(0x400); if (pdistlx(40<<CSF)) { o->xinertia /= 2; o->yinertia = -0x300; o->state = 30; o->frame = 2; // sword back, jumping sound(SND_ENEMY_JUMP); } else if (++o->timer > 50) { // timeout, p got away o->state = 10; o->xinertia = 0; } } break; // jumping up case 30: { if (o->yinertia > -0x80) { o->frame = 3; // sword swipe fwd o->damage = 9; o->state = 31; o->timer = 0; } } break; // swiping sword, in air case 31: { if (++o->timer > 2) { o->timer = 0; o->frame = 4; // sword down, in front } if (o->blockd && o->yinertia > 0) { o->xinertia = 0; o->damage = 3; o->state = 32; o->timer = 0; } } break; case 32: { if (++o->timer > 30) { o->state = 10; o->timer = 0; } } break; } o->yinertia += 0x20; LIMITY(0x5ff); }
void ai_buyobuyo_base(Object *o) { /*if (o->onscreen) { debug("state: %d", o->state); debug("timer: %d", o->timer); debug("timer2: %d", o->timer2); }*/ if (o->state < 3 && o->hp < (1000 - BUYOBUYO_BASE_HP)) { SmokeClouds(o, objprop[o->type].death_smoke_amt, 8, 8); effect(o->CenterX(), o->CenterY(), EFFECT_BOOMFLASH); o->SpawnPowerups(); o->flags &= ~FLAG_SHOOTABLE; o->damage = 0; o->state = 10; o->frame = 2; } switch(o->state) { case 0: { // ceiling has different bounding box and action point if (o->dir == RIGHT) o->sprite = SPR_BUYOBUYO_BASE_CEILING; o->state = 1; o->timer = 10; } case 1: { if (pdistlx(0x14000)) { if ((o->dir == LEFT && pdistly2(0x14000, 0x2000)) || \ (o->dir == RIGHT && pdistly2(0x2000, 0x14000))) { if (--o->timer < 0) { o->state = 2; o->timer = 0; o->animtimer = 0; } } } } break; case 2: { ANIMATE(3, 0, 1); if (++o->timer > 10) { Object *buyo = SpawnObjectAtActionPoint(o, OBJ_BUYOBUYO); buyo->dir = o->dir; sound(SND_EM_FIRE); o->frame = 0; o->CurlyTargetHere(); // cyclic: three firings then pause o->state = 1; if (++o->timer2 > 2) { o->timer = 100; o->timer2 = 0; } else { o->timer = 20; } } } break; } }
void ai_critter(Object *o) { switch(o->state) { case 0: { if (o->type == OBJ_POWER_CRITTER) { // altered physics for Power Critter o->critter.jumpheight = 0x2800; o->critter.jumpgrav = 0x1C; o->critter.falldmg = 12; } else { o->critter.jumpheight = 0; o->critter.jumpgrav = 0x40; o->critter.falldmg = 3; if (o->type == OBJ_CRITTER_HOPPING_BLUE || // first cave o->type == OBJ_CRITTER_HOPPING_GREEN || // egg 1 o->type == OBJ_CRITTER_HOPPING_AQUA || // egg 2 o->type == OBJ_CRITTER_HOPPING_RED) // last cave { o->critter.canfly = false; // critters in egg1 only 2 dmg if (o->type == OBJ_CRITTER_HOPPING_GREEN) o->critter.falldmg = 2; // critters in First Cave don't jump as high if (o->type != OBJ_CRITTER_HOPPING_BLUE) { o->critter.jumpgrav = 0x2C; } } else { // critters are purple in Maze o->sprite = SPR_CRITTER_FLYING_CYAN; o->critter.canfly = true; } } o->state = 1; } //fall thru case 1: { o->frame = 0; if (o->timer >= 8) { int attack_dist = (o->critter.canfly) ? (96 << CSF) : (64 << CSF); // close enough to attack? if (pdistlx(attack_dist) && pdistly2(96<<CSF, 48<<CSF)) { o->state = 2; o->frame = 0; o->timer = 0; } else if (pdistlx(attack_dist + (32<<CSF)) && pdistly2(128<<CSF, 48<<CSF)) { // no, but close enough to look up at "attention" and watch player FACEPLAYER; o->frame = 1; o->timer = 8; // reset timer to stop watching } else { // once a little time has passed stop watching him if he turns his back if ((o->x > player->x && player->dir==LEFT) || \ (o->x < player->x && player->dir==RIGHT)) { if (++o->timer >= 150) { o->frame = 0; o->timer = 8; } } else o->timer = 8; } } else { o->timer++; } if (o->shaketime) { // attack if shot o->state = 2; o->frame = 0; o->timer = 0; } } break; case 2: // start jump { if (++o->timer > 8) { o->state = 3; o->frame = 2; o->yinertia = -1228; sound(SND_ENEMY_JUMP); FACEPLAYER; XMOVE(0x100); } } break; case 3: // jumping { // enter flying phase as we start to come down or // if we hit the ceiling. if (o->yinertia > 0x100 || o->blocku) { // during flight we will sine-wave oscilliate around this position o->ymark = (o->y - o->critter.jumpheight); o->state = 4; o->frame = 3; o->timer = 0; } else { if (o->blockd && o->yinertia >= 0) { // jumped onto a platform before we got to fly--land immediately goto landed; } break; } } // fall-thru case 4: // flying { FACEPLAYER; // time to come down yet? // (come down immediately if we are not one of the flying critters) if (!o->critter.canfly || \ o->blockl || o->blockr || o->blocku || \ ++o->timer > 100) { o->damage = o->critter.falldmg; // increased damage if falls on player o->state = 5; o->frame = 2; o->yinertia /= 2; } else { // run the propeller ANIMATE(0, 3, 5); if ((o->timer & 3)==1) sound(SND_CRITTER_FLY); if (o->blockd) o->yinertia = -0x200; } } break; case 5: // coming down from flight { if (o->blockd) { // landed landed: ; o->damage = 2; // reset to normal damage o->state = 1; o->frame = 0; o->timer = 0; o->xinertia = 0; sound(SND_THUD); } } break; } if (o->state == 4) // flying { // fly towards player o->xinertia += (o->x > player->x) ? -0x20 : 0x20; // sine-wave oscillate o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10; LIMITX(0x200); LIMITY(0x200); } else if (o->state == 3 && o->yinertia < 0) // jumping up { o->yinertia += o->critter.jumpgrav; } else { o->yinertia += 0x40; } LIMITY(0x5ff); }
void ai_bat_hang(Object *o) { switch(o->state) { case 0: o->state = 1; case 1: // hanging and waiting if (!random(0, 100)) { o->state = 2; o->timer = 0; o->frame = 1; } if (pdistlx(0x1000) && pdistly2(0x1000, 0x9000)) { o->frame = 0; o->state = 3; } break; case 2: // blinking if (++o->timer > 8) { o->state = 1; o->frame = 0; } break; case 3: // at attention o->frame = 0; if (o->shaketime || pdistlx(0x2800)) { o->frame = 1; o->animtimer = 0; o->state = 4; o->timer = 0; } break; case 4: // falling o->yinertia += 0x20; LIMITY(0x5ff); o->timer++; if (o->timer > 20 || o->blockd) { if (o->blockd || ((player->y - 0x2000) < o->y)) { // start flying o->animtimer = 0; o->frame = 2; o->state = 5; o->ymark = o->y; if (o->blockd) o->yinertia = -0x200; } } break; case 5: // flying ANIMATE(1, 2, 4); FACEPLAYER; o->xinertia += (o->x > player->x) ? -0x20 : 0x20; o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10; LIMITX(0x200); LIMITY(0x200); if (o->blockd) o->yinertia = -0x200; if (o->blockr) o->yinertia = 0x200; break; } }