fix #H6422 - hmonas against shades

I did much of this quite some time ago, as prequisite for a different
bug report about monsters vs shades, then set it aside.  It ended up
being more complicated than I anticipated.

When deciding whether various non-weapon attacks might hit a shade,
hmonas() was not checking for blessed or silver armor that should have
been applicable.  It did check boots when kicking, but not gloves or
rings (when no gloves) when touching, or outermost of cloak/suit/shirt
when hugging, or helmet when head-butting.  (The last one is actually
moot because nothing with a head-butt attack is able to wear a helm.)

The problem was more general than just whether attacks might hit and
hurt shades.  Various undead and/or demons are also affected by blessed
and/or silver attack but weren't for non-weapon attacks by poly'd hero.

At least two unrelated bugs are fixed:  a rope golem's AT_HUGS attack
gives feedback about choking but was fully effective against monsters
which fail the can_be_strangled() test.  And it was possible to hug a
long worm's tail, rendering the entire worm immobile.

The report also suggested that all artifacts be able to hit shades for
full effect, but by the time shades are encountered everyone has an
artifact so that would nullify a shade's most interesting ability.

TODO:  monster against hero and monster against other monster need to
have similar changes.
This commit is contained in:
PatR
2019-01-22 18:15:49 -08:00
parent d0cc645961
commit deed117e7f
6 changed files with 347 additions and 100 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 dokick.c $NHDT-Date: 1547086527 2019/01/10 02:15:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.129 $ */
/* NetHack 3.6 dokick.c $NHDT-Date: 1548209738 2019/01/23 02:15:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.130 $ */
/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
@@ -28,15 +28,15 @@ STATIC_DCL void FDECL(drop_to, (coord *, SCHAR_P));
static const char kick_passes_thru[] = "kick passes harmlessly through";
/* kicking damage when not poly'd into a form with a kick attack */
STATIC_OVL void
kickdmg(mon, clumsy)
register struct monst *mon;
register boolean clumsy;
struct monst *mon;
boolean clumsy;
{
register int mdx, mdy;
register int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
int kick_skill = P_NONE;
int blessed_foot_damage = 0;
int mdx, mdy;
int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
int specialdmg, kick_skill = P_NONE;
boolean trapkilled = FALSE;
if (uarmf && uarmf->otyp == KICKING_BOOTS)
@@ -50,15 +50,13 @@ register boolean clumsy;
if (thick_skinned(mon->data))
dmg = 0;
/* attacking a shade is useless */
/* attacking a shade is normally useless */
if (mon->data == &mons[PM_SHADE])
dmg = 0;
if ((is_undead(mon->data) || is_demon(mon->data) || is_vampshifter(mon))
&& uarmf && uarmf->blessed)
blessed_foot_damage = 1;
specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
if (mon->data == &mons[PM_SHADE] && !specialdmg) {
pline_The("%s.", kick_passes_thru);
/* doesn't exercise skill or abuse alignment or frighten pet,
and shades have no passive counterattack */
@@ -90,8 +88,7 @@ register boolean clumsy;
/* a good kick exercises your dex */
exercise(A_DEX, TRUE);
}
if (blessed_foot_damage)
dmg += rnd(4);
dmg += specialdmg; /* for blessed (or hypothetically, silver) boots */
if (uarmf)
dmg += uarmf->spe;
dmg += u.udaminc; /* add ring(s) of increase damage */
@@ -189,7 +186,7 @@ xchar x, y;
*/
if (Upolyd && attacktype(youmonst.data, AT_KICK)) {
struct attack *uattk;
int sum, kickdieroll, armorpenalty,
int sum, kickdieroll, armorpenalty, specialdmg,
attknum = 0,
tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum,
&armorpenalty);
@@ -205,14 +202,16 @@ xchar x, y;
if (uattk->aatyp != AT_KICK)
continue;
if (mon->data == &mons[PM_SHADE] && (!uarmf || !uarmf->blessed)) {
kickdieroll = rnd(20);
specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
if (mon->data == &mons[PM_SHADE] && !specialdmg) {
/* doesn't matter whether it would have hit or missed,
and shades have no passive counterattack */
Your("%s %s.", kick_passes_thru, mon_nam(mon));
break; /* skip any additional kicks */
} else if (tmp > (kickdieroll = rnd(20))) {
} else if (tmp > kickdieroll) {
You("kick %s.", mon_nam(mon));
sum = damageum(mon, uattk);
sum = damageum(mon, uattk, specialdmg);
(void) passive(mon, uarmf, (boolean) (sum > 0),
(sum != 2), AT_KICK, FALSE);
if (sum == 2)