Split mcast_spell into separate functions

This commit is contained in:
Pasi Kallinen
2026-03-23 14:51:48 +02:00
parent c0f5d2dd92
commit d80e194735
+232 -115
View File
@@ -36,6 +36,22 @@ staticfn void cursetxt(struct monst *, boolean);
staticfn int choose_magic_spell(struct monst *); staticfn int choose_magic_spell(struct monst *);
staticfn int choose_clerical_spell(struct monst *); staticfn int choose_clerical_spell(struct monst *);
staticfn int m_cure_self(struct monst *, int); staticfn int m_cure_self(struct monst *, int);
staticfn void mcast_death_touch(struct monst *);
staticfn void mcast_clone_wiz(struct monst *);
staticfn void mcast_summon_mons(struct monst *);
staticfn void mcast_destroy_armor(void);
staticfn void mcast_weaken_you(struct monst *, int);
staticfn void mcast_disappear(struct monst *);
staticfn void mcast_stun_you(int);
staticfn int mcast_geyser(int);
staticfn int mcast_fire_pillar(struct monst *, int);
staticfn int mcast_lightning(struct monst *, int);
staticfn int mcast_psi_bolt(int);
staticfn int mcast_open_wounds(int);
staticfn void mcast_insects(struct monst *);
staticfn void mcast_blind_you(void);
staticfn int mcast_paralyze(struct monst *);
staticfn void mcast_confuse_you(struct monst *);
staticfn void mcast_spell(struct monst *, int, int); staticfn void mcast_spell(struct monst *, int, int);
staticfn boolean is_undirected_spell(int); staticfn boolean is_undirected_spell(int);
staticfn boolean spell_would_be_useless(struct monst *, int); staticfn boolean spell_would_be_useless(struct monst *, int);
@@ -435,31 +451,9 @@ death_inflicted_by(
* Monster wizard and cleric spellcasting functions. * Monster wizard and cleric spellcasting functions.
*/ */
/*
If dmg is zero, then the monster is not casting at you.
If the monster is intentionally not casting at you, we have previously
called spell_would_be_useless() and spellnum should always be a valid
undirected spell.
If you modify either of these, be sure to change is_undirected_spell()
and spell_would_be_useless().
*/
staticfn void staticfn void
mcast_spell(struct monst *mtmp, int dmg, int spellnum) mcast_death_touch(struct monst *mtmp)
{ {
int orig_dmg = 0;
if (dmg < 0) {
impossible("monster cast spell (%d) with negative dmg (%d)?",
spellnum, dmg);
return;
}
if (dmg == 0 && !is_undirected_spell(spellnum)) {
impossible("cast directed wizard spell (%d) with dmg=0?", spellnum);
return;
}
switch (spellnum) {
case MCAST_DEATH_TOUCH:
pline("Oh no, %s's using the touch of death!", mhe(mtmp)); pline("Oh no, %s's using the touch of death!", mhe(mtmp));
if (nonliving(gy.youmonst.data) || is_demon(gy.youmonst.data)) { if (nonliving(gy.youmonst.data) || is_demon(gy.youmonst.data)) {
You("seem no deader than before."); You("seem no deader than before.");
@@ -477,17 +471,21 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
} }
pline("Lucky for you, it didn't work!"); pline("Lucky for you, it didn't work!");
} }
dmg = 0; }
break;
case MCAST_CLONE_WIZ: staticfn void
mcast_clone_wiz(struct monst *mtmp)
{
if (mtmp->iswiz && svc.context.no_of_wizards == 1) { if (mtmp->iswiz && svc.context.no_of_wizards == 1) {
pline("Double Trouble..."); pline("Double Trouble...");
clonewiz(); clonewiz();
dmg = 0;
} else } else
impossible("bad wizard cloning?"); impossible("bad wizard cloning?");
break; }
case MCAST_SUMMON_MONS: {
staticfn void
mcast_summon_mons(struct monst *mtmp)
{
int count = nasty(mtmp); int count = nasty(mtmp);
if (!count) { if (!count) {
@@ -512,20 +510,11 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
else else
pline("%s from nowhere!", mappear); pline("%s from nowhere!", mappear);
} }
dmg = 0; }
break;
} staticfn void
case MCAST_AGGRAVATION: mcast_destroy_armor(void)
You_feel("that monsters are aware of your presence."); {
aggravate();
dmg = 0;
break;
case MCAST_CURSE_ITEMS:
You_feel("as if you need some help.");
rndcurse();
dmg = 0;
break;
case MCAST_DESTRY_ARMR:
if (Antimagic) { if (Antimagic) {
shieldeff(u.ux, u.uy); shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR); monstseesu(M_SEEN_MAGR);
@@ -537,9 +526,11 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
actually destroyed */ actually destroyed */
monstunseesu(M_SEEN_MAGR); monstunseesu(M_SEEN_MAGR);
} }
dmg = 0; }
break;
case MCAST_WEAKEN_YOU: /* drain strength */ staticfn void
mcast_weaken_you(struct monst *mtmp, int dmg)
{
if (Antimagic) { if (Antimagic) {
shieldeff(u.ux, u.uy); shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR); monstseesu(M_SEEN_MAGR);
@@ -559,9 +550,11 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
svk.killer.name[0] = '\0'; /* not killed if we get here... */ svk.killer.name[0] = '\0'; /* not killed if we get here... */
monstunseesu(M_SEEN_MAGR); monstunseesu(M_SEEN_MAGR);
} }
dmg = 0; }
break;
case MCAST_DISAPPEAR: /* makes self invisible */ staticfn void
mcast_disappear(struct monst *mtmp)
{
if (!mtmp->minvis && !mtmp->invis_blkd) { if (!mtmp->minvis && !mtmp->invis_blkd) {
if (canseemon(mtmp)) if (canseemon(mtmp))
pline_mon(mtmp, "%s suddenly %s!", Monnam(mtmp), pline_mon(mtmp, "%s suddenly %s!", Monnam(mtmp),
@@ -569,11 +562,13 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
mon_set_minvis(mtmp, FALSE); mon_set_minvis(mtmp, FALSE);
if (cansee(mtmp->mx, mtmp->my) && !canspotmon(mtmp)) if (cansee(mtmp->mx, mtmp->my) && !canspotmon(mtmp))
map_invisible(mtmp->mx, mtmp->my); map_invisible(mtmp->mx, mtmp->my);
dmg = 0;
} else } else
impossible("no reason for monster to cast disappear spell?"); impossible("no reason for monster to cast disappear spell?");
break; }
case MCAST_STUN_YOU:
staticfn void
mcast_stun_you(int dmg)
{
if (Antimagic || Free_action) { if (Antimagic || Free_action) {
shieldeff(u.ux, u.uy); shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR); monstseesu(M_SEEN_MAGR);
@@ -588,35 +583,11 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
make_stunned((HStun & TIMEOUT) + (long) dmg, FALSE); make_stunned((HStun & TIMEOUT) + (long) dmg, FALSE);
monstunseesu(M_SEEN_MAGR); monstunseesu(M_SEEN_MAGR);
} }
dmg = 0; }
break;
case MCAST_HASTE_SELF: staticfn int
mon_adjust_speed(mtmp, 1, (struct obj *) 0); mcast_geyser(int dmg)
dmg = 0; {
break;
case MCAST_CURE_SELF:
dmg = m_cure_self(mtmp, dmg);
break;
case MCAST_PSI_BOLT:
/* prior to 3.4.0 Antimagic was setting the damage to 1--this
made the spell virtually harmless to players with magic res. */
if (Antimagic) {
shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR);
dmg = (dmg + 1) / 2;
} else {
monstunseesu(M_SEEN_MAGR);
}
if (dmg <= 5)
You("get a slight %sache.", body_part(HEAD));
else if (dmg <= 10)
Your("brain is on fire!");
else if (dmg <= 20)
Your("%s suddenly aches painfully!", body_part(HEAD));
else
Your("%s suddenly aches very painfully!", body_part(HEAD));
break;
case MCAST_GEYSER:
/* this is physical damage (force not heat), /* this is physical damage (force not heat),
* not magical damage or fire damage * not magical damage or fire damage
*/ */
@@ -628,8 +599,14 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
/* make floor items wet */ /* make floor items wet */
water_damage_chain(level.objects[u.ux][u.uy], TRUE); water_damage_chain(level.objects[u.ux][u.uy], TRUE);
#endif #endif
break; return dmg;
case MCAST_FIRE_PILLAR: }
staticfn int
mcast_fire_pillar(struct monst *mtmp, int dmg)
{
int orig_dmg;
pline("A pillar of fire strikes all around you!"); pline("A pillar of fire strikes all around you!");
orig_dmg = dmg = d(8, 6); orig_dmg = dmg = d(8, 6);
if (Fire_resistance) { if (Fire_resistance) {
@@ -648,8 +625,13 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
ignite_items(gi.invent); ignite_items(gi.invent);
/* burn up flammable items on the floor, melt ice terrain */ /* burn up flammable items on the floor, melt ice terrain */
mon_spell_hits_spot(mtmp, AD_FIRE, u.ux, u.uy); mon_spell_hits_spot(mtmp, AD_FIRE, u.ux, u.uy);
break; return dmg;
case MCAST_LIGHTNING: { }
staticfn int
mcast_lightning(struct monst *mtmp, int dmg)
{
int orig_dmg;
boolean reflects; boolean reflects;
Soundeffect(se_bolt_of_lightning, 80); Soundeffect(se_bolt_of_lightning, 80);
@@ -661,7 +643,7 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
dmg = 0; dmg = 0;
if (reflects) { if (reflects) {
monstseesu(M_SEEN_REFL); monstseesu(M_SEEN_REFL);
break; return dmg;
} }
monstunseesu(M_SEEN_REFL); monstunseesu(M_SEEN_REFL);
monstseesu(M_SEEN_ELEC); monstseesu(M_SEEN_ELEC);
@@ -678,9 +660,56 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
mon_spell_hits_spot(mtmp, AD_ELEC, u.ux, u.uy); mon_spell_hits_spot(mtmp, AD_ELEC, u.ux, u.uy);
/* blind hero; no effect if already blind */ /* blind hero; no effect if already blind */
(void) flashburn((long) rnd(100), TRUE); (void) flashburn((long) rnd(100), TRUE);
break; return dmg;
}
staticfn int
mcast_psi_bolt(int dmg)
{
/* prior to 3.4.0 Antimagic was setting the damage to 1--this
made the spell virtually harmless to players with magic res. */
if (Antimagic) {
shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR);
dmg = (dmg + 1) / 2;
} else {
monstunseesu(M_SEEN_MAGR);
} }
case MCAST_INSECTS: { if (dmg <= 5)
You("get a slight %sache.", body_part(HEAD));
else if (dmg <= 10)
Your("brain is on fire!");
else if (dmg <= 20)
Your("%s suddenly aches painfully!", body_part(HEAD));
else
Your("%s suddenly aches very painfully!", body_part(HEAD));
return dmg;
}
staticfn int
mcast_open_wounds(int dmg)
{
if (Antimagic) {
shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR);
dmg = (dmg + 1) / 2;
} else {
monstunseesu(M_SEEN_MAGR);
}
if (dmg <= 5)
Your("skin itches badly for a moment.");
else if (dmg <= 10)
pline("Wounds appear on your body!");
else if (dmg <= 20)
pline("Severe wounds appear on your body!");
else
Your("body is covered with painful wounds!");
return dmg;
}
staticfn void
mcast_insects(struct monst *mtmp)
{
/* Try for insects, and if there are none /* Try for insects, and if there are none
left, go for (sticks to) snakes. -3. */ left, go for (sticks to) snakes. -3. */
struct permonst *pm = mkclass(S_ANT, 0); struct permonst *pm = mkclass(S_ANT, 0);
@@ -697,7 +726,7 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
quan = 3; quan = 3;
for (i = 0; i <= quan; i++) { for (i = 0; i <= quan; i++) {
if (!enexto(&bypos, mtmp->mux, mtmp->muy, mtmp->data)) if (!enexto(&bypos, mtmp->mux, mtmp->muy, mtmp->data))
break; return;
if ((pm = mkclass(let, 0)) != 0 if ((pm = mkclass(let, 0)) != 0
&& (mtmp2 = makemon(pm, bypos.x, bypos.y, MM_ANGRY | MM_NOMSG)) && (mtmp2 = makemon(pm, bypos.x, bypos.y, MM_ANGRY | MM_NOMSG))
!= 0) { != 0) {
@@ -760,10 +789,11 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
pline_mon(mtmp, fmt, Monnam(mtmp), what); pline_mon(mtmp, fmt, Monnam(mtmp), what);
RESTORE_WARNING_FORMAT_NONLITERAL; RESTORE_WARNING_FORMAT_NONLITERAL;
} }
dmg = 0; }
break;
} staticfn void
case MCAST_BLIND_YOU: mcast_blind_you(void)
{
/* note: resists_blnd() doesn't apply here */ /* note: resists_blnd() doesn't apply here */
if (!Blinded) { if (!Blinded) {
int num_eyes = eyecount(gy.youmonst.data); int num_eyes = eyecount(gy.youmonst.data);
@@ -774,11 +804,15 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
make_blinded(Half_spell_damage ? 100L : 200L, FALSE); make_blinded(Half_spell_damage ? 100L : 200L, FALSE);
if (!Blind) if (!Blind)
Your1(vision_clears); Your1(vision_clears);
dmg = 0;
} else } else
impossible("no reason for monster to cast blindness spell?"); impossible("no reason for monster to cast blindness spell?");
break; }
case MCAST_PARALYZE:
staticfn int
mcast_paralyze(struct monst *mtmp)
{
int dmg = 0;
if (Antimagic || Free_action) { if (Antimagic || Free_action) {
shieldeff(u.ux, u.uy); shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR); monstseesu(M_SEEN_MAGR);
@@ -796,17 +830,20 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
nomul(-dmg); nomul(-dmg);
gm.multi_reason = "paralyzed by a monster"; gm.multi_reason = "paralyzed by a monster";
gn.nomovemsg = 0; gn.nomovemsg = 0;
dmg = 0; return dmg;
break; }
case MCAST_CONFUSE_YOU:
staticfn void
mcast_confuse_you(struct monst *mtmp)
{
if (Antimagic) { if (Antimagic) {
shieldeff(u.ux, u.uy); shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR); monstseesu(M_SEEN_MAGR);
You_feel("momentarily dizzy."); You_feel("momentarily dizzy.");
} else { } else {
boolean oldprop = !!Confusion; boolean oldprop = !!Confusion;
int dmg = (int) mtmp->m_lev;
dmg = (int) mtmp->m_lev;
if (Half_spell_damage) if (Half_spell_damage)
dmg = (dmg + 1) / 2; dmg = (dmg + 1) / 2;
make_confused(HConfusion + dmg, TRUE); make_confused(HConfusion + dmg, TRUE);
@@ -816,24 +853,104 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
You_feel("%sconfused!", oldprop ? "more " : ""); You_feel("%sconfused!", oldprop ? "more " : "");
monstunseesu(M_SEEN_MAGR); monstunseesu(M_SEEN_MAGR);
} }
}
/*
If dmg is zero, then the monster is not casting at you.
If the monster is intentionally not casting at you, we have previously
called spell_would_be_useless() and spellnum should always be a valid
undirected spell.
If you modify either of these, be sure to change is_undirected_spell()
and spell_would_be_useless().
*/
staticfn void
mcast_spell(struct monst *mtmp, int dmg, int spellnum)
{
if (dmg < 0) {
impossible("monster cast spell (%d) with negative dmg (%d)?",
spellnum, dmg);
return;
}
if (dmg == 0 && !is_undirected_spell(spellnum)) {
impossible("cast directed wizard spell (%d) with dmg=0?", spellnum);
return;
}
switch (spellnum) {
case MCAST_DEATH_TOUCH:
mcast_death_touch(mtmp);
dmg = 0;
break;
case MCAST_CLONE_WIZ:
mcast_clone_wiz(mtmp);
dmg = 0;
break;
case MCAST_SUMMON_MONS:
mcast_summon_mons(mtmp);
dmg = 0;
break;
case MCAST_AGGRAVATION:
You_feel("that monsters are aware of your presence.");
aggravate();
dmg = 0;
break;
case MCAST_CURSE_ITEMS:
You_feel("as if you need some help.");
rndcurse();
dmg = 0;
break;
case MCAST_DESTRY_ARMR:
mcast_destroy_armor();
dmg = 0;
break;
case MCAST_WEAKEN_YOU: /* drain strength */
mcast_weaken_you(mtmp, dmg);
dmg = 0;
break;
case MCAST_DISAPPEAR: /* makes self invisible */
mcast_disappear(mtmp);
dmg = 0;
break;
case MCAST_STUN_YOU:
mcast_stun_you(dmg);
dmg = 0;
break;
case MCAST_HASTE_SELF:
mon_adjust_speed(mtmp, 1, (struct obj *) 0);
dmg = 0;
break;
case MCAST_CURE_SELF:
dmg = m_cure_self(mtmp, dmg);
break;
case MCAST_PSI_BOLT:
dmg = mcast_psi_bolt(dmg);
break;
case MCAST_GEYSER:
dmg = mcast_geyser(dmg);
break;
case MCAST_FIRE_PILLAR:
dmg = mcast_fire_pillar(mtmp, dmg);
break;
case MCAST_LIGHTNING:
dmg = mcast_lightning(mtmp, dmg);
break;
case MCAST_INSECTS:
mcast_insects(mtmp);
dmg = 0;
break;
case MCAST_BLIND_YOU:
mcast_blind_you();
dmg = 0;
break;
case MCAST_PARALYZE:
dmg = mcast_paralyze(mtmp);
break;
case MCAST_CONFUSE_YOU:
mcast_confuse_you(mtmp);
dmg = 0; dmg = 0;
break; break;
case MCAST_OPEN_WOUNDS: case MCAST_OPEN_WOUNDS:
if (Antimagic) { dmg = mcast_open_wounds(dmg);
shieldeff(u.ux, u.uy);
monstseesu(M_SEEN_MAGR);
dmg = (dmg + 1) / 2;
} else {
monstunseesu(M_SEEN_MAGR);
}
if (dmg <= 5)
Your("skin itches badly for a moment.");
else if (dmg <= 10)
pline("Wounds appear on your body!");
else if (dmg <= 20)
pline("Severe wounds appear on your body!");
else
Your("body is covered with painful wounds!");
break; break;
default: default:
impossible("mcastu: invalid magic spell (%d)", spellnum); impossible("mcastu: invalid magic spell (%d)", spellnum);