This might be a good solution for this problem. Basically you would assign a type to each spell or skill and check it in the code so that the position in the list no longer matters.
1. Define spell/skill types
#define TYPE_SKILL 0
#define TYPE_SPELL 1
#define TYPE_SONG 2
2. Add a variable for type to spells and skills to indicate it is one or the other.
struct spell_info_type {
byte type; /* Identifies the spell as being a spell or skill */
byte min_position; /* Position for caster */
int mana_min; /* Min amount of mana used by a spell (highest lev) */
int mana_max; /* Max amount of mana used by a spell (lowest lev) */
int mana_change; /* Change in mana used by spell from lev to lev */
int min_level[NUM_CLASSES];
int routines;
byte violent;
int targets; /* See below for use with TAR_XXX */
const char *name; /* Input size not limited. Originates from string constants. */
const char *wear_off_msg; /* Input size not limited. Originates from string constants. */
};
3. Set type in spello().
static void spello(int spl, const char *name, int max_mana, int min_mana,
int mana_change, int minpos, int targets, int violent, int routines,
const char *wearoff) {
int i;
for (i = 0; i < NUM_CLASSES; i++)
spell_info[spl].min_level = 30; // LVL_IMMORT;
spell_info[spl].type = type;
spell_info[spl].mana_max = max_mana;
spell_info[spl].mana_min = min_mana;
spell_info[spl].mana_change = mana_change;
spell_info[spl].min_position = minpos;
spell_info[spl].targets = targets;
spell_info[spl].violent = violent;
spell_info[spl].routines = routines;
spell_info[spl].name = name;
spell_info[spl].wear_off_msg = wearoff;
}
4. Set the type in mag_assign_spells()
void mag_assign_spells(void) {
int i;
/* Do not change the loop below. */
for (i = 0; i <= TOP_SPELL_DEFINE; i++)
unused_spell(i);
/* Do not change the loop above. */
spello(SPELL_FIREBALL, "fireball",TYPE_SPELL, 40, 30, 2, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE, NULL);
skillo(SKILL_BACKSTAB, "backstab",TYPE_SKILL);
4. Check the type wherever MAX_SPELLS is used.
Ex.
Instead of this in ACMD(do_cast)
if ((spellnum < 1) || (spellnum > MAX_SPELLS) || !*s) {
send_to_char(ch, "Cast what?!?\r\n");
return;
}
Do this
if ((spellnum < 1) || (spellnum > MAX_SKILLS) || SINFO.type != TYPE_SPELL || !*s) {
send_to_char(ch, "Cast what?!?\r\n");
return;
}
5. In theory you would no longer need to worry about the position in the list and couple intermix spells and skills. Just keep adding new stuff the bottom and don't change the number for anything old. Then the only limitation would be MAX_SKILLS. Changing MAX_SKILLS would still require a pwipe or conversion but if set high enough at the start it wouldn't be an issue later on.