void redraw_drawn_rectangle (struct drawn_rectangle *dr, struct pos *p, enum em em, enum vm vm) { if (dr->w <= 0 || dr->h <= 0) return; push_clipping_rectangle (dr->bitmap, dr->x, dr->y, dr->w, dr->h); struct coord tl, br; new_coord (&tl, &global_level, room_view, dr->x, dr->y); new_coord (&br, &global_level, room_view, dr->x + dr->w - 1, dr->y + dr->h - 1); struct pos ptl, pbr; posf (&tl, &ptl); posf (&br, &pbr); pos2room (&ptl, room_view, &ptl); pos2room (&pbr, room_view, &pbr); struct pos p0 = ptl; for (p0.floor = pbr.floor; p0.floor >= ptl.floor; p0.floor--) for (p0.place = ptl.place; p0.place <= pbr.place; p0.place++) if (! peq (&p0, p)) draw_confg (dr->bitmap, &p0, em, vm); pop_clipping_rectangle (); }
static bool flow (struct anim *k) { struct coord nc; struct pos np, pm, ptf; if (k->oaction != kid_jump) k->i = -1, k->misstep = k->hang = false; bool hang_front = ((k->f.dir == LEFT) ? k->key.left : k->key.right) && ! k->key.up && k->key.shift; bool hang_back = ((k->f.dir == LEFT) ? k->key.right : k->key.left) && ! k->key.up && k->key.shift; int back_dir = (k->f.dir == LEFT) ? RIGHT : LEFT; /* hang front */ survey (_m, pos, &k->f, &nc, &pm, &np); survey (_tf, pos, &k->f, &nc, &ptf, &np); if (k->i >= 8 && k->i <= 10 && hang_front && (is_hangable_pos (&pm, k->f.dir) || is_hangable_pos (&ptf, k->f.dir))) { if (is_hangable_pos (&pm, k->f.dir)) k->hang_pos = pm; else if (is_hangable_pos (&ptf, k->f.dir)) k->hang_pos = ptf; pos2room (&k->hang_pos, k->f.c.room, &k->hang_pos); k->hang = true; play_sample (hang_on_fall_sample, k->f.c.room); kid_hang (k); return false; } /* hang back */ survey (_tf, pos, &k->f, &nc, &ptf, &np); if (k->i >= 8 && k->i <= 10 && hang_back && is_hangable_pos (&ptf, back_dir)) { k->hang_pos = ptf; pos2room (&k->hang_pos, k->f.c.room, &k->hang_pos); k->hang = true; play_sample (hang_on_fall_sample, k->f.c.room); kid_turn (k); return false; } if (k->i == 17) { kid_normal (k); return false; } select_frame (k, kid_jump_frameset, k->i + 1); if (k->f.b == kid_stabilize_frameset[0].frame) k->fo.dx = +2; if (k->f.b == kid_stabilize_frameset[1].frame) k->fo.dx = +6; if (k->f.b == kid_stabilize_frameset[2].frame) k->fo.dx = +4; if (k->f.b == kid_stabilize_frameset[3].frame) k->fo.dx = +0; return true; }
bool is_pos_on_back (struct anim *k, struct pos *p) { struct pos pm, pv; survey (_m, pos, &k->f, NULL, &pm, NULL); pos2room (p, pm.room, &pv); return pm.room == pv.room && ((k->f.dir == LEFT && pv.place > pm.place) || (k->f.dir == RIGHT && pv.place < pm.place)); }
struct frame * place_frame (struct frame *f, struct frame *nf, ALLEGRO_BITMAP *b, struct pos *p, int dx, int dy) { struct pos pv; *nf = *f; pos2room (p, f->c.room, &pv); nf->b = b; new_coord (&nf->c, pv.l, pv.room, PLACE_WIDTH * pv.place + dx, PLACE_HEIGHT * pv.floor + dy); return nf; }
bool is_in_range (struct anim *k0, struct anim *k1, int r) { struct coord m0, m1; struct pos p0, p1; survey (_m, pos, &k0->f, &m0, &p0, NULL); survey (_m, pos, &k1->f, &m1, &p1, NULL); coord2room (&m1, m0.room, &m1); pos2room (&p1, p0.room, &p1); return m1.room == m0.room && p1.floor == p0.floor && abs (m1.x - m0.x) < r; }
struct pos * get_new_rel_pos (struct pos *old_src, struct pos *old_dest, struct pos *new_src, struct pos *new_dest) { struct pos nold_src; npos (old_src, &nold_src); struct pos nold_dest; npos (old_dest, &nold_dest); struct pos nnew_src; npos (new_src, &nnew_src); pos2room (&nold_dest, nold_src.room, &nold_dest); if (nold_dest.room != nold_src.room) return invalid_pos (new_dest); new_pos (new_dest, nnew_src.l, nnew_src.room, nnew_src.floor + (nold_dest.floor - nold_src.floor), nnew_src.place + (nold_dest.place - nold_src.place)); return npos (new_dest, new_dest); }
void loose_floor_fall_debug (void) { int i; for (i = 0; i < loose_floor_nmemb; i++) { struct loose_floor *l = &loose_floor[i]; if (l->action != FALL_LOOSE_FLOOR) continue; struct pos pv; pos2room (&l->p, room_view, &pv); struct coord cv; coord2room (&l->f.c, room_view, &cv); printf ("(%i,%i,%i) == (%i,%i,%i) <%i,%i,%i> <%i,%i,%i> ? %i ? %i\n", l->p.room, l->p.floor, l->p.place, pv.room, pv.floor, pv.place, l->f.c.room, l->f.c.x, l->f.c.y, cv.room, cv.x, cv.y, peq (&l->p, &pv), cpos (&l->p, &pv)); draw_falling_loose_floor (screen, &loose_floor[i].p, em, vm); } }
void fight_turn_controllable (struct anim *k) { int d = INT_MAX; int t; /* threshold */ struct anim *ke = NULL; struct anim *ke0 = get_anim_by_id (k->enemy_id); /* make the kid target the nearest enemy targeting him */ int i; for (i = 0; i < anima_nmemb; i++) { struct anim *a = &anima[i]; if (a->enemy_id != k->id || ! is_fightable_anim (a)) continue; int de = dist_enemy (a); if (de < d) { d = de; ke = a; } } if (ke && ke0 && ke->f.dir != ke0->f.dir) t = 20; else t = -1; if (ke && abs (dist_enemy (k) - d) > t) consider_enemy (k, ke); ke = get_anim_by_id (k->enemy_id); if (ke) { struct pos p, pe; survey (_m, pos, &k->f, NULL, &p, NULL); survey (_m, pos, &ke->f, NULL, &pe, NULL); pos2room (&pe, p.room, &pe); if (is_on_back (k, ke) && ! is_in_range (k, ke, INVERSION_RANGE) && is_in_fight_mode (k) && is_in_fight_mode (ke) && p.room == pe.room && p.floor == pe.floor) fight_turn (k); } }
bool is_hearing (struct anim *k0, struct anim *k1) { struct pos p0, p1; 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); return p1.room == p0.room && (is_kid_run (&k1->f) || is_kid_stop_run (&k1->f) || is_kid_jump_landing (&k1->f) || is_kid_run_jump_running (&k1->f) || is_kid_run_jump_landing (&k1->f) || (is_kid_couch (&k1->f) && k1->fall) || k1->action == kid_take_sword); }
static bool flow (struct anim *k) { struct coord nc; struct pos np, ptf, pbf; enum confg ctf; if (k->oaction != kid_couch) { k->i = -1; k->fall = k->collision = k->misstep = false; k->wait = 0; } if (k->uncouch_slowly) { k->wait = 36; k->uncouch_slowly = false; } if (k->oaction == kid_climb) k->i = 10; if (k->oaction == kid_couch_collision) k->collision = true, k->inertia = k->cinertia = 0; if (k->oaction == kid_fall) { k->fall = true; k->inertia = k->cinertia = 0; } /* if (k->i > 2 && k->hit_by_loose_floor) */ /* k->i = -1; */ /* unclimb */ int dir = (k->f.dir == LEFT) ? +1 : -1; ctf = survey (_tf, pos, &k->f, &nc, &ptf, &np)->fg; survey (_bf, pos, &k->f, &nc, &pbf, &np); struct pos ph; prel (&pbf, &ph, +1, dir); if (k->i == -1 && ! k->collision && ! k->fall && ! k->hit_by_loose_floor && k->item_pos.room == -1 && is_hangable_pos (&ph, k->f.dir) && dist_next_place (&k->f, _tf, pos, 0, true) <= 27 && ! (ctf == DOOR && k->f.dir == LEFT && door_at_pos (&ptf)->i > DOOR_CLIMB_LIMIT)) { pos2room (&ph, k->f.c.room, &k->hang_pos); kid_unclimb (k); return false; } if (k->i == 12) { k->hit_by_loose_floor = false; kid_normal (k); return false; } if (k->i == 2 && k->item_pos.room != -1 && ! k->collision && ! k->fall) { if (is_potion (&k->item_pos)) kid_drink (k); else if (is_sword (&k->item_pos)) kid_raise_sword (k); else { k->item_pos.room = -1; goto no_item; } return false; } no_item: if (k->i == 2 && k->key.down && k->cinertia == 0 && k->wait-- <= 0 && ((k->f.dir == LEFT && k->key.left) || (k->f.dir == RIGHT && k->key.right))) { k->i = 0; select_frame (k, kid_couch_frameset, 0); return true; } if (k->i != 2 || (! k->key.down && k->wait-- <= 0)) k->i++; if (k->i == 1 && k->wait > 0 && ((k->fall == true && k->hurt) || k->hit_by_loose_floor)) k->i = 2; select_frame (k, kid_couch_frameset, k->i); if (k->oaction == kid_climb) k->fo.dx += 7; if (k->i > 0 && k->i < 3) k->fo.dx -= k->cinertia; if (k->cinertia > 0) k->cinertia--; return true; }
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); } } } }
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 leave_fight_logic (struct anim *k) { /* dead character doesn't fight */ if (k->current_lives <= 0) { k->enemy_refraction = 0; forget_enemy (k); return; } /* non-fightable characters don't fight */ if (! is_fightable_anim (k)) return; /* no enemy, no need to forget */ if (k->enemy_id == -1) return; /* non-fighter doesn't fight */ if (! k->fight) return; /* character that went upstairs doesn't fight */ if (is_kid_stairs (&k->f)) { k->enemy_refraction = 0; forget_enemy (k); return; } /* who's the enemy? */ struct anim *ke = get_anim_by_id (k->enemy_id); /* if the enemy doesn't exist, forget about it */ if (! ke) { k->enemy_refraction = 0; forget_enemy (k); return; } /* if the enemy is dead no need to worry about him */ if (ke->current_lives <= 0) { k->enemy_refraction = 0; forget_enemy (k); return; } /* if the enemy went up stairs, forget about him */ if (is_kid_stairs (&ke->f)) { k->enemy_refraction = 0; forget_enemy (k); return; } /* if the enemy is not reachable, forget about him */ enum dir odir = (k->f.dir == LEFT) ? RIGHT : LEFT; struct pos p, pe; survey (_m, pos, &k->f, NULL, &p, NULL); survey (_m, pos, &ke->f, NULL, &pe, NULL); pos2room (&pe, p.room, &pe); if (! is_anim_seeing (k, ke, k->f.dir) && ! is_near (k, ke) && ! is_safe_to_follow (k, ke, k->f.dir) && ! (is_on_back (k, ke) && is_anim_seeing (k, ke, odir) && p.floor == pe.floor)) { forget_enemy (k); return; } }
void fight_ai (struct anim *k) { /* non-fightable characters don't fight */ if (! is_fightable_anim (k)) return; /* controllables and non-fighters doesn't need AI to fight */ if (k->controllable || ! k->fight) return; /* if forgetting about an enemy, no need to fight */ if (k->enemy_refraction > 0) return; /* without an enemy or awareness, no need to fight */ if (k->enemy_id == -1) { if (is_in_fight_mode (k)) leave_fight_mode (k); return; } /* first thing, enter in fight mode */ if (! is_in_fight_mode (k)) { enter_fight_mode (k); return; } /* who's the enemy? */ struct anim *ke = get_anim_by_id (k->enemy_id); /* what's the facing opposite direction? */ enum dir odir = (k->f.dir == LEFT) ? RIGHT : LEFT; /* get positions */ struct pos p, pe; survey (_m, pos, &k->f, NULL, &p, NULL); survey ((k->f.dir != ke->f.dir) ? _m : _mba, pos, &ke->f, NULL, &pe, NULL); pos2room (&pe, p.room, &pe); /* remember the place the enemy was last seen */ if (pe.room == p.room && pe.floor == p.floor) k->enemy_pos = pe; else if (pe.floor > p.floor && is_valid_pos (&k->enemy_pos) && ! is_strictly_traversable (&k->enemy_pos)) k->enemy_pos.place = pe.place; if (is_valid_pos (&k->enemy_pos) && is_strictly_traversable (&k->enemy_pos)) { struct pos pp; int d = (p.place < k->enemy_pos.place) ? -1 : +1; while (is_strictly_traversable (prel (&k->enemy_pos, &pp, +0, d))) k->enemy_pos = pp; } /* prevent enemy from passing through */ if (ke->type == KID && is_in_range (k, ke, ATTACK_RANGE) && ! is_in_fight_mode (ke) && ! ke->immortal && ! (is_kid_climb (&ke->f) && ke->i <= 7) && ke->f.dir != k->f.dir && ke->current_lives > 0 && ke->has_sword && ! is_kid_fall (&ke->f) && ! is_kid_hang (&ke->f) && ! is_kid_jump_air (&ke->f) && ! is_kid_run_jump_air (&ke->f) && is_safe_to_attack (ke)) { place_on_the_ground (&ke->f, &ke->f.c); kid_take_sword (ke); ke->auto_taken_sword = true; } /* prevent enemy from hiding near */ if (ke->type == KID && is_in_range (k, ke, INVERSION_RANGE) && ! is_in_fight_mode (ke) && ke->current_lives > 0) { if (is_safe_to_walkb (k)) fight_walkb (k); else if (is_safe_to_turn (k)) fight_turn (k); return; } /* if the enemy is on the back, turn */ if (is_on_back (k, ke) && is_anim_seeing (k, ke, odir) && p.floor == pe.floor && ! is_in_range (k, ke, INVERSION_RANGE)) { if (is_safe_to_turn (k)) fight_turn (k); else if (is_safe_to_walkb (k)) fight_walkb (k); return; } /* if too near to a wall, back off to have room for an attack */ if (fight_crel (k, +0, +1) == WALL && is_safe_to_walkb (k)) { fight_walkb (k); return; } /* /\* if the enemy can be followed in the opposite direction, turn *\/ */ /* if (! is_safe_to_follow (k, ke, k->f.dir) */ /* && is_safe_to_follow (k, ke, odir)) { */ /* fight_turn (k); */ /* return; */ /* } */ /* if the enemy is trying to bypass, attack him */ if (! is_in_fight_mode (ke) && ! ke->has_sword && ! is_kid_stairs (&ke->f) && ke->f.dir != k->f.dir && ke->current_lives > 0 && ! is_on_back (k, ke) && ((is_kid_run (&ke->f) && is_in_range (k, ke, 3 * PLACE_WIDTH - 4)) || (is_kid_run_jump (&ke->f) && is_in_range (k, ke, 4 * PLACE_WIDTH - 4)) || (is_kid_jump_air (&ke->f) && ke->i < 9 && is_in_range (k, ke, 4 * PLACE_WIDTH)))) { if (is_safe_to_attack (k)) fight_attack (k); else if (is_safe_to_walkb (k)) fight_walkb (k); return; } /* stays at least in the fight range. Advance, unless the enemy is not running towards you */ if (! is_in_range (k, ke, FIGHT_RANGE + 10) && ! is_kid_stairs (&ke->f) && (ke->f.dir == k->f.dir || p.room != pe.room || p.floor != pe.floor || ! (is_kid_run (&ke->f) || is_kid_run_jump (&ke->f) || is_kid_jump (&ke->f))) && is_safe_to_follow (k, ke, k->f.dir)) { fight_walkf (k); return; } /* if the enemy is not targeting you, do nothing more */ if (ke->enemy_id != -1 && ke->enemy_id != k->id) return; /* in fight range, if the enemy is not attacking, go towards attack range (with probability, unless the enemy is not in fight mode, then go immediately) */ if (is_in_range (k, ke, FIGHT_RANGE + 10) && ! is_in_range (k, ke, ATTACK_RANGE) && ! is_kid_stairs (&ke->f) && is_safe_to_follow (k, ke, k->f.dir) && (prandom (99) <= k->skill.advance_prob || ! is_in_fight_mode (ke)) && ! is_attacking (ke) && (! is_in_fight_mode (ke) || is_walking (ke) || ke->i >= 6 + prandom (24))) { fight_walkf (k); return; } /* in attack range, if being attacked, defend yourself (with probability) and counter attack (with probability handled elsewhere) */ if (is_in_range (k, ke, ATTACK_RANGE + 16) && ! is_on_back (k, ke) && (is_attacking (ke) && ke->i == 0) && (prandom (99) <= k->skill.defense_prob || k->refraction > 0) && ke->current_lives > 0) { fight_defense (k); fight_attack (k); return; } /* if attacking, counter defend (with probability handled elsewhere) */ if (is_in_range (k, ke, ATTACK_RANGE + 16) && is_attacking (k)) { fight_defense (k); fight_attack (k); return; } /* in attack range, if not being attacked, attack (with probability, unless the enemy is not in fight mode, then attack immediately) */ if (is_in_range (k, ke, ATTACK_RANGE) && ! is_attacking (ke) && ! is_on_back (k, ke) && ! is_kid_stairs (&ke->f) && ! ((is_kid_climb (&ke->f) || is_kid_successfully_climbing (&ke->f)) && ke->i >= 1) && ke->current_lives > 0 && (prandom (99) <= k->skill.attack_prob || ! is_in_fight_mode (ke))) { if (is_safe_to_attack (k)) fight_attack (k); else if (is_safe_to_walkb (k)) fight_walkb (k); return; } /* in hit range, back off (with probability) */ if (is_in_range (k, ke, HIT_RANGE - 10) && is_safe_to_walkb (k) && ! k->refraction && ! is_walkingb (ke) && prandom (99) <= k->skill.return_prob) { fight_walkb (k); return; } }
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); } }
void draw_room_frame_fg (ALLEGRO_BITMAP *bitmap, enum em em, enum vm vm, struct frame *f) { struct pos ptl, pbr, ptl2, pbr2; survey (_tl, posf, f, NULL, &ptl, NULL); survey (_br, posf, f, NULL, &pbr, NULL); pos2room (&ptl, room_view, &ptl); pos2room (&pbr, room_view, &pbr); survey (_tl, pos, f, NULL, &ptl2, NULL); survey (_br, pos, f, NULL, &pbr2, NULL); pos2room (&ptl2, room_view, &ptl2); pos2room (&pbr2, room_view, &pbr2); struct coord c; frame2room (f, room_view, &c); int w = al_get_bitmap_width (f->b); int h = al_get_bitmap_height (f->b); push_clipping_rectangle (bitmap, c.x, c.y, w, h); /* FALLING LOOSE FLOOR */ struct pos ptr, ptra; survey (_tr, posf, f, NULL, &ptr, NULL); prel (&ptr, &ptra, -1, +0); draw_falling_loose_floor (bitmap, &ptr, em, vm); draw_falling_loose_floor (bitmap, &ptra, em, vm); struct pos p = ptl; for (p.floor = pbr.floor; p.floor >= ptl.floor; p.floor--) for (p.place = ptl.place; p.place <= pbr.place; p.place++) switch (fake (&p)) { case SPIKES_FLOOR: draw_spikes_fg (bitmap, &p, em, vm); break; case BROKEN_FLOOR: draw_broken_floor_fg (bitmap, &p, em, vm); break; case OPENER_FLOOR: draw_opener_floor_fg (bitmap, &p, em, vm); break; case CLOSER_FLOOR: draw_closer_floor_fg (bitmap, &p, em, vm); break; case PILLAR: draw_pillar_fg (bitmap, &p, em, vm); break; case BIG_PILLAR_BOTTOM: draw_big_pillar_bottom_fg (bitmap, &p, em, vm); break; case BIG_PILLAR_TOP: draw_big_pillar_top_left (bitmap, &p, em, vm); break; case ARCH_BOTTOM: draw_arch_bottom_fg (bitmap, &p, em, vm); break; case WALL: draw_wall_fg (bitmap, &p, f, em, vm); break; case CHOPPER: draw_chopper_fg (bitmap, &p, em, vm); break; case MIRROR: draw_mirror_fg (bitmap, &p, f, em, vm); break; case ARCH_TOP_MID: draw_arch_top_mid (bitmap, &p, em, vm); break; case ARCH_TOP_SMALL: draw_arch_top_small (bitmap, &p, em, vm); break; case ARCH_TOP_LEFT: draw_arch_top_left (bitmap, &p, em, vm); break; case ARCH_TOP_RIGHT: draw_arch_top_right (bitmap, &p, em, vm); break; default: break; } p = ptl2; for (p.floor = pbr2.floor; p.floor >= ptl2.floor; p.floor--) for (p.place = ptl2.place; p.place <= pbr2.place; p.place++) switch (fake (&p)) { case WALL: draw_wall_fg (bitmap, &p, f, em, vm); break; case DOOR: draw_door_fg (bitmap, &p, f, em, vm); break; case CARPET: draw_carpet_fg (bitmap, &p, f, em, vm); break; case TCARPET: draw_carpet_fg (bitmap, &p, f, em, vm); break; default: break; } pop_clipping_rectangle (); }