]> granicus.if.org Git - nethack/commitdiff
cursed potion of levitation
authorPatR <rankin@nethack.org>
Sun, 8 May 2016 00:26:01 +0000 (17:26 -0700)
committerPatR <rankin@nethack.org>
Sun, 8 May 2016 00:26:01 +0000 (17:26 -0700)
Reported directly to devteam 7-Jan-2016, two issues with cursed
potion of levitation:
1) the go-up-stairs effect for cursed potion still let you choose
not to escape the dungeon if it occurred on level 1 stairs.  I've
left that as-is; perhaps there's a gate across the entrance.
2) both the go-up-stairs and bonk-head-on-ceiling effects were
skipped if the hero was already levitating.  I don't know whether
that was intentional but there was no comment explaining why, so
I've changed it to happen regardless of whether already levitating.

In the process, I changed the head-bonk case to do more damage when
a helmet is worn:
 old: no helmet 1..10 hp, any helmet 1 hp damage;
 new: no helmet 1..10 hp, soft hat 1..6 hp, hard helmet 1..3 hp.

Also, not in the report:  when you aren't already levitating you
get the "you float up" message, but for cursed potion there was
never any corresponding "you float down" message because you ended
up not levitating.  Now you'll levitate for 1 turn and float down
on the next, landing in a trap if one is present.

doc/fixes36.1
src/do.c
src/hack.c
src/potion.c

index 2af5329132403625c35a9e1330c0f216ff759c10..b364ad2eb9d8782ded1335072cc5122b42924c30 100644 (file)
@@ -230,6 +230,7 @@ when feel_location removed a remembered-unseen-monster glyph from a known
 Vlad's tower2 and tower3 didn't show up in wizard-mode ^O output or ^V? menu
 remove extra space from "All of your  <stack-of-potions> boil and explode."
        (also applies to potions freezing and to scrolls burning)
+effects of cursed potion of levitation were skipped if already levitating
 
 
 Fixes to Post-3.6.0 Problems that Were Exposed Via git Respository
index 734324821c701af3ada9fbdac95c7b2dfad53a78..5efa0da87bd343f8ccc3dad70a5670f758b3cb6f 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1317,7 +1317,7 @@ boolean at_stairs, falling, portal;
             if (flags.verbose || great_effort)
                 pline("%s %s up%s the %s.",
                       great_effort ? "With great effort, you" : "You",
-                      Flying ? "fly" : "climb",
+                      Levitation ? "float" : Flying ? "fly" : "climb",
                       (Flying && at_ladder) ? " along" : "",
                       at_ladder ? "ladder" : "stairs");
         } else { /* down */
index b9d1df2bb602ce75dc17e9c11114aca5497198af..e18612cc94869f68f6d2f60b2288896fd3a46af0 100644 (file)
@@ -1950,8 +1950,8 @@ boolean pick;
            turn, allowing it to do so could give the perception
            that a trap here is being triggered twice, so adjust
            the timeout to prevent that */
-        if (trap && (HLevitation & TIMEOUT) == 1L && !ELevitation
-            && !(HLevitation & ~TIMEOUT)) {
+        if (trap && (HLevitation & TIMEOUT) == 1L
+            && !(ELevitation || (HLevitation & ~(I_SPECIAL | TIMEOUT)))) {
             if (rn2(2)) { /* defer timeout */
                 incr_itimeout(&HLevitation, 1L);
             } else { /* timeout early */
index 568c48d99639a3227eacf8da652b44a8bc530008..6d3e45f96af16af1e8106ab318f900f3462f75ab 100644 (file)
@@ -957,39 +957,59 @@ register struct obj *otmp;
         break;
     case POT_LEVITATION:
     case SPE_LEVITATION:
-        if (otmp->cursed)
-            HLevitation &= ~I_SPECIAL;
+        /*
+         * BLevitation will be set if levitation is blocked due to being
+         * inside rock (currently or formerly in phazing xorn form, perhaps)
+         * but it doesn't prevent setting or incrementing Levitation timeout
+         * (which will take effect after escaping from the rock if it hasn't
+         * expired by then).
+         */
         if (!Levitation && !BLevitation) {
             /* kludge to ensure proper operation of float_up() */
             set_itimeout(&HLevitation, 1L);
             float_up();
-            /* reverse kludge */
-            set_itimeout(&HLevitation, 0L);
-            if (otmp->cursed) {
-                if ((u.ux == xupstair && u.uy == yupstair)
-                    || (sstairs.up && u.ux == sstairs.sx
-                        && u.uy == sstairs.sy)
-                    || (xupladder && u.ux == xupladder
-                        && u.uy == yupladder)) {
-                    (void) doup();
-                } else if (has_ceiling(&u.uz)) {
-                    int dmg = uarmh ? 1 : rnd(10);
-
-                    You("hit your %s on the %s.", body_part(HEAD),
-                        ceiling(u.ux, u.uy));
-                    losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
-                           KILLED_BY);
-                }
-            } /*cursed*/
-        } else
+            /* This used to set timeout back to 0, then increment it below
+               for blessed and uncursed effects.  But now we leave it so
+               that cursed effect yields "you float down" on next turn.
+               Blessed and uncursed get one extra turn duration. */
+        } else /* already levitating, or can't levitate */
             nothing++;
-        if (otmp->blessed) {
+
+        if (otmp->cursed) {
+            /* 'already levitating' used to block the cursed effect(s)
+               aside from ~I_SPECIAL; it was not clear whether that was
+               intentional; either way, it no longer does (as of 3.6.1) */
+            HLevitation &= ~I_SPECIAL; /* can't descend upon demand */
+            if (BLevitation) {
+                ; /* rising via levitation is blocked */
+            } else if ((u.ux == xupstair && u.uy == yupstair)
+                    || (sstairs.up && u.ux == sstairs.sx && u.uy == sstairs.sy)
+                    || (xupladder && u.ux == xupladder && u.uy == yupladder)) {
+                (void) doup();
+                /* in case we're already Levitating, which would have
+                   resulted in incrementing 'nothing' */
+                nothing = 0; /* not nothing after all */
+            } else if (has_ceiling(&u.uz)) {
+                int dmg = rnd(!uarmh ? 10 : !is_metallic(uarmh) ? 6 : 3);
+
+                You("hit your %s on the %s.", body_part(HEAD),
+                    ceiling(u.ux, u.uy));
+                losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
+                       KILLED_BY);
+                nothing = 0; /* not nothing after all */
+            }
+        } else if (otmp->blessed) {
+            /* at this point, timeout is already at least 1 */
             incr_itimeout(&HLevitation, rn1(50, 250));
+            /* can descend at will (stop levitating via '>') provided timeout
+               is the only factor (ie, not also wearing Lev ring or boots) */
             HLevitation |= I_SPECIAL;
-        } else
+        } else /* timeout is already at least 1 */
             incr_itimeout(&HLevitation, rn1(140, 10));
-        if (Levitation)
-            spoteffects(FALSE); /* for sinks */
+
+        if (Levitation && IS_SINK(levl[u.ux][u.uy].typ))
+            spoteffects(FALSE);
+        /* levitating blocks flying */
         float_vs_flight();
         break;
     case POT_GAIN_ENERGY: { /* M. Stephenson */