-/* NetHack 3.6 dokick.c $NHDT-Date: 1446955295 2015/11/08 04:01:35 $ $NHDT-Branch: master $:$NHDT-Revision: 1.104 $ */
+/* NetHack 3.6 dokick.c $NHDT-Date: 1517128663 2018/01/28 08:37:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.113 $ */
/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */
}
}
- (void) passive(mon, TRUE, mon->mhp > 0, AT_KICK, FALSE);
+ (void) passive(mon, uarmf, TRUE, mon->mhp > 0, AT_KICK, FALSE);
if (mon->mhp <= 0 && !trapkilled)
killed(mon);
&& !is_flyer(mon->data)) {
pline("Floating in the air, you miss wildly!");
exercise(A_DEX, FALSE);
- (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+ (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
return;
}
} else if (tmp > (kickdieroll = rnd(20))) {
You("kick %s.", mon_nam(mon));
sum = damageum(mon, uattk);
- (void) passive(mon, (boolean) (sum > 0), (sum != 2), AT_KICK,
- FALSE);
+ (void) passive(mon, uarmf, (boolean) (sum > 0),
+ (sum != 2), AT_KICK, FALSE);
if (sum == 2)
break; /* Defender died */
} else {
missum(mon, uattk, (tmp + armorpenalty > kickdieroll));
- (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+ (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
}
}
return;
if (martial() && !rn2(2))
goto doit;
Your("clumsy kick does no damage.");
- (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+ (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
return;
}
if (i < j / 10)
if (!nohands(mon->data) && !rn2(martial() ? 5 : 3)) {
pline("%s blocks your %skick.", Monnam(mon),
clumsy ? "clumsy " : "");
- (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+ (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
return;
} else {
maybe_mnexto(mon);
? "slides"
: "jumps",
clumsy ? "easily" : "nimbly", clumsy ? "clumsy " : "");
- (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+ (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
return;
}
}
-/* NetHack 3.6 uhitm.c $NHDT-Date: 1513297347 2017/12/15 00:22:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.172 $ */
+/* NetHack 3.6 uhitm.c $NHDT-Date: 1517128664 2018/01/28 08:37:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.173 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
unweapon = FALSE;
if (flags.verbose) {
if (uwep)
- You("begin bashing monsters with %s.",
- yobjnam(uwep, (char *) 0));
+ You("begin bashing monsters with %s.", yname(uwep));
else if (!cantwield(youmonst.data))
- You("begin %sing monsters with your %s %s.",
- Role_if(PM_MONK) ? "strik" : "bash",
+ You("begin %s monsters with your %s %s.",
+ ing_suffix(Role_if(PM_MONK) ? "strike" : "bash"),
uarmg ? "gloved" : "bare", /* Del Lamb */
makeplural(body_part(HAND)));
}
mhit = (tmp > dieroll);
result = known_hitum(mtmp, uwep, &mhit, tmp, armorpenalty,
uattk, dieroll);
- (void) passive(mtmp, mhit, DEADMONSTER(mtmp), AT_WEAP, !uwep);
+ (void) passive(mtmp, uwep, mhit, DEADMONSTER(mtmp), AT_WEAP, !uwep);
if (mon == mtmp)
malive = result;
}
if (tmp > dieroll)
exercise(A_DEX, TRUE);
malive = known_hitum(mon, uwep, &mhit, tmp, armorpenalty, uattk, dieroll);
+ if (wepbefore && !uwep)
+ wep_was_destroyed = TRUE;
+ (void) passive(mon, uwep, mhit, malive, AT_WEAP, wep_was_destroyed);
+
/* second attack for two-weapon combat; won't occur if Stormbringer
overrode confirmation (assumes Stormbringer is primary weapon)
or if the monster was killed or knocked to different location */
mhit = (tmp > dieroll || u.uswallow);
malive = known_hitum(mon, uswapwep, &mhit, tmp, armorpenalty, uattk,
dieroll);
+ /* second passive counter-attack only occurs if second attack hits */
+ if (mhit)
+ (void) passive(mon, uswapwep, mhit, malive, AT_WEAP, !uswapwep);
}
- if (wepbefore && !uwep)
- wep_was_destroyed = TRUE;
- (void) passive(mon, mhit, malive, AT_WEAP, wep_was_destroyed);
return malive;
}
if ((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
/* pudding is alive and healthy enough to split */
&& mon->mhp > 1 && !mon->mcan
- /* iron weapon using melee or polearm hit [3.6.1: metal weapon too] */
- && obj && obj == uwep
+ /* iron weapon using melee or polearm hit [3.6.1: metal weapon too;
+ also allow either or both weapons to cause split when twoweap] */
+ && obj && (obj == uwep || (u.twoweap && obj == uswapwep))
&& ((objects[obj->otyp].oc_material == IRON
/* allow scalpel and tsurugi to split puddings */
|| objects[obj->otyp].oc_material == METAL)
&& !(is_ammo(obj) || is_missile(obj)))
&& hand_to_hand) {
if (clone_mon(mon, 0, 0)) {
- pline("%s divides as you hit it!", Monnam(mon));
+ char withwhat[BUFSZ];
+
+ withwhat[0] = '\0';
+ if (u.twoweap && flags.verbose)
+ Sprintf(withwhat, " with %s", yname(obj));
+ pline("%s divides as you hit it%s!", Monnam(mon), withwhat);
hittxt = TRUE;
}
}
register struct monst *mon;
{
struct attack *mattk, alt_attk;
- struct obj *weapon;
+ struct obj *weapon, **originalweapon;
boolean altwep = FALSE, weapon_used = FALSE;
int i, tmp, armorpenalty, sum[NATTK], nsum = 0, dhit = 0, attknum = 0;
int dieroll;
for (i = 0; i < NATTK; i++) {
sum[i] = 0;
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
+ weapon = 0;
switch (mattk->aatyp) {
case AT_WEAP:
use_weapon:
* we currently allow the player to get each of these as a weapon
* attack. Is this really desirable?
*/
- /* approximate two-weapon mode */
- weapon = (altwep && uswapwep) ? uswapwep : uwep;
- altwep = !altwep; /* toggle for next attack */
+ /* approximate two-weapon mode; known_hitum() -> hmon() -> &c
+ might destroy the weapon argument, but it might also already
+ be Null, and we want to track that for passive() */
+ originalweapon = (altwep && uswapwep) ? &uswapwep : &uwep;
+ if (uswapwep /* set up 'altwep' flag for next iteration */
+ /* only switch to uswapwep if it's a weapon */
+ && (uswapwep->oclass == WEAPON_CLASS || is_weptool(uswapwep))
+ /* only switch if uswapwep is not bow, arrows, or darts */
+ && !(is_launcher(uswapwep) || is_ammo(uswapwep)
+ || is_missile(uswapwep))) /* dart, shuriken, boomerang */
+ altwep = !altwep; /* toggle for next attack */
+ weapon = *originalweapon;
+ if (!weapon) /* no need to go beyond no-gloves to rings; not ...*/
+ originalweapon = &uarmg; /*... subject to erosion damage */
+
tmp = find_roll_to_hit(mon, AT_WEAP, weapon, &attknum,
&armorpenalty);
dieroll = rnd(20);
dhit = (tmp > dieroll || u.uswallow);
/* Enemy dead, before any special abilities used */
- if (!known_hitum(mon, weapon, &dhit, tmp, armorpenalty, mattk,
- dieroll)) {
+ if (!known_hitum(mon, weapon, &dhit, tmp,
+ armorpenalty, mattk, dieroll)) {
sum[i] = 2;
break;
} else
sum[i] = dhit;
+ /* originalweapon points to an equipment slot which might
+ now be empty if the weapon was destroyed during the hit;
+ passive(,weapon,...) won't call passive_obj() in that case */
+ weapon = *originalweapon; /* might receive passive erosion */
/* might be a worm that gets cut in half */
if (m_at(u.ux + u.dx, u.uy + u.dy) != mon)
return (boolean) (nsum != 0);
u.mh = -1; /* dead in the current form */
rehumanize();
}
- if (sum[i] == 2)
- return (boolean) passive(mon, 1, 0, mattk->aatyp, FALSE);
- /* defender dead */
- else {
- (void) passive(mon, sum[i], 1, mattk->aatyp, FALSE);
+ if (sum[i] == 2) {
+ /* defender dead */
+ return (boolean) passive(mon, weapon, 1, 0, mattk->aatyp, FALSE);
+ } else {
+ (void) passive(mon, weapon, sum[i], 1, mattk->aatyp, FALSE);
nsum |= sum[i];
}
if (!Upolyd)
/* Special (passive) attacks on you by monsters done here.
*/
int
-passive(mon, mhit, malive, aatyp, wep_was_destroyed)
-register struct monst *mon;
-register boolean mhit;
-register int malive;
+passive(mon, weapon, mhit, malive, aatyp, wep_was_destroyed)
+struct monst *mon;
+struct obj *weapon; /* uwep or uswapwep or uarmg or uarmf or Null */
+boolean mhit;
+int malive;
uchar aatyp;
boolean wep_was_destroyed;
{
*/
switch (ptr->mattk[i].adtyp) {
case AD_FIRE:
- if (mhit && !mon->mcan) {
+ if (mhit && !mon->mcan && weapon) {
if (aatyp == AT_KICK) {
if (uarmf && !rn2(6))
(void) erode_obj(uarmf, xname(uarmf), ERODE_BURN,
EF_GREASE | EF_VERBOSE);
} else if (aatyp == AT_WEAP || aatyp == AT_CLAW
|| aatyp == AT_MAGC || aatyp == AT_TUCH)
- passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+ passive_obj(mon, weapon, &(ptr->mattk[i]));
}
break;
case AD_ACID:
if (!rn2(30))
erode_armor(&youmonst, ERODE_CORRODE);
}
- if (mhit) {
+ if (mhit && weapon) {
if (aatyp == AT_KICK) {
if (uarmf && !rn2(6))
(void) erode_obj(uarmf, xname(uarmf), ERODE_CORRODE,
EF_GREASE | EF_VERBOSE);
} else if (aatyp == AT_WEAP || aatyp == AT_CLAW
|| aatyp == AT_MAGC || aatyp == AT_TUCH)
- passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+ passive_obj(mon, weapon, &(ptr->mattk[i]));
}
exercise(A_STR, FALSE);
break;
}
break;
case AD_RUST:
- if (mhit && !mon->mcan) {
+ if (mhit && !mon->mcan && weapon) {
if (aatyp == AT_KICK) {
if (uarmf)
(void) erode_obj(uarmf, xname(uarmf), ERODE_RUST,
EF_GREASE | EF_VERBOSE);
} else if (aatyp == AT_WEAP || aatyp == AT_CLAW
|| aatyp == AT_MAGC || aatyp == AT_TUCH)
- passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+ passive_obj(mon, weapon, &(ptr->mattk[i]));
}
break;
case AD_CORR:
- if (mhit && !mon->mcan) {
+ if (mhit && !mon->mcan && weapon) {
if (aatyp == AT_KICK) {
if (uarmf)
(void) erode_obj(uarmf, xname(uarmf), ERODE_CORRODE,
EF_GREASE | EF_VERBOSE);
} else if (aatyp == AT_WEAP || aatyp == AT_CLAW
|| aatyp == AT_MAGC || aatyp == AT_TUCH)
- passive_obj(mon, (struct obj *) 0, &(ptr->mattk[i]));
+ passive_obj(mon, weapon, &(ptr->mattk[i]));
}
break;
case AD_MAGM:
break;
case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
if (mhit) {
- struct obj *obj = (struct obj *) 0;
-
if (aatyp == AT_KICK) {
- obj = uarmf;
- if (!obj)
+ if (!weapon)
break;
} else if (aatyp == AT_BITE || aatyp == AT_BUTT
|| (aatyp >= AT_STNG && aatyp < AT_WEAP)) {
break; /* no object involved */
}
- passive_obj(mon, obj, &(ptr->mattk[i]));
+ passive_obj(mon, weapon, &(ptr->mattk[i]));
}
break;
default:
struct permonst *ptr = mon->data;
int i;
+ /* [this first bit is obsolete; we're not called with Null anymore] */
/* if caller hasn't specified an object, use uwep, uswapwep or uarmg */
if (!obj) {
obj = (u.twoweap && uswapwep && !rn2(2)) ? uswapwep : uwep;