From 53adba66021b96d526884e9e1799a01f000eaac0 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 3 May 2023 12:18:15 -0700 Subject: [PATCH] maybe fix #K3909 - hurtled monster detached twice I haven't forced a test case to verify this, but the logic for calling mliquid() at the end of mhurtle() was clearly wrong. Also, implement missing case of one monster causing another to hurtle and hit the hero. Compiles but is otherwise untested. --- src/dothrow.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/dothrow.c b/src/dothrow.c index 8571ce9f9..796addcc9 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -641,9 +641,10 @@ hitfloor( * before the failed callback. */ boolean -walk_path(coord *src_cc, coord *dest_cc, - boolean (*check_proc)(genericptr_t, coordxy, coordxy), - genericptr_t arg) +walk_path( + coord *src_cc, coord *dest_cc, + boolean (*check_proc)(genericptr_t, coordxy, coordxy), + genericptr_t arg) { int err; coordxy x, y, dx, dy, x_change, y_change, i, prev_x, prev_y; @@ -982,6 +983,9 @@ will_hurtle(struct monst *mon, coordxy x, coordxy y) { if (!isok(x, y)) return FALSE; + /* redundant when called by mhurtle() but needed for mhitm_knockback() */ + if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped) + return FALSE; /* * TODO: Treat walls, doors, iron bars, etc. specially * rather than just stopping before. @@ -1025,21 +1029,43 @@ mhurtle_step(genericptr_t arg, coordxy x, coordxy y) return FALSE; return TRUE; } - if ((mtmp = m_at(x, y)) != 0) { + if ((mtmp = m_at(x, y)) != 0 && mtmp != mon) { if (canseemon(mon) || canseemon(mtmp)) pline("%s bumps into %s.", Monnam(mon), a_monnam(mtmp)); - wakeup(mon, !gc.context.mon_moving); wakeup(mtmp, !gc.context.mon_moving); + /* check whether 'mon' is turned to stone by touching 'mtmp' */ if (touch_petrifies(mtmp->data) && !which_armor(mon, W_ARMU | W_ARM | W_ARMC)) { minstapetrify(mon, !gc.context.mon_moving); newsym(mon->mx, mon->my); } + /* and whether 'mtmp' is turned to stone by being touched by 'mon' */ if (touch_petrifies(mon->data) && !which_armor(mtmp, W_ARMU | W_ARM | W_ARMC)) { minstapetrify(mtmp, !gc.context.mon_moving); newsym(mtmp->mx, mtmp->my); } + } else if (u_at(x, y)) { + /* a monster has caused 'mon' to hurtle against hero */ + pline("%s bumps into you.", Some_Monnam(mon)); + stop_occupation(); + /* check whether 'mon' is turned to stone by touching poly'd hero */ + if (Upolyd && touch_petrifies(gy.youmonst.data) + && !which_armor(mon, W_ARMU | W_ARM | W_ARMC)) { + /* give poly'd hero credit/blame despite a monster causing it */ + minstapetrify(mon, TRUE); + newsym(mon->mx, mon->my); + } + /* and whether hero is turned to stone by being touched by 'mon' */ + if (touch_petrifies(mon->data) && !(uarmu || uarm || uarmc)) { + Snprintf(gk.killer.name, sizeof gk.killer.name, "being hit by %s", + /* combine m_monnam() and noname_monnam(): + "{your,a} hurtling cockatrice" w/o assigned name */ + x_monnam(mtmp, mtmp->mtame ? ARTICLE_YOUR : ARTICLE_A, + "hurtling", EXACT_NAME | SUPPRESS_NAME, FALSE)); + instapetrify(gk.killer.name); + newsym(u.ux, u.uy); + } } return FALSE; @@ -1111,6 +1137,7 @@ mhurtle(struct monst *mon, int dx, int dy, int range) { coord mc, cc; + wakeup(mon, !gc.context.mon_moving); /* At the very least, debilitate the monster */ mon->movement = 0; mon->mstun = 1; @@ -1147,10 +1174,12 @@ mhurtle(struct monst *mon, int dx, int dy, int range) cc.x = mon->mx + (dx * range); cc.y = mon->my + (dy * range); (void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t) mon); - if (!DEADMONSTER(mon) && t_at(mon->mx, mon->my)) - (void) mintrap(mon, FORCEBUNGLE); - else - (void) minliquid(mon); + if (!DEADMONSTER(mon)) { + if (t_at(mon->mx, mon->my)) + (void) mintrap(mon, FORCEBUNGLE); + else + (void) minliquid(mon); + } return; }