From: nethack.rankin Date: Mon, 7 May 2012 01:44:38 +0000 (+0000) Subject: fix #H2645 - invulnerability during prayer is vulernable to stinking cloud X-Git-Tag: MOVE2GIT~15 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0add5217870dbc1691c4c509b0985d7556ec09c8;p=nethack fix #H2645 - invulnerability during prayer is vulernable to stinking cloud 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). --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index c239c3815..4cfeab1f0 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index e2b37fa18..71c7a54b7 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 ### */ diff --git a/src/pray.c b/src/pray.c index 9e0368e8d..da8825dd3 100644 --- a/src/pray.c +++ b/src/pray.c @@ -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 diff --git a/src/region.c b/src/region.c index c3432291d..6c779098b 100644 --- a/src/region.c +++ b/src/region.c @@ -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*/