Unify monster-hits-monster
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
158
src/mhitm.c
158
src/mhitm.c
@@ -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
|
||||
|
||||
161
src/mhitu.c
161
src/mhitu.c
@@ -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;
|
||||
|
||||
268
src/uhitm.c
268
src/uhitm.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user