void ai_doctor(Object *o) { switch(o->state) { case 10: // he chuckles o->state = 11; o->timer2 = 0; o->frame = 1; o->animtimer = 0; case 11: ANIMATE(6, 0, 1); if (++o->timer2 > 8*6) { o->frame = 0; o->state = 1; } break; case 20: // he rises up and hovers { o->state = 21; o->timer = 0; o->frame = 2; o->ymark = o->y - (32 << CSF); } case 21: { o->yinertia += (o->y > o->ymark) ? -0x20 : 0x20; LIMITY(0x200); } break; case 30: // he teleports away { o->timer = 0; o->frame = 2; o->yinertia = 0; o->state++; } case 31: { if (DoTeleportOut(o, 1)) o->Delete(); } break; case 40: // he teleports in and hovers { o->timer = 0; o->state = 41; o->frame = 2; } case 41: { if (DoTeleportIn(o, 1)) { o->state = 20; o->yinertia = -0x200; } } break; } }
void ai_balrog(Object *o) { bool fall = true; // he is greenish when he first appears in Gum Room if (DoesCurrentStageUseSpriteset(NPCSET_FROG)) o->sprite = SPR_BALROG_GREEN; switch(o->state) { case 0: { o->flags &= ~FLAG_IGNORE_SOLID; o->xinertia = 0; o->balrog.smoking = false; o->frame = 0; randblink(o, 4, 8); } break; case 10: // he jumps and flys away o->xinertia = 0; o->frame = 2; o->timer = 0; o->state++; case 11: { if (++o->timer <= 20) break; o->state++; o->yinertia = -0x800; o->flags |= FLAG_IGNORE_SOLID; } case 12: { fall = false; o->frame = 3; o->yinertia -= 0x10; if (o->y < 0) { o->Delete(); sound(SND_QUAKE); game.quaketime = 30; } } break; // he looks shocked and shakes, then flys away // used when he is "hit by something" case 20: { o->state = 21; o->frame = 5; o->xinertia = 0; o->timer = o->timer2 = 0; SmokeClouds(o, 4, 8, 8); sound(SND_BIG_CRASH); o->balrog.smoking = 1; } case 21: { o->timer2++; o->x += ((o->timer2 >> 1) & 1) ? (1<<CSF) : -(1<<CSF); if (++o->timer > 100) o->state = 10; o->yinertia += 0x20; LIMITY(0x5ff); } break; case 30: // he smiles for a moment o->frame = 6; o->timer = 0; o->state = 31; case 31: if (++o->timer > 100) o->state = o->frame = 0; break; // flashing white (spell casted on him) // this only works in Gum Room before balfrog fight, as the normal // non-greenish spritesheet doesn't include the required frame. case 40: o->state = 41; o->animtimer = 0; o->animframe = 0; case 41: { static const int flash_seq[] = { 5, 7 }; o->animate_seq(1, flash_seq, 2); } break; case 42: o->timer = 0; o->state = 43; case 43: // flashing visibility // (transforming into Balfrog stage boss; // our flashing is interlaced with his) o->timer++; o->invisible = (o->timer & 2) ? false : true; break; case 50: // he faces away o->frame = 8; o->xinertia = 0; break; case 60: // he walks o->state = 61; balrog_walk_init(o); case 61: { balrog_walk_animation(o); XMOVE(0x200); } break; // he is teleported away (looking distressed) // this is when he is sent to Labyrinth at end of Sand Zone case 70: o->xinertia = 0; o->timer = 0; o->frame = 7; o->state++; case 71: if (DoTeleportOut(o, 2)) o->Delete(); break; case 80: // hands up and shakes o->frame = 5; o->state = 81; case 81: { if (++o->timer & 2) o->x += (1 << CSF); else o->x -= (1 << CSF); } break; // fly up and lift Curly & PNPC // (post-Ballos ending scene) case 100: { o->state = 101; o->timer = 0; o->frame = 2; // prepare for jump } case 101: { if (++o->timer > 20) { o->state = 102; o->timer = 0; o->frame = 3; // fly up DeleteObjectsOfType(OBJ_NPC_PLAYER); DeleteObjectsOfType(OBJ_CURLY); CreateObject(0, 0, OBJ_BALROG_PASSENGER, 0, 0, LEFT)->linkedobject = o; CreateObject(0, 0, OBJ_BALROG_PASSENGER, 0, 0, RIGHT)->linkedobject = o; o->yinertia = -0x800; o->flags |= FLAG_IGNORE_SOLID; // so can fly through ceiling fall = false; } } break; case 102: // flying up during escape seq { fall = false; // bust through ceiling int y = ((o->y + (4<<CSF)) >> CSF) / TILE_H; if (y < 35 && y >= 0) { int x = (o->CenterX() >> CSF) / TILE_W; if (map.tiles[x][y] != 0) { // smoke needs to go at the bottom of z-order or you can't // see any of the characters through all the smoke. map_ChangeTileWithSmoke(x, y, 0, 4, false, lowestobject); map_ChangeTileWithSmoke(x-1, y, 0, 4, false, lowestobject); map_ChangeTileWithSmoke(x+1, y, 0, 4, false, lowestobject); megaquake(10, 0); sound(SND_MISSILE_HIT); } } if (o->Bottom() < -(20<<CSF)) { quake(30, 0); o->Delete(); } } break; case 500: // used during Balfrog death scene { fall = false; } break; }