From 5fd6c02170cd9e0cc5204bd2c23c1660d8992dfe Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 17 Feb 2023 14:40:26 -0800 Subject: [PATCH] pyrolisk feedback From a report 9 years ago, a pet pyrolisk was repeatedly gazing at a grey-elf and nothing happened. It turned out that the elf was wearing an elven cloak which was negating damage some of the time (most of the time back then) but with no indication that that's what was happening. This makes many types of damage that are negated by MC say so. Probably other types of damage should do likewise. --- doc/fixes3-7-0.txt | 1 + src/mhitm.c | 3 +- src/uhitm.c | 145 ++++++++++++++++++++++++++++----------------- 3 files changed, 95 insertions(+), 54 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 5565bf35f..691b87eb1 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1112,6 +1112,7 @@ dying in a wall spot (temporary gap or via Passes_walls) shared by two shops a monster capable of using a polymorph trap to deliberately change form could do so when trapped in an adjacent web or pit; if that happened, the monster remained flagged as 'trapped' and wouldn't be able to move +give feedback when some types of damage are avoided due to MC (aka negation) Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/src/mhitm.c b/src/mhitm.c index 82058a9bb..2ee234a9c 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -967,7 +967,8 @@ mdamagem(struct monst *magr, struct monst *mdef, if (!mhm.damage) return mhm.hitflags; - if ((mdef->mhp -= mhm.damage) < 1) { + mdef->mhp -= mhm.damage; + if (mdef->mhp < 1) { if (m_at(mdef->mx, mdef->my) == magr) { /* see gulpmm() */ remove_monster(mdef->mx, mdef->my); mdef->mhp = 1; /* otherwise place_monster will complain */ diff --git a/src/uhitm.c b/src/uhitm.c index 9b802d727..338542389 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -8,7 +8,7 @@ static const char brief_feeling[] = "have a %s feeling for a moment, then it passes."; -static boolean mhitm_mgc_atk_negated(struct monst *, struct monst *); +static boolean mhitm_mgc_atk_negated(struct monst *, struct monst *, boolean); static boolean known_hitum(struct monst *, struct obj *, int *, int, int, struct attack *, int); static boolean theft_petrifies(struct obj *); @@ -16,21 +16,35 @@ static void steal_it(struct monst *, struct attack *); static boolean hitum_cleave(struct monst *, struct attack *); static boolean hitum(struct monst *, struct attack *); static void hmon_hitmon_barehands(struct _hitmon_data *, struct monst *); -static void hmon_hitmon_weapon_ranged(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_weapon_melee(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_weapon(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_potion(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_misc_obj(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_do_hit(struct _hitmon_data *, struct monst *, struct obj *); +static void hmon_hitmon_weapon_ranged(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_weapon_melee(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_weapon(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_potion(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_misc_obj(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_do_hit(struct _hitmon_data *, struct monst *, + struct obj *); static void hmon_hitmon_dmg_recalc(struct _hitmon_data *, struct obj *); -static void hmon_hitmon_poison(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_jousting(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_stagger(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_pet(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_splitmon(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_msg_hit(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_msg_silver(struct _hitmon_data *, struct monst *, struct obj *); -static void hmon_hitmon_msg_lightobj(struct _hitmon_data *, struct monst *, struct obj *); +static void hmon_hitmon_poison(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_jousting(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_stagger(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_pet(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_splitmon(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_msg_hit(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_msg_silver(struct _hitmon_data *, struct monst *, + struct obj *); +static void hmon_hitmon_msg_lightobj(struct _hitmon_data *, struct monst *, + struct obj *); static boolean hmon_hitmon(struct monst *, struct obj *, int, int); static int joust(struct monst *, struct obj *); static void demonpet(void); @@ -48,15 +62,30 @@ static boolean shade_aware(struct obj *); #define PROJECTILE(obj) ((obj) && is_ammo(obj)) static boolean -mhitm_mgc_atk_negated(struct monst *magr, struct monst *mdef) +mhitm_mgc_atk_negated( + struct monst *magr, struct monst *mdef, + boolean verbosely) /* give mesg if magical cancellation prevents damage */ { - int armpro = magic_negation(mdef); - boolean negated = !(rn2(10) >= 3 * armpro); + int armpro; + boolean negated; - /* since hero can't be cancelled, only defender's armor applies */ - if (magr == &gy.youmonst) - return negated; - return magr->mcan || negated; + /* mcan doesn't apply to youmonst; hero can't be cancelled */ + if (magr != &gy.youmonst && magr->mcan) + return TRUE; /* no message if attacker has been cancelled */ + + armpro = magic_negation(mdef); + negated = !(rn2(10) >= 3 * armpro); + if (negated) { + /* attack has been thwarted by negation, aka magical cancellation */ + if (verbosely) { + if (mdef == &gy.youmonst) + You("avoid harm."); + else if (gv.vis && canseemon(mdef)) + pline("%s avoids harm.", Monnam(mdef)); + } + return TRUE; + } + return FALSE; } /* multi_reason is usually a literal string; here we generate one that @@ -2123,7 +2152,8 @@ mhitm_ad_dcay(struct monst *magr, struct attack *mattk, struct monst *mdef, return; } mhm->done = TRUE; - mhm->hitflags = (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED)); + mhm->hitflags = (MM_DEF_DIED + | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED)); return; } erode_armor(mdef, ERODE_ROT); @@ -2133,10 +2163,11 @@ mhitm_ad_dcay(struct monst *magr, struct attack *mattk, struct monst *mdef, } void -mhitm_ad_dren(struct monst *magr, struct attack *mattk, struct monst *mdef, - struct mhitm_data *mhm) +mhitm_ad_dren( + struct monst *magr, struct attack *mattk, + struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, FALSE); if (magr == &gy.youmonst) { /* uhitm */ @@ -2163,7 +2194,7 @@ mhitm_ad_drli( struct monst *magr, struct attack *mattk, struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (magr == &gy.youmonst) { /* uhitm */ @@ -2240,7 +2271,7 @@ mhitm_ad_fire( struct monst *magr, struct attack *mattk, struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); struct permonst *pd = mdef->data; if (magr == &gy.youmonst) { @@ -2303,8 +2334,9 @@ mhitm_ad_fire( if ((int) magr->m_lev > rn2(20)) ignite_items(gi.invent); burn_away_slime(); - } else + } else { mhm->damage = 0; + } } else { /* mhitm */ if (negated) { @@ -2351,7 +2383,7 @@ mhitm_ad_cold( struct monst *magr, struct attack *mattk, struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (magr == &gy.youmonst) { /* uhitm */ @@ -2407,7 +2439,7 @@ mhitm_ad_elec( struct monst *magr, struct attack *mattk, struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (magr == &gy.youmonst) { /* uhitm */ @@ -2579,10 +2611,11 @@ mhitm_ad_sgld( void -mhitm_ad_tlpt(struct monst *magr, struct attack *mattk, struct monst *mdef, - struct mhitm_data *mhm) +mhitm_ad_tlpt( + struct monst *magr, struct attack *mattk, + struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (magr == &gy.youmonst) { /* uhitm */ @@ -2809,10 +2842,11 @@ mhitm_ad_curs(struct monst *magr, struct attack *mattk, struct monst *mdef, } void -mhitm_ad_drst(struct monst *magr, struct attack *mattk, struct monst *mdef, - struct mhitm_data *mhm) +mhitm_ad_drst( + struct monst *magr, struct attack *mattk, + struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, FALSE); struct permonst *pa = magr->data; if (magr == &gy.youmonst) { @@ -2972,7 +3006,7 @@ mhitm_ad_stck( struct monst *magr, struct attack *mattk, struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, FALSE); struct permonst *pd = mdef->data; if (magr == &gy.youmonst) { @@ -3082,7 +3116,7 @@ mhitm_ad_plys( struct monst *magr, struct attack *mattk, struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (magr == &gy.youmonst) { /* uhitm */ @@ -3124,10 +3158,11 @@ mhitm_ad_plys( } void -mhitm_ad_slee(struct monst *magr, struct attack *mattk, struct monst *mdef, - struct mhitm_data *mhm UNUSED) +mhitm_ad_slee( + struct monst *magr, struct attack *mattk, + struct monst *mdef, struct mhitm_data *mhm UNUSED) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (magr == &gy.youmonst) { /* uhitm */ @@ -3165,11 +3200,13 @@ mhitm_ad_slee(struct monst *magr, struct attack *mattk, struct monst *mdef, } } +/* slime */ void -mhitm_ad_slim(struct monst *magr, struct attack *mattk, struct monst *mdef, - struct mhitm_data *mhm) +mhitm_ad_slim( + struct monst *magr, struct attack *mattk, + struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); struct permonst *pd = mdef->data; if (magr == &gy.youmonst) { @@ -3238,15 +3275,16 @@ mhitm_ad_slim(struct monst *magr, struct attack *mattk, struct monst *mdef, } void -mhitm_ad_ench(struct monst *magr, struct attack *mattk, struct monst *mdef, - struct mhitm_data *mhm UNUSED) +mhitm_ad_ench( + struct monst *magr, struct attack *mattk, + struct monst *mdef, struct mhitm_data *mhm UNUSED) { if (magr == &gy.youmonst) { /* uhitm */ /* there's no msomearmor() function, so just do damage */ } else if (mdef == &gy.youmonst) { /* mhitu */ - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, FALSE); hitmsg(magr, mattk); /* uncancelled is sufficient enough; please @@ -3289,7 +3327,7 @@ mhitm_ad_slow( struct monst *magr, struct attack *mattk, struct monst *mdef, struct mhitm_data *mhm UNUSED) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (defended(mdef, AD_SLOW)) return; @@ -3360,10 +3398,11 @@ mhitm_ad_conf(struct monst *magr, struct attack *mattk, struct monst *mdef, } void -mhitm_ad_poly(struct monst *magr, struct attack *mattk, - struct monst *mdef, struct mhitm_data *mhm) +mhitm_ad_poly( + struct monst *magr, struct attack *mattk, + struct monst *mdef, struct mhitm_data *mhm) { - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); if (magr == &gy.youmonst) { /* uhitm */ @@ -3845,7 +3884,7 @@ mhitm_ad_were( return; } else if (mdef == &gy.youmonst) { /* mhitu */ - boolean negated = mhitm_mgc_atk_negated(magr, mdef); + boolean negated = mhitm_mgc_atk_negated(magr, mdef, TRUE); hitmsg(magr, mattk); if (!negated && !rn2(4) && u.ulycn == NON_PM