From b57bc61a80ea0e9bace91ca844fe42aaa90a6190 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Thu, 5 Dec 2002 02:07:20 +0000 Subject: [PATCH] jousting 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. --- doc/fixes34.1 | 2 ++ src/uhitm.c | 79 ++++++++++++++++++++++++++++++++++++++++----------- src/weapon.c | 7 ----- 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/doc/fixes34.1 b/doc/fixes34.1 index 3ffb6eeeb..0fdc838fb 100644 --- a/doc/fixes34.1 +++ b/doc/fixes34.1 @@ -316,6 +316,8 @@ don't crash teleporting out of a monster while engulfed, punished but not carrying the ball web breaking should consider steed strength and other characteristics 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 diff --git a/src/uhitm.c b/src/uhitm.c index 49880d9aa..f0dd789d0 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -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. */ /* 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 boolean FDECL(hitum, (struct monst *,int,struct attack *)); 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 int FDECL(explum, (struct monst *,struct attack *)); STATIC_DCL void FDECL(start_engulf, (struct monst *)); @@ -419,17 +423,20 @@ struct attack *uattk; if(!*mhit) { missum(mon, uattk); } else { - int oldhp = mon->mhp; + int oldhp = mon->mhp, + x = u.ux + u.dx, y = u.uy + u.dy; - /* KMH, conduct */ - if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) - u.uconduct.weaphit++; + /* KMH, conduct */ + if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) + u.uconduct.weaphit++; - /* we hit the monster; be careful: it might die! */ - notonhead = (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy); + /* we hit the monster; be careful: it might die or + be knocked into a different location */ + notonhead = (mon->mx != x || mon->my != y); malive = hmon(mon, uwep, 0); - /* This assumes that Stormbringer was uwep not uswapwep */ - if (malive && u.twoweap && !override_confirmation) + /* this assumes that Stormbringer was uwep not uswapwep */ + if (malive && u.twoweap && !override_confirmation && + m_at(x, y) == mon) malive = hmon(mon, uswapwep, 0); if (malive) { /* monster still alive */ @@ -453,7 +460,7 @@ struct attack *uattk; --u.uconduct.weaphit; } if (mon->wormno && *mhit) - cutworm(mon, u.ux+u.dx, u.uy+u.dy, uwep); + cutworm(mon, x, y, uwep); } } return(malive); @@ -512,10 +519,11 @@ int thrown; boolean get_dmg_bonus = TRUE; boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE; boolean silvermsg = FALSE; + boolean valid_weapon_attack = FALSE; + boolean unarmed = !uwep && !uarm && !uarms; #ifdef STEED - boolean jousting = FALSE; + int jousting = 0; #endif - boolean valid_weapon_attack = FALSE; int wtype; struct obj *monwep; char yourbuf[BUFSZ]; @@ -620,9 +628,12 @@ int thrown; && hates_silver(mdat)) silvermsg = TRUE; #ifdef STEED - if (u.usteed && !thrown && - weapon_type(obj) == P_LANCE && mon != u.ustuck) - jousting = TRUE; + if (u.usteed && !thrown && tmp > 0 && + weapon_type(obj) == P_LANCE && mon != u.ustuck) { + jousting = joust(mon, obj); + /* exercise skill even for minimal damage hits */ + if (jousting) valid_weapon_attack = TRUE; + } #endif if(!thrown && obj == uwep && obj->otyp == BOOMERANG && !rnl(3)) { @@ -679,6 +690,8 @@ int thrown; change_luck(-2); useup(obj); obj = (struct obj *) 0; + unarmed = FALSE; /* avoid obj==0 confusion */ + get_dmg_bonus = FALSE; hittxt = TRUE; } tmp = 1; @@ -908,8 +921,15 @@ int thrown; #ifdef STEED if (jousting) { + tmp += d(2, (obj == uwep) ? 10 : 2); /* [was in dmgval()] */ You("joust %s%s", 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 */ if (mon->mhp > tmp) { mhurtle(mon, u.dx, u.dy, 1); @@ -920,7 +940,7 @@ int thrown; #endif /* 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) && !bigmonst(mdat) && !thick_skinned(mdat)) { if (canspotmon(mon)) @@ -1051,7 +1071,32 @@ struct attack *mattk; 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. * diff --git a/src/weapon.c b/src/weapon.c index b3ff14ee5..37eca580f 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -286,13 +286,6 @@ struct monst *mon; otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) { 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))) bonus += rnd(4); if (is_axe(otmp) && is_wooden(ptr)) -- 2.40.0