fix github issue #666 - cursed light vs worn light

Another gold dragon scales/mail issue, reported bu vultur-cadens:
reading a cursed scroll of light extinguishes carried light sources
except for wielded Sunsword and worn gold dragon scales/mail; there
was a special message for Sunsword (preventing the hero from being in
darkness) but no such message for gold dragon scales/mail.  Replace
the special message with a more generic one applicable to both cases.

Also, implement the suggestion that cursed light degrade the amount
of light being emitted (which varies by bless/curse state) for those
two cases.  Sunsword has a 75% chance to resist, gold dragon scales
25% chance.  And add the inverse:  blessed scroll of light might
increase the amount of light by improving their bless/curse state.
The resistance check applies here too and isn't inverted; Sunsword
is still fairly likely to resist.

Uncursed scroll of light, spell of light regardless of skill, zapped
or broken wand of light have so such effect.

Closes #666
This commit is contained in:
PatR
2022-02-04 16:20:03 -08:00
parent 0fba9cf896
commit e8341dc9d7
4 changed files with 98 additions and 27 deletions

View File

@@ -1447,7 +1447,7 @@ H2Opotion_dip(
boolean useeit, /* will hero see the glow/aura? */
const char *objphrase) /* "Your widget glows" or "Steed's saddle glows" */
{
void (*func)(struct obj *) = 0;
void (*func)(struct obj *) = (void (*)(struct obj *)) 0;
const char *glowcolor = 0;
#define COST_alter (-2)
#define COST_none (-1)
@@ -1528,6 +1528,38 @@ H2Opotion_dip(
return res;
}
/* used when blessed or cursed scroll of light interacts with artifact light;
if the lit object (Sunsword or gold dragon scales/mail) doesn't resist,
treat like dipping it in holy or unholy water (BUC change, glow message) */
void
impact_arti_light(
struct obj *obj, /* wielded Sunsword or worn gold dragon scales/mail */
boolean worsen, /* True: lower BUC state unless already cursed;
* False: raise BUC state unless already blessed */
boolean seeit) /* True: give "<obj> glows <color>" message */
{
struct obj *otmp;
/* if already worst/best BUC it can be, or if it resists, do nothing */
if ((worsen ? obj->cursed : obj->blessed) || obj_resists(obj, 75, 25))
return;
/* curse() and bless() take care of maybe_adjust_light() */
otmp = mksobj(POT_WATER, TRUE, FALSE);
if (worsen)
curse(otmp);
else
bless(otmp);
H2Opotion_dip(otmp, obj, seeit, seeit ? Yobjnam2(obj, "glow") : "");
dealloc_obj(otmp);
#if 0 /* defer this until caller has used up the scroll so it won't be
* visible; player was told that it disappeared as hero read it */
if (carried(obj)) /* carried() will always be True here */
update_inventory();
#endif
return;
}
/* potion obj hits monster mon, which might be youmonst; obj always used up */
void
potionhit(struct monst *mon, struct obj *obj, int how)

View File

@@ -1578,13 +1578,13 @@ seffect_light(struct obj **sobjp)
pline("Tiny lights sparkle in the air momentarily.");
} else {
/* surround with cancelled tame lights which won't explode */
struct monst *mon;
boolean sawlights = FALSE;
int numlights = rn1(2,3) + (sblessed * 2);
int i;
int i, numlights = rn1(2, 3) + (sblessed * 2);
for (i = 0; i < numlights; ++i) {
struct monst * mon = makemon(&mons[pm], u.ux, u.uy,
MM_EDOG | NO_MINVENT | MM_NOMSG);
mon = makemon(&mons[pm], u.ux, u.uy,
MM_EDOG | NO_MINVENT | MM_NOMSG);
initedog(mon);
mon->msleeping = 0;
mon->mcan = TRUE;
@@ -2279,32 +2279,65 @@ set_lit(int x, int y, genericptr_t val)
}
void
litroom(register boolean on, struct obj* obj)
litroom(
boolean on, /* True: make nearby area lit; False: cursed scroll */
struct obj *obj) /* scroll, spellbook (for spell), or wand of light */
{
char is_lit; /* value is irrelevant; we use its address
as a `not null' flag for set_lit() */
struct obj *otmp;
boolean blessed_effect = (obj && obj->oclass == SCROLL_CLASS
&& obj->blessed);
char is_lit = 0; /* value is irrelevant but assign something anyway; its
* address is used as a 'not null' flag for set_lit() */
/* first produce the text (provided you're not blind) */
/* update object lights and produce message (provided you're not blind) */
if (!on) {
register struct obj *otmp;
int still_lit = 0;
if (!Blind) {
if (u.uswallow) {
pline("It seems even darker in here than before.");
} else {
if (uwep && artifact_light(uwep) && uwep->lamplit)
pline("Suddenly, the only light left comes from %s!",
the(xname(uwep)));
/*
* The magic douses lamps,&c too and might curse artifact lights.
*
* FIXME?
* Shouldn't this affect all lit objects in the area of effect
* rather than just those carried by the hero?
*/
for (otmp = g.invent; otmp; otmp = otmp->nobj) {
if (otmp->lamplit) {
if (!artifact_light(otmp))
(void) snuff_lit(otmp);
else
You("are surrounded by darkness!");
/* wielded Sunsword or worn gold dragon scales/mail;
maybe lower its BUC state if not already cursed */
impact_arti_light(otmp, TRUE, (boolean) !Blind);
if (otmp->lamplit)
++still_lit;
}
}
/* the magic douses lamps, et al, too */
for (otmp = g.invent; otmp; otmp = otmp->nobj)
if (otmp->lamplit)
(void) snuff_lit(otmp);
/* scroll of light becomes discovered when not blind, so some
message to justify that is needed */
if (Blind) {
/* for the still_lit case, we don't know at this point whether
anything currently visibly lit is going to go dark; if this
message came after the darkening, we could count visibly
lit squares before and after to know; we do know that being
swallowed won't be affected--the interior is still lit */
if (still_lit)
pline_The("ambient light seems dimmer.");
else if (u.uswallow)
pline("It seems even darker in here than before.");
else
You("are surrounded by darkness!");
}
} else { /* on */
if (blessed_effect) {
/* might bless artifact lights; no effect on ordinary lights */
for (otmp = g.invent; otmp; otmp = otmp->nobj) {
if (otmp->lamplit && artifact_light(otmp))
/* wielded Sunsword or worn gold dragon scales/mail;
maybe raise its BUC state if not already blessed */
impact_arti_light(otmp, FALSE, (boolean) !Blind);
}
}
if (u.uswallow) {
if (Blind)
; /* no feedback */
@@ -2338,16 +2371,15 @@ litroom(register boolean on, struct obj* obj)
if (rnum >= 0) {
for (rx = g.rooms[rnum].lx - 1; rx <= g.rooms[rnum].hx + 1; rx++)
for (ry = g.rooms[rnum].ly - 1; ry <= g.rooms[rnum].hy + 1; ry++)
for (ry = g.rooms[rnum].ly - 1;
ry <= g.rooms[rnum].hy + 1; ry++)
set_lit(rx, ry,
(genericptr_t) (on ? &is_lit : (char *) 0));
g.rooms[rnum].rlit = on;
}
/* hallways remain dark on the rogue level */
} else
do_clear_area(u.ux, u.uy,
(obj && obj->oclass == SCROLL_CLASS && obj->blessed)
? 9 : 5,
do_clear_area(u.ux, u.uy, blessed_effect ? 9 : 5,
set_lit, (genericptr_t) (on ? &is_lit : (char *) 0));
/*
@@ -2379,6 +2411,7 @@ litroom(register boolean on, struct obj* obj)
free((genericptr_t) gremlin);
} while (gremlins);
}
return;
}
static void