|
|
|
|
@@ -14,6 +14,7 @@ static boolean known_hitum(struct monst *, struct obj *, int *, int, int,
|
|
|
|
|
static boolean theft_petrifies(struct obj *);
|
|
|
|
|
static void steal_it(struct monst *, struct attack *);
|
|
|
|
|
static boolean hitum_cleave(struct monst *, struct attack *);
|
|
|
|
|
static boolean double_punch(void);
|
|
|
|
|
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 *,
|
|
|
|
|
@@ -714,21 +715,37 @@ hitum_cleave(
|
|
|
|
|
return (target && DEADMONSTER(target)) ? FALSE : TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* returns True if hero is fighting without a weapon and has sufficient
|
|
|
|
|
skill in bare-handeded combat or martial arts to attack twice */
|
|
|
|
|
static boolean
|
|
|
|
|
double_punch(void)
|
|
|
|
|
{
|
|
|
|
|
/* note: P_BARE_HANDED_COMBAT and P_MARTIAL_ARTS are equivalent */
|
|
|
|
|
int skl_lvl = P_SKILL(P_BARE_HANDED_COMBAT);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Chance to attempt a second bare-handed or martial arts hit:
|
|
|
|
|
* restricted (0), [not applicable; no one is restricted]
|
|
|
|
|
* unskilled (1) : 0%
|
|
|
|
|
* basic (2) : 0%
|
|
|
|
|
* skilled (3) : 20%
|
|
|
|
|
* expert (4) : 40%
|
|
|
|
|
* master (5) : 60%
|
|
|
|
|
* grandmaster (6) : 80%
|
|
|
|
|
*/
|
|
|
|
|
if (!uwep && skl_lvl > P_BASIC)
|
|
|
|
|
return (skl_lvl - P_BASIC) > rn2(5);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* hit target monster; returns TRUE if it still lives */
|
|
|
|
|
static boolean
|
|
|
|
|
hitum(struct monst *mon, struct attack *uattk)
|
|
|
|
|
{
|
|
|
|
|
boolean malive, wep_was_destroyed = FALSE;
|
|
|
|
|
struct obj *wepbefore = uwep;
|
|
|
|
|
int armorpenalty, attknum = 0,
|
|
|
|
|
x = u.ux + u.dx, y = u.uy + u.dy,
|
|
|
|
|
oldumort = u.umortality,
|
|
|
|
|
tmp = find_roll_to_hit(mon, uattk->aatyp, uwep,
|
|
|
|
|
&attknum, &armorpenalty),
|
|
|
|
|
dieroll = rnd(20),
|
|
|
|
|
mhit = (tmp > dieroll || u.uswallow);
|
|
|
|
|
|
|
|
|
|
mon_maybe_unparalyze(mon);
|
|
|
|
|
int tmp, dieroll, mhit, armorpenalty, attknum = 0,
|
|
|
|
|
x = u.ux + u.dx, y = u.uy + u.dy, oldumort = u.umortality;
|
|
|
|
|
|
|
|
|
|
/* Cleaver attacks three spots, 'mon' and one on either side of 'mon';
|
|
|
|
|
it can't be part of dual-wielding but we guard against that anyway;
|
|
|
|
|
@@ -737,22 +754,34 @@ hitum(struct monst *mon, struct attack *uattk)
|
|
|
|
|
&& !u.uswallow && !u.ustuck && !NODIAG(u.umonnum))
|
|
|
|
|
return hitum_cleave(mon, uattk);
|
|
|
|
|
|
|
|
|
|
/* 0: single hit, 1: first of two hits; affects strength bonus and
|
|
|
|
|
silver rings; known_hitum() -> hmon() -> hmon_hitmon() will copy
|
|
|
|
|
gt.twohits into struct _hitmon_data hmd.twohits */
|
|
|
|
|
gt.twohits = (uwep ? u.twoweap : double_punch()) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
tmp = find_roll_to_hit(mon, uattk->aatyp, uwep, &attknum, &armorpenalty);
|
|
|
|
|
mon_maybe_unparalyze(mon);
|
|
|
|
|
dieroll = rnd(20);
|
|
|
|
|
mhit = (tmp > dieroll || u.uswallow);
|
|
|
|
|
if (tmp > dieroll)
|
|
|
|
|
exercise(A_DEX, TRUE);
|
|
|
|
|
|
|
|
|
|
/* gb.bhitpos is set up by caller */
|
|
|
|
|
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 hero became paralyzed by passive counter-attack, or if hero
|
|
|
|
|
was killed by passive counter-attack and got life-saved, or if
|
|
|
|
|
monster was killed or knocked to different location */
|
|
|
|
|
if (u.twoweap && !(go.override_confirmation
|
|
|
|
|
|| gm.multi < 0 || u.umortality > oldumort
|
|
|
|
|
|| !malive || m_at(x, y) != mon)) {
|
|
|
|
|
/* second attack for two-weapon combat or skilled unarmed combat;
|
|
|
|
|
won't occur if Stormbringer overrode confirmation (assumes
|
|
|
|
|
Stormbringer is primary weapon), or if hero became paralyzed by
|
|
|
|
|
passive counter-attack, or if hero was killed by passive
|
|
|
|
|
counter-attack and got life-saved, or if monster was killed or
|
|
|
|
|
knocked to different location */
|
|
|
|
|
if (gt.twohits && !(go.override_confirmation
|
|
|
|
|
|| gm.multi < 0 || u.umortality > oldumort
|
|
|
|
|
|| !malive || m_at(x, y) != mon)) {
|
|
|
|
|
gt.twohits = 2; /* second of 2 hits */
|
|
|
|
|
tmp = find_roll_to_hit(mon, uattk->aatyp, uswapwep, &attknum,
|
|
|
|
|
&armorpenalty);
|
|
|
|
|
mon_maybe_unparalyze(mon);
|
|
|
|
|
@@ -764,6 +793,7 @@ hitum(struct monst *mon, struct attack *uattk)
|
|
|
|
|
if (mhit)
|
|
|
|
|
(void) passive(mon, uswapwep, mhit, malive, AT_WEAP, !uswapwep);
|
|
|
|
|
}
|
|
|
|
|
gt.twohits = 0;
|
|
|
|
|
return malive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -790,7 +820,7 @@ hmon(struct monst *mon,
|
|
|
|
|
static void
|
|
|
|
|
hmon_hitmon_barehands(struct _hitmon_data *hmd, struct monst *mon)
|
|
|
|
|
{
|
|
|
|
|
long silverhit = 0L; /* armor mask */
|
|
|
|
|
long spcdmgflg, silverhit = 0L; /* worn masks */
|
|
|
|
|
|
|
|
|
|
if (hmd->mdat == &mons[PM_SHADE]) {
|
|
|
|
|
hmd->dmg = 0;
|
|
|
|
|
@@ -804,11 +834,32 @@ hmon_hitmon_barehands(struct _hitmon_data *hmd, struct monst *mon)
|
|
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
|
hmd->dmg += special_dmgval(&gy.youmonst, mon,
|
|
|
|
|
(W_ARMG | W_RINGL | W_RINGR), &silverhit);
|
|
|
|
|
hmd->barehand_silver_rings = (((silverhit & W_RINGL) ? 1 : 0)
|
|
|
|
|
+ ((silverhit & W_RINGR) ? 1 : 0));
|
|
|
|
|
get both bonuses, and two silver rings don't give double bonus.
|
|
|
|
|
When making only one hit, both rings are checked (backwards
|
|
|
|
|
compatibility => playability), but when making two hits, only the
|
|
|
|
|
ring on the hand making the attack is checked. */
|
|
|
|
|
spcdmgflg = uarmg ? W_ARMG
|
|
|
|
|
: ((hmd->twohits == 0 || hmd->twohits == 1) ? W_RINGR : 0L
|
|
|
|
|
| (hmd->twohits == 0 || hmd->twohits == 2) ? W_RINGL : 0L);
|
|
|
|
|
hmd->dmg += special_dmgval(&gy.youmonst, mon, spcdmgflg, &silverhit);
|
|
|
|
|
|
|
|
|
|
/* copy silverhit info back into struct _hitmon_data *hmd */
|
|
|
|
|
switch (hmd->twohits) {
|
|
|
|
|
case 0: /* only one hit being attempted; a silver ring on either hand
|
|
|
|
|
* applies but having silver rings on both is same as just one */
|
|
|
|
|
hmd->barehand_silver_rings = (silverhit & (W_RINGR | W_RINGL)) ? 1 : 0;
|
|
|
|
|
break;
|
|
|
|
|
case 1: /* first of two or more hit attempts; right ring applies */
|
|
|
|
|
hmd->barehand_silver_rings = (silverhit & W_RINGR) ? 1 : 0;
|
|
|
|
|
break;
|
|
|
|
|
case 2: /* second of two or more hit attempts; left ring applies */
|
|
|
|
|
hmd->barehand_silver_rings = (silverhit & W_RINGL) ? 1 : 0;
|
|
|
|
|
break;
|
|
|
|
|
default: /* third or later of more than two hit attempts (poly'd hero);
|
|
|
|
|
* rings were applied on first and second hits */
|
|
|
|
|
hmd->barehand_silver_rings = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (hmd->barehand_silver_rings > 0)
|
|
|
|
|
hmd->silvermsg = TRUE;
|
|
|
|
|
}
|
|
|
|
|
@@ -1308,19 +1359,39 @@ hmon_hitmon_do_hit(
|
|
|
|
|
static void
|
|
|
|
|
hmon_hitmon_dmg_recalc(struct _hitmon_data *hmd, struct obj *obj)
|
|
|
|
|
{
|
|
|
|
|
int dmgbonus = 0;
|
|
|
|
|
int dmgbonus = 0, strbonus, absbonus;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Potential bonus (or penalty) from worn ring of increase damage
|
|
|
|
|
* (or intrinsic bonus from eating same) or from strength.
|
|
|
|
|
* (or intrinsic bonus from eating same) or from strength. Strength
|
|
|
|
|
* bonus is increased for melee with two-handed weapons and decreased
|
|
|
|
|
* for dual attacks (but when both hit, the total for the two is more
|
|
|
|
|
* than the bonus for a regular single hit).
|
|
|
|
|
*/
|
|
|
|
|
if (hmd->get_dmg_bonus) {
|
|
|
|
|
/* for dual attacks, udaminc applies to both, and two-handed
|
|
|
|
|
weapons use it as-is */
|
|
|
|
|
dmgbonus = u.udaminc;
|
|
|
|
|
/* throwing using a propellor gets an increase-damage bonus
|
|
|
|
|
but not a strength one; other attacks get both */
|
|
|
|
|
but not a strength one; other attacks get both;
|
|
|
|
|
for dual attacks, 3/4 of the strength bonus is used; when
|
|
|
|
|
both attacks hit, overall bonus is 3/2 rather than doubled;
|
|
|
|
|
melee hit with two-handed weapon uses 3/2 strength bonus to
|
|
|
|
|
appoximately match double hit with two-weapon ('approximate'
|
|
|
|
|
becase udaminc skews in favor of two-weapon); the 3/2 factor
|
|
|
|
|
for two-handed strength does not apply to polearms unless
|
|
|
|
|
hero is simply bashing with one of those and does not apply
|
|
|
|
|
to jousting because lances are one-handed */
|
|
|
|
|
if (hmd->thrown != HMON_THROWN
|
|
|
|
|
|| !obj || !uwep || !ammo_and_launcher(obj, uwep))
|
|
|
|
|
dmgbonus += dbon();
|
|
|
|
|
|| !obj || !uwep || !ammo_and_launcher(obj, uwep)) {
|
|
|
|
|
strbonus = dbon();
|
|
|
|
|
absbonus = abs(strbonus);
|
|
|
|
|
if (hmd->twohits)
|
|
|
|
|
strbonus = ((3 * absbonus + 2) / 4) * sgn(strbonus);
|
|
|
|
|
else if (hmd->thrown == HMON_MELEE && uwep && bimanual(uwep))
|
|
|
|
|
strbonus = ((3 * absbonus + 1) / 2) * sgn(strbonus);
|
|
|
|
|
dmgbonus += strbonus;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -1594,6 +1665,7 @@ hmon_hitmon(
|
|
|
|
|
|
|
|
|
|
hmd.dmg = 0;
|
|
|
|
|
hmd.thrown = thrown;
|
|
|
|
|
hmd.twohits = thrown ? 0 : gt.twohits;
|
|
|
|
|
hmd.dieroll = dieroll;
|
|
|
|
|
hmd.mdat = mon->data;
|
|
|
|
|
hmd.use_weapon_skill = FALSE;
|
|
|
|
|
@@ -5133,7 +5205,7 @@ hmonas(struct monst *mon)
|
|
|
|
|
struct obj *weapon, **originalweapon;
|
|
|
|
|
boolean altwep = FALSE, weapon_used = FALSE, odd_claw = TRUE;
|
|
|
|
|
int i, tmp, dieroll, armorpenalty, sum[NATTK],
|
|
|
|
|
dhit = 0, attknum = 0, multi_claw = 0;
|
|
|
|
|
dhit = 0, attknum = 0, multi_claw = 0, multi_weap = 0;
|
|
|
|
|
boolean monster_survived;
|
|
|
|
|
|
|
|
|
|
/* not used here but umpteen mhitm_ad_xxxx() need this */
|
|
|
|
|
@@ -5145,11 +5217,14 @@ hmonas(struct monst *mon)
|
|
|
|
|
for (i = 0; i < NATTK; i++) {
|
|
|
|
|
sum[i] = M_ATTK_MISS;
|
|
|
|
|
mattk = getmattk(&gy.youmonst, mon, i, sum, &alt_attk);
|
|
|
|
|
if (mattk->aatyp == AT_WEAP)
|
|
|
|
|
++multi_weap;
|
|
|
|
|
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 */
|
|
|
|
|
gt.twohits = 0;
|
|
|
|
|
|
|
|
|
|
gs.skipdrin = FALSE; /* [see mattackm(mhitm.c)] */
|
|
|
|
|
|
|
|
|
|
@@ -5215,6 +5290,8 @@ hmonas(struct monst *mon)
|
|
|
|
|
mon_maybe_unparalyze(mon);
|
|
|
|
|
dieroll = rnd(20);
|
|
|
|
|
dhit = (tmp > dieroll || u.uswallow);
|
|
|
|
|
if (multi_weap > 1)
|
|
|
|
|
++gt.twohits;
|
|
|
|
|
/* caller must set gb.bhitpos */
|
|
|
|
|
monster_survived = known_hitum(mon, weapon, &dhit, tmp,
|
|
|
|
|
armorpenalty, mattk, dieroll);
|
|
|
|
|
@@ -5540,6 +5617,7 @@ hmonas(struct monst *mon)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gv.vis = FALSE; /* reset */
|
|
|
|
|
gt.twohits = 0;
|
|
|
|
|
/* return value isn't used, but make it match hitum()'s */
|
|
|
|
|
return !DEADMONSTER(mon);
|
|
|
|
|
}
|
|
|
|
|
@@ -5547,15 +5625,16 @@ hmonas(struct monst *mon)
|
|
|
|
|
/* Special (passive) attacks on you by monsters done here.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
passive(struct monst *mon,
|
|
|
|
|
struct obj *weapon, /* uwep or uswapwep or uarmg or uarmf or Null */
|
|
|
|
|
boolean mhitb,
|
|
|
|
|
boolean maliveb,
|
|
|
|
|
uchar aatyp,
|
|
|
|
|
boolean wep_was_destroyed)
|
|
|
|
|
passive(
|
|
|
|
|
struct monst *mon,
|
|
|
|
|
struct obj *weapon, /* uwep or uswapwep or uarmg or uarmf or Null */
|
|
|
|
|
boolean mhitb,
|
|
|
|
|
boolean maliveb,
|
|
|
|
|
uchar aatyp,
|
|
|
|
|
boolean wep_was_destroyed)
|
|
|
|
|
{
|
|
|
|
|
register struct permonst *ptr = mon->data;
|
|
|
|
|
register int i, tmp;
|
|
|
|
|
struct permonst *ptr = mon->data;
|
|
|
|
|
int i, tmp;
|
|
|
|
|
int mhit = mhitb ? M_ATTK_HIT : M_ATTK_MISS;
|
|
|
|
|
int malive = maliveb ? M_ATTK_HIT : M_ATTK_MISS;
|
|
|
|
|
|
|
|
|
|
|