Merge branch 'NetHack-3.6.2'
This commit is contained in:
@@ -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
|
||||
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;
|
||||
cursed is allowed but weapon will be dropped, just like in two-weapon
|
||||
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
|
||||
|
||||
@@ -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. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1907,6 +1907,7 @@ E int NDECL(dogaze);
|
||||
E int NDECL(dohide);
|
||||
E int NDECL(dopoly);
|
||||
E int NDECL(domindblast);
|
||||
E void NDECL(uunstick);
|
||||
E void FDECL(skinback, (BOOLEAN_P));
|
||||
E const char *FDECL(mbodypart, (struct monst *, 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 *));
|
||||
E boolean FDECL(attack, (struct monst *));
|
||||
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 int FDECL(passive, (struct monst *, struct obj *, BOOLEAN_P, int,
|
||||
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 int FDECL(hitval, (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 boolean FDECL(monmightthrowwep, (struct obj *));
|
||||
E struct obj *FDECL(select_hwep, (struct monst *));
|
||||
|
||||
@@ -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 */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define slithy(ptr) (((ptr)->mflags1 & M1_SLITHY) != 0L)
|
||||
#define is_wooden(ptr) ((ptr) == &mons[PM_WOOD_GOLEM])
|
||||
#define thick_skinned(ptr) (((ptr)->mflags1 & M1_THICK_HIDE) != 0L)
|
||||
#define hug_throttles(ptr) ((ptr) == &mons[PM_ROPE_GOLEM])
|
||||
#define slimeproof(ptr) \
|
||||
((ptr) == &mons[PM_GREEN_SLIME] || flaming(ptr) || noncorporeal(ptr))
|
||||
#define lays_eggs(ptr) (((ptr)->mflags1 & M1_OVIPAROUS) != 0L)
|
||||
|
||||
35
src/dokick.c
35
src/dokick.c
@@ -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. */
|
||||
|
||||
@@ -23,15 +23,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)
|
||||
@@ -45,15 +45,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 */
|
||||
@@ -85,8 +83,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 */
|
||||
@@ -184,7 +181,7 @@ xchar x, y;
|
||||
*/
|
||||
if (Upolyd && attacktype(g.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);
|
||||
@@ -200,14 +197,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)
|
||||
|
||||
13
src/mon.c
13
src/mon.c
@@ -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) Derek S. Ray, 2015. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -1941,9 +1941,14 @@ register struct monst *mtmp;
|
||||
if (mtmp->mhpmax <= 0)
|
||||
mtmp->mhpmax = 10;
|
||||
mtmp->mhp = mtmp->mhpmax;
|
||||
/* this can happen if previously a fog cloud */
|
||||
if (u.uswallow && (mtmp == u.ustuck))
|
||||
expels(mtmp, mtmp->data, FALSE);
|
||||
/* mtmp==u.ustuck can happen if previously a fog cloud
|
||||
or poly'd hero is hugging a vampire bat */
|
||||
if (mtmp == u.ustuck) {
|
||||
if (u.uswallow)
|
||||
expels(mtmp, mtmp->data, FALSE);
|
||||
else
|
||||
uunstick();
|
||||
}
|
||||
if (in_door) {
|
||||
coord new_xy;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
/* 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 NDECL(break_armor);
|
||||
STATIC_DCL void FDECL(drop_weapon, (int));
|
||||
STATIC_DCL void NDECL(uunstick);
|
||||
STATIC_DCL int FDECL(armor_to_dragon, (int));
|
||||
STATIC_DCL void NDECL(newman);
|
||||
STATIC_DCL void NDECL(polysense);
|
||||
@@ -743,10 +742,14 @@ int mntmp;
|
||||
}
|
||||
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))
|
||||
u.ustuck = 0;
|
||||
else if (sticky && !sticks(g.youmonst.data))
|
||||
uunstick();
|
||||
|
||||
if (u.usteed) {
|
||||
if (touch_petrifies(u.usteed->data) && !Stone_resistance && rnl(3)) {
|
||||
pline("%s touch %s.", no_longer_petrify_resistant,
|
||||
@@ -1537,9 +1540,13 @@ domindblast()
|
||||
return 1;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
void
|
||||
uunstick()
|
||||
{
|
||||
if (!u.ustuck) {
|
||||
impossible("uunstick: no ustuck?");
|
||||
return;
|
||||
}
|
||||
pline("%s is no longer in your clutches.", Monnam(u.ustuck));
|
||||
u.ustuck = 0;
|
||||
}
|
||||
|
||||
283
src/uhitm.c
283
src/uhitm.c
@@ -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) Robert Patrick Rankin, 2012. */
|
||||
/* 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 */
|
||||
g.bhitpos.x = u.ux + u.dx;
|
||||
g.bhitpos.y = u.uy + u.dy;
|
||||
notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
|
||||
if (attack_checks(mtmp, uwep))
|
||||
return TRUE;
|
||||
|
||||
@@ -681,6 +682,7 @@ int dieroll;
|
||||
/* not grapnels; applied implies uwep */
|
||||
|| (thrown == HMON_APPLIED && is_pole(uwep)));
|
||||
int jousting = 0;
|
||||
long silverhit = 0L;
|
||||
int wtype;
|
||||
struct obj *monwep;
|
||||
char unconventional[BUFSZ]; /* substituted for word "attack" in msg */
|
||||
@@ -698,23 +700,15 @@ int dieroll;
|
||||
else
|
||||
tmp = rnd(2);
|
||||
valid_weapon_attack = (tmp > 1);
|
||||
/* blessed gloves give bonuses when fighting 'bare-handed' */
|
||||
if (uarmg && uarmg->blessed
|
||||
&& (is_undead(mdat) || is_demon(mdat) || is_vampshifter(mon)))
|
||||
tmp += rnd(4);
|
||||
/* So do silver rings. Note: rings are worn under gloves, so you
|
||||
* don't get both bonuses.
|
||||
*/
|
||||
if (!uarmg) {
|
||||
if (uleft && objects[uleft->otyp].oc_material == SILVER)
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* Blessed gloves give bonuses when fighting 'bare-handed'. So do
|
||||
silver rings. Note: rings are worn under gloves, so you don't
|
||||
get both bonuses, and two silver rings don't give double bonus. */
|
||||
tmp += special_dmgval(&youmonst, mon, (W_ARMG | W_RINGL | W_RINGR),
|
||||
&silverhit);
|
||||
barehand_silver_rings += (((silverhit & W_RINGL) ? 1 : 0)
|
||||
+ ((silverhit & W_RINGR) ? 1 : 0));
|
||||
if (barehand_silver_rings > 0)
|
||||
silvermsg = TRUE;
|
||||
} else {
|
||||
if (!(artifact_light(obj) && obj->lamplit))
|
||||
Strcpy(saved_oname, cxname(obj));
|
||||
@@ -1566,9 +1560,10 @@ struct attack *mattk;
|
||||
}
|
||||
|
||||
int
|
||||
damageum(mdef, mattk)
|
||||
damageum(mdef, mattk, specialdmg)
|
||||
register struct monst *mdef;
|
||||
register struct attack *mattk;
|
||||
int specialdmg; /* blessed and/or silver bonus against various things */
|
||||
{
|
||||
register struct permonst *pd = mdef->data;
|
||||
int armpro, tmp = d((int) mattk->damn, (int) mattk->damd);
|
||||
@@ -1604,19 +1599,24 @@ register struct attack *mattk;
|
||||
case AD_HEAL: /* likewise */
|
||||
case AD_PHYS:
|
||||
physical:
|
||||
if (pd == &mons[PM_SHADE]) {
|
||||
tmp = 0;
|
||||
if (!specialdmg)
|
||||
impossible("bad shade attack function flow?");
|
||||
}
|
||||
tmp += specialdmg;
|
||||
|
||||
if (mattk->aatyp == AT_WEAP) {
|
||||
if (uwep)
|
||||
tmp = 0;
|
||||
} else if (mattk->aatyp == AT_KICK) {
|
||||
/* hmonas() uses known_hitum() to deal physical damage,
|
||||
then also damageum() for non-AD_PHYS; don't inflict
|
||||
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))
|
||||
tmp = 0;
|
||||
if (pd == &mons[PM_SHADE]) {
|
||||
if (!(uarmf && uarmf->blessed)) {
|
||||
impossible("bad shade attack function flow?");
|
||||
tmp = 0;
|
||||
} else
|
||||
tmp = rnd(4); /* bless damage */
|
||||
}
|
||||
tmp = (mattk->aatyp == AT_KICK) ? 0 : (tmp + 1) / 2;
|
||||
/* add ring(s) of increase damage */
|
||||
if (u.udaminc > 0) {
|
||||
/* applies even if damage was 0 */
|
||||
@@ -2117,7 +2117,7 @@ register struct attack *mattk;
|
||||
}
|
||||
|
||||
/* Use up amulet of life saving */
|
||||
if (!!(otmp = mlifesaver(mdef)))
|
||||
if ((otmp = mlifesaver(mdef)) != 0)
|
||||
m_useup(mdef, otmp);
|
||||
|
||||
newuhs(FALSE);
|
||||
@@ -2279,9 +2279,20 @@ register struct monst *mon;
|
||||
{
|
||||
struct attack *mattk, alt_attk;
|
||||
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 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++) {
|
||||
sum[i] = 0;
|
||||
@@ -2289,7 +2300,9 @@ register struct monst *mon;
|
||||
weapon = 0;
|
||||
switch (mattk->aatyp) {
|
||||
case AT_WEAP:
|
||||
/* if (!uwep) goto weaponless; */
|
||||
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
|
||||
get to make another weapon attack (note: monsters who
|
||||
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. */
|
||||
if (dhit && mattk->adtyp != AD_SPEL && mattk->adtyp != AD_PHYS)
|
||||
sum[i] = damageum(mon, mattk);
|
||||
sum[i] = damageum(mon, mattk, 0);
|
||||
break;
|
||||
case AT_CLAW:
|
||||
if (uwep && !cantwield(g.youmonst.data) && !weapon_used)
|
||||
@@ -2373,73 +2386,189 @@ register struct monst *mon;
|
||||
case AT_STNG:
|
||||
case AT_BUTT:
|
||||
case AT_TENT:
|
||||
/*weaponless:*/
|
||||
tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
|
||||
&attknum, &armorpenalty);
|
||||
dieroll = rnd(20);
|
||||
dhit = (tmp > dieroll || u.uswallow);
|
||||
if (dhit) {
|
||||
int compat;
|
||||
int compat, specialdmg;
|
||||
long silverhit = 0L;
|
||||
const char *verb = 0; /* verb or body part */
|
||||
|
||||
if (!u.uswallow
|
||||
&& (compat = could_seduce(&g.youmonst, mon, mattk))) {
|
||||
&& (compat = could_seduce(&g.youmonst, mon, mattk)) != 0) {
|
||||
You("%s %s %s.",
|
||||
mon->mcansee && haseyes(mon->data) ? "smile at"
|
||||
: "talk to",
|
||||
(mon->mcansee && haseyes(mon->data)) ? "smile at"
|
||||
: "talk to",
|
||||
mon_nam(mon),
|
||||
compat == 2 ? "engagingly" : "seductively");
|
||||
(compat == 2) ? "engagingly" : "seductively");
|
||||
/* doesn't anger it; no wakeup() */
|
||||
sum[i] = damageum(mon, mattk);
|
||||
sum[i] = damageum(mon, mattk, 0);
|
||||
break;
|
||||
}
|
||||
wakeup(mon, TRUE);
|
||||
/* maybe this check should be in damageum()? */
|
||||
if (mon->data == &mons[PM_SHADE]
|
||||
&& !(mattk->aatyp == AT_KICK && uarmf
|
||||
&& uarmf->blessed)) {
|
||||
Your("attack passes harmlessly through %s.",
|
||||
mon_nam(mon));
|
||||
|
||||
specialdmg = 0; /* blessed and/or silver bonus */
|
||||
switch (mattk->aatyp) {
|
||||
case AT_CLAW:
|
||||
case AT_TUCH:
|
||||
/* 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;
|
||||
}
|
||||
if (mattk->aatyp == AT_KICK)
|
||||
You("kick %s.", mon_nam(mon));
|
||||
else if (mattk->aatyp == AT_BITE)
|
||||
You("bite %s.", mon_nam(mon));
|
||||
else if (mattk->aatyp == AT_STNG)
|
||||
You("sting %s.", mon_nam(mon));
|
||||
else if (mattk->aatyp == AT_BUTT)
|
||||
You("butt %s.", mon_nam(mon));
|
||||
else if (mattk->aatyp == AT_TUCH)
|
||||
You("touch %s.", mon_nam(mon));
|
||||
else if (mattk->aatyp == AT_TENT)
|
||||
Your("tentacles suck %s.", mon_nam(mon));
|
||||
else
|
||||
You("hit %s.", mon_nam(mon));
|
||||
sum[i] = damageum(mon, mattk);
|
||||
} else {
|
||||
if (mon->data == &mons[PM_SHADE] && !specialdmg) {
|
||||
if (!strcmp(verb, "hit")
|
||||
|| (mattk->aatyp == AT_CLAW && humanoid(mon->data)))
|
||||
verb = "attack";
|
||||
Your("%s %s harmlessly through %s.",
|
||||
verb, vtense(verb, "pass"), mon_nam(mon));
|
||||
} else {
|
||||
if (mattk->aatyp == AT_TENT) {
|
||||
Your("tentacles suck %s.", mon_nam(mon));
|
||||
} else {
|
||||
if (mattk->aatyp == AT_CLAW)
|
||||
verb = "hit"; /* not "claws" */
|
||||
You("%s %s.", verb, mon_nam(mon));
|
||||
if (silverhit && flags.verbose)
|
||||
silver_sears(&youmonst, mon, silverhit);
|
||||
}
|
||||
sum[i] = damageum(mon, mattk, specialdmg);
|
||||
}
|
||||
} else { /* !dhit */
|
||||
missum(mon, mattk, (tmp + armorpenalty > dieroll));
|
||||
}
|
||||
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
|
||||
* already grabbed in a previous attack
|
||||
*/
|
||||
already grabbed in a previous attack */
|
||||
dhit = 1;
|
||||
wakeup(mon, TRUE);
|
||||
if (mon->data == &mons[PM_SHADE])
|
||||
Your("hug passes harmlessly through %s.", mon_nam(mon));
|
||||
else if (!sticks(mon->data) && !u.uswallow) {
|
||||
if (mon == u.ustuck) {
|
||||
pline("%s is being %s.", Monnam(mon),
|
||||
u.umonnum == PM_ROPE_GOLEM ? "choked" : "crushed");
|
||||
sum[i] = damageum(mon, mattk);
|
||||
} else if (i >= 2 && sum[i - 1] && sum[i - 2]) {
|
||||
You("grab %s!", mon_nam(mon));
|
||||
u.ustuck = mon;
|
||||
sum[i] = damageum(mon, mattk);
|
||||
/* choking hug/throttling grab uses hands (gloves or rings);
|
||||
normal hug uses outermost of cloak/suit/shirt */
|
||||
specialdmg = special_dmgval(&youmonst, mon,
|
||||
byhand ? (W_ARMG | W_RINGL | W_RINGR)
|
||||
: (W_ARMC | W_ARM | W_ARMU),
|
||||
&silverhit);
|
||||
if (unconcerned) {
|
||||
/* strangling something which can't be strangled */
|
||||
if (mattk != &alt_attk) {
|
||||
alt_attk = *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 */
|
||||
dhit = -1;
|
||||
|
||||
113
src/weapon.c
113
src/weapon.c
@@ -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) Robert Patrick Rankin, 2011. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -350,6 +350,117 @@ struct monst *mon;
|
||||
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));
|
||||
#define Oselect(x) \
|
||||
if ((otmp = oselect(mtmp, x)) != 0) \
|
||||
|
||||
Reference in New Issue
Block a user