Use a common funcion for all monster healing

Previously, the code for monster healing was repeated every time it
was needed; this commit sends it all through a common function, which
will make it easier to make changes to how monster healing works in
the future.

This is just a code reorganisation and won't have any gameplay
effect unless I made a mistake.
This commit is contained in:
Alex Smith
2025-01-12 18:20:13 +00:00
parent f0a0a74dcc
commit 97e0e934e8
13 changed files with 59 additions and 46 deletions

View File

@@ -1756,6 +1756,7 @@ extern struct monst *get_iter_mons(boolean (*)(struct monst *));
extern struct monst *get_iter_mons_xy(boolean (*)(struct monst *,
coordxy, coordxy),
coordxy, coordxy);
extern int healmon(struct monst *, int, int) NONNULLARG1;
extern void rescham(void);
extern void restartcham(void);
extern void restore_cham(struct monst *) NONNULLARG1;

View File

@@ -1636,9 +1636,7 @@ artifact_hit(
healup(drain, 0, FALSE, FALSE);
} else {
assert(magr != 0);
magr->mhp += drain;
if (magr->mhp > magr->mhpmax)
magr->mhp = magr->mhpmax;
healmon(magr, drain, 0);
}
}
return vis;
@@ -1664,9 +1662,7 @@ artifact_hit(
}
losexp("life drainage");
if (magr && magr->mhp < magr->mhpmax) {
magr->mhp += (abs(oldhpmax - u.uhpmax) + 1) / 2;
if (magr->mhp > magr->mhpmax)
magr->mhp = magr->mhpmax;
healmon(magr, (abs(oldhpmax - u.uhpmax) + 1) / 2, 0);
}
return TRUE;
}

View File

@@ -876,7 +876,7 @@ engulfer_digests_food(struct obj *obj)
} else if (could_grow) {
(void) grow_up(u.ustuck, (struct monst *) 0);
} else if (could_heal) {
u.ustuck->mhp = u.ustuck->mhpmax;
healmon(u.ustuck, u.ustuck->mhpmax, 0);
/* False: don't realize that sight is cured from inside */
mcureblindness(u.ustuck, FALSE);
}

View File

@@ -675,10 +675,7 @@ mon_catchup_elapsed_time(
/* recover lost hit points */
if (!regenerates(mtmp->data))
imv /= 20;
if (mtmp->mhp + imv >= mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
else
mtmp->mhp += imv;
healmon(mtmp, imv, 0);
set_mon_lastmove(mtmp);
}

View File

@@ -363,8 +363,7 @@ m_cure_self(struct monst *mtmp, int dmg)
if (canseemon(mtmp))
pline_mon(mtmp, "%s looks better.", Monnam(mtmp));
/* note: player healing does 6d4; this used to do 1d8 */
if ((mtmp->mhp += d(3, 6)) > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
healmon(mtmp, d(3, 6), 0);
dmg = 0;
}
return dmg;

View File

@@ -1093,7 +1093,7 @@ mdamagem(
return (M_ATTK_DEF_DIED
| (!DEADMONSTER(magr) ? 0 : M_ATTK_AGR_DIED));
} else if (pd == &mons[PM_NURSE]) {
magr->mhp = magr->mhpmax;
healmon(magr, magr->mhpmax, 0);
}
mon_givit(magr, pd);
}
@@ -1390,9 +1390,7 @@ passivemm(
}
if (canseemon(magr))
pline_mon(magr, "%s is suddenly very cold!", Monnam(magr));
mdef->mhp += tmp / 2;
if (mdef->mhpmax < mdef->mhp)
mdef->mhpmax = mdef->mhp;
healmon(mdef, tmp/2, tmp/2);
if (mdef->mhpmax > ((int) (mdef->m_lev + 1) * 8))
(void) split_mon(mdef, magr);
break;

View File

@@ -1351,9 +1351,7 @@ m_consume_obj(struct monst *mtmp, struct obj *otmp)
/* non-pet: Heal up to the object's weight in hp */
if (!ispet && mtmp->mhp < mtmp->mhpmax) {
mtmp->mhp += objects[otmp->otyp].oc_weight;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
healmon(mtmp, objects[otmp->otyp].oc_weight, 0);
}
if (Has_contents(otmp))
meatbox(mtmp, otmp);
@@ -1398,7 +1396,7 @@ m_consume_obj(struct monst *mtmp, struct obj *otmp)
}
}
if (heal)
mtmp->mhp = mtmp->mhpmax;
healmon(mtmp, mtmp->mhpmax, 0);
if ((eyes || heal) && !mtmp->mcansee)
mcureblindness(mtmp, canseemon(mtmp));
if (ispet && deadmimic)
@@ -4462,6 +4460,44 @@ get_iter_mons_xy(
}
/* Heal the given monster by amt hitpoints, unless it is somehow prevented
from healing. "overheal" is the maximum amount by which the max HP will
increase to allow for the healing (the resulting HP caps at max HP +
overheal, and the max HP stays the some unless it needs to increase to
accommodate the new HP). Overhealing the player is not currently
implemented by this method.
This function should only be used for situations which are conceptually
heals, rather than other situations where a monster's HP is set, so that
"prevent healing" effects work correctly. In particular, it should not
be used for cases where a monster's HP is restored upon revival, or when
a monster is created. It also shouldn't be used for lifesaving, which
overrides "cannot heal" effects.
amt and overheal must not be negative (0 is allowed, and a very common
amount for overheal). Returns the number of hitpoints healed. */
int
healmon(struct monst *mtmp, int amt, int overheal)
{
if (mtmp == &gy.youmonst) {
int oldhp = Upolyd ? u.mh : u.uhp;
healup(amt, 0, 0, 0);
return (Upolyd ? u.mh : u.uhp) - oldhp;
} else {
int oldhp = mtmp->mhp;
if (mtmp->mhp + amt > mtmp->mhpmax + overheal) {
mtmp->mhpmax += overheal;
mtmp->mhp = mtmp->mhpmax;
} else {
mtmp->mhp += amt;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhpmax = mtmp->mhp;
}
return mtmp->mhp - oldhp;
}
}
/* force all chameleons and mimics to become themselves and werecreatures
to revert to human form; called when Protection_from_shape_changers gets
activated via wearing or eating ring or via #wizintrinsic */
@@ -5535,10 +5571,7 @@ golemeffects(struct monst *mon, int damtype, int dam)
mon_adjust_speed(mon, -1, (struct obj *) 0);
}
if (heal) {
if (mon->mhp < mon->mhpmax) {
mon->mhp += heal;
if (mon->mhp > mon->mhpmax)
mon->mhp = mon->mhpmax;
if (healmon(mon, heal, 0)) {
if (cansee(mon->mx, mon->my))
pline_mon(mon, "%s seems healthier.", Monnam(mon));
}

View File

@@ -1139,9 +1139,7 @@ use_defensive(struct monst *mtmp)
case MUSE_POT_HEALING:
mquaffmsg(mtmp, otmp);
i = d(6 + 2 * bcsign(otmp), 4);
mtmp->mhp += i;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = ++mtmp->mhpmax;
healmon(mtmp, i, 1);
if (!otmp->cursed && !mtmp->mcansee)
mcureblindness(mtmp, vismon);
if (vismon)
@@ -1153,9 +1151,7 @@ use_defensive(struct monst *mtmp)
case MUSE_POT_EXTRA_HEALING:
mquaffmsg(mtmp, otmp);
i = d(6 + 2 * bcsign(otmp), 8);
mtmp->mhp += i;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2));
healmon(mtmp, i, otmp->blessed ? 5 : 2);
if (!mtmp->mcansee)
mcureblindness(mtmp, vismon);
if (vismon)
@@ -1168,7 +1164,7 @@ use_defensive(struct monst *mtmp)
mquaffmsg(mtmp, otmp);
if (otmp->otyp == POT_SICKNESS)
unbless(otmp); /* Pestilence */
mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 8 : 4));
healmon(mtmp, mtmp->mhpmax, otmp->blessed ? 8 : 4);
if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS)
mcureblindness(mtmp, vismon);
if (vismon)

View File

@@ -1740,7 +1740,7 @@ potionhit(struct monst *mon, struct obj *obj, int how)
do_healing:
angermon = FALSE;
if (mon->mhp < mon->mhpmax) {
mon->mhp = mon->mhpmax;
healmon(mon, mon->mhpmax, 0);
if (canseemon(mon))
pline("%s looks sound and hale again.", Monnam(mon));
}
@@ -1827,9 +1827,7 @@ potionhit(struct monst *mon, struct obj *obj, int how)
angermon = FALSE;
if (canseemon(mon))
pline("%s looks healthier.", Monnam(mon));
mon->mhp += d(2, 6);
if (mon->mhp > mon->mhpmax)
mon->mhp = mon->mhpmax;
healmon(mon, d(2, 6), 0);
if (is_were(mon->data) && is_human(mon->data)
&& !Protection_from_shape_changers)
new_were(mon); /* transform into beast */

View File

@@ -5931,9 +5931,7 @@ passive(
You("are suddenly very cold!");
mdamageu(mon, tmp);
/* monster gets stronger with your heat! */
mon->mhp += (tmp + rn2(2)) / 2;
if (mon->mhpmax < mon->mhp)
mon->mhpmax = mon->mhp;
healmon(mon, (tmp + rn2(2)) / 2, (tmp + 1) / 2);
/* at a certain point, the monster will reproduce! */
if (mon->mhpmax > (((int) mon->m_lev) + 1) * 8)
(void) split_mon(mon, &gy.youmonst);

View File

@@ -123,7 +123,7 @@ new_were(struct monst *mon)
mon->mcanmove = 1;
}
/* regenerate by 1/4 of the lost hit points */
mon->mhp += (mon->mhpmax - mon->mhp) / 4;
healmon(mon, (mon->mhpmax - mon->mhp) / 4, 0);
newsym(mon->mx, mon->my);
mon_break_armor(mon, FALSE);
possibly_unwield(mon, FALSE);

View File

@@ -396,7 +396,7 @@ tactics(struct monst *mtmp)
/* if you're not around, cast healing spells */
if (distu(mx, my) > (BOLT_LIM * BOLT_LIM))
if (mtmp->mhp <= mtmp->mhpmax - 8) {
mtmp->mhp += rnd(8);
healmon(mtmp, rnd(8), 0);
return 1;
}
FALLTHROUGH;

View File

@@ -434,9 +434,7 @@ bhitm(struct monst *mtmp, struct obj *otmp)
int delta = mtmp->mhpmax - mtmp->mhp;
wake = FALSE; /* wakeup() makes the target angry */
mtmp->mhp += healamt;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
healmon(mtmp, healamt, 0);
/* plain healing must be blessed to cure blindness; extra
healing only needs to not be cursed, so spell always cures
[potions quaffed by monsters behave slightly differently;
@@ -4250,10 +4248,9 @@ zhitm(
case ZT_DEATH: /* death/disintegration */
if (abs(type) != ZT_BREATH(ZT_DEATH)) { /* death */
if (mon->data == &mons[PM_DEATH]) {
mon->mhpmax += mon->mhpmax / 2;
healmon(mon, mon->mhpmax * 3 / 2, mon->mhpmax / 2);
if (mon->mhpmax >= MAGIC_COOKIE)
mon->mhpmax = MAGIC_COOKIE - 1;
mon->mhp = mon->mhpmax;
tmp = 0;
break;
}