Unify monster-hits-monster

This commit is contained in:
Pasi Kallinen
2020-11-30 19:08:59 +02:00
parent f543763695
commit 0d445a7a7c
5 changed files with 348 additions and 248 deletions

View File

@@ -1282,6 +1282,7 @@ E void FDECL(rustm, (struct monst *, struct obj *));
/* ### mhitu.c ### */
E void FDECL(hitmsg, (struct monst *, struct attack *));
E const char *FDECL(mpoisons_subj, (struct monst *, struct attack *));
E void NDECL(u_slow_down);
E struct monst *NDECL(cloneu);
@@ -2754,6 +2755,8 @@ E boolean FDECL(attack, (struct monst *));
E boolean FDECL(hmon, (struct monst *, struct obj *, int, int));
E boolean FDECL(shade_miss, (struct monst *, struct monst *, struct obj *,
BOOLEAN_P, BOOLEAN_P));
E void FDECL(mhitm_ad_rust, (struct monst *, struct attack *, struct monst *, struct mhitm_data *));
E void FDECL(mhitm_ad_corr, (struct monst *, struct attack *, struct monst *, struct mhitm_data *));
E int FDECL(damageum, (struct monst *, struct attack *, int));
E void FDECL(missum, (struct monst *, struct attack *, BOOLEAN_P));
E int FDECL(passive, (struct monst *, struct obj *, BOOLEAN_P, int,

View File

@@ -86,6 +86,12 @@
#define AD_SAMU 252 /* hits, may steal Amulet (Wizard) */
#define AD_CURS 253 /* random curse (ex. gremlin) */
struct mhitm_data {
int damage;
int hitflags; /* MM_DEF_DIED | MM_AGR_DIED | ... */
boolean done;
};
/*
* Monster to monster attacks. When a monster attacks another (mattackm),
* any or all of the following can be returned. See mattackm() for more

View File

@@ -858,10 +858,11 @@ int dieroll;
struct obj *obj;
char buf[BUFSZ];
struct permonst *pa = magr->data, *pd = mdef->data;
int armpro, num,
tmp = d((int) mattk->damn, (int) mattk->damd),
res = MM_MISS;
int armpro, num;
boolean cancelled;
struct mhitm_data mhm;
mhm.damage = d((int) mattk->damn, (int) mattk->damd);
mhm.hitflags = MM_MISS;
if ((touch_petrifies(pd) /* or flesh_petrifies() */
|| (mattk->adtyp == AD_DGST && pd == &mons[PM_MEDUSA]))
@@ -914,7 +915,7 @@ int dieroll;
}
if (flags.verbose && !Deaf)
verbalize("Burrrrp!");
tmp = mdef->mhp;
mhm.damage = mdef->mhp;
/* Use up amulet of life saving */
if ((obj = mlifesaver(mdef)) != 0)
m_useup(mdef, obj);
@@ -955,7 +956,7 @@ int dieroll;
goto physical;
case AD_LEGS:
if (magr->mcan) {
tmp = 0;
mhm.damage = 0;
break;
}
goto physical;
@@ -967,11 +968,11 @@ int dieroll;
mwep = 0;
if (shade_miss(magr, mdef, mwep, FALSE, TRUE)) {
tmp = 0;
mhm.damage = 0;
} else if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
/* [no 'kicking boots' check needed; monsters with kick attacks
can't wear boots and monsters that wear boots don't kick] */
tmp = 0;
mhm.damage = 0;
} else if (mwep) { /* non-Null 'mwep' implies AT_WEAP || AT_CLAW */
struct obj *marmg;
@@ -979,19 +980,19 @@ int dieroll;
&& touch_petrifies(&mons[mwep->corpsenm]))
goto do_stone;
tmp += dmgval(mwep, mdef);
mhm.damage += dmgval(mwep, mdef);
if ((marmg = which_armor(magr, W_ARMG)) != 0
&& marmg->otyp == GAUNTLETS_OF_POWER)
tmp += rn1(4, 3); /* 3..6 */
if (tmp < 1) /* is this necessary? mhitu.c has it... */
tmp = 1;
mhm.damage += rn1(4, 3); /* 3..6 */
if (mhm.damage < 1) /* is this necessary? mhitu.c has it... */
mhm.damage = 1;
if (mwep->oartifact) {
/* when magr's weapon is an artifact, caller suppressed its
usual 'hit' message in case artifact_hit() delivers one;
now we'll know and might need to deliver skipped message
(note: if there's no message there'll be no auxilliary
damage so the message here isn't coming too late) */
if (!artifact_hit(magr, mdef, mwep, &tmp, dieroll)) {
if (!artifact_hit(magr, mdef, mwep, &mhm.damage, dieroll)) {
if (g.vis)
pline("%s hits %s.", Monnam(magr),
mon_nam_too(mdef, magr));
@@ -1003,20 +1004,20 @@ int dieroll;
return (MM_DEF_DIED
| (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
if (tmp)
if (mhm.damage)
rustm(mdef, mwep);
} else if (pa == &mons[PM_PURPLE_WORM] && pd == &mons[PM_SHRIEKER]) {
/* hack to enhance mm_aggression(); we don't want purple
worm's bite attack to kill a shrieker because then it
won't swallow the corpse; but if the target survives,
the subsequent engulf attack should accomplish that */
if (tmp >= mdef->mhp && mdef->mhp > 1)
tmp = mdef->mhp - 1;
if (mhm.damage >= mdef->mhp && mdef->mhp > 1)
mhm.damage = mdef->mhp - 1;
}
break;
case AD_FIRE:
if (cancelled) {
tmp = 0;
mhm.damage = 0;
break;
}
if (g.vis && canseemon(mdef))
@@ -1033,22 +1034,22 @@ int dieroll;
return 0;
return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
mhm.damage += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
mhm.damage += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
if (resists_fire(mdef)) {
if (g.vis && canseemon(mdef))
pline_The("fire doesn't seem to burn %s!", mon_nam(mdef));
shieldeff(mdef->mx, mdef->my);
golemeffects(mdef, AD_FIRE, tmp);
tmp = 0;
golemeffects(mdef, AD_FIRE, mhm.damage);
mhm.damage = 0;
}
/* only potions damage resistant players in destroy_item */
tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
mhm.damage += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
ignite_items(mdef->minvent);
break;
case AD_COLD:
if (cancelled) {
tmp = 0;
mhm.damage = 0;
break;
}
if (g.vis && canseemon(mdef))
@@ -1057,39 +1058,39 @@ int dieroll;
if (g.vis && canseemon(mdef))
pline_The("frost doesn't seem to chill %s!", mon_nam(mdef));
shieldeff(mdef->mx, mdef->my);
golemeffects(mdef, AD_COLD, tmp);
tmp = 0;
golemeffects(mdef, AD_COLD, mhm.damage);
mhm.damage = 0;
}
tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
mhm.damage += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
break;
case AD_ELEC:
if (cancelled) {
tmp = 0;
mhm.damage = 0;
break;
}
if (g.vis && canseemon(mdef))
pline("%s gets zapped!", Monnam(mdef));
tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
mhm.damage += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
if (resists_elec(mdef)) {
if (g.vis && canseemon(mdef))
pline_The("zap doesn't shock %s!", mon_nam(mdef));
shieldeff(mdef->mx, mdef->my);
golemeffects(mdef, AD_ELEC, tmp);
tmp = 0;
golemeffects(mdef, AD_ELEC, mhm.damage);
mhm.damage = 0;
}
/* only rings damage resistant players in destroy_item */
tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
mhm.damage += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
break;
case AD_ACID:
if (magr->mcan) {
tmp = 0;
mhm.damage = 0;
break;
}
if (resists_acid(mdef)) {
if (g.vis && canseemon(mdef))
pline("%s is covered in %s, but it seems harmless.",
Monnam(mdef), hliquid("acid"));
tmp = 0;
mhm.damage = 0;
} else if (g.vis && canseemon(mdef)) {
pline("%s is covered in %s!", Monnam(mdef), hliquid("acid"));
pline("It burns %s!", mon_nam(mdef));
@@ -1100,27 +1101,14 @@ int dieroll;
acid_damage(MON_WEP(mdef));
break;
case AD_RUST:
if (magr->mcan)
break;
if (completelyrusts(pd)) { /* PM_IRON_GOLEM */
if (g.vis && canseemon(mdef))
pline("%s %s to pieces!", Monnam(mdef),
!mlifesaver(mdef) ? "falls" : "starts to fall");
monkilled(mdef, (char *) 0, AD_RUST);
if (!DEADMONSTER(mdef))
return 0;
return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
erode_armor(mdef, ERODE_RUST);
mdef->mstrategy &= ~STRAT_WAITFORU;
tmp = 0;
mhitm_ad_rust(magr, mattk, mdef, &mhm);
if (mhm.done)
return mhm.hitflags;
break;
case AD_CORR:
if (magr->mcan)
break;
erode_armor(mdef, ERODE_CORRODE);
mdef->mstrategy &= ~STRAT_WAITFORU;
tmp = 0;
mhitm_ad_corr(magr, mattk, mdef, &mhm);
if (mhm.done)
return mhm.hitflags;
break;
case AD_DCAY:
if (magr->mcan)
@@ -1138,7 +1126,7 @@ int dieroll;
}
erode_armor(mdef, ERODE_CORRODE);
mdef->mstrategy &= ~STRAT_WAITFORU;
tmp = 0;
mhm.damage = 0;
break;
case AD_STON:
if (magr->mcan)
@@ -1149,7 +1137,7 @@ int dieroll;
goto post_stone;
if (poly_when_stoned(pd)) {
mon_to_stone(mdef);
tmp = 0;
mhm.damage = 0;
break;
}
if (!resists_ston(mdef)) {
@@ -1163,10 +1151,10 @@ int dieroll;
You(brief_feeling, "peculiarly sad");
return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
tmp = (mattk->adtyp == AD_STON ? 0 : 1);
mhm.damage = (mattk->adtyp == AD_STON ? 0 : 1);
break;
case AD_TLPT:
if (!cancelled && tmp < mdef->mhp && !tele_restrict(mdef)) {
if (!cancelled && mhm.damage < mdef->mhp && !tele_restrict(mdef)) {
char mdef_Monnam[BUFSZ];
boolean wasseen = canspotmon(mdef);
@@ -1178,10 +1166,10 @@ int dieroll;
(void) rloc(mdef, TRUE);
if (g.vis && wasseen && !canspotmon(mdef) && mdef != u.usteed)
pline("%s suddenly disappears!", mdef_Monnam);
if (tmp >= mdef->mhp) { /* see hitmu(mhitu.c) */
if (mhm.damage >= mdef->mhp) { /* see hitmu(mhitu.c) */
if (mdef->mhp == 1)
++mdef->mhp;
tmp = mdef->mhp - 1;
mhm.damage = mdef->mhp - 1;
}
}
break;
@@ -1240,7 +1228,7 @@ int dieroll;
mdef->mcansee = 0;
mdef->mstrategy &= ~STRAT_WAITFORU;
}
tmp = 0;
mhm.damage = 0;
break;
case AD_HALU:
if (!magr->mcan && haseyes(pd) && mdef->mcansee) {
@@ -1250,7 +1238,7 @@ int dieroll;
mdef->mconf = 1;
mdef->mstrategy &= ~STRAT_WAITFORU;
}
tmp = 0;
mhm.damage = 0;
break;
case AD_CURS:
if (!night() && (pa == &mons[PM_GREMLIN]))
@@ -1283,7 +1271,7 @@ int dieroll;
}
break;
case AD_SGLD:
tmp = 0;
mhm.damage = 0;
if (magr->mcan)
break;
/* technically incorrect; no check for stealing gold from
@@ -1312,11 +1300,11 @@ int dieroll;
break;
case AD_DRLI: /* drain life */
if (!cancelled && !rn2(3) && !resists_drli(mdef)) {
tmp = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */
mhm.damage = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */
if (g.vis && canspotmon(mdef))
pline("%s becomes weaker!", Monnam(mdef));
if (mdef->mhpmax - tmp > (int) mdef->m_lev) {
mdef->mhpmax -= tmp;
if (mdef->mhpmax - mhm.damage > (int) mdef->m_lev) {
mdef->mhpmax -= mhm.damage;
} else {
/* limit floor of mhpmax reduction to current m_lev + 1;
avoid increasing it if somehow already less than that */
@@ -1324,7 +1312,7 @@ int dieroll;
mdef->mhpmax = (int) mdef->m_lev + 1;
}
if (mdef->m_lev == 0) /* automatic kill if drained past level 0 */
tmp = mdef->mhp;
mhm.damage = mdef->mhp;
else
mdef->m_lev--;
@@ -1386,13 +1374,13 @@ int dieroll;
pline("%s suddenly disappears!", buf);
}
}
tmp = 0;
mhm.damage = 0;
break;
case AD_DREN:
if (!cancelled && !rn2(4))
xdrainenergym(mdef, (boolean) (g.vis && canspotmon(mdef)
&& mattk->aatyp != AT_ENGL));
tmp = 0;
mhm.damage = 0;
break;
case AD_DRST:
case AD_DRDX:
@@ -1407,11 +1395,11 @@ int dieroll;
mon_nam(mdef));
} else {
if (rn2(10))
tmp += rn1(10, 6);
mhm.damage += rn1(10, 6);
else {
if (g.vis && canspotmon(mdef))
pline_The("poison was deadly...");
tmp = mdef->mhp;
mhm.damage = mdef->mhp;
}
}
}
@@ -1421,7 +1409,7 @@ int dieroll;
if (g.vis && canspotmon(mdef))
pline("%s doesn't seem harmed.", Monnam(mdef));
/* Not clear what to do for green slimes */
tmp = 0;
mhm.damage = 0;
/* don't bother with additional DRIN attacks since they wouldn't
be able to hit target on head either */
g.skipdrin = TRUE; /* affects mattackm()'s attack loop */
@@ -1435,7 +1423,7 @@ int dieroll;
}
break;
}
res = eat_brains(magr, mdef, g.vis, &tmp);
mhm.hitflags = eat_brains(magr, mdef, g.vis, &mhm.damage);
break;
case AD_SLIM:
if (cancelled)
@@ -1446,41 +1434,41 @@ int dieroll;
(boolean) (g.vis && canseemon(mdef))))
pd = mdef->data;
mdef->mstrategy &= ~STRAT_WAITFORU;
res = MM_HIT;
mhm.hitflags = MM_HIT;
}
/* munslime attempt could have been fatal,
potentially to multiple monsters (SCR_FIRE) */
if (DEADMONSTER(magr))
res |= MM_AGR_DIED;
mhm.hitflags |= MM_AGR_DIED;
if (DEADMONSTER(mdef))
res |= MM_DEF_DIED;
tmp = 0;
mhm.hitflags |= MM_DEF_DIED;
mhm.damage = 0;
}
break;
case AD_STCK:
if (cancelled)
tmp = 0;
mhm.damage = 0;
break;
case AD_WRAP: /* monsters cannot grab one another, it's too hard */
if (magr->mcan)
tmp = 0;
mhm.damage = 0;
break;
case AD_ENCH:
/* there's no msomearmor() function, so just do damage */
/* if (cancelled) break; */
break;
case AD_POLY:
if (!magr->mcan && tmp < mdef->mhp)
tmp = mon_poly(magr, mdef, tmp);
if (!magr->mcan && mhm.damage < mdef->mhp)
mhm.damage = mon_poly(magr, mdef, mhm.damage);
break;
default:
tmp = 0;
mhm.damage = 0;
break;
}
if (!tmp)
return res;
if (!mhm.damage)
return mhm.hitflags;
if ((mdef->mhp -= tmp) < 1) {
if ((mdef->mhp -= mhm.damage) < 1) {
if (m_at(mdef->mx, mdef->my) == magr) { /* see gulpmm() */
remove_monster(mdef->mx, mdef->my);
mdef->mhp = 1; /* otherwise place_monster will complain */
@@ -1495,8 +1483,8 @@ int dieroll;
monkilled(mdef, "", (int) mattk->adtyp);
g.zombify = FALSE; /* reset */
if (!DEADMONSTER(mdef))
return res; /* mdef lifesaved */
else if (res == MM_AGR_DIED)
return mhm.hitflags; /* mdef lifesaved */
else if (mhm.hitflags == MM_AGR_DIED)
return (MM_DEF_DIED | MM_AGR_DIED);
if (mattk->adtyp == AD_DGST) {
@@ -1518,7 +1506,7 @@ int dieroll;
return (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
}
return (res == MM_AGR_DIED) ? MM_AGR_DIED : MM_HIT;
return (mhm.hitflags == MM_AGR_DIED) ? MM_AGR_DIED : MM_HIT;
}
int

View File

@@ -8,7 +8,6 @@
static NEARDATA struct obj *mon_currwep = (struct obj *) 0;
static void FDECL(hitmsg, (struct monst *, struct attack *));
static void FDECL(missmu, (struct monst *, BOOLEAN_P, struct attack *));
static void FDECL(mswings, (struct monst *, struct obj *));
static void FDECL(wildmiss, (struct monst *, struct attack *));
@@ -25,7 +24,7 @@ static int FDECL(passiveum, (struct permonst *, struct monst *,
#define ld() ((yyyymmdd((time_t) 0) - (getyear() * 10000L)) == 0xe5)
static void
void
hitmsg(mtmp, mattk)
struct monst *mtmp;
struct attack *mattk;
@@ -970,10 +969,12 @@ register struct attack *mattk;
{
struct permonst *mdat = mtmp->data;
int uncancelled, ptmp;
int dmg, armpro, permdmg, tmphp;
int armpro, permdmg, tmphp;
char buf[BUFSZ];
struct permonst *olduasmon = g.youmonst.data;
int res;
struct mhitm_data mhm;
mhm.hitflags = MM_MISS;
if (!canspotmon(mtmp))
map_invisible(mtmp->mx, mtmp->my);
@@ -1002,9 +1003,9 @@ register struct attack *mattk;
}
/* First determine the base damage done */
dmg = d((int) mattk->damn, (int) mattk->damd);
mhm.damage = d((int) mattk->damn, (int) mattk->damd);
if ((is_undead(mdat) || is_vampshifter(mtmp)) && midnight())
dmg += d((int) mattk->damn, (int) mattk->damd); /* extra damage */
mhm.damage += d((int) mattk->damn, (int) mattk->damd); /* extra damage */
/* Next a cancellation factor.
* Use uncancelled when cancellation factor takes into account certain
@@ -1020,7 +1021,7 @@ register struct attack *mattk;
if (mattk->aatyp == AT_HUGS && !sticks(g.youmonst.data)) {
if (!u.ustuck && rn2(2)) {
if (u_slip_free(mtmp, mattk)) {
dmg = 0;
mhm.damage = 0;
} else {
set_ustuck(mtmp);
pline("%s grabs you!", Monnam(mtmp));
@@ -1040,22 +1041,22 @@ register struct attack *mattk;
if (otmp->otyp == CORPSE
&& touch_petrifies(&mons[otmp->corpsenm])) {
dmg = 1;
mhm.damage = 1;
pline("%s hits you with the %s corpse.", Monnam(mtmp),
mons[otmp->corpsenm].mname);
if (!Stoned)
goto do_stone;
}
dmg += dmgval(otmp, &g.youmonst);
mhm.damage += dmgval(otmp, &g.youmonst);
if ((marmg = which_armor(mtmp, W_ARMG)) != 0
&& marmg->otyp == GAUNTLETS_OF_POWER)
dmg += rn1(4, 3); /* 3..6 */
if (dmg <= 0)
dmg = 1;
mhm.damage += rn1(4, 3); /* 3..6 */
if (mhm.damage <= 0)
mhm.damage = 1;
if (!(otmp->oartifact && artifact_hit(mtmp, &g.youmonst, otmp,
&dmg, g.mhitu_dieroll)))
&mhm.damage, g.mhitu_dieroll)))
hitmsg(mtmp, mattk);
if (!dmg)
if (!mhm.damage)
break;
if (objects[otmp->otyp].oc_material == SILVER
&& Hate_silver) {
@@ -1065,7 +1066,7 @@ register struct attack *mattk;
/* this redundancy necessary because you have
to take the damage _before_ being cloned;
need to have at least 2 hp left to split */
tmp = dmg;
tmp = mhm.damage;
if (u.uac < 0)
tmp -= rnd(-u.uac);
if (tmp < 1)
@@ -1081,12 +1082,12 @@ register struct attack *mattk;
/* inflict damage now; we know it can't be fatal */
u.mh -= tmp;
g.context.botl = 1;
dmg = 0; /* don't inflict more damage below */
mhm.damage = 0; /* don't inflict more damage below */
if (cloneu())
You("divide as %s hits you!", mon_nam(mtmp));
}
rustm(&g.youmonst, otmp);
} else if (mattk->aatyp != AT_TUCH || dmg != 0
} else if (mattk->aatyp != AT_TUCH || mhm.damage != 0
|| mtmp != u.ustuck)
hitmsg(mtmp, mattk);
}
@@ -1094,7 +1095,7 @@ register struct attack *mattk;
case AD_DISE:
hitmsg(mtmp, mattk);
if (!diseasemu(mdat))
dmg = 0;
mhm.damage = 0;
break;
case AD_FIRE:
hitmsg(mtmp, mattk);
@@ -1107,7 +1108,7 @@ register struct attack *mattk;
break;
} else if (Fire_resistance) {
pline_The("fire doesn't feel hot!");
dmg = 0;
mhm.damage = 0;
}
if ((int) mtmp->m_lev > rn2(20))
destroy_item(SCROLL_CLASS, AD_FIRE);
@@ -1119,7 +1120,7 @@ register struct attack *mattk;
ignite_items(g.invent);
burn_away_slime();
} else
dmg = 0;
mhm.damage = 0;
break;
case AD_COLD:
hitmsg(mtmp, mattk);
@@ -1127,12 +1128,12 @@ register struct attack *mattk;
pline("You're covered in frost!");
if (Cold_resistance) {
pline_The("frost doesn't seem cold!");
dmg = 0;
mhm.damage = 0;
}
if ((int) mtmp->m_lev > rn2(20))
destroy_item(POTION_CLASS, AD_COLD);
} else
dmg = 0;
mhm.damage = 0;
break;
case AD_ELEC:
hitmsg(mtmp, mattk);
@@ -1140,14 +1141,14 @@ register struct attack *mattk;
You("get zapped!");
if (Shock_resistance) {
pline_The("zap doesn't shock you!");
dmg = 0;
mhm.damage = 0;
}
if ((int) mtmp->m_lev > rn2(20))
destroy_item(WAND_CLASS, AD_ELEC);
if ((int) mtmp->m_lev > rn2(20))
destroy_item(RING_CLASS, AD_ELEC);
} else
dmg = 0;
mhm.damage = 0;
break;
case AD_SLEE:
hitmsg(mtmp, mattk);
@@ -1165,11 +1166,11 @@ register struct attack *mattk;
if (can_blnd(mtmp, &g.youmonst, mattk->aatyp, (struct obj *) 0)) {
if (!Blind)
pline("%s blinds you!", Monnam(mtmp));
make_blinded(Blinded + (long) dmg, FALSE);
make_blinded(Blinded + (long) mhm.damage, FALSE);
if (!Blind)
Your1(vision_clears);
}
dmg = 0;
mhm.damage = 0;
break;
case AD_DRST:
ptmp = A_STR;
@@ -1207,9 +1208,9 @@ register struct attack *mattk;
}
/* negative armor class doesn't reduce this damage */
if (Half_physical_damage)
dmg = (dmg + 1) / 2;
mdamageu(mtmp, dmg);
dmg = 0; /* don't inflict a second dose below */
mhm.damage = (mhm.damage + 1) / 2;
mdamageu(mtmp, mhm.damage);
mhm.damage = 0; /* don't inflict a second dose below */
if (!uarmh || uarmh->otyp != DUNCE_CAP) {
/* eat_brains() will miss if target is mindless (won't
@@ -1260,11 +1261,11 @@ register struct attack *mattk;
*/
if ((u.usteed || Levitation || Flying) && !is_flyer(mtmp->data)) {
pline("%s tries to reach your %s %s!", Monst_name, sidestr, leg);
dmg = 0;
mhm.damage = 0;
} else if (mtmp->mcan) {
pline("%s nuzzles against your %s %s!", Monnam(mtmp),
sidestr, leg);
dmg = 0;
mhm.damage = 0;
} else {
if (uarmf) {
if (rn2(2) && (uarmf->otyp == LOW_BOOTS
@@ -1277,7 +1278,7 @@ register struct attack *mattk;
} else {
pline("%s scratches your %s boot!", Monst_name,
sidestr);
dmg = 0;
mhm.damage = 0;
break;
}
} else
@@ -1330,7 +1331,7 @@ register struct attack *mattk;
if ((!mtmp->mcan || u.ustuck == mtmp) && !sticks(g.youmonst.data)) {
if (!u.ustuck && !rn2(10)) {
if (u_slip_free(mtmp, mattk)) {
dmg = 0;
mhm.damage = 0;
} else {
set_ustuck(mtmp); /* before message, for botl update */
pline("%s swings itself around you!", Monnam(mtmp));
@@ -1352,13 +1353,13 @@ register struct attack *mattk;
You("are being crushed.");
}
} else {
dmg = 0;
mhm.damage = 0;
if (flags.verbose)
pline("%s brushes against your %s.", Monnam(mtmp),
body_part(LEG));
}
} else
dmg = 0;
mhm.damage = 0;
break;
case AD_WERE:
hitmsg(mtmp, mattk);
@@ -1462,16 +1463,16 @@ register struct attack *mattk;
particularly if the teleportation had been controlled
[applying the damage first and not teleporting if fatal
is another alternative but it has its own complications] */
if ((Half_physical_damage ? (dmg - 1) / 2 : dmg)
if ((Half_physical_damage ? (mhm.damage - 1) / 2 : mhm.damage)
>= (tmphp = (Upolyd ? u.mh : u.uhp))) {
dmg = tmphp - 1;
mhm.damage = tmphp - 1;
if (Half_physical_damage)
dmg *= 2; /* doesn't actually increase damage; we only
mhm.damage *= 2; /* doesn't actually increase damage; we only
* get here if half the original damage would
* would have been fatal, so double reduced
* damage will be less than original damage */
if (dmg < 1) { /* implies (tmphp <= 1) */
dmg = 1;
if (mhm.damage < 1) { /* implies (tmphp <= 1) */
mhm.damage = 1;
/* this might increase current HP beyond maximum HP but
it will be immediately reduced below, so that should
be indistinguishable from zero damage; we don't drop
@@ -1487,22 +1488,14 @@ register struct attack *mattk;
}
break;
case AD_RUST:
hitmsg(mtmp, mattk);
if (mtmp->mcan)
break;
if (completelyrusts(g.youmonst.data)) {
You("rust!");
/* KMH -- this is okay with unchanging */
rehumanize();
break;
}
erode_armor(&g.youmonst, ERODE_RUST);
mhitm_ad_rust(mtmp, mattk, &g.youmonst, &mhm);
if (mhm.done)
return mhm.hitflags;
break;
case AD_CORR:
hitmsg(mtmp, mattk);
if (mtmp->mcan)
break;
erode_armor(&g.youmonst, ERODE_CORRODE);
mhitm_ad_corr(mtmp, mattk, &g.youmonst, &mhm);
if (mhm.done)
return mhm.hitflags;
break;
case AD_DCAY:
hitmsg(mtmp, mattk);
@@ -1568,12 +1561,12 @@ register struct attack *mattk;
monflee(mtmp, d(3, 6), TRUE, FALSE);
return 3;
}
dmg = 0;
mhm.damage = 0;
} else {
if (Role_if(PM_HEALER)) {
if (!Deaf && !(g.moves % 5))
verbalize("Doc, I can't help you unless you cooperate.");
dmg = 0;
mhm.damage = 0;
} else
hitmsg(mtmp, mattk);
}
@@ -1601,8 +1594,8 @@ register struct attack *mattk;
case AD_STUN:
hitmsg(mtmp, mattk);
if (!mtmp->mcan && !rn2(4)) {
make_stunned((HStun & TIMEOUT) + (long) dmg, TRUE);
dmg /= 2;
make_stunned((HStun & TIMEOUT) + (long) mhm.damage, TRUE);
mhm.damage /= 2;
}
break;
case AD_ACID:
@@ -1611,13 +1604,13 @@ register struct attack *mattk;
if (Acid_resistance) {
pline("You're covered in %s, but it seems harmless.",
hliquid("acid"));
dmg = 0;
mhm.damage = 0;
} else {
pline("You're covered in %s! It burns!", hliquid("acid"));
exercise(A_STR, FALSE);
}
else
dmg = 0;
mhm.damage = 0;
break;
case AD_SLOW:
hitmsg(mtmp, mattk);
@@ -1627,20 +1620,20 @@ register struct attack *mattk;
case AD_DREN:
hitmsg(mtmp, mattk);
if (uncancelled && !rn2(4)) /* 25% chance */
drain_en(dmg);
dmg = 0;
drain_en(mhm.damage);
mhm.damage = 0;
break;
case AD_CONF:
hitmsg(mtmp, mattk);
if (!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
mtmp->mspec_used = mtmp->mspec_used + (dmg + rn2(6));
mtmp->mspec_used = mtmp->mspec_used + (mhm.damage + rn2(6));
if (Confusion)
You("are getting even more confused.");
else
You("are getting confused.");
make_confused(HConfusion + dmg, FALSE);
make_confused(HConfusion + mhm.damage, FALSE);
}
dmg = 0;
mhm.damage = 0;
break;
case AD_DETH:
pline("%s reaches out with its deadly touch.", Monnam(mtmp));
@@ -1657,7 +1650,7 @@ register struct attack *mattk;
g.killer.format = KILLED_BY_AN;
Strcpy(g.killer.name, "touch of death");
done(DIED);
dmg = 0;
mhm.damage = 0;
break;
}
/*FALLTHRU*/
@@ -1673,7 +1666,7 @@ register struct attack *mattk;
if (Antimagic)
shieldeff(u.ux, u.uy);
pline("Lucky for you, it didn't work!");
dmg = 0;
mhm.damage = 0;
break;
}
break;
@@ -1694,11 +1687,11 @@ register struct attack *mattk;
break;
if (flaming(g.youmonst.data)) {
pline_The("slime burns away!");
dmg = 0;
mhm.damage = 0;
} else if (Unchanging || noncorporeal(g.youmonst.data)
|| g.youmonst.data == &mons[PM_GREEN_SLIME]) {
You("are unaffected.");
dmg = 0;
mhm.damage = 0;
} else if (!Slimed) {
You("don't feel very well.");
make_slimed(10L, (char *) 0);
@@ -1739,35 +1732,35 @@ register struct attack *mattk;
}
break;
case AD_POLY:
if (uncancelled && Maybe_Half_Phys(dmg) < (Upolyd ? u.mh : u.uhp))
dmg = mon_poly(mtmp, &g.youmonst, dmg);
if (uncancelled && Maybe_Half_Phys(mhm.damage) < (Upolyd ? u.mh : u.uhp))
mhm.damage = mon_poly(mtmp, &g.youmonst, mhm.damage);
break;
default:
dmg = 0;
mhm.damage = 0;
break;
}
if ((Upolyd ? u.mh : u.uhp) < 1) {
/* already dead? call rehumanize() or done_in_by() as appropriate */
mdamageu(mtmp, 1);
dmg = 0;
mhm.damage = 0;
}
/* Negative armor class reduces damage done instead of fully protecting
* against hits.
*/
if (dmg && u.uac < 0) {
dmg -= rnd(-u.uac);
if (dmg < 1)
dmg = 1;
if (mhm.damage && u.uac < 0) {
mhm.damage -= rnd(-u.uac);
if (mhm.damage < 1)
mhm.damage = 1;
}
if (dmg) {
if (mhm.damage) {
if (Half_physical_damage
/* Mitre of Holiness */
|| (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh)
&& (is_undead(mtmp->data) || is_demon(mtmp->data)
|| is_vampshifter(mtmp))))
dmg = (dmg + 1) / 2;
mhm.damage = (mhm.damage + 1) / 2;
if (permdmg) { /* Death's life force drain */
int lowerlimit, *hpmax_p;
@@ -1780,13 +1773,13 @@ register struct attack *mattk;
* otherwise 0..50%
* Never reduces hpmax below 1 hit point per level.
*/
permdmg = rn2(dmg / 2 + 1);
permdmg = rn2(mhm.damage / 2 + 1);
if (Upolyd || u.uhpmax > 25 * u.ulevel)
permdmg = dmg;
permdmg = mhm.damage;
else if (u.uhpmax > 10 * u.ulevel)
permdmg += dmg / 2;
permdmg += mhm.damage / 2;
else if (u.uhpmax > 5 * u.ulevel)
permdmg += dmg / 4;
permdmg += mhm.damage / 4;
if (Upolyd) {
hpmax_p = &u.mhmax;
@@ -1805,10 +1798,10 @@ register struct attack *mattk;
g.context.botl = 1;
}
mdamageu(mtmp, dmg);
mdamageu(mtmp, mhm.damage);
}
if (dmg)
if (mhm.damage)
res = passiveum(olduasmon, mtmp, mattk);
else
res = 1;

View File

@@ -1689,6 +1689,118 @@ struct attack *mattk;
mpickobj(mdef, gold);
}
void
mhitm_ad_rust(magr, mattk, mdef, mhm)
struct monst *magr;
struct attack *mattk;
struct monst *mdef;
struct mhitm_data *mhm;
{
struct permonst *pd = mdef->data;
if (magr == &g.youmonst) {
/* uhitm */
if (completelyrusts(pd)) { /* iron golem */
/* note: the life-saved case is hypothetical because
life-saving doesn't work for golems */
pline("%s %s to pieces!", Monnam(mdef),
!mlifesaver(mdef) ? "falls" : "starts to fall");
xkilled(mdef, XKILL_NOMSG);
mhm->hitflags |= MM_DEF_DIED;
}
erode_armor(mdef, ERODE_RUST);
mhm->damage = 0; /* damageum(), int tmp */
} else if (mdef == &g.youmonst) {
/* mhitu */
hitmsg(magr, mattk);
if (magr->mcan) {
return;
}
if (completelyrusts(pd)) {
You("rust!");
/* KMH -- this is okay with unchanging */
rehumanize();
return;
}
erode_armor(&g.youmonst, ERODE_RUST);
} else {
/* mhitm */
if (magr->mcan)
return;
if (completelyrusts(pd)) { /* PM_IRON_GOLEM */
if (g.vis && canseemon(mdef))
pline("%s %s to pieces!", Monnam(mdef),
!mlifesaver(mdef) ? "falls" : "starts to fall");
monkilled(mdef, (char *) 0, AD_RUST);
if (!DEADMONSTER(mdef)) {
mhm->hitflags = MM_MISS;
mhm->done = TRUE;
return;
}
mhm->hitflags = (MM_DEF_DIED | (grow_up(magr, mdef) ? 0 : MM_AGR_DIED));
mhm->done = TRUE;
return;
}
erode_armor(mdef, ERODE_RUST);
mdef->mstrategy &= ~STRAT_WAITFORU;
mhm->damage = 0; /* mdamagem(), int tmp */
}
}
void
mhitm_ad_corr(magr, mattk, mdef, mhm)
struct monst *magr;
struct attack *mattk;
struct monst *mdef;
struct mhitm_data *mhm;
{
struct permonst *pd = mdef->data;
if (magr == &g.youmonst) {
/* uhitm */
erode_armor(mdef, ERODE_CORRODE);
mhm->damage = 0;
} else if (mdef == &g.youmonst) {
/* mhitu */
hitmsg(magr, mattk);
if (magr->mcan)
return;
erode_armor(mdef, ERODE_CORRODE);
} else {
/* mhitm */
if (magr->mcan)
return;
erode_armor(mdef, ERODE_CORRODE);
mdef->mstrategy &= ~STRAT_WAITFORU;
mhm->damage = 0;
}
}
/* Template for monster hits monster for AD_FOO.
- replace "break" with return
- replace "return" with mhm->done = TRUE
*/
void
mhitm_ad_FOO(magr, mattk, mdef, mhm)
struct monst *magr;
struct attack *mattk;
struct monst *mdef;
struct mhitm_data *mhm;
{
struct permonst *pd = mdef->data;
if (magr == &g.youmonst) {
/* uhitm */
/* TODO */
} else if (mdef == &g.youmonst) {
/* mhitu */
/* TODO */
} else {
/* mhitm */
/* TODO */
}
}
int
damageum(mdef, mattk, specialdmg)
register struct monst *mdef;
@@ -1696,9 +1808,12 @@ register struct attack *mattk;
int specialdmg; /* blessed and/or silver bonus against various things */
{
register struct permonst *pd = mdef->data;
int armpro, tmp = d((int) mattk->damn, (int) mattk->damd);
int armpro;
boolean negated;
struct obj *mongold;
struct mhitm_data mhm;
mhm.damage = d((int) mattk->damn, (int) mattk->damd);
mhm.hitflags = MM_MISS;
armpro = magic_negation(mdef);
/* since hero can't be cancelled, only defender's armor applies */
@@ -1720,7 +1835,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
case AD_LEGS:
#if 0
if (u.ucancelled) {
tmp = 0;
mhm.damage = 0;
break;
}
#endif
@@ -1730,39 +1845,39 @@ int specialdmg; /* blessed and/or silver bonus against various things */
case AD_PHYS:
physical:
if (pd == &mons[PM_SHADE]) {
tmp = 0;
mhm.damage = 0;
if (!specialdmg)
impossible("bad shade attack function flow?");
}
tmp += specialdmg;
mhm.damage += specialdmg;
if (mattk->aatyp == AT_WEAP) {
/* hmonas() uses known_hitum() to deal physical damage,
then also damageum() for non-AD_PHYS; don't inflict
extra physical damage for unusual damage types */
tmp = 0;
mhm.damage = 0;
} else if (mattk->aatyp == AT_KICK
|| mattk->aatyp == AT_CLAW
|| mattk->aatyp == AT_TUCH
|| mattk->aatyp == AT_HUGS) {
if (thick_skinned(pd))
tmp = (mattk->aatyp == AT_KICK) ? 0 : (tmp + 1) / 2;
mhm.damage = (mattk->aatyp == AT_KICK) ? 0 : (mhm.damage + 1) / 2;
/* add ring(s) of increase damage */
if (u.udaminc > 0) {
/* applies even if damage was 0 */
tmp += u.udaminc;
} else if (tmp > 0) {
mhm.damage += u.udaminc;
} else if (mhm.damage > 0) {
/* ring(s) might be negative; avoid converting
0 to non-0 or positive to non-positive */
tmp += u.udaminc;
if (tmp < 1)
tmp = 1;
mhm.damage += u.udaminc;
if (mhm.damage < 1)
mhm.damage = 1;
}
}
break;
case AD_FIRE:
if (negated) {
tmp = 0;
mhm.damage = 0;
break;
}
if (!Blind)
@@ -1779,26 +1894,26 @@ int specialdmg; /* blessed and/or silver bonus against various things */
(pd == &mons[PM_PAPER_GOLEM]) ? " paper"
: (pd == &mons[PM_STRAW_GOLEM]) ? " straw" : "");
xkilled(mdef, XKILL_NOMSG | XKILL_NOCORPSE);
tmp = 0;
mhm.damage = 0;
break;
/* Don't return yet; keep hp<1 and tmp=0 for pet msg */
/* Don't return yet; keep hp<1 and mhm.damage=0 for pet msg */
}
tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
mhm.damage += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
mhm.damage += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
if (resists_fire(mdef)) {
if (!Blind)
pline_The("fire doesn't heat %s!", mon_nam(mdef));
golemeffects(mdef, AD_FIRE, tmp);
golemeffects(mdef, AD_FIRE, mhm.damage);
shieldeff(mdef->mx, mdef->my);
tmp = 0;
mhm.damage = 0;
}
/* only potions damage resistant players in destroy_item */
tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
mhm.damage += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
ignite_items(mdef->minvent);
break;
case AD_COLD:
if (negated) {
tmp = 0;
mhm.damage = 0;
break;
}
if (!Blind)
@@ -1807,43 +1922,43 @@ int specialdmg; /* blessed and/or silver bonus against various things */
shieldeff(mdef->mx, mdef->my);
if (!Blind)
pline_The("frost doesn't chill %s!", mon_nam(mdef));
golemeffects(mdef, AD_COLD, tmp);
tmp = 0;
golemeffects(mdef, AD_COLD, mhm.damage);
mhm.damage = 0;
}
tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
mhm.damage += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
break;
case AD_ELEC:
if (negated) {
tmp = 0;
mhm.damage = 0;
break;
}
if (!Blind)
pline("%s is zapped!", Monnam(mdef));
tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
mhm.damage += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
if (resists_elec(mdef)) {
if (!Blind)
pline_The("zap doesn't shock %s!", mon_nam(mdef));
golemeffects(mdef, AD_ELEC, tmp);
golemeffects(mdef, AD_ELEC, mhm.damage);
shieldeff(mdef->mx, mdef->my);
tmp = 0;
mhm.damage = 0;
}
/* only rings damage resistant players in destroy_item */
tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
mhm.damage += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
break;
case AD_ACID:
if (resists_acid(mdef))
tmp = 0;
mhm.damage = 0;
break;
case AD_STON:
if (!munstone(mdef, TRUE))
minstapetrify(mdef, TRUE);
tmp = 0;
mhm.damage = 0;
break;
case AD_SSEX:
case AD_SEDU:
case AD_SITM:
steal_it(mdef, mattk);
tmp = 0;
mhm.damage = 0;
break;
case AD_SGLD:
/* This you as a leprechaun, so steal
@@ -1861,11 +1976,11 @@ int specialdmg; /* blessed and/or silver bonus against various things */
}
}
exercise(A_DEX, TRUE);
tmp = 0;
mhm.damage = 0;
break;
case AD_TLPT:
if (tmp <= 0)
tmp = 1;
if (mhm.damage <= 0)
mhm.damage = 1;
if (!negated) {
char nambuf[BUFSZ];
boolean u_saw_mon = (canseemon(mdef)
@@ -1876,10 +1991,10 @@ int specialdmg; /* blessed and/or silver bonus against various things */
if (u_teleport_mon(mdef, FALSE) && u_saw_mon
&& !(canseemon(mdef) || (u.uswallow && u.ustuck == mdef)))
pline("%s suddenly disappears!", nambuf);
if (tmp >= mdef->mhp) { /* see hitmu(mhitu.c) */
if (mhm.damage >= mdef->mhp) { /* see hitmu(mhitu.c) */
if (mdef->mhp == 1)
++mdef->mhp;
tmp = mdef->mhp - 1;
mhm.damage = mdef->mhp - 1;
}
}
break;
@@ -1888,12 +2003,12 @@ int specialdmg; /* blessed and/or silver bonus against various things */
if (!Blind && mdef->mcansee)
pline("%s is blinded.", Monnam(mdef));
mdef->mcansee = 0;
tmp += mdef->mblinded;
if (tmp > 127)
tmp = 127;
mdef->mblinded = tmp;
mhm.damage += mdef->mblinded;
if (mhm.damage > 127)
mhm.damage = 127;
mdef->mblinded = mhm.damage;
}
tmp = 0;
mhm.damage = 0;
break;
case AD_CURS:
if (night() && !rn2(10) && !mdef->mcan) {
@@ -1902,27 +2017,27 @@ int specialdmg; /* blessed and/or silver bonus against various things */
pline("Some writing vanishes from %s head!",
s_suffix(mon_nam(mdef)));
xkilled(mdef, XKILL_NOMSG);
/* Don't return yet; keep hp<1 and tmp=0 for pet msg */
/* Don't return yet; keep hp<1 and mhm.damage=0 for pet msg */
} else {
mdef->mcan = 1;
You("chuckle.");
}
}
tmp = 0;
mhm.damage = 0;
break;
case AD_DRLI: /* drain life */
if (!negated && !rn2(3) && !resists_drli(mdef)) {
tmp = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */
mhm.damage = d(2, 6); /* Stormbringer uses monhp_per_lvl(usually 1d8) */
pline("%s becomes weaker!", Monnam(mdef));
if (mdef->mhpmax - tmp > (int) mdef->m_lev) {
mdef->mhpmax -= tmp;
if (mdef->mhpmax - mhm.damage > (int) mdef->m_lev) {
mdef->mhpmax -= mhm.damage;
} else {
/* limit floor of mhpmax reduction to current m_lev + 1;
avoid increasing it if somehow already less than that */
if (mdef->mhpmax > (int) mdef->m_lev)
mdef->mhpmax = (int) mdef->m_lev + 1;
}
mdef->mhp -= tmp;
mdef->mhp -= mhm.damage;
/* !m_lev: level 0 monster is killed regardless of hit points
rather than drop to level -1; note: some non-living creatures
(golems, vortices) are subject to life-drain */
@@ -1932,26 +2047,21 @@ int specialdmg; /* blessed and/or silver bonus against various things */
xkilled(mdef, XKILL_NOMSG);
} else
mdef->m_lev--;
tmp = 0; /* damage has already been inflicted */
mhm.damage = 0; /* damage has already been inflicted */
/* unlike hitting with Stormbringer, wounded hero doesn't
heal any from the drained life */
}
break;
case AD_RUST:
if (completelyrusts(pd)) { /* iron golem */
/* note: the life-saved case is hypothetical because
life-saving doesn't work for golems */
pline("%s %s to pieces!", Monnam(mdef),
!mlifesaver(mdef) ? "falls" : "starts to fall");
xkilled(mdef, XKILL_NOMSG);
}
erode_armor(mdef, ERODE_RUST);
tmp = 0;
mhitm_ad_rust(&g.youmonst, mattk, mdef, &mhm);
if (mhm.done)
return mhm.hitflags;
break;
case AD_CORR:
erode_armor(mdef, ERODE_CORRODE);
tmp = 0;
mhitm_ad_corr(&g.youmonst, mattk, mdef, &mhm);
if (mhm.done)
return mhm.hitflags;
break;
case AD_DCAY:
if (completelyrots(pd)) { /* wood golem or leather golem */
@@ -1960,12 +2070,12 @@ int specialdmg; /* blessed and/or silver bonus against various things */
xkilled(mdef, XKILL_NOMSG);
}
erode_armor(mdef, ERODE_ROT);
tmp = 0;
mhm.damage = 0;
break;
case AD_DREN:
if (!negated && !rn2(4))
xdrainenergym(mdef, TRUE);
tmp = 0;
mhm.damage = 0;
break;
case AD_DRST:
case AD_DRDX:
@@ -1977,9 +2087,9 @@ int specialdmg; /* blessed and/or silver bonus against various things */
} else {
if (!rn2(10)) {
Your("poison was deadly...");
tmp = mdef->mhp;
mhm.damage = mdef->mhp;
} else
tmp += rn1(10, 6);
mhm.damage += rn1(10, 6);
}
}
break;
@@ -1992,7 +2102,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
because they'll be just as harmless as this one (and also
to reduce verbosity) */
g.skipdrin = TRUE;
tmp = 0;
mhm.damage = 0;
if (!Unchanging && pd == &mons[PM_GREEN_SLIME]) {
if (!Slimed) {
You("suck in some slime and don't feel very well.");
@@ -2011,7 +2121,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
break;
}
(void) eat_brains(&g.youmonst, mdef, TRUE, &tmp);
(void) eat_brains(&g.youmonst, mdef, TRUE, &mhm.damage);
break;
}
case AD_STCK:
@@ -2022,7 +2132,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
if (!sticks(pd)) {
if (!u.ustuck && !rn2(10)) {
if (m_slips_free(mdef, mattk)) {
tmp = 0;
mhm.damage = 0;
} else {
You("swing yourself around %s!", mon_nam(mdef));
set_ustuck(mdef);
@@ -2032,20 +2142,20 @@ int specialdmg; /* blessed and/or silver bonus against various things */
if (is_pool(u.ux, u.uy) && !is_swimmer(pd)
&& !amphibious(pd)) {
You("drown %s...", mon_nam(mdef));
tmp = mdef->mhp;
mhm.damage = mdef->mhp;
} else if (mattk->aatyp == AT_HUGS)
pline("%s is being crushed.", Monnam(mdef));
} else {
tmp = 0;
mhm.damage = 0;
if (flags.verbose)
You("brush against %s %s.", s_suffix(mon_nam(mdef)),
mbodypart(mdef, LEG));
}
} else
tmp = 0;
mhm.damage = 0;
break;
case AD_PLYS:
if (!negated && mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
if (!negated && mdef->mcanmove && !rn2(3) && mhm.damage < mdef->mhp) {
if (!Blind)
pline("%s is frozen by you!", Monnam(mdef));
paralyze_monst(mdef, rnd(10));
@@ -2072,7 +2182,7 @@ int specialdmg; /* blessed and/or silver bonus against various things */
/* munslime attempt could have been fatal */
if (DEADMONSTER(mdef))
return 2; /* skip death message */
tmp = 0;
mhm.damage = 0;
}
break;
case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */
@@ -2096,26 +2206,26 @@ int specialdmg; /* blessed and/or silver bonus against various things */
}
break;
case AD_POLY:
if (!negated && tmp < mdef->mhp)
tmp = mon_poly(&g.youmonst, mdef, tmp);
if (!negated && mhm.damage < mdef->mhp)
mhm.damage = mon_poly(&g.youmonst, mdef, mhm.damage);
break;
default:
tmp = 0;
mhm.damage = 0;
break;
}
mdef->mstrategy &= ~STRAT_WAITFORU; /* in case player is very fast */
mdef->mhp -= tmp;
mdef->mhp -= mhm.damage;
if (DEADMONSTER(mdef)) {
if (mdef->mtame && !cansee(mdef->mx, mdef->my)) {
You_feel("embarrassed for a moment.");
if (tmp)
xkilled(mdef, XKILL_NOMSG); /* !tmp but hp<1: already killed */
if (mhm.damage)
xkilled(mdef, XKILL_NOMSG); /* !mhm.damage but hp<1: already killed */
} else if (!flags.verbose) {
You("destroy it!");
if (tmp)
if (mhm.damage)
xkilled(mdef, XKILL_NOMSG);
} else if (tmp)
} else if (mhm.damage)
killed(mdef);
return 2;
}