Part I:  it's possible to use two-weapon combat while wielding a
lance (which seems odd to me); the second weapon would hit even if the
the first delivered a lance jousting blow that knocked the target away.

     Part II:  always getting the joust knockback effect when hitting
with a lance while mounted was too powerful; implement a suggestion
from the newsgroup that it be a random chance based on skill level.

     Related:  it's now possible to break your lance when hitting; when
adding that, I noticed that it was theoretically possible (didn't try
to reproduce) for a shattered boomerang or mirror to yield the stagger
bonus sometimes given for unarmed attacks.
This commit is contained in:
nethack.rankin
2002-12-05 02:07:20 +00:00
parent 9b1b13ef1d
commit b57bc61a80
3 changed files with 65 additions and 25 deletions

View File

@@ -316,6 +316,8 @@ don't crash teleporting out of a monster while engulfed, punished but not
carrying the ball carrying the ball
web breaking should consider steed strength and other characteristics web breaking should consider steed strength and other characteristics
various missing or inappropriate "killed by" death messages various missing or inappropriate "killed by" death messages
second attack for two-weapon combat will miss if first knocks target away
jousting effect no longer occurs every time riding character hits with lance
Platform- and/or Interface-Specific Fixes Platform- and/or Interface-Specific Fixes

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)uhitm.c 3.4 2002/11/07 */ /* SCCS Id: @(#)uhitm.c 3.4 2002/11/29 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -8,6 +8,10 @@ STATIC_DCL boolean FDECL(known_hitum, (struct monst *,int *,struct attack *));
STATIC_DCL void FDECL(steal_it, (struct monst *, struct attack *)); STATIC_DCL void FDECL(steal_it, (struct monst *, struct attack *));
STATIC_DCL boolean FDECL(hitum, (struct monst *,int,struct attack *)); STATIC_DCL boolean FDECL(hitum, (struct monst *,int,struct attack *));
STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *,struct obj *,int)); STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *,struct obj *,int));
#ifdef STEED
STATIC_DCL int FDECL(joust, (struct monst *,struct obj *));
#endif
STATIC_DCL void NDECL(demonpet);
STATIC_DCL boolean FDECL(m_slips_free, (struct monst *mtmp,struct attack *mattk)); STATIC_DCL boolean FDECL(m_slips_free, (struct monst *mtmp,struct attack *mattk));
STATIC_DCL int FDECL(explum, (struct monst *,struct attack *)); STATIC_DCL int FDECL(explum, (struct monst *,struct attack *));
STATIC_DCL void FDECL(start_engulf, (struct monst *)); STATIC_DCL void FDECL(start_engulf, (struct monst *));
@@ -419,17 +423,20 @@ struct attack *uattk;
if(!*mhit) { if(!*mhit) {
missum(mon, uattk); missum(mon, uattk);
} else { } else {
int oldhp = mon->mhp; int oldhp = mon->mhp,
x = u.ux + u.dx, y = u.uy + u.dy;
/* KMH, conduct */ /* KMH, conduct */
if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
u.uconduct.weaphit++; u.uconduct.weaphit++;
/* we hit the monster; be careful: it might die! */ /* we hit the monster; be careful: it might die or
notonhead = (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy); be knocked into a different location */
notonhead = (mon->mx != x || mon->my != y);
malive = hmon(mon, uwep, 0); malive = hmon(mon, uwep, 0);
/* This assumes that Stormbringer was uwep not uswapwep */ /* this assumes that Stormbringer was uwep not uswapwep */
if (malive && u.twoweap && !override_confirmation) if (malive && u.twoweap && !override_confirmation &&
m_at(x, y) == mon)
malive = hmon(mon, uswapwep, 0); malive = hmon(mon, uswapwep, 0);
if (malive) { if (malive) {
/* monster still alive */ /* monster still alive */
@@ -453,7 +460,7 @@ struct attack *uattk;
--u.uconduct.weaphit; --u.uconduct.weaphit;
} }
if (mon->wormno && *mhit) if (mon->wormno && *mhit)
cutworm(mon, u.ux+u.dx, u.uy+u.dy, uwep); cutworm(mon, x, y, uwep);
} }
} }
return(malive); return(malive);
@@ -512,10 +519,11 @@ int thrown;
boolean get_dmg_bonus = TRUE; boolean get_dmg_bonus = TRUE;
boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE; boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
boolean silvermsg = FALSE; boolean silvermsg = FALSE;
#ifdef STEED
boolean jousting = FALSE;
#endif
boolean valid_weapon_attack = FALSE; boolean valid_weapon_attack = FALSE;
boolean unarmed = !uwep && !uarm && !uarms;
#ifdef STEED
int jousting = 0;
#endif
int wtype; int wtype;
struct obj *monwep; struct obj *monwep;
char yourbuf[BUFSZ]; char yourbuf[BUFSZ];
@@ -620,9 +628,12 @@ int thrown;
&& hates_silver(mdat)) && hates_silver(mdat))
silvermsg = TRUE; silvermsg = TRUE;
#ifdef STEED #ifdef STEED
if (u.usteed && !thrown && if (u.usteed && !thrown && tmp > 0 &&
weapon_type(obj) == P_LANCE && mon != u.ustuck) weapon_type(obj) == P_LANCE && mon != u.ustuck) {
jousting = TRUE; jousting = joust(mon, obj);
/* exercise skill even for minimal damage hits */
if (jousting) valid_weapon_attack = TRUE;
}
#endif #endif
if(!thrown && obj == uwep && obj->otyp == BOOMERANG && if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
!rnl(3)) { !rnl(3)) {
@@ -679,6 +690,8 @@ int thrown;
change_luck(-2); change_luck(-2);
useup(obj); useup(obj);
obj = (struct obj *) 0; obj = (struct obj *) 0;
unarmed = FALSE; /* avoid obj==0 confusion */
get_dmg_bonus = FALSE;
hittxt = TRUE; hittxt = TRUE;
} }
tmp = 1; tmp = 1;
@@ -908,8 +921,15 @@ int thrown;
#ifdef STEED #ifdef STEED
if (jousting) { if (jousting) {
tmp += d(2, (obj == uwep) ? 10 : 2); /* [was in dmgval()] */
You("joust %s%s", You("joust %s%s",
mon_nam(mon), canseemon(mon) ? exclam(tmp) : "."); mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
if (jousting < 0) {
Your("%s shatters on impact!", doname(obj));
/* minor side-effect: broken lance won't split puddings */
useup(obj);
obj = 0;
}
/* avoid migrating a dead monster */ /* avoid migrating a dead monster */
if (mon->mhp > tmp) { if (mon->mhp > tmp) {
mhurtle(mon, u.dx, u.dy, 1); mhurtle(mon, u.dx, u.dy, 1);
@@ -920,7 +940,7 @@ int thrown;
#endif #endif
/* VERY small chance of stunning opponent if unarmed. */ /* VERY small chance of stunning opponent if unarmed. */
if (tmp > 1 && !thrown && !obj && !uwep && !uarm && !uarms && !Upolyd) { if (unarmed && tmp > 1 && !thrown && !obj && !Upolyd) {
if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) && if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) &&
!bigmonst(mdat) && !thick_skinned(mdat)) { !bigmonst(mdat) && !thick_skinned(mdat)) {
if (canspotmon(mon)) if (canspotmon(mon))
@@ -1051,7 +1071,32 @@ struct attack *mattk;
return FALSE; return FALSE;
} }
STATIC_DCL void NDECL(demonpet); /* used when hitting a monster with a lance while mounted */
STATIC_OVL int /* 1: joust hit; 0: ordinary hit; -1: joust but break lance */
joust(mon, obj)
struct monst *mon; /* target */
struct obj *obj; /* weapon */
{
int skill_rating, joust_dieroll;
if (Fumbling || Stunned) return 0;
/* if using two weapons, use worse of lance and two-weapon skills */
skill_rating = P_SKILL(weapon_type(obj)); /* lance skill */
if (u.twoweap && P_SKILL(P_TWO_WEAPON_COMBAT) < skill_rating)
skill_rating = P_SKILL(P_TWO_WEAPON_COMBAT);
if (skill_rating == P_ISRESTRICTED) skill_rating = P_UNSKILLED; /* 0=>1 */
/* odds to joust are expert:80%, skilled:60%, basic:40%, unskilled:20% */
if ((joust_dieroll = rn2(5)) < skill_rating) {
if (joust_dieroll == 0 && rnl(50) == (50-1) &&
!unsolid(mon->data) && !obj_resists(obj, 0, 100))
return -1; /* hit that breaks lance */
return 1; /* successful joust */
}
return 0; /* no joust bonus; revert to ordinary attack */
}
/* /*
* Send in a demon pet for the hero. Exercise wisdom. * Send in a demon pet for the hero. Exercise wisdom.
* *

View File

@@ -286,13 +286,6 @@ struct monst *mon;
otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) { otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) {
int bonus = 0; int bonus = 0;
#ifdef STEED
/* KMH -- Lances are especially made for riding */
if (otmp == uwep && u.usteed &&
objects[otmp->otyp].oc_skill == P_LANCE)
bonus += d(2,10);
#endif
if (otmp->blessed && (is_undead(ptr) || is_demon(ptr))) if (otmp->blessed && (is_undead(ptr) || is_demon(ptr)))
bonus += rnd(4); bonus += rnd(4);
if (is_axe(otmp) && is_wooden(ptr)) if (is_axe(otmp) && is_wooden(ptr))