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

@@ -991,6 +991,8 @@ a change to wounded legs handling resulted in not recovering lost dexterity
rather than having legs be explicitly healed
turning movement into commands broke the rest_on_space option; it also
interfered with using pick-axe plus autodig in downward direction
cursed scroll of light had special message when wielding Sunsword that didn't
work for wearing gold dragon scales/mail
curses: 'msg_window' option wasn't functional for curses unless the binary
also included tty support
@@ -1370,6 +1372,9 @@ drinking blessed potion of full healing heals wounded legs, either hero's or
drinking uncursed potion of full healing or blessed potion of extra healing
heal hero's wounded legs when not riding; no effect on steed if riding
cancellation explodes most magical traps
reading a blessed scroll of light has a chance to improve bless/curse state
of wielded Sunsword or worn gold dragon scales/mail similar to dipping
those into holy water; cursed scroll has chance to worsen the state
Platform- and/or Interface-Specific New Features

View File

@@ -2097,6 +2097,7 @@ extern int dopotion(struct obj *);
extern int peffects(struct obj *);
extern void healup(int, int, boolean, boolean);
extern void strange_feeling(struct obj *, const char *);
extern void impact_arti_light(struct obj *, boolean, boolean);
extern void potionhit(struct monst *, struct obj *, int);
extern void potionbreathe(struct obj *);
extern int dodip(void);

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