More mcastu code reorg
Instead of using two separate functions with switch-cases for wizard and clerical spell lists, define the spell lists as arrays and use a single function to pick a spell from the lists. Adds levels to the monster spells, using the switch-case values, with some minor fudging.
This commit is contained in:
@@ -6,30 +6,30 @@
|
|||||||
#define MCF_HOSTILE 0x0004 /* cast by hostile monsters only */
|
#define MCF_HOSTILE 0x0004 /* cast by hostile monsters only */
|
||||||
|
|
||||||
#if defined(MCASTU_ENUM)
|
#if defined(MCASTU_ENUM)
|
||||||
#define MONSPELL(def, flags) MCAST_##def
|
#define MONSPELL(def, lvl, flags) MCAST_##def
|
||||||
#elif defined(MCASTU_INIT)
|
#elif defined(MCASTU_INIT)
|
||||||
#define MONSPELL(def, flags) flags
|
#define MONSPELL(def, lvl, flags) { lvl, flags }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MONSPELL(PSI_BOLT, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(PSI_BOLT, 0, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(OPEN_WOUNDS, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(OPEN_WOUNDS, 0, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(LIGHTNING, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(CURE_SELF, 1, MCF_INDIRECT),
|
||||||
MONSPELL(FIRE_PILLAR, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(HASTE_SELF, 2, MCF_INDIRECT),
|
||||||
MONSPELL(GEYSER, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(CONFUSE_YOU, 2, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(DEATH_TOUCH, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(STUN_YOU, 3, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(CURE_SELF, MCF_INDIRECT),
|
MONSPELL(DISAPPEAR, 4, MCF_INDIRECT),
|
||||||
MONSPELL(HASTE_SELF, MCF_INDIRECT),
|
MONSPELL(PARALYZE, 4, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(DISAPPEAR, MCF_INDIRECT),
|
MONSPELL(BLIND_YOU, 6, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(AGGRAVATION, MCF_INDIRECT|MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(WEAKEN_YOU, 6, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(STUN_YOU, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(DESTRY_ARMR, 8, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(WEAKEN_YOU, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(INSECTS, 8, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
|
||||||
MONSPELL(CONFUSE_YOU, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(CURSE_ITEMS, 10, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(PARALYZE, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(LIGHTNING, 11, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(BLIND_YOU, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(FIRE_PILLAR, 12, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(DESTRY_ARMR, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(GEYSER, 13, MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(CURSE_ITEMS, MCF_HOSTILE|MCF_SIGHT),
|
MONSPELL(AGGRAVATION, 13, MCF_INDIRECT|MCF_HOSTILE|MCF_SIGHT),
|
||||||
MONSPELL(INSECTS, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
|
MONSPELL(SUMMON_MONS, 15, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
|
||||||
MONSPELL(SUMMON_MONS, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
|
MONSPELL(CLONE_WIZ, 18, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
|
||||||
MONSPELL(CLONE_WIZ, MCF_HOSTILE|MCF_INDIRECT|MCF_SIGHT),
|
MONSPELL(DEATH_TOUCH, 20, MCF_HOSTILE|MCF_SIGHT),
|
||||||
|
|
||||||
#undef MONSPELL
|
#undef MONSPELL
|
||||||
|
|||||||
163
src/mcastu.c
163
src/mcastu.c
@@ -11,15 +11,32 @@ enum mcast_spells {
|
|||||||
};
|
};
|
||||||
#undef MCASTU_ENUM
|
#undef MCASTU_ENUM
|
||||||
|
|
||||||
|
struct _mcast_data {
|
||||||
|
int level;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
#define MCASTU_INIT
|
#define MCASTU_INIT
|
||||||
static int mcast_flags[] = {
|
static struct _mcast_data mcast_data[] = {
|
||||||
#include "mcastu.h"
|
#include "mcastu.h"
|
||||||
};
|
};
|
||||||
#undef MCASTU_INIT
|
#undef MCASTU_INIT
|
||||||
|
|
||||||
|
/* spell lists for specific monster casters */
|
||||||
|
/* the spells in the list should be in ascending level order */
|
||||||
|
static int mon_cleric_spells[] = {
|
||||||
|
MCAST_OPEN_WOUNDS, MCAST_CURE_SELF, MCAST_CONFUSE_YOU, MCAST_PARALYZE,
|
||||||
|
MCAST_BLIND_YOU, MCAST_INSECTS, MCAST_CURSE_ITEMS, MCAST_LIGHTNING,
|
||||||
|
MCAST_FIRE_PILLAR, MCAST_GEYSER
|
||||||
|
};
|
||||||
|
static int mon_wizard_spells[] = {
|
||||||
|
MCAST_PSI_BOLT, MCAST_CURE_SELF, MCAST_HASTE_SELF, MCAST_STUN_YOU,
|
||||||
|
MCAST_DISAPPEAR, MCAST_WEAKEN_YOU, MCAST_DESTRY_ARMR, MCAST_CURSE_ITEMS,
|
||||||
|
MCAST_AGGRAVATION, MCAST_SUMMON_MONS, MCAST_CLONE_WIZ, MCAST_DEATH_TOUCH
|
||||||
|
};
|
||||||
|
|
||||||
staticfn void cursetxt(struct monst *, boolean);
|
staticfn void cursetxt(struct monst *, boolean);
|
||||||
staticfn int choose_magic_spell(struct monst *);
|
staticfn int choose_monster_spell(struct monst *, int);
|
||||||
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_death_touch(struct monst *);
|
||||||
staticfn void mcast_clone_wiz(struct monst *);
|
staticfn void mcast_clone_wiz(struct monst *);
|
||||||
@@ -67,107 +84,42 @@ cursetxt(struct monst *mtmp, boolean undirected)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert a level-based random selection into a specific mage spell;
|
/* choose a spell for monster to cast */
|
||||||
inappropriate choices will be screened out by spell_would_be_useless() */
|
|
||||||
staticfn int
|
staticfn int
|
||||||
choose_magic_spell(struct monst *mtmp)
|
choose_monster_spell(struct monst *mtmp, int adtyp)
|
||||||
{
|
{
|
||||||
int spellval = rn2(mtmp->m_lev);
|
int *list = NULL;
|
||||||
|
int i, spellval, len = 0;
|
||||||
|
int maxlev;
|
||||||
|
|
||||||
/* for 3.4.3 and earlier, val greater than 22 selected default spell */
|
/* which spell list to use? */
|
||||||
while (spellval > 24 && rn2(25))
|
if (adtyp == AD_SPEL) {
|
||||||
spellval = rn2(spellval);
|
list = mon_wizard_spells;
|
||||||
|
len = SIZE(mon_wizard_spells);
|
||||||
|
} else if (adtyp == AD_CLRC) {
|
||||||
|
list = mon_cleric_spells;
|
||||||
|
len = SIZE(mon_cleric_spells);
|
||||||
|
}
|
||||||
|
|
||||||
switch (spellval) {
|
if (!list || len < 1)
|
||||||
case 24:
|
|
||||||
case 23:
|
|
||||||
if (Antimagic || Hallucination)
|
|
||||||
return MCAST_PSI_BOLT;
|
return MCAST_PSI_BOLT;
|
||||||
FALLTHROUGH;
|
|
||||||
/*FALLTHRU*/
|
|
||||||
case 22:
|
|
||||||
case 21:
|
|
||||||
case 20:
|
|
||||||
return MCAST_DEATH_TOUCH;
|
|
||||||
case 19:
|
|
||||||
case 18:
|
|
||||||
return MCAST_CLONE_WIZ;
|
|
||||||
case 17:
|
|
||||||
case 16:
|
|
||||||
case 15:
|
|
||||||
return MCAST_SUMMON_MONS;
|
|
||||||
case 14:
|
|
||||||
case 13:
|
|
||||||
return MCAST_AGGRAVATION;
|
|
||||||
case 12:
|
|
||||||
case 11:
|
|
||||||
case 10:
|
|
||||||
return MCAST_CURSE_ITEMS;
|
|
||||||
case 9:
|
|
||||||
case 8:
|
|
||||||
return MCAST_DESTRY_ARMR;
|
|
||||||
case 7:
|
|
||||||
case 6:
|
|
||||||
return MCAST_WEAKEN_YOU;
|
|
||||||
case 5:
|
|
||||||
case 4:
|
|
||||||
return MCAST_DISAPPEAR;
|
|
||||||
case 3:
|
|
||||||
return MCAST_STUN_YOU;
|
|
||||||
case 2:
|
|
||||||
return MCAST_HASTE_SELF;
|
|
||||||
case 1:
|
|
||||||
return MCAST_CURE_SELF;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
return MCAST_PSI_BOLT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert a level-based random selection into a specific cleric spell */
|
/* max spell level in this monster spell list */
|
||||||
staticfn int
|
maxlev = mcast_data[list[len - 1]].level;
|
||||||
choose_clerical_spell(struct monst *mtmp)
|
|
||||||
{
|
|
||||||
int spellnum = rn2(mtmp->m_lev);
|
|
||||||
|
|
||||||
/* for 3.4.3 and earlier, num greater than 13 selected the default spell
|
/* which level spell to cast? */
|
||||||
*/
|
spellval = rn2(mtmp->m_lev);
|
||||||
while (spellnum > 15 && rn2(16))
|
if (spellval > maxlev && rn2(maxlev))
|
||||||
spellnum = rn2(spellnum);
|
spellval = rn2(maxlev);
|
||||||
|
|
||||||
switch (spellnum) {
|
/* find the highest spell in the list we could cast */
|
||||||
case 15:
|
for (i = len-1; i >= 0; i--)
|
||||||
case 14:
|
if (mcast_data[list[i]].level <= spellval
|
||||||
if (rn2(3))
|
&& !spell_would_be_useless(mtmp, list[i]))
|
||||||
return MCAST_OPEN_WOUNDS;
|
return list[i];
|
||||||
FALLTHROUGH;
|
|
||||||
/*FALLTHRU*/
|
/* or return the first spell in the list */
|
||||||
case 13:
|
return list[0];
|
||||||
return MCAST_GEYSER;
|
|
||||||
case 12:
|
|
||||||
return MCAST_FIRE_PILLAR;
|
|
||||||
case 11:
|
|
||||||
return MCAST_LIGHTNING;
|
|
||||||
case 10:
|
|
||||||
case 9:
|
|
||||||
return MCAST_CURSE_ITEMS;
|
|
||||||
case 8:
|
|
||||||
return MCAST_INSECTS;
|
|
||||||
case 7:
|
|
||||||
case 6:
|
|
||||||
return MCAST_BLIND_YOU;
|
|
||||||
case 5:
|
|
||||||
case 4:
|
|
||||||
return MCAST_PARALYZE;
|
|
||||||
case 3:
|
|
||||||
case 2:
|
|
||||||
return MCAST_CONFUSE_YOU;
|
|
||||||
case 1:
|
|
||||||
return MCAST_CURE_SELF;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
return MCAST_OPEN_WOUNDS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return values:
|
/* return values:
|
||||||
@@ -201,10 +153,7 @@ castmu(
|
|||||||
int cnt = 40;
|
int cnt = 40;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (mattk->adtyp == AD_SPEL)
|
spellnum = choose_monster_spell(mtmp, mattk->adtyp);
|
||||||
spellnum = choose_magic_spell(mtmp);
|
|
||||||
else
|
|
||||||
spellnum = choose_clerical_spell(mtmp);
|
|
||||||
/* not trying to attack? don't allow directed spells */
|
/* not trying to attack? don't allow directed spells */
|
||||||
if (!thinks_it_foundyou) {
|
if (!thinks_it_foundyou) {
|
||||||
if (!is_undirected_spell(spellnum)
|
if (!is_undirected_spell(spellnum)
|
||||||
@@ -950,7 +899,7 @@ mcast_spell(struct monst *mtmp, int dmg, int spellnum)
|
|||||||
staticfn boolean
|
staticfn boolean
|
||||||
is_undirected_spell(int spellnum)
|
is_undirected_spell(int spellnum)
|
||||||
{
|
{
|
||||||
if ((mcast_flags[spellnum] & MCF_INDIRECT) != 0)
|
if ((mcast_data[spellnum].flags & MCF_INDIRECT) != 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -967,13 +916,13 @@ spell_would_be_useless(struct monst *mtmp, int spellnum)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* spell is only cast by hostile monsters */
|
/* spell is only cast by hostile monsters */
|
||||||
if ((mcast_flags[spellnum] & MCF_HOSTILE) != 0) {
|
if ((mcast_data[spellnum].flags & MCF_HOSTILE) != 0) {
|
||||||
if (mtmp->mpeaceful)
|
if (mtmp->mpeaceful)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* spell needs the monster to see hero */
|
/* spell needs the monster to see hero */
|
||||||
if ((mcast_flags[spellnum] & MCF_SIGHT) != 0) {
|
if ((mcast_data[spellnum].flags & MCF_SIGHT) != 0) {
|
||||||
boolean mcouldseeu = couldsee(mtmp->mx, mtmp->my);
|
boolean mcouldseeu = couldsee(mtmp->mx, mtmp->my);
|
||||||
|
|
||||||
if (!mcouldseeu)
|
if (!mcouldseeu)
|
||||||
@@ -981,6 +930,14 @@ spell_would_be_useless(struct monst *mtmp, int spellnum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (spellnum) {
|
switch (spellnum) {
|
||||||
|
case MCAST_DEATH_TOUCH:
|
||||||
|
if ((Antimagic || Hallucination) && !rn2(2))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
case MCAST_GEYSER:
|
||||||
|
if (!rn2(5))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
case MCAST_CLONE_WIZ:
|
case MCAST_CLONE_WIZ:
|
||||||
/* only the Wizard is allowed to clone himself */
|
/* only the Wizard is allowed to clone himself */
|
||||||
if (!mtmp->iswiz || svc.context.no_of_wizards > 1)
|
if (!mtmp->iswiz || svc.context.no_of_wizards > 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user