void fight_hit (struct anim *k, struct anim *ke) { if (k->immortal || k->sword_immune) return; if (k->current_lives <= 0) return; if (is_anim_fall (&k->f) || is_kid_stairs (&k->f)) return; place_on_the_ground (&k->f, &k->f.c); k->xf.b = NULL; if (! is_in_fight_mode (k)) k->current_lives = 0; else k->current_lives--; if (! is_guard (ke)) upgrade_skill (&ke->skill, &k->skill, k->total_lives); int d = (k->f.dir == LEFT) ? +1 : -1; struct pos pb; survey (_m, pos, &k->f, NULL, &k->p, NULL); prel (&k->p, &pb, 0, d); if (k->current_lives <= 0 && ! is_strictly_traversable (&pb)) { k->current_lives = 0; k->death_reason = FIGHT_DEATH; ke->alert_cycle = anim_cycle; anim_die (k); } else anim_sword_hit (k); if (is_in_fight_mode (k)) { backoff_from_range (ke, k, ATTACK_RANGE - 20, true, false); get_in_range (ke, k, ATTACK_RANGE - 10, false, false); } k->splash = true; if (k->id == current_kid_id) { mr.flicker = 2; mr.color = get_flicker_blood_color (); play_audio (&harm_audio, NULL, k->id); } else play_audio (&guard_hit_audio, NULL, k->id); }
static bool flow (struct anim *k) { struct pos p; if (k->oaction != kid_drink) k->i = -1, k->wait = 4, k->reverse = false; if (k->i < 14 && ! k->reverse) k->i++; else if (k->wait > 0) k->wait--; else if (k->i == 14 && k->wait == 0) k->reverse = true, k->i = 10; else if (k->i == 10 && k->reverse) k->i = 7; else { kid_normal (k); invalid_pos (&k->item_pos); return false; } if (k->i == 14 && k->wait == 1) switch (k->item) { case EMPTY_POTION: break; case SMALL_LIFE_POTION: increase_kid_current_lives (k); break; case BIG_LIFE_POTION: increase_kid_total_lives (k); break; case SMALL_POISON_POTION: if (k->immortal || k->poison_immune) break; k->current_lives--; k->splash = true; if (k->current_lives == 0) k->death_reason = POTION_DEATH; play_sample (harm_sample, NULL, k->id); if (k->id == current_kid_id) { mr.flicker = 2; mr.color = get_flicker_blood_color (); } break; case BIG_POISON_POTION: if (k->immortal || k->poison_immune) break; k->current_lives = 0; k->splash = true; k->death_reason = POTION_DEATH; play_sample (harm_sample, NULL, k->id); if (k->id == current_kid_id) { mr.flicker = 2; mr.color = get_flicker_blood_color (); } break; case FLOAT_POTION: float_kid (k); break; case FLIP_POTION: if (screen_flags) screen_flags = 0; else { switch (prandom_pos (&k->item_pos, 2)) { case 0: screen_flags ^= ALLEGRO_FLIP_VERTICAL; break; case 1: screen_flags ^= ALLEGRO_FLIP_HORIZONTAL; break; case 2: screen_flags ^= ALLEGRO_FLIP_VERTICAL | ALLEGRO_FLIP_HORIZONTAL; break; } } break; case ACTIVATION_POTION: p.room = 8, p.floor = p.place = 0; activate_con (&p); break; default: break; } select_frame (k, kid_drink_frameset, k->i); if (k->i == 14 && k->wait < 4) k->fo.dx = 0; if (k->i == 10 && k->reverse) k->fo.dx = -2, k->fo.dy = +1; if (k->i == 7 && k->reverse) k->fo.dx = +1; return true; }
void compute_loose_floor_fall (struct loose_floor *l) { int speed = 3 * ++l->i; if (speed > 29) speed = 29; struct frame nf; struct frame_offset fo; fo.b = l->f.b; fo.dx = 0; fo.dy = speed; next_frame (&l->f, &nf, &fo); struct coord mbo_f, mbo_nf; struct pos fpmbo_f, nfpmbo_f, fpmbo_nf, nfpmbo_nf; enum confg fcmbo_f; fcmbo_f = survey (_mbo, posf, &l->f, &mbo_f, &fpmbo_f, &nfpmbo_f)->fg; survey (_mbo, posf, &nf, &mbo_nf, &fpmbo_nf, &nfpmbo_nf); struct pos p; /* hit kid */ int i; for (i = 0; i < anima_nmemb; i++) { struct coord kmt, ambo_f, ambo_nf; struct pos np, kpmt; struct anim *a = &anima[i]; if (is_anim_dead (&a->f) || a->immortal || a->loose_floor_immune) continue; survey (_mt, pos, &a->f, &kmt, &kpmt, &np); coord2room (&mbo_f, kpmt.room, &ambo_f); coord2room (&mbo_nf, kpmt.room, &ambo_nf); if (peq (&nfpmbo_f, &kpmt) && ambo_f.y <= kmt.y && ambo_nf.y >= kmt.y && ! a->hit_by_loose_floor && ! is_kid_hang_or_climb (&a->f) && ! is_kid_fall (&a->f)) { a->hit_by_loose_floor = true; a->splash = true; a->current_lives--; a->uncouch_slowly = true; /* ensure kid doesn't couch in thin air (might occur when hit while jumping, for example) */ place_on_the_ground (&a->f, &a->f.c); play_sample (hit_wall_sample, kpmt.room); alert_guards (&kpmt); if (a->id == current_kid_id) { video_effect.color = get_flicker_blood_color (); start_video_effect (VIDEO_FLICKERING, SECS_TO_VCYCLES (0.1)); } if (a->current_lives <= 0) { a->p = kpmt; anim_die_suddenly (a); a->death_reason = LOOSE_FLOOR_DEATH; } else if (a->type == KID) kid_couch (a); } } /* fall */ if (is_strictly_traversable (&fpmbo_f) || peq (&fpmbo_f, &fpmbo_nf)) { /* the floor hit a rigid structure */ if (is_rigid_con (&fpmbo_nf)) prel (&fpmbo_nf, &p, -1, 0); /* the floor continue to fall */ else { l->f = nf; if (is_strictly_traversable (&fpmbo_nf)) l->p = fpmbo_nf; must_sort = true; return; } /* the floor hit the ground */ } else { struct loose_floor *m; p = fpmbo_f; switch (fcmbo_f) { case LOOSE_FLOOR: /* loose floor isn't ground */ m = loose_floor_at_pos (&fpmbo_f); if (m) m->p.room = -1; must_remove = true; l->f = nf; l->f.b = get_correct_falling_loose_floor_bitmap (dv_broken_floor); l->p = fpmbo_f; l->i = 0; con (&fpmbo_f)->fg = NO_FLOOR; must_sort = true; play_sample (broken_floor_sample, p.room); alert_guards (&p); return; case OPENER_FLOOR: break_opener_floor (&fpmbo_f); break; case CLOSER_FLOOR: break_closer_floor (&fpmbo_f); break; case SPIKES_FLOOR: break_spikes_floor (&fpmbo_f); break; case LEVEL_DOOR: break_level_door (&fpmbo_f); break; default: break; } } /* reach here only if the floor hit a rigid structure or the ground */ if (con (&p)->fg != LEVEL_DOOR) con (&p)->fg = BROKEN_FLOOR; shake_loose_floor_row (&p); l->p.room = -1; must_remove = true; must_sort = true; play_sample (broken_floor_sample, p.room); alert_guards (&p); }
void compute_choppers (void) { size_t i, j; for (i = 0; i < chopper_nmemb; i++) { struct chopper *c = &chopper[i]; if (c->inactive) continue; switch (c->i) { case 0: if (! c->alert) c->alert = ! should_chomp (&c->p); if ((c->wait-- <= 0 && should_chomp (&c->p) && (anim_cycle % CHOPPER_WAIT) == prandom_pos (&c->p, CHOPPER_WAIT - 1)) || c->activate) { c->i++; register_changed_pos (&c->p, CHPOS_CHOPPER); } break; case 1: c->i++; if (c->alert) { alert_guards (&c->p); c->alert = false; } play_sample (chopper_sample, &c->p, -1); register_changed_pos (&c->p, CHPOS_CHOPPER); break; case 2: c->i++; register_changed_pos (&c->p, CHPOS_CHOPPER); break; case 3: c->i++; register_changed_pos (&c->p, CHPOS_CHOPPER); break; case 4: c->i = 0; c->wait = CHOPPER_WAIT; c->activate = false; register_changed_pos (&c->p, CHPOS_CHOPPER); break; } if (c->i != 1 && c->i != 2 ) continue; /* chomp kid */ for (j = 0; j < anima_nmemb; j++) { struct anim *a = &anima[j]; if (a->type == MOUSE || is_anim_fall (&a->f) || a->immortal || a->chopper_immune || (a->action == kid_walk && a->walk != -1)) continue; struct pos pbf, pbb; survey (_bf, pos, &a->f, NULL, &pbf, NULL); survey (_bb, pos, &a->f, NULL, &pbb, NULL); pos2room (&pbf, c->p.room, &pbf); pos2room (&pbb, c->p.room, &pbb); if ((((pbf.room == c->p.room && pbf.floor == c->p.floor) || (pbb.room == c->p.room && pbb.floor == c->p.floor)) && ((a->f.dir == LEFT && pbf.place < c->p.place && pbb.place >= c->p.place) || (a->f.dir == RIGHT && pbf.place >= c->p.place && pbb.place < c->p.place))) && (! is_anim_dead (&a->f) || ! is_anim_chopped (&a->f))) { if (a->type != SKELETON) c->blood = true; a->splash = true; a->p = c->p; a->death_reason = CHOPPER_DEATH; if (a->id == current_kid_id) { mr.flicker = 2; mr.color = get_flicker_blood_color (); } if (a->type == SKELETON) play_sample (skeleton_sample, &c->p, -1); else play_sample (chopped_sample, &c->p, -1); anim_die_chopped (a); } } } }