fix #2495 - light vs gremlins (trunk only)
From a bug report, flashing yourself with a camera while in gremlin form blinded as with any other form, but didn't inflict any damage the way that flashing a monster gremlin does. This fixes that, and also makes light from wand/scroll/spell that hits you-as-gremlin or monster gremlins do 1d5 damage too. It happens even if the target is already in a lit spot, but doesn't continue afterwards: simply being in a lit spot doesn't cause any damage, nor does lamp light.
This commit is contained in:
@@ -394,6 +394,8 @@ if hero dragged iron ball into temporary corridor and then killed vault guard,
|
|||||||
the portion of corridor currently in existence would become permanent
|
the portion of corridor currently in existence would become permanent
|
||||||
on Plane of Water, restrict levitation and flying to air bubbles;
|
on Plane of Water, restrict levitation and flying to air bubbles;
|
||||||
elsewhere, restrict them such that they don't work inside solid rock
|
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
|
Platform- and/or Interface-Specific Fixes
|
||||||
|
|||||||
+3
-1
@@ -2341,6 +2341,7 @@ E int FDECL(passive, (struct monst *,BOOLEAN_P,int,UCHAR_P,BOOLEAN_P));
|
|||||||
E void FDECL(passive_obj, (struct monst *,struct obj *,struct attack *));
|
E void FDECL(passive_obj, (struct monst *,struct obj *,struct attack *));
|
||||||
E void FDECL(stumble_onto_mimic, (struct monst *));
|
E void FDECL(stumble_onto_mimic, (struct monst *));
|
||||||
E int FDECL(flash_hits_mon, (struct monst *,struct obj *));
|
E int FDECL(flash_hits_mon, (struct monst *,struct obj *));
|
||||||
|
E void FDECL(light_hits_gremlin, (struct monst *,int));
|
||||||
|
|
||||||
/* ### unixmain.c ### */
|
/* ### unixmain.c ### */
|
||||||
|
|
||||||
@@ -2685,6 +2686,8 @@ E void FDECL(zapnodir, (struct obj *));
|
|||||||
E int NDECL(dozap);
|
E int NDECL(dozap);
|
||||||
E int FDECL(zapyourself, (struct obj *,BOOLEAN_P));
|
E int FDECL(zapyourself, (struct obj *,BOOLEAN_P));
|
||||||
E void FDECL(ubreatheu, (struct attack *));
|
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 *,
|
E boolean FDECL(cancel_monst, (struct monst *,struct obj *,
|
||||||
BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
|
BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
|
||||||
E void NDECL(zapsetup);
|
E void NDECL(zapsetup);
|
||||||
@@ -2710,7 +2713,6 @@ E void FDECL(destroy_item, (int,int));
|
|||||||
E int FDECL(destroy_mitem, (struct monst *,int,int));
|
E int FDECL(destroy_mitem, (struct monst *,int,int));
|
||||||
E int FDECL(resist, (struct monst *,CHAR_P,int,int));
|
E int FDECL(resist, (struct monst *,CHAR_P,int,int));
|
||||||
E void NDECL(makewish);
|
E void NDECL(makewish);
|
||||||
E boolean FDECL(flashburn, (long));
|
|
||||||
|
|
||||||
#endif /* !MAKEDEFS_C && !LEV_LEX_C */
|
#endif /* !MAKEDEFS_C && !LEV_LEX_C */
|
||||||
|
|
||||||
|
|||||||
+36
-2
@@ -1158,6 +1158,9 @@ struct obj *sobj; /* scroll, or fake spellbook object for scroll-like spell */
|
|||||||
if (!confused || rn2(5)) {
|
if (!confused || rn2(5)) {
|
||||||
if(!Blind) known = TRUE;
|
if(!Blind) known = TRUE;
|
||||||
litroom(!confused && !scursed, sobj);
|
litroom(!confused && !scursed, sobj);
|
||||||
|
if (!confused && !scursed) {
|
||||||
|
if (lightdamage(sobj, TRUE, 5)) known = TRUE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* could be scroll of create monster, don't set known ...*/
|
/* could be scroll of create monster, don't set known ...*/
|
||||||
(void) create_critters(1, !scursed ?
|
(void) create_critters(1, !scursed ?
|
||||||
@@ -1518,6 +1521,14 @@ int chg; /* recharging */
|
|||||||
exercise(A_STR, FALSE);
|
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.
|
* Low-level lit-field update routine.
|
||||||
*/
|
*/
|
||||||
@@ -1526,9 +1537,18 @@ set_lit(x,y,val)
|
|||||||
int x, y;
|
int x, y;
|
||||||
genericptr_t val;
|
genericptr_t val;
|
||||||
{
|
{
|
||||||
if (val)
|
struct monst *mtmp;
|
||||||
|
struct litmon *gremlin;
|
||||||
|
|
||||||
|
if (val) {
|
||||||
levl[x][y].lit = 1;
|
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;
|
levl[x][y].lit = 0;
|
||||||
snuff_light_source(x, y);
|
snuff_light_source(x, y);
|
||||||
}
|
}
|
||||||
@@ -1627,6 +1647,20 @@ do_it:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vision_full_recalc = 1; /* delayed vision recalculation */
|
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
|
STATIC_OVL void
|
||||||
|
|||||||
+18
-10
@@ -2609,16 +2609,7 @@ struct obj *otmp; /* source of flash */
|
|||||||
/* Rule #1: Keep them out of the light. */
|
/* Rule #1: Keep them out of the light. */
|
||||||
amt = otmp->otyp == WAN_LIGHT ? d(1 + otmp->spe, 4) :
|
amt = otmp->otyp == WAN_LIGHT ? d(1 + otmp->spe, 4) :
|
||||||
rn2(min(mtmp->mhp,4));
|
rn2(min(mtmp->mhp,4));
|
||||||
pline("%s %s!", Monnam(mtmp), amt > mtmp->mhp / 2 ?
|
light_hits_gremlin(mtmp, amt);
|
||||||
"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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (mtmp->mhp > 0) {
|
if (mtmp->mhp > 0) {
|
||||||
if (!context.mon_moving) setmangry(mtmp);
|
if (!context.mon_moving) setmangry(mtmp);
|
||||||
@@ -2632,4 +2623,21 @@ struct obj *otmp; /* source of flash */
|
|||||||
return res;
|
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*/
|
/*uhitm.c*/
|
||||||
|
|||||||
@@ -1963,6 +1963,7 @@ register struct obj *obj;
|
|||||||
case SPE_LIGHT:
|
case SPE_LIGHT:
|
||||||
litroom(TRUE,obj);
|
litroom(TRUE,obj);
|
||||||
if (!Blind) known = TRUE;
|
if (!Blind) known = TRUE;
|
||||||
|
if (lightdamage(obj, TRUE, 5)) known = TRUE;
|
||||||
break;
|
break;
|
||||||
case WAN_SECRET_DOOR_DETECTION:
|
case WAN_SECRET_DOOR_DETECTION:
|
||||||
case SPE_DETECT_UNSEEN:
|
case SPE_DETECT_UNSEEN:
|
||||||
@@ -2279,7 +2280,9 @@ boolean ordinary;
|
|||||||
damage = d(obj->spe, 25);
|
damage = d(obj->spe, 25);
|
||||||
#ifdef TOURIST
|
#ifdef TOURIST
|
||||||
case EXPENSIVE_CAMERA:
|
case EXPENSIVE_CAMERA:
|
||||||
|
if (!damage) damage = 5;
|
||||||
#endif
|
#endif
|
||||||
|
damage = lightdamage(obj, ordinary, damage);
|
||||||
damage += rnd(25);
|
damage += rnd(25);
|
||||||
if (flashburn((long)damage)) learn_it = TRUE;
|
if (flashburn((long)damage)) learn_it = TRUE;
|
||||||
damage = 0; /* reset */
|
damage = 0; /* reset */
|
||||||
@@ -2377,6 +2380,38 @@ struct attack *mattk;
|
|||||||
zhitu(dtyp, mattk->damn, fltxt, u.ux, u.uy);
|
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
|
boolean
|
||||||
flashburn(duration)
|
flashburn(duration)
|
||||||
long duration;
|
long duration;
|
||||||
|
|||||||
Reference in New Issue
Block a user