Large monster can knock back smaller ones
When a monster at least two sizes larger hits another one, there's a chance the smaller defender will be knocked back. This applies also to hero, attacking when polymorphed to a large monster, or defending from a large monster. Most of the monsters that can knock back are giants and dragons. Idea and some of the code from EvilHack.
This commit is contained in:
@@ -971,6 +971,7 @@ wielding a bec de corbin makes ravens generate peaceful
|
||||
moving with 'm' prefix allows hero to enter a known pit carefully
|
||||
rangers always succeed in disarming bear traps, unless impaired
|
||||
bigroom variant 2 may have ice floor in unlit areas
|
||||
some large monsters can knock back smaller monsters with a hit
|
||||
|
||||
|
||||
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
||||
|
||||
@@ -2919,6 +2919,8 @@ extern void do_stone_mon(struct monst *, struct attack *, struct monst *,
|
||||
extern int damageum(struct monst *, struct attack *, int);
|
||||
extern int explum(struct monst *, struct attack *);
|
||||
extern void missum(struct monst *, struct attack *, boolean);
|
||||
extern boolean mhitm_knockback(struct monst *, struct monst *,struct attack *,
|
||||
int *, boolean);
|
||||
extern int passive(struct monst *, struct obj *, boolean, boolean, uchar,
|
||||
boolean);
|
||||
extern void passive_obj(struct monst *, struct obj *, struct attack *);
|
||||
|
||||
@@ -946,6 +946,9 @@ mdamagem(struct monst *magr, struct monst *mdef,
|
||||
}
|
||||
|
||||
mhitm_adtyping(magr, mattk, mdef, &mhm);
|
||||
|
||||
(void) mhitm_knockback(magr, mdef, mattk, &mhm.hitflags, (MON_WEP(magr) != 0));
|
||||
|
||||
if (mhm.done)
|
||||
return mhm.hitflags;
|
||||
|
||||
|
||||
@@ -1032,6 +1032,9 @@ hitmu(register struct monst *mtmp, register struct attack *mattk)
|
||||
mhm.damage += d((int) mattk->damn, (int) mattk->damd); /* extra dmg */
|
||||
|
||||
mhitm_adtyping(mtmp, mattk, &g.youmonst, &mhm);
|
||||
|
||||
(void) mhitm_knockback(mtmp, &g.youmonst, mattk, &mhm.hitflags, (MON_WEP(mtmp) != 0));
|
||||
|
||||
if (mhm.done)
|
||||
return mhm.hitflags;
|
||||
|
||||
|
||||
96
src/uhitm.c
96
src/uhitm.c
@@ -3459,9 +3459,11 @@ mhitm_ad_phys(struct monst *magr, struct attack *mattk, struct monst *mdef,
|
||||
if (!u.ustuck && rn2(2)) {
|
||||
if (u_slip_free(magr, mattk)) {
|
||||
mhm->damage = 0;
|
||||
mhm->hitflags |= MM_MISS;
|
||||
} else {
|
||||
set_ustuck(magr);
|
||||
pline("%s grabs you!", Monnam(magr));
|
||||
mhm->hitflags |= MM_HIT;
|
||||
}
|
||||
} else if (u.ustuck == magr) {
|
||||
exercise(A_STR, FALSE);
|
||||
@@ -3497,8 +3499,10 @@ mhitm_ad_phys(struct monst *magr, struct attack *mattk, struct monst *mdef,
|
||||
mhm->damage = 1;
|
||||
if (!(otmp->oartifact && artifact_hit(magr, mdef, otmp,
|
||||
&mhm->damage,
|
||||
g.mhitu_dieroll)))
|
||||
g.mhitu_dieroll))) {
|
||||
hitmsg(magr, mattk);
|
||||
mhm->hitflags |= MM_HIT;
|
||||
}
|
||||
if (!mhm->damage)
|
||||
return;
|
||||
if (objects[otmp->otyp].oc_material == SILVER
|
||||
@@ -3531,8 +3535,10 @@ mhitm_ad_phys(struct monst *magr, struct attack *mattk, struct monst *mdef,
|
||||
}
|
||||
rustm(&g.youmonst, otmp);
|
||||
} else if (mattk->aatyp != AT_TUCH || mhm->damage != 0
|
||||
|| magr != u.ustuck)
|
||||
|| magr != u.ustuck) {
|
||||
hitmsg(magr, mattk);
|
||||
mhm->hitflags |= MM_HIT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* mhitm */
|
||||
@@ -3574,6 +3580,7 @@ mhitm_ad_phys(struct monst *magr, struct attack *mattk, struct monst *mdef,
|
||||
if (g.vis)
|
||||
pline("%s hits %s.", Monnam(magr),
|
||||
mon_nam_too(mdef, magr));
|
||||
mhm->hitflags |= MM_HIT;
|
||||
}
|
||||
/* artifact_hit updates 'tmp' but doesn't inflict any
|
||||
damage; however, it might cause carried items to be
|
||||
@@ -4213,6 +4220,7 @@ damageum(
|
||||
}
|
||||
|
||||
mhitm_adtyping(&g.youmonst, mattk, mdef, &mhm);
|
||||
|
||||
if (mhm.done)
|
||||
return mhm.hitflags;
|
||||
|
||||
@@ -4543,6 +4551,87 @@ missum(struct monst *mdef, struct attack *mattk, boolean wouldhavehit)
|
||||
wakeup(mdef, TRUE);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
boolean u_agr = (magr == &g.youmonst);
|
||||
boolean u_def = (mdef == &g.youmonst);
|
||||
|
||||
/* 1/6 chance of attack knocking back a monster */
|
||||
if (rn2(6))
|
||||
return FALSE;
|
||||
|
||||
/* monsters must be alive */
|
||||
if ((!u_agr && DEADMONSTER(magr))
|
||||
|| (!u_def && DEADMONSTER(mdef)))
|
||||
return FALSE;
|
||||
|
||||
/* attacker must be much larger than defender */
|
||||
if (!(magr->data->msize > (mdef->data->msize + 1)))
|
||||
return FALSE;
|
||||
|
||||
/* only certain attacks qualify for knockback */
|
||||
if (!((mattk->adtyp == AD_PHYS)
|
||||
&& (mattk->aatyp == AT_CLAW
|
||||
|| mattk->aatyp == AT_KICK
|
||||
|| mattk->aatyp == AT_BUTT
|
||||
|| (mattk->aatyp == AT_WEAP && !weapon_used))))
|
||||
return FALSE;
|
||||
|
||||
/* the attack must have hit */
|
||||
/* mon-vs-mon code path doesn't set up hitflags */
|
||||
if ((u_agr || u_def) && !(*hitflags & MM_HIT))
|
||||
return FALSE;
|
||||
|
||||
/* give the message */
|
||||
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! */
|
||||
|
||||
pline("%s knock%s %s %s with a %s %s!",
|
||||
u_agr ? "You" : Monnam(magr),
|
||||
u_agr ? "" : "s",
|
||||
u_def ? "you" : y_monnam(mdef),
|
||||
dosteed ? "out of your saddle" : "back",
|
||||
rn2(2) ? "forceful" : "powerful",
|
||||
rn2(2) ? "blow" : "strike");
|
||||
}
|
||||
|
||||
/* do the actual knockback effect */
|
||||
if (u_def) {
|
||||
if (u.usteed)
|
||||
dismount_steed(DISMOUNT_FELL);
|
||||
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);
|
||||
} 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));
|
||||
if (DEADMONSTER(mdef))
|
||||
*hitflags |= MM_DEF_DIED;
|
||||
else if (!rn2(4))
|
||||
mdef->mstun = 1;
|
||||
}
|
||||
if (!u_agr) {
|
||||
if (DEADMONSTER(magr))
|
||||
*hitflags |= MM_AGR_DIED;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* attack monster as a monster; returns True if mon survives */
|
||||
static boolean
|
||||
hmonas(struct monst *mon)
|
||||
@@ -4920,6 +5009,9 @@ hmonas(struct monst *mon)
|
||||
mattk->aatyp, FALSE);
|
||||
}
|
||||
|
||||
if (mhitm_knockback(&g.youmonst, mon, mattk, &sum[i], weapon_used))
|
||||
break;
|
||||
|
||||
/* don't use sum[i] beyond this point;
|
||||
'i' will be out of bounds if we get here via 'goto' */
|
||||
passivedone:
|
||||
|
||||
Reference in New Issue
Block a user