Reduce code duplication in extrinsics-protect-items code

The same checks were being repeated for every damage type; this
sends them through two centralised functions (one for checking
whether an extrinsic blocks a specific instance of item destruction
and one for the enlightenment message), so that new mechanisms of
item destruction prevention will need to change only one point in
the code.
This commit is contained in:
Alex Smith
2023-12-05 04:34:24 +00:00
parent 2d8ba944e1
commit 7ca9951996
5 changed files with 55 additions and 29 deletions

View File

@@ -3582,7 +3582,8 @@ extern void melt_ice_away(union any *, long);
extern int zap_over_floor(coordxy, coordxy, int, boolean *, boolean, short);
extern void fracture_rock(struct obj *);
extern boolean break_statue(struct obj *);
extern boolean u_adtyp_resistance_obj(int);
extern int u_adtyp_resistance_obj(int);
extern boolean inventory_resistance_check(int);
extern char *item_what(int);
extern void destroy_item(int, int);
extern int destroy_mitem(struct monst *, int, int);

View File

@@ -2524,8 +2524,9 @@ breakobj(
}
/*
* Check to see if obj is going to break, but don't actually break it.
* Return 0 if the object isn't going to break, 1 if it is.
* Check to see if obj (which has just hit hard something at speed, e.g.
* thrown or dropped from height) is going to break, but don't actually
* break it. Return 0 if the object isn't going to break, 1 if it is.
*/
boolean
breaktest(struct obj *obj)

View File

@@ -1429,6 +1429,19 @@ weapon_insight(int final)
} /* skill applies */
}
static void
item_resistance_message(int adtyp, const char *prot_message, int final)
{
int protection = u_adtyp_resistance_obj(adtyp);
if (protection) {
boolean somewhat = protection < 99;
enl_msg("Your items ",
somewhat ? "are somewhat" : "are",
somewhat ? "were somewhat" : "were",
prot_message, item_what(adtyp));
}
}
/* attributes: intrinsics and the like, other non-obvious capabilities */
static void
attributes_enlightenment(int unused_mode UNUSED, int final)
@@ -1469,26 +1482,18 @@ 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",
item_what(AD_FIRE));
item_resistance_message(AD_FIRE, " protected from fire", final);
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",
item_what(AD_COLD));
item_resistance_message(AD_COLD, " protected from cold", final);
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", item_what(AD_DISN));
item_resistance_message(AD_DISN, " protected from disintegration", final);
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", item_what(AD_ELEC));
item_resistance_message(AD_ELEC, " protected from electric shocks", final);
if (Poison_resistance)
you_are("poison resistant", from_what(POISON_RES));
if (Acid_resistance) {
@@ -1497,9 +1502,7 @@ attributes_enlightenment(int unused_mode UNUSED, int final)
"acid resistant");
you_are(buf, from_what(ACID_RES));
}
if (u_adtyp_resistance_obj(AD_ACID))
enl_msg("Your items ", "are", "were", " protected from acid",
item_what(AD_ACID));
item_resistance_message(AD_ACID, " protected from acid", final);
if (Drain_resistance)
you_are("level-drain resistant", from_what(DRAIN_RES));
if (Sick_resistance)

View File

@@ -198,7 +198,7 @@ erode_obj(
switch (type) {
case ERODE_BURN:
if (uvictim && u_adtyp_resistance_obj(AD_FIRE) && rn2(100))
if (uvictim && inventory_resistance_check(AD_FIRE))
return ER_NOTHING;
vulnerable = is_flammable(otmp);
check_grease = FALSE;
@@ -215,7 +215,7 @@ erode_obj(
cost_type = COST_ROT;
break;
case ERODE_CORRODE:
if (uvictim && u_adtyp_resistance_obj(AD_ACID) && rn2(100))
if (uvictim && inventory_resistance_check(AD_ACID))
return ER_NOTHING;
vulnerable = is_corrodeable(otmp);
is_primary = FALSE;
@@ -4362,7 +4362,7 @@ acid_damage(struct obj* obj)
victim = carried(obj) ? &gy.youmonst : mcarried(obj) ? obj->ocarry : NULL;
vismon = victim && (victim != &gy.youmonst) && canseemon(victim);
if (victim == &gy.youmonst && u_adtyp_resistance_obj(AD_ACID) && rn2(100))
if (victim == &gy.youmonst && inventory_resistance_check(AD_ACID))
return;
if (obj->greased) {

View File

@@ -4317,7 +4317,7 @@ zhitu(
break;
case ZT_DEATH:
if (abstyp == ZT_BREATH(ZT_DEATH)) {
boolean disn_prot = u_adtyp_resistance_obj(AD_DISN) && rn2(100);
boolean disn_prot = inventory_resistance_check(AD_DISN);
if (Disint_resistance) {
You("are not disintegrated.");
@@ -5391,20 +5391,41 @@ adtyp_to_prop(int dmgtyp)
return 0; /* prop_types start at 1 */
}
/* is hero wearing or wielding an object with resistance
to attack damage type */
boolean
/* Is hero wearing or wielding an object with resistance to attack
damage type? Returns the percentage protectoin that the object
gives. */
int
u_adtyp_resistance_obj(int dmgtyp)
{
int prop = adtyp_to_prop(dmgtyp);
if (!prop)
return FALSE;
return 0;
if ((u.uprops[prop].extrinsic & (W_ARMOR | W_ACCESSORY | W_WEP)) != 0)
return TRUE;
return 99; /* 99% protected */
return FALSE;
return 0;
}
/* Rolls to see whether an object in inventory resists damage from the
given damage type, due to an equipped item protecting it. Use
u_adtyp_resistance_obj to discover whether objects are protected in
general (e.g. for enlightenment) and this function to actually do
the roll to see whether a specific object is protected.
This function doesn't check for other reasons why an object might
be protected; you will usually need to do an obj_resists() call
too. */
boolean
inventory_resistance_check(int dmgtyp)
{
int prob = u_adtyp_resistance_obj(dmgtyp);
if (!prob)
return FALSE;
return rn2(100) < prob;
}
/* for enlightenment; currently only useful in wizard mode; cf from_what() */
@@ -5491,7 +5512,7 @@ destroy_one_item(struct obj *obj, int osym, int dmgtyp)
quan = 0L;
/* external worn item protects inventory? */
if (u_adtyp_resistance_obj(dmgtyp) && rn2(100))
if (inventory_resistance_check(dmgtyp))
return;
switch (dmgtyp) {