]> granicus.if.org Git - nethack/commitdiff
fix #H2645 - invulnerability during prayer is vulernable to stinking cloud
authornethack.rankin <nethack.rankin>
Mon, 7 May 2012 01:44:38 +0000 (01:44 +0000)
committernethack.rankin <nethack.rankin>
Mon, 7 May 2012 01:44:38 +0000 (01:44 +0000)
     From a bug report, stinking cloud
harms hero even when u.uninvulnerable is set during successful prayer.
This makes the cloud harmless during prayer as he suggested.

     It also makes being inside a stinking cloud become a major trouble
that prayer can fix.  (With magical breathing such a cloud is harmless and
with poison resistance it is just a nuisance; it won't be considered to be
trouble in such cases.)  The fix is to clear away the cloud, or to teleport
the hero if he's inside multiple overlapping clouds or in one that is
marked as permanent (which I think isn't currently possible).

doc/fixes35.0
include/extern.h
src/pray.c
src/region.c

index c239c38152112f9f2d44c7c968592857ff2e4cf8..4cfeab1f029e6fa173ab630ac105f7d5b88502c6 100644 (file)
@@ -838,6 +838,7 @@ declining to attack a peaceful monster via movement used up nutrition even
        though no action took place
 declining to attack a peaceful monster via kicking woke nearby monsters and
        scuffed engraving at hero's location even though no action took place
+make hero be immune from stinking cloud damage during successful prayer
 
 
 Platform- and/or Interface-Specific Fixes
@@ -1043,6 +1044,8 @@ repeatedly setting the fruit option will check to see if fruits have been
     created, so the user can't easily overflow the maximum this way
 bones files now include extra data to identify dead hero and reason for death
 dipping multiple potions in another potion may only dip part of their stack
+make being inside a stinking cloud (when not immune or resistant) become a
+       major trouble which is fixable by prayer
 
 
 Platform- and/or Interface-Specific New Features
index e2b37fa18c0a939de76197bc20224e9f674c8aea..71c7a54b72662fe902c56d2361d0523377ea95c7 100644 (file)
@@ -1932,6 +1932,8 @@ E void FDECL(show_region, (NhRegion*, XCHAR_P, XCHAR_P));
 E void FDECL(save_regions, (int,int));
 E void FDECL(rest_regions, (int,BOOLEAN_P));
 E NhRegion* FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, int));
+E boolean NDECL(region_danger);
+E void NDECL(region_safety);
 
 /* ### restore.c ### */
 
index 9e0368e8d123fdffe2bb23b2541f1c82d0a82af0..da8825dd38fc454fc21be734b9a14077bd0b3e93 100644 (file)
@@ -69,12 +69,13 @@ static int p_type; /* (-1)-3: (-1)=really naughty, 3=really good */
  * order to have the values be meaningful.
  */
 
-#define TROUBLE_STONED                 13
-#define TROUBLE_SLIMED                 12
-#define TROUBLE_STRANGLED              11
-#define TROUBLE_LAVA                   10
-#define TROUBLE_SICK                    9
-#define TROUBLE_STARVING                8
+#define TROUBLE_STONED                 14
+#define TROUBLE_SLIMED                 13
+#define TROUBLE_STRANGLED              12
+#define TROUBLE_LAVA                   11
+#define TROUBLE_SICK                   10
+#define TROUBLE_STARVING                9
+#define TROUBLE_REGION                  8      /* stinking cloud */
 #define TROUBLE_HIT                     7
 #define TROUBLE_LYCANTHROPE             6
 #define TROUBLE_COLLAPSING              5
@@ -168,6 +169,7 @@ in_trouble()
        if(u.utrap && u.utraptype == TT_LAVA) return(TROUBLE_LAVA);
        if(Sick) return(TROUBLE_SICK);
        if(u.uhs >= WEAK) return(TROUBLE_STARVING);
+       if (region_danger()) return TROUBLE_REGION;
        if (critically_low_hp(FALSE)) return TROUBLE_HIT;
        if(u.ulycn >= LOW_PM) return(TROUBLE_LYCANTHROPE);
        if(near_capacity() >= EXT_ENCUMBER && AMAX(A_STR)-ABASE(A_STR) > 3)
@@ -200,7 +202,7 @@ in_trouble()
        /*
         * minor troubles
         */
-       if(Punished || (u.utrap && u.utraptype == TT_BURIEDBALL))
+       if (Punished || (u.utrap && u.utraptype == TT_BURIEDBALL))
                return(TROUBLE_PUNISHED);
        if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING) ||
                Cursed_obj(uarmf, FUMBLE_BOOTS))
@@ -336,6 +338,10 @@ register int trouble;
                    You_feel("better.");
                    make_sick(0L, (char *) 0, FALSE, SICK_ALL);
                    break;
+           case TROUBLE_REGION:
+                   /* stinking cloud, with hero vulnerable to HP loss */
+                   region_safety();
+                   break;
            case TROUBLE_HIT:
                    /* "fix all troubles" will keep trying if hero has
                       5 or less hit points, so make sure they're always
index c3432291d29e12f50dfa09025b18ddce674fb818..6c779098b36337ec6a127aa2f0b27126f52334b4 100644 (file)
@@ -918,7 +918,7 @@ genericptr_t p2;
     reg = (NhRegion *) p1;
     dam = reg->arg.a_int;
     if (p2 == (genericptr_t)0) {               /* This means *YOU* Bozo! */
-       if (nonliving(youmonst.data) || Breathless)
+       if (u.uinvulnerable || nonliving(youmonst.data) || Breathless)
            return FALSE;
        if (!Blind) {
            Your("%s sting.", makeplural(body_part(EYE)));
@@ -1000,4 +1000,59 @@ int damage;
     return cloud;
 }
 
+/* for checking troubles during prayer; is hero at risk? */
+boolean
+region_danger()
+{
+    int i, f_indx, n = 0;
+
+    for (i = 0; i < n_regions; i++) {
+       /* only care about regions that hero is in */
+       if (!hero_inside(regions[i])) continue;
+       f_indx = regions[i]->inside_f;
+       /* the only type of region we understand is gas_cloud */
+       if (f_indx == INSIDE_GAS_CLOUD) {
+           /* completely harmless if you don't need to breathe */
+           if (nonliving(youmonst.data) || Breathless) continue;
+           /* minor inconvenience if you're posion resistant;
+              not harmful enough to be a prayer-level trouble */
+           if (Poison_resistance) continue;
+           ++n;
+       }
+    }
+    return n ? TRUE : FALSE;
+}
+
+/* for fixing trouble at end of prayer;
+   danger detected at start of prayer might have expired by now */
+void
+region_safety()
+{
+    NhRegion *r = 0;
+    int i, f_indx, n = 0;
+
+    for (i = 0; i < n_regions; i++) {
+       /* only care about regions that hero is in */
+       if (!hero_inside(regions[i])) continue;
+       f_indx = regions[i]->inside_f;
+       /* the only type of region we understand is gas_cloud */
+       if (f_indx == INSIDE_GAS_CLOUD) {
+           if (!n++ && regions[i]->ttl >= 0) r = regions[i];
+       }
+    }
+
+    if (n > 1 || (n == 1 && !r)) {
+       /* multiple overlapping cloud regions or non-expiring one */
+       safe_teleds(FALSE);
+    } else if (r) {
+       remove_region(r);
+       pline_The("gas cloud enveloping you dissipates.");
+    } else {
+       /* cloud dissipated on its own, so nothing needs to be done */
+       pline_The("gas cloud has dissipated.");
+    }
+    /* maybe cure blindness too */
+    if ((Blinded && TIMEOUT) == 1L) make_blinded(0L, TRUE);
+}
+
 /*region.c*/