monster hits another monster hard enough to knock it back? */
| 5244 | |
| 5245 | /* monster hits another monster hard enough to knock it back? */ |
| 5246 | boolean |
| 5247 | mhitm_knockback( |
| 5248 | struct monst *magr, /* attacker; might be hero */ |
| 5249 | struct monst *mdef, /* defender; might be hero (only if magr isn't) */ |
| 5250 | struct attack *mattk, /* attack type and damage info */ |
| 5251 | int *hitflags, /* modified if magr or mdef dies */ |
| 5252 | boolean weapon_used) /* True: via weapon hit */ |
| 5253 | { |
| 5254 | char magrbuf[BUFSZ], mdefbuf[BUFSZ]; |
| 5255 | struct obj *otmp; |
| 5256 | const char *knockedhow; |
| 5257 | coordxy dx, dy, defx, defy; |
| 5258 | int knockdistance = rn2(3) ? 1 : 2; /* 67%: 1 step, 33%: 2 steps */ |
| 5259 | int chance = 6; /* 1/6 chance of attack knocking back a monster */ |
| 5260 | boolean u_agr = (magr == &gy.youmonst); |
| 5261 | boolean u_def = (mdef == &gy.youmonst); |
| 5262 | boolean was_u = FALSE, dismount = FALSE; |
| 5263 | struct obj *wep = weapon_used ? (u_agr ? uwep : MON_WEP(magr)) |
| 5264 | : (struct obj *) 0; |
| 5265 | |
| 5266 | if (wep && is_art(wep, ART_OGRESMASHER)) |
| 5267 | chance = 2; |
| 5268 | |
| 5269 | if (rn2(chance)) |
| 5270 | return FALSE; |
| 5271 | |
| 5272 | /* only certain attacks qualify for knockback */ |
| 5273 | if (!((mattk->adtyp == AD_PHYS) |
| 5274 | && (mattk->aatyp == AT_CLAW |
| 5275 | || mattk->aatyp == AT_KICK |
| 5276 | || mattk->aatyp == AT_BUTT |
| 5277 | || mattk->aatyp == AT_WEAP))) |
| 5278 | return FALSE; |
| 5279 | |
| 5280 | /* don't knockback if attacker also wants to grab or engulf */ |
| 5281 | if (attacktype(magr->data, AT_ENGL) |
| 5282 | || attacktype(magr->data, AT_HUGS) |
| 5283 | || sticks(magr->data)) |
| 5284 | return FALSE; |
| 5285 | |
| 5286 | /* decide where the first step will place the target; not accurate |
| 5287 | for being knocked out of saddle but doesn't need to be; used for |
| 5288 | test_move() and for message before actual hurtle */ |
| 5289 | defx = u_def ? u.ux : mdef->mx; |
| 5290 | defy = u_def ? u.uy : mdef->my; |
| 5291 | dx = sgn(defx - (u_agr ? u.ux : magr->mx)); |
| 5292 | dy = sgn(defy - (u_agr ? u.uy : magr->my)); |
| 5293 | |
| 5294 | /* can't move most targets into or out of a doorway diagonally */ |
| 5295 | if (u_def) { |
| 5296 | if (!test_move(defx, defy, dx, dy, TEST_MOVE)) |
| 5297 | return FALSE; |
| 5298 | } else { |
| 5299 | /* subset of test_move() */ |
| 5300 | if (!isok(defx + dx, defy + dy)) |
| 5301 | return FALSE; |
| 5302 | if (IS_DOOR(levl[defx][defy].typ) |
| 5303 | && (defx - magr->mx && defy - magr->my) |
no test coverage detected