From 546fea7db89448bcf70d69310ec85ad49b5e3b0d Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 3 Oct 2022 15:53:35 -0700 Subject: [PATCH] getting knocked off flying steed I was trying to reproduce the reported "no monster to remove" warning from remove_monster() when a mounted hero was knocked off jabberwocky steed but so far haven't been able to. While trying, I came across a more minor bug. The hero got knocked off a flying steed and got feedback of "you fly off" rather than "you fall off". Flying capability came from the steed and dismount feedback is aware of that but calls u_locomotion() which isn't. This commit fixes that. This adds some groundwork (DISMOUNT_KNOCKED) for better dismount control. With a map fragment of |.... |.Du. |.... I got knocked off my steed by the attacking dragon and ended up with |..@. |.Du. |.... It would be better to prefer spot 1, then the 2s, then 3s, then 4s (not sure about farther spots if none of those are available) |.432 |.D@1 |.432 when forced to dismount by knockback. This does _not_ implement that. --- include/hack.h | 11 ++++++----- src/steed.c | 18 ++++++++++++++---- src/uhitm.c | 43 +++++++++++++++++++++++++------------------ 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/include/hack.h b/include/hack.h index 59beb4ce7..af66cd132 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 hack.h $NHDT-Date: 1652861829 2022/05/18 08:17:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.181 $ */ +/* NetHack 3.7 hack.h $NHDT-Date: 1664837602 2022/10/03 22:53:22 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.196 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Pasi Kallinen, 2017. */ /* NetHack may be freely redistributed. See license for details. */ @@ -75,10 +75,11 @@ enum dismount_types { DISMOUNT_GENERIC = 0, DISMOUNT_FELL = 1, DISMOUNT_THROWN = 2, - DISMOUNT_POLY = 3, - DISMOUNT_ENGULFED = 4, - DISMOUNT_BONES = 5, - DISMOUNT_BYCHOICE = 6 + DISMOUNT_KNOCKED = 3, /* hero hit for knockback effect */ + DISMOUNT_POLY = 4, + DISMOUNT_ENGULFED = 5, + DISMOUNT_BONES = 6, + DISMOUNT_BYCHOICE = 7 }; /* polyself flags */ diff --git a/src/steed.c b/src/steed.c index 515d35819..68de17f85 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 steed.c $NHDT-Date: 1646171628 2022/03/01 21:53:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.95 $ */ +/* NetHack 3.7 steed.c $NHDT-Date: 1664837604 2022/10/03 22:53:24 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.100 $ */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -445,6 +445,13 @@ landing_spot( boolean found = FALSE; struct trap *t; + /* + * TODO: + * for reason==DISMOUNT_KNOCKED, prefer the spot directly behind + * current position relative to the attacker; first need to figure + * how to obtain attacker information... + */ + /* avoid known traps (i == 0) and boulders, but allow them as a backup */ if (reason != DISMOUNT_BYCHOICE || Stunned || Confusion || Fumbling) i = 1; @@ -498,18 +505,21 @@ dismount_steed( /* Sanity check */ if (!mtmp) /* Just return silently */ return; - u.usteed = 0; /* affects Fly test; could hypothetically affect Lev */ + u.usteed = 0; /* affects Fly test; could hypothetically affect Lev; + * also affects u_locomotion() */ ufly = Flying ? TRUE : FALSE; ulev = Levitation ? TRUE : FALSE; + verb = u_locomotion("fall"); /* only used for _FELL and _KNOCKED */ u.usteed = mtmp; /* Check the reason for dismounting */ otmp = which_armor(mtmp, W_SADDLE); switch (reason) { case DISMOUNT_THROWN: + verb = "are thrown"; + /*FALLTHRU*/ + case DISMOUNT_KNOCKED: case DISMOUNT_FELL: - verb = (reason == DISMOUNT_THROWN) ? "are thrown" - : u_locomotion("fall"); You("%s off of %s!", verb, mon_nam(mtmp)); if (!have_spot) have_spot = landing_spot(&cc, reason, 1); diff --git a/src/uhitm.c b/src/uhitm.c index 779ccef55..cb369e0f3 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 uhitm.c $NHDT-Date: 1650963745 2022/04/26 09:02:25 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.348 $ */ +/* NetHack 3.7 uhitm.c $NHDT-Date: 1664837605 2022/10/03 22:53:25 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.364 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1511,6 +1511,8 @@ hmon_hitmon( return destroyed ? FALSE : TRUE; } +RESTORE_WARNING_FORMAT_NONLITERAL + /* joust or martial arts punch is knocking the target back; that might kill 'mon' (via trap) before known_hitum() has a chance to do so; return True if we kill mon, False otherwise */ @@ -1586,8 +1588,6 @@ shade_aware(struct obj *obj) return FALSE; } -RESTORE_WARNING_FORMAT_NONLITERAL - /* used for hero vs monster and monster vs monster; also handles monster vs hero but that won't happen because hero can't be a shade */ boolean @@ -4593,8 +4593,8 @@ m_is_steadfast(struct monst *mtmp) struct obj *otmp = is_u ? uwep : MON_WEP(mtmp); /* must be on the ground */ - if ((is_u && (Flying || Levitation)) - || (!is_u && (is_flyer(mtmp->data) || is_floater(mtmp->data)))) + if (is_u ? (Flying || Levitation) + : (is_flyer(mtmp->data) || is_floater(mtmp->data))) return FALSE; if (is_art(otmp, ART_GIANTSLAYER)) @@ -4604,11 +4604,12 @@ m_is_steadfast(struct monst *mtmp) /* monster hits another monster hard enough to knock it back? */ boolean -mhitm_knockback(struct monst *magr, - struct monst *mdef, - struct attack *mattk, - int *hitflags, - boolean weapon_used) +mhitm_knockback( + struct monst *magr, /* attacker; might be hero */ + struct monst *mdef, /* defender; might be hero (only if magr isn't) */ + struct attack *mattk, /* attack type and damage info */ + int *hitflags, /* modified if magr or mdef dies */ + boolean weapon_used) /* True: via weapon hit */ { boolean u_agr = (magr == &g.youmonst); boolean u_def = (mdef == &g.youmonst); @@ -4651,10 +4652,13 @@ mhitm_knockback(struct monst *magr, if (u_def || canseemon(mdef)) { boolean dosteed = u_def && u.usteed; - /* uhitm: You knock the gnome back with a powerful blow! */ - /* mhitu: The red dragon knocks you back with a forceful blow! */ - /* mhitm: The fire giant knocks the gnome back with a forceful strike! */ - + /* + * uhitm: You knock the gnome back with a powerful blow! + * mhitu: The red dragon knocks you back with a forceful blow! + * mhitm: The fire giant knocks the gnome back with a forceful strike! + * + * TODO? if saddle is cursed, knock both hero and steed back? + */ pline("%s knock%s %s %s with a %s %s!", u_agr ? "You" : Monnam(magr), u_agr ? "" : "s", @@ -4662,22 +4666,25 @@ mhitm_knockback(struct monst *magr, dosteed ? "out of your saddle" : "back", rn2(2) ? "forceful" : "powerful", rn2(2) ? "blow" : "strike"); + } else if (u_agr) { + /* hero knocks unseen foe back; noticed by touch */ + You("knock %s back!", some_mon_nam(mdef)); } /* do the actual knockback effect */ if (u_def) { if (u.usteed) - dismount_steed(DISMOUNT_FELL); + dismount_steed(DISMOUNT_KNOCKED); else hurtle(u.ux - magr->mx, u.uy - magr->my, rnd(2), FALSE); + if (!rn2(4)) - make_stunned((HStun & TIMEOUT) + (long) rnd(2) + 1, TRUE); + make_stunned((HStun & TIMEOUT) + (long) rnd(2) + 1L, TRUE); } else { coordxy x = u_agr ? u.ux : magr->mx; coordxy y = u_agr ? u.uy : magr->my; - mhurtle(mdef, mdef->mx - x, - mdef->my - y, rnd(2)); + mhurtle(mdef, mdef->mx - x, mdef->my - y, rnd(2)); if (DEADMONSTER(mdef)) *hitflags |= MM_DEF_DIED; else if (!rn2(4))