Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2019-01-23 00:42:41 -05:00
8 changed files with 369 additions and 107 deletions
+8 -1
View File
@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.232 $ $NHDT-Date: 1547849604 2019/01/18 22:13:24 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.235 $ $NHDT-Date: 1548209734 2019/01/23 02:15:34 $
This fixes36.2 file is here to capture information about updates in the 3.6.x This fixes36.2 file is here to capture information about updates in the 3.6.x
lineage following the release of 3.6.1 in April 2018. Please note, however, lineage following the release of 3.6.1 in April 2018. Please note, however,
@@ -343,6 +343,13 @@ the simulation of dual weapon combat when polymorphed into a form with more
even when current shape couldn't handle silver, or if it was cursed; even when current shape couldn't handle silver, or if it was cursed;
cursed is allowed but weapon will be dropped, just like in two-weapon cursed is allowed but weapon will be dropped, just like in two-weapon
demons gated in other demons without any message demons gated in other demons without any message
if vampire revives from from dead bat/cloud/wolf shape held by hero poly'd
into grabber, release it from hero's grasp
various non-weapon attacks while polymorphed didn't inflict blessed or silver
weapon damage when worn items contacted vulnerable target monsters
hero poly'd into rope golem form could choke headless or non-breathing monsts
hero poly'd into creature with hug attack could hug a long worm's tail which
rendered the whole worm immobile
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
+5 -2
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1547486885 2019/01/14 17:28:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.682 $ */ /* NetHack 3.6 extern.h $NHDT-Date: 1548209735 2019/01/23 02:15:35 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.684 $ */
/* Copyright (c) Steve Creps, 1988. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1907,6 +1907,7 @@ E int NDECL(dogaze);
E int NDECL(dohide); E int NDECL(dohide);
E int NDECL(dopoly); E int NDECL(dopoly);
E int NDECL(domindblast); E int NDECL(domindblast);
E void NDECL(uunstick);
E void FDECL(skinback, (BOOLEAN_P)); E void FDECL(skinback, (BOOLEAN_P));
E const char *FDECL(mbodypart, (struct monst *, int)); E const char *FDECL(mbodypart, (struct monst *, int));
E const char *FDECL(body_part, (int)); E const char *FDECL(body_part, (int));
@@ -2516,7 +2517,7 @@ E int FDECL(find_roll_to_hit, (struct monst *, UCHAR_P, struct obj *,
int *, int *)); int *, int *));
E boolean FDECL(attack, (struct monst *)); E boolean FDECL(attack, (struct monst *));
E boolean FDECL(hmon, (struct monst *, struct obj *, int, int)); E boolean FDECL(hmon, (struct monst *, struct obj *, int, int));
E int FDECL(damageum, (struct monst *, struct attack *)); E int FDECL(damageum, (struct monst *, struct attack *, int));
E void FDECL(missum, (struct monst *, struct attack *, BOOLEAN_P)); E void FDECL(missum, (struct monst *, struct attack *, BOOLEAN_P));
E int FDECL(passive, (struct monst *, struct obj *, BOOLEAN_P, int, E int FDECL(passive, (struct monst *, struct obj *, BOOLEAN_P, int,
UCHAR_P, BOOLEAN_P)); UCHAR_P, BOOLEAN_P));
@@ -2733,6 +2734,8 @@ E int FDECL(vms_get_saved_games, (const char *, char ***));
E const char *FDECL(weapon_descr, (struct obj *)); E const char *FDECL(weapon_descr, (struct obj *));
E int FDECL(hitval, (struct obj *, struct monst *)); E int FDECL(hitval, (struct obj *, struct monst *));
E int FDECL(dmgval, (struct obj *, struct monst *)); E int FDECL(dmgval, (struct obj *, struct monst *));
E int FDECL(special_dmgval, (struct monst *, struct monst *, long, long *));
E void FDECL(silver_sears, (struct monst *, struct monst *, long));
E struct obj *FDECL(select_rwep, (struct monst *)); E struct obj *FDECL(select_rwep, (struct monst *));
E boolean FDECL(monmightthrowwep, (struct obj *)); E boolean FDECL(monmightthrowwep, (struct obj *));
E struct obj *FDECL(select_hwep, (struct monst *)); E struct obj *FDECL(select_hwep, (struct monst *));
+2 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mondata.h $NHDT-Date: 1547086248 2019/01/10 02:10:48 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.35 $ */ /* NetHack 3.6 mondata.h $NHDT-Date: 1548209737 2019/01/23 02:15:37 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.36 $ */
/* Copyright (c) 1989 Mike Threepoint */ /* Copyright (c) 1989 Mike Threepoint */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -59,6 +59,7 @@
#define slithy(ptr) (((ptr)->mflags1 & M1_SLITHY) != 0L) #define slithy(ptr) (((ptr)->mflags1 & M1_SLITHY) != 0L)
#define is_wooden(ptr) ((ptr) == &mons[PM_WOOD_GOLEM]) #define is_wooden(ptr) ((ptr) == &mons[PM_WOOD_GOLEM])
#define thick_skinned(ptr) (((ptr)->mflags1 & M1_THICK_HIDE) != 0L) #define thick_skinned(ptr) (((ptr)->mflags1 & M1_THICK_HIDE) != 0L)
#define hug_throttles(ptr) ((ptr) == &mons[PM_ROPE_GOLEM])
#define slimeproof(ptr) \ #define slimeproof(ptr) \
((ptr) == &mons[PM_GREEN_SLIME] || flaming(ptr) || noncorporeal(ptr)) ((ptr) == &mons[PM_GREEN_SLIME] || flaming(ptr) || noncorporeal(ptr))
#define lays_eggs(ptr) (((ptr)->mflags1 & M1_OVIPAROUS) != 0L) #define lays_eggs(ptr) (((ptr)->mflags1 & M1_OVIPAROUS) != 0L)
+17 -18
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. */ /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -23,15 +23,15 @@ STATIC_DCL void FDECL(drop_to, (coord *, SCHAR_P));
static const char kick_passes_thru[] = "kick passes harmlessly through"; 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 STATIC_OVL void
kickdmg(mon, clumsy) kickdmg(mon, clumsy)
register struct monst *mon; struct monst *mon;
register boolean clumsy; boolean clumsy;
{ {
register int mdx, mdy; int mdx, mdy;
register int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15; int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
int kick_skill = P_NONE; int specialdmg, kick_skill = P_NONE;
int blessed_foot_damage = 0;
boolean trapkilled = FALSE; boolean trapkilled = FALSE;
if (uarmf && uarmf->otyp == KICKING_BOOTS) if (uarmf && uarmf->otyp == KICKING_BOOTS)
@@ -45,15 +45,13 @@ register boolean clumsy;
if (thick_skinned(mon->data)) if (thick_skinned(mon->data))
dmg = 0; dmg = 0;
/* attacking a shade is useless */ /* attacking a shade is normally useless */
if (mon->data == &mons[PM_SHADE]) if (mon->data == &mons[PM_SHADE])
dmg = 0; dmg = 0;
if ((is_undead(mon->data) || is_demon(mon->data) || is_vampshifter(mon)) specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
&& uarmf && uarmf->blessed)
blessed_foot_damage = 1;
if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) { if (mon->data == &mons[PM_SHADE] && !specialdmg) {
pline_The("%s.", kick_passes_thru); pline_The("%s.", kick_passes_thru);
/* doesn't exercise skill or abuse alignment or frighten pet, /* doesn't exercise skill or abuse alignment or frighten pet,
and shades have no passive counterattack */ and shades have no passive counterattack */
@@ -85,8 +83,7 @@ register boolean clumsy;
/* a good kick exercises your dex */ /* a good kick exercises your dex */
exercise(A_DEX, TRUE); exercise(A_DEX, TRUE);
} }
if (blessed_foot_damage) dmg += specialdmg; /* for blessed (or hypothetically, silver) boots */
dmg += rnd(4);
if (uarmf) if (uarmf)
dmg += uarmf->spe; dmg += uarmf->spe;
dmg += u.udaminc; /* add ring(s) of increase damage */ dmg += u.udaminc; /* add ring(s) of increase damage */
@@ -184,7 +181,7 @@ xchar x, y;
*/ */
if (Upolyd && attacktype(g.youmonst.data, AT_KICK)) { if (Upolyd && attacktype(g.youmonst.data, AT_KICK)) {
struct attack *uattk; struct attack *uattk;
int sum, kickdieroll, armorpenalty, int sum, kickdieroll, armorpenalty, specialdmg,
attknum = 0, attknum = 0,
tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum, tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum,
&armorpenalty); &armorpenalty);
@@ -200,14 +197,16 @@ xchar x, y;
if (uattk->aatyp != AT_KICK) if (uattk->aatyp != AT_KICK)
continue; 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, /* doesn't matter whether it would have hit or missed,
and shades have no passive counterattack */ and shades have no passive counterattack */
Your("%s %s.", kick_passes_thru, mon_nam(mon)); Your("%s %s.", kick_passes_thru, mon_nam(mon));
break; /* skip any additional kicks */ break; /* skip any additional kicks */
} else if (tmp > (kickdieroll = rnd(20))) { } else if (tmp > kickdieroll) {
You("kick %s.", mon_nam(mon)); You("kick %s.", mon_nam(mon));
sum = damageum(mon, uattk); sum = damageum(mon, uattk, specialdmg);
(void) passive(mon, uarmf, (boolean) (sum > 0), (void) passive(mon, uarmf, (boolean) (sum > 0),
(sum != 2), AT_KICK, FALSE); (sum != 2), AT_KICK, FALSE);
if (sum == 2) if (sum == 2)
+9 -4
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 mon.c $NHDT-Date: 1545430257 2018/12/21 22:10:57 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.276 $ */ /* NetHack 3.6 mon.c $NHDT-Date: 1548208236 2019/01/23 01:50:36 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.277 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */ /*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1941,9 +1941,14 @@ register struct monst *mtmp;
if (mtmp->mhpmax <= 0) if (mtmp->mhpmax <= 0)
mtmp->mhpmax = 10; mtmp->mhpmax = 10;
mtmp->mhp = mtmp->mhpmax; mtmp->mhp = mtmp->mhpmax;
/* this can happen if previously a fog cloud */ /* mtmp==u.ustuck can happen if previously a fog cloud
if (u.uswallow && (mtmp == u.ustuck)) or poly'd hero is hugging a vampire bat */
expels(mtmp, mtmp->data, FALSE); if (mtmp == u.ustuck) {
if (u.uswallow)
expels(mtmp, mtmp->data, FALSE);
else
uunstick();
}
if (in_door) { if (in_door) {
coord new_xy; coord new_xy;
+10 -3
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 polyself.c $NHDT-Date: 1547086249 2019/01/10 02:10:49 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.125 $ */ /* NetHack 3.6 polyself.c $NHDT-Date: 1548208238 2019/01/23 01:50:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.126 $ */
/* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -25,7 +25,6 @@ STATIC_DCL void FDECL(check_strangling, (BOOLEAN_P));
STATIC_DCL void FDECL(polyman, (const char *, const char *)); STATIC_DCL void FDECL(polyman, (const char *, const char *));
STATIC_DCL void NDECL(break_armor); STATIC_DCL void NDECL(break_armor);
STATIC_DCL void FDECL(drop_weapon, (int)); STATIC_DCL void FDECL(drop_weapon, (int));
STATIC_DCL void NDECL(uunstick);
STATIC_DCL int FDECL(armor_to_dragon, (int)); STATIC_DCL int FDECL(armor_to_dragon, (int));
STATIC_DCL void NDECL(newman); STATIC_DCL void NDECL(newman);
STATIC_DCL void NDECL(polysense); STATIC_DCL void NDECL(polysense);
@@ -743,10 +742,14 @@ int mntmp;
} }
newsym(u.ux, u.uy); /* Change symbol */ newsym(u.ux, u.uy); /* Change symbol */
/* [note: this 'sticky' handling is only sufficient for changing from
grabber to engulfer or vice versa because engulfing by poly'd hero
always ends immediately so won't be in effect during a polymorph] */
if (!sticky && !u.uswallow && u.ustuck && sticks(g.youmonst.data)) if (!sticky && !u.uswallow && u.ustuck && sticks(g.youmonst.data))
u.ustuck = 0; u.ustuck = 0;
else if (sticky && !sticks(g.youmonst.data)) else if (sticky && !sticks(g.youmonst.data))
uunstick(); uunstick();
if (u.usteed) { if (u.usteed) {
if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) { if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) {
pline("%s touch %s.", no_longer_petrify_resistant, pline("%s touch %s.", no_longer_petrify_resistant,
@@ -1537,9 +1540,13 @@ domindblast()
return 1; return 1;
} }
STATIC_OVL void void
uunstick() uunstick()
{ {
if (!u.ustuck) {
impossible("uunstick: no ustuck?");
return;
}
pline("%s is no longer in your clutches.", Monnam(u.ustuck)); pline("%s is no longer in your clutches.", Monnam(u.ustuck));
u.ustuck = 0; u.ustuck = 0;
} }
+206 -77
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1548125661 2019/01/22 02:54:21 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.202 $ */ /* NetHack 3.6 uhitm.c $NHDT-Date: 1548209742 2019/01/23 02:15:42 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.203 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -387,6 +387,7 @@ register struct monst *mtmp;
it uses g.bhitpos instead; it might map an invisible monster there */ it uses g.bhitpos instead; it might map an invisible monster there */
g.bhitpos.x = u.ux + u.dx; g.bhitpos.x = u.ux + u.dx;
g.bhitpos.y = u.uy + u.dy; g.bhitpos.y = u.uy + u.dy;
notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
if (attack_checks(mtmp, uwep)) if (attack_checks(mtmp, uwep))
return TRUE; return TRUE;
@@ -681,6 +682,7 @@ int dieroll;
/* not grapnels; applied implies uwep */ /* not grapnels; applied implies uwep */
|| (thrown == HMON_APPLIED && is_pole(uwep))); || (thrown == HMON_APPLIED && is_pole(uwep)));
int jousting = 0; int jousting = 0;
long silverhit = 0L;
int wtype; int wtype;
struct obj *monwep; struct obj *monwep;
char unconventional[BUFSZ]; /* substituted for word "attack" in msg */ char unconventional[BUFSZ]; /* substituted for word "attack" in msg */
@@ -698,23 +700,15 @@ int dieroll;
else else
tmp = rnd(2); tmp = rnd(2);
valid_weapon_attack = (tmp > 1); valid_weapon_attack = (tmp > 1);
/* blessed gloves give bonuses when fighting 'bare-handed' */ /* Blessed gloves give bonuses when fighting 'bare-handed'. So do
if (uarmg && uarmg->blessed silver rings. Note: rings are worn under gloves, so you don't
&& (is_undead(mdat) || is_demon(mdat) || is_vampshifter(mon))) get both bonuses, and two silver rings don't give double bonus. */
tmp += rnd(4); tmp += special_dmgval(&youmonst, mon, (W_ARMG | W_RINGL | W_RINGR),
/* So do silver rings. Note: rings are worn under gloves, so you &silverhit);
* don't get both bonuses. barehand_silver_rings += (((silverhit & W_RINGL) ? 1 : 0)
*/ + ((silverhit & W_RINGR) ? 1 : 0));
if (!uarmg) { if (barehand_silver_rings > 0)
if (uleft && objects[uleft->otyp].oc_material == SILVER) silvermsg = TRUE;
barehand_silver_rings++;
if (uright && objects[uright->otyp].oc_material == SILVER)
barehand_silver_rings++;
if (barehand_silver_rings && mon_hates_silver(mon)) {
tmp += rnd(20);
silvermsg = TRUE;
}
}
} else { } else {
if (!(artifact_light(obj) && obj->lamplit)) if (!(artifact_light(obj) && obj->lamplit))
Strcpy(saved_oname, cxname(obj)); Strcpy(saved_oname, cxname(obj));
@@ -1566,9 +1560,10 @@ struct attack *mattk;
} }
int int
damageum(mdef, mattk) damageum(mdef, mattk, specialdmg)
register struct monst *mdef; register struct monst *mdef;
register struct attack *mattk; register struct attack *mattk;
int specialdmg; /* blessed and/or silver bonus against various things */
{ {
register struct permonst *pd = mdef->data; register struct permonst *pd = mdef->data;
int armpro, tmp = d((int) mattk->damn, (int) mattk->damd); int armpro, tmp = d((int) mattk->damn, (int) mattk->damd);
@@ -1604,19 +1599,24 @@ register struct attack *mattk;
case AD_HEAL: /* likewise */ case AD_HEAL: /* likewise */
case AD_PHYS: case AD_PHYS:
physical: physical:
if (pd == &mons[PM_SHADE]) {
tmp = 0;
if (!specialdmg)
impossible("bad shade attack function flow?");
}
tmp += specialdmg;
if (mattk->aatyp == AT_WEAP) { if (mattk->aatyp == AT_WEAP) {
if (uwep) /* hmonas() uses known_hitum() to deal physical damage,
tmp = 0; then also damageum() for non-AD_PHYS; don't inflict
} else if (mattk->aatyp == AT_KICK) { extra physical damage for unusual damage types */
tmp = 0;
} else if (mattk->aatyp == AT_KICK
|| mattk->aatyp == AT_CLAW
|| mattk->aatyp == AT_TUCH
|| mattk->aatyp == AT_HUGS) {
if (thick_skinned(pd)) if (thick_skinned(pd))
tmp = 0; tmp = (mattk->aatyp == AT_KICK) ? 0 : (tmp + 1) / 2;
if (pd == &mons[PM_SHADE]) {
if (!(uarmf && uarmf->blessed)) {
impossible("bad shade attack function flow?");
tmp = 0;
} else
tmp = rnd(4); /* bless damage */
}
/* add ring(s) of increase damage */ /* add ring(s) of increase damage */
if (u.udaminc > 0) { if (u.udaminc > 0) {
/* applies even if damage was 0 */ /* applies even if damage was 0 */
@@ -2117,7 +2117,7 @@ register struct attack *mattk;
} }
/* Use up amulet of life saving */ /* Use up amulet of life saving */
if (!!(otmp = mlifesaver(mdef))) if ((otmp = mlifesaver(mdef)) != 0)
m_useup(mdef, otmp); m_useup(mdef, otmp);
newuhs(FALSE); newuhs(FALSE);
@@ -2279,9 +2279,20 @@ register struct monst *mon;
{ {
struct attack *mattk, alt_attk; struct attack *mattk, alt_attk;
struct obj *weapon, **originalweapon; struct obj *weapon, **originalweapon;
boolean altwep = FALSE, weapon_used = FALSE; boolean altwep = FALSE, weapon_used = FALSE, odd_claw = TRUE;
int i, tmp, armorpenalty, sum[NATTK], nsum = 0, dhit = 0, attknum = 0; int i, tmp, armorpenalty, sum[NATTK], nsum = 0, dhit = 0, attknum = 0;
int dieroll; int dieroll, multi_claw = 0;
/* with just one touch/claw/weapon attack, both rings matter;
with more than one, alternate right and left when checking
whether silver ring causes successful hit */
for (i = 0; i < NATTK; i++) {
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
if (mattk->aatyp == AT_WEAP
|| mattk->aatyp == AT_CLAW || mattk->aatyp == AT_TUCH)
++multi_claw;
}
multi_claw = (multi_claw > 1); /* switch from count to yes/no */
for (i = 0; i < NATTK; i++) { for (i = 0; i < NATTK; i++) {
sum[i] = 0; sum[i] = 0;
@@ -2289,7 +2300,9 @@ register struct monst *mon;
weapon = 0; weapon = 0;
switch (mattk->aatyp) { switch (mattk->aatyp) {
case AT_WEAP: case AT_WEAP:
/* if (!uwep) goto weaponless; */
use_weapon: use_weapon:
odd_claw = !odd_claw; /* see case AT_CLAW,AT_TUCH below */
/* if we've already hit with a two-handed weapon, we don't /* if we've already hit with a two-handed weapon, we don't
get to make another weapon attack (note: monsters who get to make another weapon attack (note: monsters who
use weapons do not have this restriction, but they also use weapons do not have this restriction, but they also
@@ -2358,7 +2371,7 @@ register struct monst *mon;
} }
/* Do not print "You hit" message; known_hitum already did it. */ /* Do not print "You hit" message; known_hitum already did it. */
if (dhit && mattk->adtyp != AD_SPEL && mattk->adtyp != AD_PHYS) if (dhit && mattk->adtyp != AD_SPEL && mattk->adtyp != AD_PHYS)
sum[i] = damageum(mon, mattk); sum[i] = damageum(mon, mattk, 0);
break; break;
case AT_CLAW: case AT_CLAW:
if (uwep && !cantwield(g.youmonst.data) && !weapon_used) if (uwep && !cantwield(g.youmonst.data) && !weapon_used)
@@ -2373,73 +2386,189 @@ register struct monst *mon;
case AT_STNG: case AT_STNG:
case AT_BUTT: case AT_BUTT:
case AT_TENT: case AT_TENT:
/*weaponless:*/
tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0, tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
&attknum, &armorpenalty); &attknum, &armorpenalty);
dieroll = rnd(20); dieroll = rnd(20);
dhit = (tmp > dieroll || u.uswallow); dhit = (tmp > dieroll || u.uswallow);
if (dhit) { if (dhit) {
int compat; int compat, specialdmg;
long silverhit = 0L;
const char *verb = 0; /* verb or body part */
if (!u.uswallow if (!u.uswallow
&& (compat = could_seduce(&g.youmonst, mon, mattk))) { && (compat = could_seduce(&g.youmonst, mon, mattk)) != 0) {
You("%s %s %s.", You("%s %s %s.",
mon->mcansee && haseyes(mon->data) ? "smile at" (mon->mcansee && haseyes(mon->data)) ? "smile at"
: "talk to", : "talk to",
mon_nam(mon), mon_nam(mon),
compat == 2 ? "engagingly" : "seductively"); (compat == 2) ? "engagingly" : "seductively");
/* doesn't anger it; no wakeup() */ /* doesn't anger it; no wakeup() */
sum[i] = damageum(mon, mattk); sum[i] = damageum(mon, mattk, 0);
break; break;
} }
wakeup(mon, TRUE); wakeup(mon, TRUE);
/* maybe this check should be in damageum()? */
if (mon->data == &mons[PM_SHADE] specialdmg = 0; /* blessed and/or silver bonus */
&& !(mattk->aatyp == AT_KICK && uarmf switch (mattk->aatyp) {
&& uarmf->blessed)) { case AT_CLAW:
Your("attack passes harmlessly through %s.", case AT_TUCH:
mon_nam(mon)); /* verb=="claws" may be overridden below */
verb = (mattk->aatyp == AT_TUCH) ? "touch" : "claws";
/* decide if silver-hater will be hit by silver ring(s);
for 'multi_claw' where attacks alternate right/left,
assume 'even' claw or touch attacks use right hand
or paw, 'odd' ones use left for ring interaction;
even vs odd is based on actual attacks rather
than on index into mon->dat->mattk[] so that {bite,
claw,claw} instead of {claw,claw,bite} doesn't
make poly'd hero mysteriously become left-handed */
odd_claw = !odd_claw;
specialdmg = special_dmgval(&youmonst, mon,
W_ARMG
| ((odd_claw || !multi_claw)
? W_RINGL : 0L)
| ((!odd_claw || !multi_claw)
? W_RINGR : 0L),
&silverhit);
break;
case AT_TENT:
/* assumes mind flayer's tentacles-on-head rather
than sea monster's tentacle-as-arm */
verb = "tentacles";
break;
case AT_KICK:
verb = "kick";
specialdmg = special_dmgval(&youmonst, mon, W_ARMF,
&silverhit);
break;
case AT_BUTT:
verb = "head butt"; /* mbodypart(mon,HEAD)=="head" */
/* hypothetical; if any form with a head-butt attack
could wear a helmet, it would hit shades when
wearing a blessed (or silver) one */
specialdmg = special_dmgval(&youmonst, mon, W_ARMH,
&silverhit);
break;
case AT_BITE:
verb = "bite";
break;
case AT_STNG:
verb = "sting";
break;
default:
verb = "hit";
break; break;
} }
if (mattk->aatyp == AT_KICK) if (mon->data == &mons[PM_SHADE] && !specialdmg) {
You("kick %s.", mon_nam(mon)); if (!strcmp(verb, "hit")
else if (mattk->aatyp == AT_BITE) || (mattk->aatyp == AT_CLAW && humanoid(mon->data)))
You("bite %s.", mon_nam(mon)); verb = "attack";
else if (mattk->aatyp == AT_STNG) Your("%s %s harmlessly through %s.",
You("sting %s.", mon_nam(mon)); verb, vtense(verb, "pass"), mon_nam(mon));
else if (mattk->aatyp == AT_BUTT) } else {
You("butt %s.", mon_nam(mon)); if (mattk->aatyp == AT_TENT) {
else if (mattk->aatyp == AT_TUCH) Your("tentacles suck %s.", mon_nam(mon));
You("touch %s.", mon_nam(mon)); } else {
else if (mattk->aatyp == AT_TENT) if (mattk->aatyp == AT_CLAW)
Your("tentacles suck %s.", mon_nam(mon)); verb = "hit"; /* not "claws" */
else You("%s %s.", verb, mon_nam(mon));
You("hit %s.", mon_nam(mon)); if (silverhit && flags.verbose)
sum[i] = damageum(mon, mattk); silver_sears(&youmonst, mon, silverhit);
} else { }
sum[i] = damageum(mon, mattk, specialdmg);
}
} else { /* !dhit */
missum(mon, mattk, (tmp + armorpenalty > dieroll)); missum(mon, mattk, (tmp + armorpenalty > dieroll));
} }
break; break;
case AT_HUGS: case AT_HUGS: {
int specialdmg;
long silverhit = 0L;
boolean byhand = hug_throttles(&mons[u.umonnum]), /* rope golem */
unconcerned = (byhand && !can_be_strangled(mon));
if (sticks(mon->data) || u.uswallow || notonhead
|| (byhand && (uwep || !has_head(mon->data)))) {
/* can't hold a holder due to subsequent ambiguity over
who is holding whom; can't hug engulfer from inside;
can't hug a worm tail (would immobilize entire worm!);
byhand: can't choke something that lacks a head;
not allowed to make a choking hug if wielding a weapon
(but might have grabbed w/o weapon, then wielded one,
and may even be attacking a different monster now) */
if (byhand && uwep && u.ustuck
&& !(sticks(u.ustuck->data) || u.uswallow))
uunstick();
continue; /* not 'break'; bypass passive counter-attack */
}
/* automatic if prev two attacks succeed, or if /* automatic if prev two attacks succeed, or if
* already grabbed in a previous attack already grabbed in a previous attack */
*/
dhit = 1; dhit = 1;
wakeup(mon, TRUE); wakeup(mon, TRUE);
if (mon->data == &mons[PM_SHADE]) /* choking hug/throttling grab uses hands (gloves or rings);
Your("hug passes harmlessly through %s.", mon_nam(mon)); normal hug uses outermost of cloak/suit/shirt */
else if (!sticks(mon->data) && !u.uswallow) { specialdmg = special_dmgval(&youmonst, mon,
if (mon == u.ustuck) { byhand ? (W_ARMG | W_RINGL | W_RINGR)
pline("%s is being %s.", Monnam(mon), : (W_ARMC | W_ARM | W_ARMU),
u.umonnum == PM_ROPE_GOLEM ? "choked" : "crushed"); &silverhit);
sum[i] = damageum(mon, mattk); if (unconcerned) {
} else if (i >= 2 && sum[i - 1] && sum[i - 2]) { /* strangling something which can't be strangled */
You("grab %s!", mon_nam(mon)); if (mattk != &alt_attk) {
u.ustuck = mon; alt_attk = *mattk;
sum[i] = damageum(mon, mattk); mattk = &alt_attk;
} }
/* change damage to 1d1; not strangling but still
doing [minimal] physical damage to victim's body */
mattk->damn = mattk->damd = 1;
/* don't give 'unconcerned' feedback if there is extra damage
or if it is nearly destroyed or if creature doesn't have
the mental ability to be concerned in the first place */
if (specialdmg || mindless(mon->data)
|| mon->mhp <= 1 + max(u.udaminc, 1))
unconcerned = FALSE;
} }
break; if (mon->data == &mons[PM_SHADE]) {
const char *verb = byhand ? "grasp" : "hug";
/* hugging a shade; successful if blessed outermost armor
for normal hug, or blessed gloves or silver ring(s) for
choking hug; deals damage but never grabs hold */
if (specialdmg) {
You("%s %s%s", verb, mon_nam(mon), exclam(specialdmg));
if (silverhit && flags.verbose)
silver_sears(&youmonst, mon, silverhit);
sum[i] = damageum(mon, mattk, specialdmg);
} else {
Your("%s passes harmlessly through %s.",
verb, mon_nam(mon));
}
break;
}
/* hug attack against ordinary foe */
if (mon == u.ustuck) {
pline("%s is being %s%s.", Monnam(mon),
byhand ? "throttled" : "crushed",
/* extra feedback for non-breather being choked */
unconcerned ? " but doesn't seem concerned" : "");
if (silverhit && flags.verbose)
silver_sears(&youmonst, mon, silverhit);
sum[i] = damageum(mon, mattk, specialdmg);
} else if (i >= 2 && sum[i - 1] && sum[i - 2]) {
/* in case we're hugging a new target while already
holding something else; yields feedback
"<u.ustuck> is no longer in your clutches" */
if (u.ustuck && u.ustuck != mon)
uunstick();
You("grab %s!", mon_nam(mon));
u.ustuck = mon;
if (silverhit && flags.verbose)
silver_sears(&youmonst, mon, silverhit);
sum[i] = damageum(mon, mattk, specialdmg);
}
break; /* AT_HUGS */
}
case AT_EXPL: /* automatic hit if next to */ case AT_EXPL: /* automatic hit if next to */
dhit = -1; dhit = -1;
+112 -1
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 weapon.c $NHDT-Date: 1547025169 2019/01/09 09:12:49 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.68 $ */ /* NetHack 3.6 weapon.c $NHDT-Date: 1548209744 2019/01/23 02:15:44 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.69 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -350,6 +350,117 @@ struct monst *mon;
return tmp; return tmp;
} }
/* check whether blessed and/or silver damage applies for *non-weapon* hit;
return value is the amount of the extra damage */
int
special_dmgval(magr, mdef, armask, silverhit_p)
struct monst *magr, *mdef;
long armask; /* armor mask, multiple bits accepted for W_ARMC|W_ARM|W_ARMU
* or W_ARMG|W_RINGL|W_RINGR only */
long *silverhit_p; /* output flag mask for silver bonus */
{
struct obj *obj;
struct permonst *ptr = mdef->data;
boolean left_ring = (armask & W_RINGL) ? TRUE : FALSE,
right_ring = (armask & W_RINGR) ? TRUE : FALSE;
long silverhit = 0L;
int bonus = 0;
obj = 0;
if (armask & (W_ARMC | W_ARM | W_ARMU)) {
if ((armask & W_ARMC) != 0L
&& (obj = which_armor(magr, W_ARMC)) != 0)
armask = W_ARMC;
else if ((armask & W_ARM) != 0L
&& (obj = which_armor(magr, W_ARM)) != 0)
armask = W_ARM;
else if ((armask & W_ARMU) != 0L
&& (obj = which_armor(magr, W_ARMU)) != 0)
armask = W_ARMU;
else
armask = 0L;
} else if (armask & (W_ARMG | W_RINGL | W_RINGR)) {
armask = ((obj = which_armor(magr, W_ARMG)) != 0) ? W_ARMG : 0L;
} else {
obj = which_armor(magr, armask);
}
if (obj) {
if (obj->blessed
&& (is_undead(ptr) || is_demon(ptr) || is_vampshifter(mdef)))
bonus += rnd(4);
/* the only silver armor is shield of reflection (silver dragon
scales refer to color, not material) and the only way to hit
with one--aside from throwing--is to wield it and perform a
weapon hit, but we include a general check here */
if (objects[obj->otyp].oc_material == SILVER
&& mon_hates_silver(mdef)) {
bonus += rnd(20);
silverhit |= armask;
}
/* when no gloves we check for silver rings (blessed rings ignored) */
} else if ((left_ring || right_ring) && magr == &youmonst) {
if (left_ring && uleft) {
if (objects[uleft->otyp].oc_material == SILVER
&& mon_hates_silver(mdef)) {
bonus += rnd(20);
silverhit |= W_RINGL;
}
}
if (right_ring && uright) {
if (objects[uright->otyp].oc_material == SILVER
&& mon_hates_silver(mdef)) {
/* two silver rings don't give double silver damage
but 'silverhit' messages might be adjusted for them */
if (!(silverhit & W_RINGL))
bonus += rnd(20);
silverhit |= W_RINGR;
}
}
}
if (silverhit_p)
*silverhit_p = silverhit;
return bonus;
}
/* give a "silver <item> sears <target>" message;
not used for weapon hit, so we only handle rings */
void
silver_sears(magr, mdef, silverhit)
struct monst *magr UNUSED;
struct monst *mdef;
long silverhit;
{
char rings[20]; /* plenty of room for "rings" */
int ltyp = ((uleft && (silverhit & W_RINGL) != 0L)
? uleft->otyp : STRANGE_OBJECT),
rtyp = ((uright && (silverhit & W_RINGR) != 0L)
? uright->otyp : STRANGE_OBJECT);
boolean both,
l_ag = (objects[ltyp].oc_material == SILVER && uleft->dknown),
r_ag = (objects[rtyp].oc_material == SILVER && uright->dknown);
if ((silverhit & (W_RINGL | W_RINGR)) != 0L) {
/* plural if both the same type (so not multi_claw and both rings
are non-Null) and either both known or neither known, or both
silver (in case there is ever more than one type of silver ring)
and both known; singular if multi_claw (where one of ltyp or
rtyp will always be STRANGE_OBJECT) even if both rings are known
silver [see hmonas(uhitm.c) for explanation of 'multi_claw'] */
both = ((ltyp == rtyp && uleft->dknown == uright->dknown)
|| (l_ag && r_ag));
Sprintf(rings, "ring%s", both ? "s" : "");
Your("%s%s %s %s!",
(l_ag || r_ag) ? "silver "
: both ? ""
: ((silverhit & W_RINGL) != 0L) ? "left "
: "right ",
rings, vtense(rings, "sear"), mon_nam(mdef));
}
}
STATIC_DCL struct obj *FDECL(oselect, (struct monst *, int)); STATIC_DCL struct obj *FDECL(oselect, (struct monst *, int));
#define Oselect(x) \ #define Oselect(x) \
if ((otmp = oselect(mtmp, x)) != 0) \ if ((otmp = oselect(mtmp, x)) != 0) \