* Called for the following distance effects: * when a weapon is thrown (weapon == THROWN_WEAPON) * when an object is kicked (KICKED_WEAPON) * when an IMMEDIATE wand is zapped (ZAPPED_WAND) * when a light beam is flashed (FLASHED_LIGHT) * when a mirror is applied (INVIS_BEAM) * A thrown/kicked object falls down at end of its range or when a monster * is hit. The
| 3824 | * If fhitm returns non-zero value, stops the beam and returns the monster |
| 3825 | */ |
| 3826 | struct monst * |
| 3827 | bhit( |
| 3828 | int ddx, int ddy, int range, /* direction and range */ |
| 3829 | enum bhit_call_types weapon, /* defined in hack.h */ |
| 3830 | int (*fhitm)(MONST_P, OBJ_P), /* fns called when mon/obj hit */ |
| 3831 | int (*fhito)(OBJ_P, OBJ_P), |
| 3832 | struct obj **pobj) /* object tossed/used, set to NULL |
| 3833 | * if object is destroyed */ |
| 3834 | { |
| 3835 | struct monst *mtmp, *result = (struct monst *) 0; |
| 3836 | struct obj *obj = *pobj; |
| 3837 | struct trap *ttmp; |
| 3838 | uchar typ; |
| 3839 | boolean shopdoor = FALSE, point_blank = TRUE; |
| 3840 | boolean in_skip = FALSE, allow_skip = FALSE; |
| 3841 | boolean tethered_weapon = FALSE; |
| 3842 | int skiprange_start = 0, skiprange_end = 0, skipcount = 0; |
| 3843 | struct obj *was_returning = (iflags.returning_missile == obj) ? obj |
| 3844 | : (struct obj *) 0; |
| 3845 | |
| 3846 | if (weapon == KICKED_WEAPON) { |
| 3847 | /* object starts one square in front of player */ |
| 3848 | gb.bhitpos.x = u.ux + ddx; |
| 3849 | gb.bhitpos.y = u.uy + ddy; |
| 3850 | range--; |
| 3851 | } else { |
| 3852 | gb.bhitpos.x = u.ux; |
| 3853 | gb.bhitpos.y = u.uy; |
| 3854 | } |
| 3855 | |
| 3856 | if (weapon == THROWN_WEAPON && obj && obj->otyp == ROCK) { |
| 3857 | skiprange(range, &skiprange_start, &skiprange_end); |
| 3858 | allow_skip = !rn2(3); |
| 3859 | } |
| 3860 | |
| 3861 | if (weapon == FLASHED_LIGHT) { |
| 3862 | tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam)); |
| 3863 | } else if (weapon == THROWN_TETHERED_WEAPON && obj) { |
| 3864 | tethered_weapon = TRUE; |
| 3865 | weapon = THROWN_WEAPON; /* simplify 'if's that follow below */ |
| 3866 | tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng)); |
| 3867 | } else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) |
| 3868 | tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng)); |
| 3869 | |
| 3870 | while (range-- > 0) { |
| 3871 | coordxy x, y; |
| 3872 | int xyglyph; |
| 3873 | |
| 3874 | gb.bhitpos.x += ddx; |
| 3875 | gb.bhitpos.y += ddy; |
| 3876 | x = gb.bhitpos.x; |
| 3877 | y = gb.bhitpos.y; |
| 3878 | |
| 3879 | if (!isok(x, y)) { |
| 3880 | gb.bhitpos.x -= ddx; |
| 3881 | gb.bhitpos.y -= ddy; |
| 3882 | break; |
| 3883 | } |
no test coverage detected