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
|
moving with 'm' prefix allows hero to enter a known pit carefully
|
||||||
rangers always succeed in disarming bear traps, unless impaired
|
rangers always succeed in disarming bear traps, unless impaired
|
||||||
bigroom variant 2 may have ice floor in unlit areas
|
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
|
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 damageum(struct monst *, struct attack *, int);
|
||||||
extern int explum(struct monst *, struct attack *);
|
extern int explum(struct monst *, struct attack *);
|
||||||
extern void missum(struct monst *, struct attack *, boolean);
|
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,
|
extern int passive(struct monst *, struct obj *, boolean, boolean, uchar,
|
||||||
boolean);
|
boolean);
|
||||||
extern void passive_obj(struct monst *, struct obj *, struct attack *);
|
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);
|
mhitm_adtyping(magr, mattk, mdef, &mhm);
|
||||||
|
|
||||||
|
(void) mhitm_knockback(magr, mdef, mattk, &mhm.hitflags, (MON_WEP(magr) != 0));
|
||||||
|
|
||||||
if (mhm.done)
|
if (mhm.done)
|
||||||
return mhm.hitflags;
|
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 */
|
mhm.damage += d((int) mattk->damn, (int) mattk->damd); /* extra dmg */
|
||||||
|
|
||||||
mhitm_adtyping(mtmp, mattk, &g.youmonst, &mhm);
|
mhitm_adtyping(mtmp, mattk, &g.youmonst, &mhm);
|
||||||
|
|
||||||
|
(void) mhitm_knockback(mtmp, &g.youmonst, mattk, &mhm.hitflags, (MON_WEP(mtmp) != 0));
|
||||||
|
|
||||||
if (mhm.done)
|
if (mhm.done)
|
||||||
return mhm.hitflags;
|
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.ustuck && rn2(2)) {
|
||||||
if (u_slip_free(magr, mattk)) {
|
if (u_slip_free(magr, mattk)) {
|
||||||
mhm->damage = 0;
|
mhm->damage = 0;
|
||||||
|
mhm->hitflags |= MM_MISS;
|
||||||
} else {
|
} else {
|
||||||
set_ustuck(magr);
|
set_ustuck(magr);
|
||||||
pline("%s grabs you!", Monnam(magr));
|
pline("%s grabs you!", Monnam(magr));
|
||||||
|
mhm->hitflags |= MM_HIT;
|
||||||
}
|
}
|
||||||
} else if (u.ustuck == magr) {
|
} else if (u.ustuck == magr) {
|
||||||
exercise(A_STR, FALSE);
|
exercise(A_STR, FALSE);
|
||||||
@@ -3497,8 +3499,10 @@ mhitm_ad_phys(struct monst *magr, struct attack *mattk, struct monst *mdef,
|
|||||||
mhm->damage = 1;
|
mhm->damage = 1;
|
||||||
if (!(otmp->oartifact && artifact_hit(magr, mdef, otmp,
|
if (!(otmp->oartifact && artifact_hit(magr, mdef, otmp,
|
||||||
&mhm->damage,
|
&mhm->damage,
|
||||||
g.mhitu_dieroll)))
|
g.mhitu_dieroll))) {
|
||||||
hitmsg(magr, mattk);
|
hitmsg(magr, mattk);
|
||||||
|
mhm->hitflags |= MM_HIT;
|
||||||
|
}
|
||||||
if (!mhm->damage)
|
if (!mhm->damage)
|
||||||
return;
|
return;
|
||||||
if (objects[otmp->otyp].oc_material == SILVER
|
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);
|
rustm(&g.youmonst, otmp);
|
||||||
} else if (mattk->aatyp != AT_TUCH || mhm->damage != 0
|
} else if (mattk->aatyp != AT_TUCH || mhm->damage != 0
|
||||||
|| magr != u.ustuck)
|
|| magr != u.ustuck) {
|
||||||
hitmsg(magr, mattk);
|
hitmsg(magr, mattk);
|
||||||
|
mhm->hitflags |= MM_HIT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* mhitm */
|
/* mhitm */
|
||||||
@@ -3574,6 +3580,7 @@ mhitm_ad_phys(struct monst *magr, struct attack *mattk, struct monst *mdef,
|
|||||||
if (g.vis)
|
if (g.vis)
|
||||||
pline("%s hits %s.", Monnam(magr),
|
pline("%s hits %s.", Monnam(magr),
|
||||||
mon_nam_too(mdef, magr));
|
mon_nam_too(mdef, magr));
|
||||||
|
mhm->hitflags |= MM_HIT;
|
||||||
}
|
}
|
||||||
/* artifact_hit updates 'tmp' but doesn't inflict any
|
/* artifact_hit updates 'tmp' but doesn't inflict any
|
||||||
damage; however, it might cause carried items to be
|
damage; however, it might cause carried items to be
|
||||||
@@ -4213,6 +4220,7 @@ damageum(
|
|||||||
}
|
}
|
||||||
|
|
||||||
mhitm_adtyping(&g.youmonst, mattk, mdef, &mhm);
|
mhitm_adtyping(&g.youmonst, mattk, mdef, &mhm);
|
||||||
|
|
||||||
if (mhm.done)
|
if (mhm.done)
|
||||||
return mhm.hitflags;
|
return mhm.hitflags;
|
||||||
|
|
||||||
@@ -4543,6 +4551,87 @@ missum(struct monst *mdef, struct attack *mattk, boolean wouldhavehit)
|
|||||||
wakeup(mdef, TRUE);
|
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 */
|
/* attack monster as a monster; returns True if mon survives */
|
||||||
static boolean
|
static boolean
|
||||||
hmonas(struct monst *mon)
|
hmonas(struct monst *mon)
|
||||||
@@ -4920,6 +5009,9 @@ hmonas(struct monst *mon)
|
|||||||
mattk->aatyp, FALSE);
|
mattk->aatyp, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mhitm_knockback(&g.youmonst, mon, mattk, &sum[i], weapon_used))
|
||||||
|
break;
|
||||||
|
|
||||||
/* don't use sum[i] beyond this point;
|
/* don't use sum[i] beyond this point;
|
||||||
'i' will be out of bounds if we get here via 'goto' */
|
'i' will be out of bounds if we get here via 'goto' */
|
||||||
passivedone:
|
passivedone:
|
||||||
|
|||||||
Reference in New Issue
Block a user