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 remember terrain, objects, and monsters being revealed; if 'obj' is Null, is being hit by a camera's light flash */
| 254 | remember terrain, objects, and monsters being revealed; |
| 255 | if 'obj' is Null, <x,y> is being hit by a camera's light flash */ |
| 256 | void |
| 257 | show_transient_light(struct obj *obj, coordxy x, coordxy y) |
| 258 | { |
| 259 | light_source *ls = 0; |
| 260 | anything cameraflash; |
| 261 | struct monst *mon; |
| 262 | int radius_squared; |
| 263 | |
| 264 | /* Null object indicates camera flash */ |
| 265 | if (!obj) { |
| 266 | /* no need to temporarily light an already lit spot */ |
| 267 | if (levl[x][y].lit) |
| 268 | return; |
| 269 | |
| 270 | cameraflash = cg.zeroany; |
| 271 | /* radius 0 will just light <x,y>; cameraflash.a_obj is Null */ |
| 272 | ls = new_light_core(x, y, 0, LS_OBJECT, &cameraflash); |
| 273 | /* pacify static analysis; 'ls' is never Null for |
| 274 | new_light_core(,,0,LS_OBJECT,&zeroany) */ |
| 275 | assert(ls != NULL); |
| 276 | } else { |
| 277 | /* thrown or kicked object which is emitting light; validate its |
| 278 | light source to obtain its radius (for monster sightings) */ |
| 279 | for (ls = gl.light_base; ls; ls = ls->next) { |
| 280 | if (ls->type != LS_OBJECT) |
| 281 | continue; |
| 282 | if (ls->id.a_obj == obj) |
| 283 | break; |
| 284 | } |
| 285 | assert(obj != NULL); /* necessary condition to get into this 'else' */ |
| 286 | if (!ls || obj->where != OBJ_FREE) { |
| 287 | impossible("transient light %s %s %s not %s?", |
| 288 | obj->lamplit ? "lit" : "unlit", |
| 289 | simpleonames(obj), otense(obj, "are"), |
| 290 | !ls ? "a light source" : "free"); |
| 291 | return; |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | if (obj) /* put lit candle or lamp temporarily on the map */ |
| 296 | place_object(obj, gb.bhitpos.x, gb.bhitpos.y); |
| 297 | else /* camera flash: no object; directly set light source's location */ |
| 298 | ls->x = x, ls->y = y; |
| 299 | |
| 300 | /* full recalc; runs do_light_sources() */ |
| 301 | vision_recalc(0); |
| 302 | flush_screen(0); |
| 303 | |
| 304 | radius_squared = ls->range * ls->range; |
| 305 | for (mon = fmon; mon; mon = mon->nmon) { |
| 306 | if (DEADMONSTER(mon) || (mon->isgd && !mon->mx)) |
| 307 | continue; |
| 308 | /* light range is the radius of a circle and we're limiting |
| 309 | canseemon() to a square enclosing that circle, but setting |
| 310 | mtemplit 'erroneously' for a seen monster is not a problem; |
| 311 | it just flags monsters for another canseemon() check when |
| 312 | 'obj' has reached its destination after missile traversal */ |
| 313 | if (dist2(mon->mx, mon->my, x, y) <= radius_squared) { |
no test coverage detected