diff --git a/src/do_wear.c b/src/do_wear.c index 51b9059a6..d6c52c4ae 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 do_wear.c $NHDT-Date: 1720895740 2024/07/13 18:35:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.188 $ */ +/* NetHack 3.7 do_wear.c $NHDT-Date: 1727251255 2024/09/25 08:00:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.191 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -940,9 +940,24 @@ Amulet_on(void) case AMULET_OF_LIFE_SAVING: case AMULET_VERSUS_POISON: case AMULET_OF_REFLECTION: - case AMULET_OF_MAGICAL_BREATHING: case FAKE_AMULET_OF_YENDOR: break; + case AMULET_OF_MAGICAL_BREATHING: { + boolean was_in_poison_gas; + + /* amulet is already on; we need to check hero's gas-cloud status + when it was off */ + EMagical_breathing &= ~W_AMUL; + was_in_poison_gas = region_danger(); + EMagical_breathing |= W_AMUL; + if (was_in_poison_gas) { + You("are no longer bothered by the poison gas."); + makeknown(AMULET_OF_MAGICAL_BREATHING); + } + /* no need to check for becoming able to breathe underwater; + if we are underwater, we already can or we would have drowned */ + break; + } case AMULET_OF_UNCHANGING: if (Slimed) make_slimed(0L, (char *) 0); @@ -1039,8 +1054,7 @@ Amulet_off(void) break; case AMULET_OF_MAGICAL_BREATHING: if (Underwater) { - /* HMagical_breathing must be set off - before calling drown() */ + /* HMagical_breathing must be set off before calling drown() */ setworn((struct obj *) 0, W_AMUL); if (!cant_drown(gy.youmonst.data) && !Swimming) { You("suddenly inhale an unhealthy amount of %s!", @@ -1049,6 +1063,9 @@ Amulet_off(void) } return; } + /* + * FIXME: we need a poison gas region check here + */ break; case AMULET_OF_STRANGULATION: if (Strangled) { diff --git a/src/region.c b/src/region.c index 3a51ae15c..b38f0487f 100644 --- a/src/region.c +++ b/src/region.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 region.c $NHDT-Date: 1723580898 2024/08/13 20:28:18 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.98 $ */ +/* NetHack 3.7 region.c $NHDT-Date: 1727251269 2024/09/25 08:01:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.104 $ */ /* Copyright (c) 1996 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -1410,7 +1410,14 @@ region_safety(void) if (n > 1 || (n == 1 && !r)) { /* multiple overlapping cloud regions or non-expiring one */ - safe_teleds(TELEDS_NO_FLAGS); + (void) safe_teleds(TELEDS_NO_FLAGS); + /* maybe there's no safe place available; must get hero out of danger + or prayer's "fix all troubles" result will get stuck in a loop */ + if (region_danger()) { + set_itimeout(&HMagical_breathing, (long) (d(4, 4) + 4)); + /* not already Breathless or wouldn't be in region danger */ + You_feel("able to breathe."); + } } else if (r) { remove_region(r); pline_The("gas cloud enveloping you dissipates."); diff --git a/src/timeout.c b/src/timeout.c index 0369df143..b924a2041 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 timeout.c $NHDT-Date: 1723580900 2024/08/13 20:28:20 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.190 $ */ +/* NetHack 3.7 timeout.c $NHDT-Date: 1727251273 2024/09/25 08:01:13 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.193 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -56,6 +56,8 @@ static const struct propname { /* timed pass-walls is a potential prayer result if surrounded by stone with nowhere to be safely teleported to */ { PASSES_WALLS, "pass thru walls" }, + /* likewise for magical breathing vs poison gas regions */ + { MAGICAL_BREATHING, "magical breathing" }, /* timed fire resistance and water walking are possible in explore mode (as well as in wizard mode) after life-saving in lava if it fails to teleport the hero to safety and player declines to die */ @@ -92,7 +94,6 @@ static const struct propname { { TELEPORT_CONTROL, "teleport control" }, { FLYING, "flying" }, { SWIMMING, "swimming" }, - { MAGICAL_BREATHING, "magical breathing" }, { SLOW_DIGESTION, "slow digestion" }, { HALF_SPDAM, "half spell damage" }, { HALF_PHDAM, "half physical damage" }, @@ -534,7 +535,33 @@ phaze_dialogue(void) return; if (((HPasses_walls & TIMEOUT) % 2L) && i > 0L && i <= SIZE(phaze_texts)) - pline1(phaze_texts[SIZE(phaze_texts) - i]); + pline("%s", phaze_texts[SIZE(phaze_texts) - i]); +} + +/* Similar to Passes_walls, if prayer tries to save hero from a poison + gas region but can't, (HMagical_breathing & TIMEOUT) will be set to + a small value. Unlike Passes_walls, there's no joke message. */ +static NEARDATA const char *const region_texts[] = { + "You seem to have some trouble breathing.", + "The air here seems foul.", +}; + +staticfn void +region_dialogue(void) +{ + boolean breathless, in_poison_gas_cloud; + long r = (HMagical_breathing & TIMEOUT), i = r / 2L; + + /* might have poly'd into non-breather or moved out of gas cloud */ + HMagical_breathing &= ~TIMEOUT; + breathless = breathless(&mons[u.umonnum]); + in_poison_gas_cloud = region_danger(); + HMagical_breathing |= r; + if (breathless || !in_poison_gas_cloud) + return; + + if ((r % 2L) && i > 0L && i <= SIZE(region_texts)) + pline("%s", region_texts[SIZE(region_texts) - i]); } /* when a status timeout is fatal, keep the status line indicator shown @@ -600,6 +627,8 @@ nh_timeout(void) levitation_dialogue(); if (HPasses_walls & TIMEOUT) phaze_dialogue(); + if (HMagical_breathing & TIMEOUT) + region_dialogue(); if (HSleepy & TIMEOUT) sleep_dialogue(); if (u.mtimedone && !--u.mtimedone) { @@ -844,6 +873,13 @@ nh_timeout(void) !Upolyd ? "normal" : "unusual"); } break; + case MAGICAL_BREATHING: + if (!Breathless) { + if (region_danger()) + You("cough%s", + Poison_resistance ? "." : " and spit blood!"); + } + break; case STRANGLED: svk.killer.format = KILLED_BY; Strcpy(svk.killer.name,