From: Pasi Kallinen Date: Mon, 6 Sep 2021 17:06:19 +0000 (+0300) Subject: Resistances gained from worn or wielded items also protect inventory X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9942b65df78dd55a7806ec6ea2821693a7131c97;p=nethack Resistances gained from worn or wielded items also protect inventory --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index efda5f29d..e5f97aae4 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -605,6 +605,7 @@ yet another fix for display problems during restore: if game is saved while restore will try to update hero's spot when making sure objects aren't being obfuscated by hallucination, but when displaying the hero there instead it would access steed pointer before that has been set up +resistances gained from worn or wielded items also protect hero's inventory Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 591645763..27ce86eaf 100644 --- a/include/extern.h +++ b/include/extern.h @@ -3222,6 +3222,7 @@ extern void melt_ice_away(union any *, long); extern int zap_over_floor(xchar, xchar, int, boolean *, short); extern void fracture_rock(struct obj *); extern boolean break_statue(struct obj *); +extern boolean u_adtyp_resistance_obj(int); extern void destroy_item(int, int); extern int destroy_mitem(struct monst *, int, int); extern int resist(struct monst *, char, int, int); diff --git a/src/insight.c b/src/insight.c index 908001c91..2bfd58e05 100644 --- a/src/insight.c +++ b/src/insight.c @@ -1373,18 +1373,28 @@ attributes_enlightenment(int unused_mode UNUSED, int final) you_are("magic-protected", from_what(ANTIMAGIC)); if (Fire_resistance) you_are("fire resistant", from_what(FIRE_RES)); + if (u_adtyp_resistance_obj(AD_FIRE)) + enl_msg("Your items ", "are", "were", " protected from fire", ""); if (Cold_resistance) you_are("cold resistant", from_what(COLD_RES)); + if (u_adtyp_resistance_obj(AD_COLD)) + enl_msg("Your items ", "are", "were", " protected from cold", ""); if (Sleep_resistance) you_are("sleep resistant", from_what(SLEEP_RES)); if (Disint_resistance) you_are("disintegration-resistant", from_what(DISINT_RES)); + if (u_adtyp_resistance_obj(AD_DISN)) + enl_msg("Your items ", "are", "were", " protected from disintegration", ""); if (Shock_resistance) you_are("shock resistant", from_what(SHOCK_RES)); + if (u_adtyp_resistance_obj(AD_ELEC)) + enl_msg("Your items ", "are", "were", " protected from electric shocks", ""); if (Poison_resistance) you_are("poison resistant", from_what(POISON_RES)); if (Acid_resistance) you_are("acid resistant", from_what(ACID_RES)); + if (u_adtyp_resistance_obj(AD_ACID)) + enl_msg("Your items ", "are", "were", " protected from acid", ""); if (Drain_resistance) you_are("level-drain resistant", from_what(DRAIN_RES)); if (Sick_resistance) diff --git a/src/trap.c b/src/trap.c index 6fd29ecf5..c55e02d23 100644 --- a/src/trap.c +++ b/src/trap.c @@ -187,6 +187,8 @@ erode_obj( switch (type) { case ERODE_BURN: + if (uvictim && u_adtyp_resistance_obj(AD_FIRE) && rn2(100)) + return ER_NOTHING; vulnerable = is_flammable(otmp); check_grease = FALSE; cost_type = COST_BURN; @@ -202,6 +204,8 @@ erode_obj( cost_type = COST_ROT; break; case ERODE_CORRODE: + if (uvictim && u_adtyp_resistance_obj(AD_ACID) && rn2(100)) + return ER_NOTHING; vulnerable = is_corrodeable(otmp); is_primary = FALSE; cost_type = COST_CORRODE; @@ -3871,6 +3875,9 @@ acid_damage(struct obj* obj) victim = carried(obj) ? &g.youmonst : mcarried(obj) ? obj->ocarry : NULL; vismon = victim && (victim != &g.youmonst) && canseemon(victim); + if (victim == &g.youmonst && u_adtyp_resistance_obj(AD_ACID) && rn2(100)) + return; + if (obj->greased) { grease_protect(obj, (char *) 0, victim); } else if (obj->oclass == SCROLL_CLASS && obj->otyp != SCR_BLANK_PAPER) { diff --git a/src/zap.c b/src/zap.c index 245968e64..f27f82d23 100644 --- a/src/zap.c +++ b/src/zap.c @@ -23,6 +23,7 @@ static boolean zap_steed(struct obj *); static void skiprange(int, int *, int *); static int zap_hit(int, int); static void disintegrate_mon(struct monst *, int, const char *); +static int adtyp_to_prop(int); static void backfire(struct obj *); static int zap_ok(struct obj *); static void boxlock_invent(struct obj *); @@ -3965,10 +3966,14 @@ zhitu(int type, int nd, const char *fltxt, xchar sx, xchar sy) break; case ZT_DEATH: if (abstyp == ZT_BREATH(ZT_DEATH)) { + boolean disn_prot = u_adtyp_resistance_obj(AD_DISN) && rn2(100); + if (Disint_resistance) { You("are not disintegrated."); monstseesu(M_SEEN_DISINT); break; + } else if (disn_prot) { + break; } else if (uarms) { /* destroy shield; other possessions are safe */ (void) destroy_arm(uarms); @@ -4940,6 +4945,36 @@ break_statue(struct obj *obj) return TRUE; } +/* convert attack damage AD_foo to property resistance */ +static int +adtyp_to_prop(int dmgtyp) +{ + switch (dmgtyp) { + case AD_COLD: return COLD_RES; + case AD_FIRE: return FIRE_RES; + case AD_ELEC: return SHOCK_RES; + case AD_ACID: return ACID_RES; + case AD_DISN: return DISINT_RES; + default: return 0; /* prop_types start at 1 */ + } +} + +/* is hero wearing or wielding an object with resistance + to attack damage type */ +boolean +u_adtyp_resistance_obj(int dmgtyp) +{ + int prop = adtyp_to_prop(dmgtyp); + + if (!prop) + return FALSE; + + if ((u.uprops[prop].extrinsic & (W_ARMOR | W_ACCESSORY | W_WEP)) != 0) + return TRUE; + + return FALSE; +} + /* * destroy_strings[dindx][0:singular,1:plural,2:killer_reason] * [0] freezing potion @@ -4979,6 +5014,10 @@ destroy_one_item(struct obj *obj, int osym, int dmgtyp) dmg = dindx = 0; quan = 0L; + /* external worn item protects inventory? */ + if (u_adtyp_resistance_obj(dmgtyp) && rn2(100)) + return; + switch (dmgtyp) { case AD_COLD: if (osym == POTION_CLASS && obj->otyp != POT_OIL) {