]> granicus.if.org Git - nethack/commitdiff
fix github issue #666 - cursed light vs worn light
authorPatR <rankin@nethack.org>
Sat, 5 Feb 2022 00:20:03 +0000 (16:20 -0800)
committerPatR <rankin@nethack.org>
Sat, 5 Feb 2022 00:20:03 +0000 (16:20 -0800)
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

doc/fixes3-7-0.txt
include/extern.h
src/potion.c
src/read.c

index db268ac6a0e21ad6751baa8678c819f865cc1285..a10ff63387db2d4b67702c33e6968b50a6ef0371 100644 (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
index 1285bf5e1aae86f3a7c94c48b7585cbeab9d226a..2cbe6c487cedf48fe18144ae6bc8d874b4d6aeb2 100644 (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);
index e21dc3548c75e2c9918601346e9f3ba437af62ea..172cfd10ab72a656dc16833632cd87a2685c9ae3 100644 (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)
index df09611d48e183c2ccd3ecaf5c5f5fe8f7b92edf..d02d848f53d631e67075c603f6d954e5aeadb3cf 100644 (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