implement #986 - camera flash 'tweak'

Implement the suggested feature that a camera's flash actually update
hero's memory of the map as it traverses across the level.  Turned
out to be more work than anticipated despite having the code for a
thrown or kicked lit candle or lamp to build upon.

Among other things it needed to update the circle code to handle
previously unused radius 0 to operate on the center point only.  I've
never touched that before and hope this hasn't introduced any bugs.

Also removes several instances of vision code operating on column #0.
(At least one is still present.)
This commit is contained in:
PatR
2020-05-09 13:07:35 -07:00
parent d564fa8ac7
commit 59818fb6ab
7 changed files with 206 additions and 102 deletions

View File

@@ -324,6 +324,8 @@ extended achievement and conduct fields for xlogfile
record amount of gold in hero's possession in xlogfile record amount of gold in hero's possession in xlogfile
new objects: amulets of flying and guarding new objects: amulets of flying and guarding
new monsters: displacer beast ('f') and genetic engineer ('Q') new monsters: displacer beast ('f') and genetic engineer ('Q')
make camera flash which reveals previously unseen map features or objects or
monsters record those on the hero's map; monsters revert to 'unseen'
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features

View File

@@ -52,7 +52,7 @@
/* /*
* Circle information * Circle information
*/ */
#define MAX_RADIUS 15 /* this is in points from the source */ #define MAX_RADIUS 16 /* this is in points from the source */
/* Use this macro to get a list of distances of the edges (see vision.c). */ /* Use this macro to get a list of distances of the edges (see vision.c). */
#define circle_ptr(z) (&circle_data[(int) circle_start[z]]) #define circle_ptr(z) (&circle_data[(int) circle_start[z]])

View File

@@ -75,11 +75,16 @@ struct obj *obj;
(u.dz > 0) ? surface(u.ux, u.uy) : ceiling(u.ux, u.uy)); (u.dz > 0) ? surface(u.ux, u.uy) : ceiling(u.ux, u.uy));
} else if (!u.dx && !u.dy) { } else if (!u.dx && !u.dy) {
(void) zapyourself(obj, TRUE); (void) zapyourself(obj, TRUE);
} else if ((mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT, } else {
(int FDECL((*), (MONST_P, OBJ_P))) 0, mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT,
(int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj)) != 0) { (int FDECL((*), (MONST_P, OBJ_P))) 0,
obj->ox = u.ux, obj->oy = u.uy; (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
(void) flash_hits_mon(mtmp, obj); obj->ox = u.ux, obj->oy = u.uy; /* flash_hits_mon() wants this */
if (mtmp)
(void) flash_hits_mon(mtmp, obj);
/* normally bhit() would do this but for FLASHED_LIGHT we want it
to be deferred until after flash_hits_mon() */
transient_light_cleanup();
} }
return 1; return 1;
} }

View File

@@ -41,6 +41,9 @@
#define LSF_SHOW 0x1 /* display the light source */ #define LSF_SHOW 0x1 /* display the light source */
#define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */ #define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */
static light_source *FDECL(new_light_core, (XCHAR_P, XCHAR_P, int, int,
anything *));
static void NDECL(discard_flashes);
static void FDECL(write_ls, (NHFILE *, light_source *)); static void FDECL(write_ls, (NHFILE *, light_source *));
static int FDECL(maybe_write_ls, (NHFILE *, int, BOOLEAN_P)); static int FDECL(maybe_write_ls, (NHFILE *, int, BOOLEAN_P));
@@ -49,18 +52,31 @@ extern char circle_data[];
extern char circle_start[]; extern char circle_start[];
/* Create a new light source. */ /* Create a new light source. Caller (and extern.h) doesn't need to know
anything about type 'light_source'. */
void void
new_light_source(x, y, range, type, id) new_light_source(x, y, range, type, id)
xchar x, y; xchar x, y;
int range, type; int range, type;
anything *id; anything *id;
{
(void) new_light_core(x, y, range, type, id);
}
/* Create a new light source and return it. Only used within this file. */
static light_source *
new_light_core(x, y, range, type, id)
xchar x, y;
int range, type;
anything *id;
{ {
light_source *ls; light_source *ls;
if (range > MAX_RADIUS || range < 1) { if (range > MAX_RADIUS || range < 0
impossible("new_light_source: illegal range %d", range); /* camera flash uses radius 0 and passes Null object */
return; || (range == 0 && (type != LS_OBJECT || id->a_obj != 0))) {
impossible("new_light_source: illegal range %d", range);
return (light_source *) 0;
} }
ls = (light_source *) alloc(sizeof *ls); ls = (light_source *) alloc(sizeof *ls);
@@ -75,6 +91,7 @@ new_light_source(x, y, range, type, id)
g.light_base = ls; g.light_base = ls;
g.vision_full_recalc = 1; /* make the source show up */ g.vision_full_recalc = 1; /* make the source show up */
return ls;
} }
/* /*
@@ -95,7 +112,7 @@ anything *id;
(in particular: chameleon vs prot. from shape changers) */ (in particular: chameleon vs prot. from shape changers) */
switch (type) { switch (type) {
case LS_OBJECT: case LS_OBJECT:
tmp_id.a_uint = id->a_obj->o_id; tmp_id.a_uint = id->a_obj ? id->a_obj->o_id : 0;
break; break;
case LS_MONSTER: case LS_MONSTER:
tmp_id.a_uint = id->a_monst->m_id; tmp_id.a_uint = id->a_monst->m_id;
@@ -145,7 +162,8 @@ char **cs_rows;
* vision recalc. * vision recalc.
*/ */
if (ls->type == LS_OBJECT) { if (ls->type == LS_OBJECT) {
if (get_obj_location(ls->id.a_obj, &ls->x, &ls->y, 0)) if (ls->range == 0 /* camera flash; caller has set ls->{x,y} */
|| get_obj_location(ls->id.a_obj, &ls->x, &ls->y, 0))
ls->flags |= LSF_SHOW; ls->flags |= LSF_SHOW;
} else if (ls->type == LS_MONSTER) { } else if (ls->type == LS_MONSTER) {
if (get_mon_location(ls->id.a_monst, &ls->x, &ls->y, 0)) if (get_mon_location(ls->id.a_monst, &ls->x, &ls->y, 0))
@@ -177,8 +195,8 @@ char **cs_rows;
for (; y <= max_y; y++) { for (; y <= max_y; y++) {
row = cs_rows[y]; row = cs_rows[y];
offset = limits[abs(y - ls->y)]; offset = limits[abs(y - ls->y)];
if ((min_x = (ls->x - offset)) < 0) if ((min_x = (ls->x - offset)) < 1)
min_x = 0; min_x = 1;
if ((max_x = (ls->x + offset)) >= COLNO) if ((max_x = (ls->x + offset)) >= COLNO)
max_x = COLNO - 1; max_x = COLNO - 1;
@@ -210,62 +228,94 @@ char **cs_rows;
/* lit 'obj' has been thrown or kicked and is passing through x,y on the /* lit 'obj' has been thrown or kicked and is passing through x,y on the
way to its destination; show its light so that hero has a chance to way to its destination; show its light so that hero has a chance to
remember terrain, objects, and monsters being revealed */ remember terrain, objects, and monsters being revealed;
if 'obj' is Null, <x,y> is being hit by a camera's light flash */
void void
show_transient_light(obj, x, y) show_transient_light(obj, x, y)
struct obj *obj; struct obj *obj;
int x, y; int x, y;
{ {
light_source *ls; light_source *ls = 0;
anything cameraflash;
struct monst *mon; struct monst *mon;
int radius_squared; int radius_squared;
/* caller has verified obj->lamplit and that hero is not Blind; /* Null object indicates camera flash */
validate light source and obtain its radius (for monster sightings) */ if (!obj) {
for (ls = g.light_base; ls; ls = ls->next) { /* no need to temporarily light an already lit spot */
if (ls->type != LS_OBJECT) if (levl[x][y].lit)
continue; return;
if (ls->id.a_obj == obj)
break; cameraflash = cg.zeroany;
/* radius 0 will just light <x,y>; cameraflash.a_obj is Null */
ls = new_light_core(x, y, 0, LS_OBJECT, &cameraflash);
} else {
/* thrown or kicked object which is emitting light; validate its
light source to obtain its radius (for monster sightings) */
for (ls = g.light_base; ls; ls = ls->next) {
if (ls->type != LS_OBJECT)
continue;
if (ls->id.a_obj == obj)
break;
}
} }
if (!ls || obj->where != OBJ_FREE) { if (!ls || (obj && obj->where != OBJ_FREE)) {
impossible("transient light %s %s is not %s?", impossible("transient light %s %s is not %s?",
obj->lamplit ? "lit" : "unlit", xname(obj), obj->lamplit ? "lit" : "unlit", xname(obj),
!ls ? "a light source" : "free"); !ls ? "a light source" : "free");
} else { return;
/* "expensive" but rare */ }
place_object(obj, g.bhitpos.x, g.bhitpos.y); /* temporarily put on map */
vision_recalc(0);
flush_screen(0);
delay_output();
remove_object(obj); /* take back off of map */
radius_squared = ls->range * ls->range; if (obj) /* put lit candle or lamp temporarily on the map */
for (mon = fmon; mon; mon = mon->nmon) { place_object(obj, g.bhitpos.x, g.bhitpos.y);
if (DEADMONSTER(mon)) else /* camera flash: no object; directly set light source's location */
continue; ls->x = x, ls->y = y;
/* light range is the radius of a circle and we're limiting
canseemon() to a square exclosing that circle, but setting /* full recalc; runs do_light_sources() */
mtemplit 'erroneously' for a seen monster is not a problem; vision_recalc(0);
it just flags monsters for another canseemon() check when flush_screen(0);
'obj' has reached its destination after missile traversal */
if (dist2(mon->mx, mon->my, x, y) <= radius_squared radius_squared = ls->range * ls->range;
&& canseemon(mon)) for (mon = fmon; mon; mon = mon->nmon) {
if (DEADMONSTER(mon) || (mon->isgd && !mon->mx))
continue;
/* light range is the radius of a circle and we're limiting
canseemon() to a square exclosing that circle, but setting
mtemplit 'erroneously' for a seen monster is not a problem;
it just flags monsters for another canseemon() check when
'obj' has reached its destination after missile traversal */
if (dist2(mon->mx, mon->my, x, y) <= radius_squared) {
if (canseemon(mon))
mon->mtemplit = 1; mon->mtemplit = 1;
/* [what about worm tails?] */
} }
/* [what about worm tails?] */
}
if (obj) { /* take thrown/kicked candle or lamp off the map */
delay_output();
remove_object(obj);
} }
} }
/* draw "remembered, unseen monster" glyph at locations where a monster /* delete any camera flash light sources and draw "remembered, unseen
was flagged for being visible during transient light movement but can't monster" glyph at locations where a monster was flagged for being
be seen now */ visible during transient light movement but can't be seen now */
void void
transient_light_cleanup() transient_light_cleanup()
{ {
struct monst *mon; struct monst *mon;
int mtempcount = 0; int mtempcount;
/* in case we're cleaning up a camera flash, remove all object light
sources which aren't associated with a specific object */
discard_flashes();
if (g.vision_full_recalc) /* set by del_light_source() */
vision_recalc(0);
/* for thrown/kicked candle or lamp or for camera flash, some
monsters may have been mapped in light which has now gone away
so need to be replaced by "remembered, unseen monster" glyph */
mtempcount = 0;
for (mon = fmon; mon; mon = mon->nmon) { for (mon = fmon; mon; mon = mon->nmon) {
if (DEADMONSTER(mon)) if (DEADMONSTER(mon))
continue; continue;
@@ -276,9 +326,22 @@ transient_light_cleanup()
map_invisible(mon->mx, mon->my); map_invisible(mon->mx, mon->my);
} }
} }
if (mtempcount) { if (mtempcount)
vision_recalc(0);
flush_screen(0); flush_screen(0);
}
/* camera flashes have Null object; caller wants to get rid of them now */
static void
discard_flashes()
{
light_source *ls, *nxt_ls;
for (ls = g.light_base; ls; ls = nxt_ls) {
nxt_ls = ls->next;
if (ls->type != LS_OBJECT)
continue;
if (!ls->id.a_obj)
del_light_source(LS_OBJECT, &ls->id);
} }
} }
@@ -318,6 +381,13 @@ int range;
int count, actual, is_global; int count, actual, is_global;
light_source **prev, *curr; light_source **prev, *curr;
/* camera flash light sources have Null object and would trigger
impossible("no id!") below; they can only happen here if we're
in the midst of a panic save and they wouldn't be useful after
restore so just throw any that are present away */
discard_flashes();
g.vision_full_recalc = 0;
if (perform_bwrite(nhfp)) { if (perform_bwrite(nhfp)) {
count = maybe_write_ls(nhfp, range, FALSE); count = maybe_write_ls(nhfp, range, FALSE);
if (nhfp->structlevel) { if (nhfp->structlevel) {
@@ -330,7 +400,7 @@ int range;
} }
if (release_data(nhfp)) { if (release_data(nhfp)) {
for (prev = &g.light_base; (curr = *prev) != 0;) { for (prev = &g.light_base; (curr = *prev) != 0; ) {
if (!curr->id.a_monst) { if (!curr->id.a_monst) {
impossible("save_light_sources: no id! [range=%d]", range); impossible("save_light_sources: no id! [range=%d]", range);
is_global = 0; is_global = 0;

View File

@@ -3110,14 +3110,21 @@ struct monst *mon;
u.umconf--; u.umconf--;
} }
/* returns 1 if light flash has noticeable effect on 'mtmp', 0 otherwise */
int int
flash_hits_mon(mtmp, otmp) flash_hits_mon(mtmp, otmp)
struct monst *mtmp; struct monst *mtmp;
struct obj *otmp; /* source of flash */ struct obj *otmp; /* source of flash */
{ {
int tmp, amt, res = 0, useeit = canseemon(mtmp); struct rm *lev;
int tmp, amt, useeit, res = 0;
if (mtmp->msleeping) { if (g.notonhead)
return 0;
lev = &levl[mtmp->mx][mtmp->my];
useeit = canseemon(mtmp);
if (mtmp->msleeping && haseyes(mtmp->data)) {
mtmp->msleeping = 0; mtmp->msleeping = 0;
if (useeit) { if (useeit) {
pline_The("flash awakens %s.", mon_nam(mtmp)); pline_The("flash awakens %s.", mon_nam(mtmp));
@@ -3144,8 +3151,19 @@ struct obj *otmp; /* source of flash */
mtmp->mcansee = 0; mtmp->mcansee = 0;
mtmp->mblinded = (tmp < 3) ? 0 : rnd(1 + 50 / tmp); mtmp->mblinded = (tmp < 3) ? 0 : rnd(1 + 50 / tmp);
} }
} else if (flags.verbose && useeit) {
if (lev->lit)
pline("The flash of light shines on %s.", mon_nam(mtmp));
else
pline("%s is illuminated.", Monnam(mtmp));
res = 2; /* 'message has been given' temporary value */
} }
} }
if (res) {
if (!lev->lit)
display_nhwindow(WIN_MESSAGE, TRUE);
res &= 1; /* change temporary 2 back to 0 */
}
return res; return res;
} }

View File

@@ -24,45 +24,48 @@
* *
*/ */
const char circle_data[] = { const char circle_data[] = {
/* 0*/ 1, 1, /* 0*/ 0,
/* 2*/ 2, 2, 1, /* 1*/ 1, 1,
/* 5*/ 3, 3, 2, 1, /* 3*/ 2, 2, 1,
/* 9*/ 4, 4, 4, 3, 2, /* 6*/ 3, 3, 2, 1,
/* 14*/ 5, 5, 5, 4, 3, 2, /* 10*/ 4, 4, 4, 3, 2,
/* 20*/ 6, 6, 6, 5, 5, 4, 2, /* 15*/ 5, 5, 5, 4, 3, 2,
/* 27*/ 7, 7, 7, 6, 6, 5, 4, 2, /* 21*/ 6, 6, 6, 5, 5, 4, 2,
/* 35*/ 8, 8, 8, 7, 7, 6, 6, 4, 2, /* 28*/ 7, 7, 7, 6, 6, 5, 4, 2,
/* 44*/ 9, 9, 9, 9, 8, 8, 7, 6, 5, 3, /* 36*/ 8, 8, 8, 7, 7, 6, 6, 4, 2,
/* 54*/ 10, 10, 10, 10, 9, 9, 8, 7, 6, 5, 3, /* 45*/ 9, 9, 9, 9, 8, 8, 7, 6, 5, 3,
/* 65*/ 11, 11, 11, 11, 10, 10, 9, 9, 8, 7, 5, 3, /* 55*/ 10, 10, 10, 10, 9, 9, 8, 7, 6, 5, 3,
/* 77*/ 12, 12, 12, 12, 11, 11, 10, 10, 9, 8, 7, 5, 3, /* 66*/ 11, 11, 11, 11, 10, 10, 9, 9, 8, 7, 5, 3,
/* 90*/ 13, 13, 13, 13, 12, 12, 12, 11, 10, 10, 9, 7, 6, 3, /* 78*/ 12, 12, 12, 12, 11, 11, 10, 10, 9, 8, 7, 5, 3,
/*104*/ 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 10, 9, 8, 6, 3, /* 91*/ 13, 13, 13, 13, 12, 12, 12, 11, 10, 10, 9, 7, 6, 3,
/*119*/ 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 10, 9, 8, 6, 3, /*105*/ 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 10, 9, 8, 6, 3,
/*135*/ 16 /* MAX_RADIUS+1; used to terminate range loops -dlc */ /*120*/ 15, 15, 15, 15, 14, 14, 14, 13, 13, 12, 11, 10, 9, 8, 6, 3,
/*136*/ 16 /* MAX_RADIUS+1; used to terminate range loops -dlc */
}; };
/* /*
* These are the starting indexes into the circle_data[] array for a * These are the starting indexes into the circle_data[] array for a
* circle of a given radius. * circle of a given radius. Radius 0 used to be unused, but is now
* used for a single point: temporary light source of a camera flash
* as it traverses its path.
*/ */
const char circle_start[] = { const char circle_start[] = {
/* */ 0, /* circles of radius zero are not used */ /* 0*/ 0,
/* 1*/ 0, /* 1*/ 1,
/* 2*/ 2, /* 2*/ 3,
/* 3*/ 5, /* 3*/ 6,
/* 4*/ 9, /* 4*/ 10,
/* 5*/ 14, /* 5*/ 15,
/* 6*/ 20, /* 6*/ 21,
/* 7*/ 27, /* 7*/ 38,
/* 8*/ 35, /* 8*/ 36,
/* 9*/ 44, /* 9*/ 45,
/*10*/ 54, /*10*/ 55,
/*11*/ 65, /*11*/ 66,
/*12*/ 77, /*12*/ 78,
/*13*/ 90, /*13*/ 91,
/*14*/ 104, /*14*/ 105,
/*15*/ 119, /*15*/ 120,
}; };
/*==========================================================================*/ /*==========================================================================*/
@@ -263,11 +266,10 @@ char **rmin, **rmax;
nrmin = *rmin; nrmin = *rmin;
nrmax = *rmax; nrmax = *rmax;
(void) memset((genericptr_t) * *rows, 0, (void) memset((genericptr_t) **rows, 0, ROWNO * COLNO); /* see nothing */
ROWNO * COLNO); /* we see nothing */
for (row = 0; row < ROWNO; row++) { /* set row min & max */ for (row = 0; row < ROWNO; row++) { /* set row min & max */
*nrmin++ = COLNO - 1; *nrmin++ = COLNO - 1;
*nrmax++ = 0; *nrmax++ = 1;
} }
} }
@@ -490,23 +492,23 @@ void
vision_recalc(control) vision_recalc(control)
int control; int control;
{ {
extern unsigned char seenv_matrix[3][3]; /* from display.c */
static unsigned char colbump[COLNO + 1]; /* cols to bump sv */
char **temp_array; /* points to the old vision array */ char **temp_array; /* points to the old vision array */
char **next_array; /* points to the new vision array */ char **next_array; /* points to the new vision array */
char *next_row; /* row pointer for the new array */ char *next_row; /* row pointer for the new array */
char *old_row; /* row pointer for the old array */ char *old_row; /* row pointer for the old array */
char *next_rmin; /* min pointer for the new array */ char *next_rmin; /* min pointer for the new array */
char *next_rmax; /* max pointer for the new array */ char *next_rmax; /* max pointer for the new array */
const char *ranges; /* circle ranges -- used for xray & night vision */ const char *ranges; /* circle ranges -- used for xray & night vision */
int row = 0; /* row counter (outer loop) */ int row = 0; /* row counter (outer loop) */
int start, stop; /* inner loop starting/stopping index */ int start, stop; /* inner loop starting/stopping index */
int dx, dy; /* one step from a lit door or lit wall (see below) */ int dx, dy; /* one step from a lit door or lit wall (see below) */
register int col; /* inner loop counter */ register int col; /* inner loop counter */
register struct rm *lev; /* pointer to current pos */ register struct rm *lev; /* pointer to current pos */
struct rm *flev; /* pointer to position in "front" of current pos */ struct rm *flev; /* pointer to position in "front" of current pos */
extern unsigned char seenv_matrix[3][3]; /* from display.c */ unsigned char *sv; /* ptr to seen angle bits */
static unsigned char colbump[COLNO + 1]; /* cols to bump sv */ int oldseenv; /* previous seenv value */
unsigned char *sv; /* ptr to seen angle bits */
int oldseenv; /* previous seenv value */
g.vision_full_recalc = 0; /* reset flag */ g.vision_full_recalc = 0; /* reset flag */
if (g.in_mklev || !iflags.vision_inited) if (g.in_mklev || !iflags.vision_inited)
@@ -532,7 +534,6 @@ int control;
* *
* + Monsters to see with the "new" vision, even on the rogue * + Monsters to see with the "new" vision, even on the rogue
* level. * level.
*
* + Monsters can see you even when you're in a pit. * + Monsters can see you even when you're in a pit.
*/ */
view_from(u.uy, u.ux, next_array, next_rmin, next_rmax, 0, view_from(u.uy, u.ux, next_array, next_rmin, next_rmax, 0,
@@ -564,7 +565,7 @@ int control;
} else if (Is_rogue_level(&u.uz)) { } else if (Is_rogue_level(&u.uz)) {
rogue_vision(next_array, next_rmin, next_rmax); rogue_vision(next_array, next_rmin, next_rmax);
} else { } else {
int has_night_vision = 1; /* hero has night vision */ int lo_col, has_night_vision = 1; /* hero has night vision */
if (Underwater && !Is_waterlevel(&u.uz)) { if (Underwater && !Is_waterlevel(&u.uz)) {
/* /*
@@ -574,8 +575,9 @@ int control;
*/ */
has_night_vision = 0; has_night_vision = 0;
lo_col = max(u.ux - 1, 1);
for (row = u.uy - 1; row <= u.uy + 1; row++) for (row = u.uy - 1; row <= u.uy + 1; row++)
for (col = u.ux - 1; col <= u.ux + 1; col++) { for (col = lo_col; col <= u.ux + 1; col++) {
if (!isok(col, row) || !is_pool(col, row)) if (!isok(col, row) || !is_pool(col, row))
continue; continue;
@@ -592,7 +594,7 @@ int control;
if (row >= ROWNO) if (row >= ROWNO)
break; break;
next_rmin[row] = max(0, u.ux - 1); next_rmin[row] = max(1, u.ux - 1);
next_rmax[row] = min(COLNO - 1, u.ux + 1); next_rmax[row] = min(COLNO - 1, u.ux + 1);
next_row = next_array[row]; next_row = next_array[row];
@@ -620,11 +622,12 @@ int control;
dy = v_abs(u.uy - row); dy = v_abs(u.uy - row);
next_row = next_array[row]; next_row = next_array[row];
start = max(0, u.ux - ranges[dy]); start = max(1, u.ux - ranges[dy]);
stop = min(COLNO - 1, u.ux + ranges[dy]); stop = min(COLNO - 1, u.ux + ranges[dy]);
for (col = start; col <= stop; col++) { for (col = start; col <= stop; col++) {
char old_row_val = next_row[col]; char old_row_val = next_row[col];
next_row[col] |= IN_SIGHT; next_row[col] |= IN_SIGHT;
oldseenv = levl[col][row].seenv; oldseenv = levl[col][row].seenv;
levl[col][row].seenv = SVALL; /* see all! */ levl[col][row].seenv = SVALL; /* see all! */
@@ -663,7 +666,7 @@ int control;
dy = v_abs(u.uy - row); dy = v_abs(u.uy - row);
next_row = next_array[row]; next_row = next_array[row];
start = max(0, u.ux - ranges[dy]); start = max(1, u.ux - ranges[dy]);
stop = min(COLNO - 1, u.ux + ranges[dy]); stop = min(COLNO - 1, u.ux + ranges[dy]);
for (col = start; col <= stop; col++) for (col = start; col <= stop; col++)

View File

@@ -3320,6 +3320,8 @@ struct obj **pobj; /* object tossed/used, set to NULL
/* iron bars will block anything big enough and break some things */ /* iron bars will block anything big enough and break some things */
if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) { if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) {
if (obj->lamplit && !Blind)
show_transient_light(obj, g.bhitpos.x, g.bhitpos.y);
if (typ == IRONBARS if (typ == IRONBARS
&& hits_bars(pobj, x - ddx, y - ddy, g.bhitpos.x, g.bhitpos.y, && hits_bars(pobj, x - ddx, y - ddy, g.bhitpos.x, g.bhitpos.y,
point_blank ? 0 : !rn2(5), 1)) { point_blank ? 0 : !rn2(5), 1)) {
@@ -3328,9 +3330,11 @@ struct obj **pobj; /* object tossed/used, set to NULL
g.bhitpos.x -= ddx; g.bhitpos.x -= ddx;
g.bhitpos.y -= ddy; g.bhitpos.y -= ddy;
break; break;
} else if (obj->lamplit && !Blind) {
show_transient_light(obj, g.bhitpos.x, g.bhitpos.y);
} }
} else if (weapon == FLASHED_LIGHT) {
if (!Blind)
show_transient_light((struct obj *) 0,
g.bhitpos.x, g.bhitpos.y);
} }
if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) { if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
@@ -3546,6 +3550,8 @@ struct obj **pobj; /* object tossed/used, set to NULL
pay_for_damage("destroy", FALSE); pay_for_damage("destroy", FALSE);
bhit_done: bhit_done:
/* note: for FLASHED_LIGHT, _caller_ must call transient_light_cleanup()
after possibly calling flash_hits_mon() */
if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
transient_light_cleanup(); transient_light_cleanup();