From: PatR Date: Sun, 8 May 2016 00:26:01 +0000 (-0700) Subject: cursed potion of levitation X-Git-Tag: NetHack-3.6.1_RC01~788 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=70ff2c2b3ea49b59b1a18d35c6be6adc037997d0;p=nethack cursed potion of levitation 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. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 2af532913..b364ad2eb 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -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 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 diff --git a/src/do.c b/src/do.c index 734324821..5efa0da87 100644 --- 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 */ diff --git a/src/hack.c b/src/hack.c index b9d1df2bb..e18612cc9 100644 --- a/src/hack.c +++ b/src/hack.c @@ -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 */ diff --git a/src/potion.c b/src/potion.c index 568c48d99..6d3e45f96 100644 --- a/src/potion.c +++ b/src/potion.c @@ -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 */