bool is_pos_seeing (struct pos *p0, struct anim *k1, enum dir dir) { struct coord m0, m1, mt1, mb1; struct pos p, p1, pk, pke; con_m (p0, &m0); coord_f cf; if (is_kid_climb (&k1->f) || is_anim_fall (&k1->f)) { coord2room (_mt (&k1->f, &mt1), m0.room, &mt1); coord2room (_m (&k1->f, &m1), m0.room, &m1); coord2room (_mbo (&k1->f, &mb1), m0.room, &mb1); double dt, dm, db; dt = (mt1.room == m0.room) ? dist_coord (&m0, &mt1) : INFINITY; dm = (m1.room == m0.room) ? dist_coord (&m0, &m1) : INFINITY; db = (mb1.room == m0.room) ? dist_coord (&m0, &mb1) : INFINITY; if (dt <= dm && dt <= db) cf = (dir == LEFT) ? _tr : _tl; else if (db <= dt && db <= dm) cf = (dir == LEFT) ? _br : _bl; else cf = (dir == LEFT) ? _mr : _ml; } else cf = (dir == LEFT) ? _mr : _ml; surveyo (cf, -8, +0, pos, &k1->f, &m1, NULL, NULL); coord2room (&m0, p0->room, &m0); coord2room (&m1, p0->room, &m1); pos (&m1, &p1); if (dir == LEFT) { if (is_opaque_at_left (p0)) return false; if (is_opaque_at_right (&p1)) return false; if (peqr (&p1, p0, +0, -1)) return true; prel (p0, &pk, +0, -1); prel (&p1, &pke, +0, +1); } else { if (is_opaque_at_right (p0)) return false; if (is_opaque_at_left (&p1)) return false; if (peqr (&p1, p0, +0, +1)) return true; prel (p0, &pk, +0, +1); prel (&p1, &pke, +0, -1); } if (peq (p0, &p1)) return true; first_confg (&pk, &pke, opaque_cs, &p); return p0->room == p1.room && m1.room == m0.room && p1.floor == p0->floor && ! (dir == LEFT && m1.x > m0.x) && ! (dir == RIGHT && m1.x < m0.x) && p.room == -1; }
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); }
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); } } } }
static bool flow (struct anim *k) { struct pos pmt; bool keep_sword = k->key.down; bool defense = k->key.up && ! k->key.shift && ! k->key.left && ! k->key.right; bool attack = k->key.shift && ! k->key.up && ! k->key.left && ! k->key.right; bool walkf = ((k->f.dir == RIGHT) && k->key.right) || ((k->f.dir == LEFT) && k->key.left); bool walkb = ((k->f.dir == RIGHT) && k->key.left) || ((k->f.dir == LEFT) && k->key.right); struct anim *ke = get_anim_by_id (k->enemy_id); k->keep_sword_fast = (k->enemy_id != -1 && ke->current_lives > 0 && ! is_anim_fall (&ke->f)); if (k->oaction != kid_sword_normal) k->i = -1; if (k->oaction == kid_sword_normal && k->current_lives <= 0) { survey (_mt, pos, &k->f, NULL, &pmt, NULL); k->p = pmt; kid_die (k); return false; } if (k->oaction == kid_sword_normal) { if (keep_sword) { /* keep_sword_fast = true; */ kid_keep_sword (k); return false; } if (defense) { kid_sword_defense (k); return false; } if (attack) { kid_sword_attack (k); return false; } if (walkf) { kid_sword_walkf (k); return false; } if (walkb) { kid_sword_walkb (k); return false; } } k->fo.b = kid_sword_normal_00; k->fo.dx = k->fo.dy = +0; select_xframe (&k->xf, sword_frameset, 13); if (k->f.b == kid_take_sword_frameset[3].frame) k->fo.dx = -4; if (k->f.b == kid_sword_walkf_frameset[1].frame) k->fo.dx = +5; if (k->f.b == kid_sword_walkb_frameset[1].frame) k->fo.dx = +2; k->i++; return true; }
bool is_safe_to_follow (struct anim *k0, struct anim *k1, enum dir dir) { /* not aware of enemy position */ if (! is_valid_pos (&k0->enemy_pos)) return false; struct pos p0, p, p1, pke, pk; survey (_m, pos, &k0->f, NULL, &p0, NULL); survey ((k0->f.dir == LEFT) ? _mr : _ml, pos, &k1->f, NULL, &p1, NULL); pos2room (&p1, p0.room, &p1); /* not reachable, to start with */ if (p0.room != p1.room) return false; if (p0.floor > p1.floor) return false; /* the character went down after the enemy */ if (p0.floor != k0->enemy_pos.floor) { /* enum dir odir = (dir == LEFT) ? RIGHT : LEFT; */ /* if (is_on_back (k0, k1) && is_seeing (k0, k1, odir) */ /* && p0.floor == p1.floor) return true; */ if (is_anim_seeing (k0, k1, LEFT) || is_anim_seeing (k0, k1, RIGHT)) return true; return false; } /* if falling the chasing is inevitable (necessary to prevent leave_fight_logic from forgeting enemy based on the facing direction of the is_in_range check) */ if (is_anim_fall (&k0->f)) return true; if (dir == LEFT) { if (! is_safe_at_left (&p0)) return false; if (! is_safe_at_right (&k0->enemy_pos, &k0->f)) return false; if (peqr (&k0->enemy_pos, &p0, +0, -1)) return true; prel (&p0, &pk, +0, -1); prel (&k0->enemy_pos, &pke, +0, +1); if (is_collidable_at_right (&pk, &k0->f)) return false; } else { if (! is_safe_at_right (&p0, &k0->f)) return false; if (! is_safe_at_left (&k0->enemy_pos)) return false; if (peqr (&k0->enemy_pos, &p0, +0, +1)) return true; prel (&p0, &pk, +0, +1); prel (&k0->enemy_pos, &pke, +0, -1); if (is_collidable_at_right (&p0, &k0->f)) return false; } /* enemy went down */ if (is_traversable (&k0->enemy_pos)) { prel (&k0->enemy_pos, &pke, +1, +0); if (is_traversable (&pke) || fg (&pke) == SPIKES_FLOOR) return false; int d = (dir == LEFT) ? -1 : +1; if (peq (&pk, &k0->enemy_pos)) return true; prel (&k0->enemy_pos, &pke, +0, -1 * d); } else if (peq (&p0, &k0->enemy_pos) && ! (is_anim_seeing (k0, k1, LEFT) || is_anim_seeing (k0, k1, RIGHT))) return false; first_confg (&pk, &pke, dangerous_cs, &p); if (is_valid_pos (&p)) return false; first_confg (&pk, &pke, door_cs, &p); if (! is_valid_pos (&p)) return true; else return door_at_pos (&p)->action == OPEN_DOOR || ! is_collidable_at_right (&p, &k0->f); }
void draw_room_anim_fg_sub (ALLEGRO_BITMAP *bitmap, enum em em, enum vm vm, struct anim *a) { struct pos pm, ptl, ptr, ptl2, ptr2; struct frame *f = &a->f; struct coord c; frame2room (f, room_view, &c); int w = al_get_bitmap_width (f->b); int h = al_get_bitmap_height (f->b); survey (_m, posf, f, NULL, &pm, NULL); survey (_tl, posf, f, NULL, &ptl, NULL); survey (_tr, posf, f, NULL, &ptr, NULL); pos2room (&pm, room_view, &pm); pos2room (&ptl, room_view, &ptl); pos2room (&ptr, room_view, &ptr); survey (_tl, pos, f, NULL, &ptl2, NULL); survey (_tr, pos, f, NULL, &ptr2, NULL); pos2room (&ptl2, room_view, &ptl2); pos2room (&ptr2, room_view, &ptr2); push_clipping_rectangle (bitmap, c.x, c.y, w, h); /* SWORD */ if (fake (&pm) == CARPET && a->f.dir == RIGHT && a->xf.b) { struct coord c2; int w2 = al_get_bitmap_width (a->xf.b); int h2 = al_get_bitmap_height (a->xf.b); xframe_coord (&a->f, &a->xf, &c2); ignore_clipping_rectangle_intersection = true; push_clipping_rectangle (bitmap, c2.x, c2.y, w2, h2); push_drawn_rectangle (bitmap); draw_confg_right (bitmap, &pm, em, vm); redraw_drawn_rectangle (pop_drawn_rectangle (), &pm, em, vm); pop_clipping_rectangle (); ignore_clipping_rectangle_intersection = false; } /* CLIMBING STAIRS */ if (is_kid_stairs (f)) draw_level_door_fg (bitmap, &a->p, f, em, vm); /* FALLING */ if (is_anim_fall (f)) { push_clipping_rectangle (bitmap, PLACE_WIDTH * ptr2.place, PLACE_HEIGHT * ptr2.floor + 56, PLACE_WIDTH + 12, PLACE_HEIGHT - 53); push_drawn_rectangle (bitmap); if (! is_strictly_traversable_fake (&ptr2)) draw_confg (bitmap, &ptr2, em, vm); if (! is_strictly_traversable_fake (&ptr)) draw_confg (bitmap, &ptr, em, vm); redraw_drawn_rectangle (pop_drawn_rectangle (), &ptr2, em, vm); pop_clipping_rectangle (); } /* VERTICAL JUMP */ if (is_kid_vjump_touching_above (f)) { push_clipping_rectangle (bitmap, PLACE_WIDTH * ptl2.place, PLACE_HEIGHT * ptl2.floor + 56, 2 * PLACE_WIDTH, PLACE_HEIGHT - 56 + 3); push_drawn_rectangle (bitmap); draw_confg (bitmap, &ptl2, em, vm); draw_confg (bitmap, &ptr, em, vm); redraw_drawn_rectangle (pop_drawn_rectangle (), &ptl2, em, vm); pop_clipping_rectangle (); } /* HANGING */ if (is_kid_hang (f)) { struct pos p; get_hanged_pos (&a->hang_pos, f->dir, &p); struct pos pb; prel (&p, &pb, +0, f->dir == LEFT ? +1 : -1); pos2room (&p, room_view, &p); pos2room (&pb, room_view, &pb); if (f->dir == RIGHT) { push_clipping_rectangle (bitmap, PLACE_WIDTH * p.place, PLACE_HEIGHT * p.floor + 56, PLACE_WIDTH, PLACE_HEIGHT - 53); push_drawn_rectangle (bitmap); draw_confg (bitmap, &p, em, vm); redraw_drawn_rectangle (pop_drawn_rectangle (), &p, em, vm); } else { push_clipping_rectangle (bitmap, PLACE_WIDTH * pb.place, PLACE_HEIGHT * pb.floor + 56, PLACE_WIDTH, PLACE_HEIGHT - 53); push_drawn_rectangle (bitmap); draw_confg (bitmap, &pb, em, vm); redraw_drawn_rectangle (pop_drawn_rectangle (), &pb, em, vm); } pop_clipping_rectangle (); } /* CLIMBING FLOOR */ if (is_kid_climb (f)) { struct pos p; get_hanged_pos (&a->hang_pos, f->dir, &p); struct pos pb; prel (&p, &pb, +0, f->dir == LEFT ? +1 : -1); pos2room (&p, room_view, &p); pos2room (&pb, room_view, &pb); if (f->dir == RIGHT) { int dy, w; if (f->b == kid_climb_00 || f->b == kid_climb_01 || f->b == kid_climb_02 || f->b == kid_climb_08 || f->b == kid_climb_09) { dy = 55; w = 18; } else if (f->b == kid_climb_05 || f->b == kid_climb_06) { dy = 53; w = 22; } else if (f->b == kid_climb_03 || f->b == kid_climb_07 || f->b == kid_climb_04) { dy = 53; w = 21; } push_clipping_rectangle (bitmap, PLACE_WIDTH * p.place, PLACE_HEIGHT * p.floor + dy, w, PLACE_HEIGHT - dy + 3); push_drawn_rectangle (bitmap); draw_confg (bitmap, &p, em, vm); redraw_drawn_rectangle (pop_drawn_rectangle (), &p, em, vm); } else { push_clipping_rectangle (bitmap, PLACE_WIDTH * pb.place, PLACE_HEIGHT * pb.floor + 54, PLACE_WIDTH, PLACE_HEIGHT - 54 + 3); push_drawn_rectangle (bitmap); draw_confg (bitmap, &pb, em, vm); redraw_drawn_rectangle (pop_drawn_rectangle (), &pb, em, vm); } pop_clipping_rectangle (); } pop_clipping_rectangle (); draw_room_frame_fg (bitmap, em, vm, f); /* xframe */ if (a->xf.b) { struct frame xf; xframe_frame (&a->f, &a->xf, &xf); draw_room_frame_fg (bitmap, em, vm, &xf); } /* splash */ if (a->splash) { struct frame sf; splash_frame (&a->f, &sf); draw_room_frame_fg (bitmap, em, vm, &sf); } }