the portion of corridor currently in existence would become permanent
on Plane of Water, restrict levitation and flying to air bubbles;
elsewhere, restrict them such that they don't work inside solid rock
+wand/scroll/spell of light now hurts gremlins (lamp/candle light doesn't)
+ditto for hero in gremlin form (camera too)
Platform- and/or Interface-Specific Fixes
E void FDECL(passive_obj, (struct monst *,struct obj *,struct attack *));
E void FDECL(stumble_onto_mimic, (struct monst *));
E int FDECL(flash_hits_mon, (struct monst *,struct obj *));
+E void FDECL(light_hits_gremlin, (struct monst *,int));
/* ### unixmain.c ### */
E int NDECL(dozap);
E int FDECL(zapyourself, (struct obj *,BOOLEAN_P));
E void FDECL(ubreatheu, (struct attack *));
+E int FDECL(lightdamage, (struct obj *,BOOLEAN_P,int));
+E boolean FDECL(flashburn, (long));
E boolean FDECL(cancel_monst, (struct monst *,struct obj *,
BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
E void NDECL(zapsetup);
E int FDECL(destroy_mitem, (struct monst *,int,int));
E int FDECL(resist, (struct monst *,CHAR_P,int,int));
E void NDECL(makewish);
-E boolean FDECL(flashburn, (long));
#endif /* !MAKEDEFS_C && !LEV_LEX_C */
if (!confused || rn2(5)) {
if(!Blind) known = TRUE;
litroom(!confused && !scursed, sobj);
+ if (!confused && !scursed) {
+ if (lightdamage(sobj, TRUE, 5)) known = TRUE;
+ }
} else {
/* could be scroll of create monster, don't set known ...*/
(void) create_critters(1, !scursed ?
exercise(A_STR, FALSE);
}
+/* used to collect gremlins being hit by light so that they can be processed
+ after vision for the entire lit area has been brought up to date */
+struct litmon {
+ struct monst *mon;
+ struct litmon *nxt;
+};
+STATIC_VAR struct litmon *gremlins = 0;
+
/*
* Low-level lit-field update routine.
*/
int x, y;
genericptr_t val;
{
- if (val)
+ struct monst *mtmp;
+ struct litmon *gremlin;
+
+ if (val) {
levl[x][y].lit = 1;
- else {
+ if ((mtmp = m_at(x, y)) != 0 && mtmp->data == &mons[PM_GREMLIN]) {
+ gremlin = (struct litmon *)alloc(sizeof *gremlin);
+ gremlin->mon = mtmp;
+ gremlin->nxt = gremlins;
+ gremlins = gremlin;
+ }
+ } else {
levl[x][y].lit = 0;
snuff_light_source(x, y);
}
}
vision_full_recalc = 1; /* delayed vision recalculation */
+ if (gremlins) {
+ struct litmon *gremlin;
+
+ /* can't delay vision recalc after all */
+ vision_recalc(0);
+ /* after vision has been updated, monsters who are affected
+ when hit by light can now be hit by it */
+ do {
+ gremlin = gremlins;
+ gremlins = gremlin->nxt;
+ light_hits_gremlin(gremlin->mon, rnd(5));
+ free((genericptr_t)gremlin);
+ } while (gremlins);
+ }
}
STATIC_OVL void
/* Rule #1: Keep them out of the light. */
amt = otmp->otyp == WAN_LIGHT ? d(1 + otmp->spe, 4) :
rn2(min(mtmp->mhp,4));
- pline("%s %s!", Monnam(mtmp), amt > mtmp->mhp / 2 ?
- "wails in agony" : "cries out in pain");
- if ((mtmp->mhp -= amt) <= 0) {
- if (context.mon_moving)
- monkilled(mtmp, (char *)0, AD_BLND);
- else
- killed(mtmp);
- } else if (cansee(mtmp->mx,mtmp->my) && !canspotmon(mtmp)){
- map_invisible(mtmp->mx, mtmp->my);
- }
+ light_hits_gremlin(mtmp, amt);
}
if (mtmp->mhp > 0) {
if (!context.mon_moving) setmangry(mtmp);
return res;
}
+void
+light_hits_gremlin(mon, dmg)
+struct monst *mon;
+int dmg;
+{
+ pline("%s %s!", Monnam(mon),
+ (dmg > mon->mhp / 2) ? "wails in agony" : "cries out in pain");
+ if ((mon->mhp -= dmg) <= 0) {
+ if (context.mon_moving)
+ monkilled(mon, (char *)0, AD_BLND);
+ else
+ killed(mon);
+ } else if (cansee(mon->mx, mon->my) && !canspotmon(mon)) {
+ map_invisible(mon->mx, mon->my);
+ }
+}
+
/*uhitm.c*/
case SPE_LIGHT:
litroom(TRUE,obj);
if (!Blind) known = TRUE;
+ if (lightdamage(obj, TRUE, 5)) known = TRUE;
break;
case WAN_SECRET_DOOR_DETECTION:
case SPE_DETECT_UNSEEN:
damage = d(obj->spe, 25);
#ifdef TOURIST
case EXPENSIVE_CAMERA:
+ if (!damage) damage = 5;
#endif
+ damage = lightdamage(obj, ordinary, damage);
damage += rnd(25);
if (flashburn((long)damage)) learn_it = TRUE;
damage = 0; /* reset */
zhitu(dtyp, mattk->damn, fltxt, u.ux, u.uy);
}
+/* light damages hero in gremlin form */
+int
+lightdamage(obj, ordinary, amt)
+struct obj *obj; /* item making light (fake book if spell) */
+boolean ordinary; /* wand/camera zap vs wand destruction */
+int amt; /* pseudo-damage used to determine blindness duration */
+{
+ char buf[BUFSZ];
+ const char *how;
+ int dmg = amt;
+
+ if (dmg && youmonst.data == &mons[PM_GREMLIN]) {
+ /* reduce high values (from destruction of wand with many charges) */
+ dmg = rnd(dmg);
+ if (dmg > 10) dmg = 10 + rnd(dmg - 10);
+ if (dmg > 20) dmg = 20;
+ pline("Ow, that light hurts%c", (dmg > 2 || u.mh <= 5) ? '!' : '.');
+ /* [composing killer/reason is superfluous here; if fatal, cause
+ of death will always be "killed while stuck in creature form"] */
+ if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
+ ordinary = FALSE; /* say blasted rather than zapped */
+ how = (obj->oclass != SPBOOK_CLASS) ?
+ (const char *)ansimpleoname(obj) : "spell of light";
+ Sprintf(buf, "%s %sself with %s",
+ ordinary ? "zapped" : "blasted", uhim(), how);
+ /* might rehumanize(); could be fatal, but only for Unchanging */
+ losehp(Maybe_Half_Phys(dmg), buf, NO_KILLER_PREFIX);
+ }
+ return dmg;
+}
+
+/* light[ning] causes blindness */
boolean
flashburn(duration)
long duration;