Luckily, I turned out to be wrong. Just goes to show that you should trust nobody
The spell_info struct is initialized at the end of spell_parser.c, and as such need not be neither loaded nor free'd.
Code:
diff --git a/src/magic.c b/src/magic.c
index 7dd4abd..681ba8b 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -68,12 +68,20 @@ void affect_update(void)
else if (af->duration == -1) /* No action */
;
else {
- if ((af->spell > 0) && (af->spell <= MAX_SPELLS))
- if (!af->next || (af->next->spell != af->spell) ||
- (af->next->duration > 0))
- if (spell_info[af->spell].wear_off_msg)
- send_to_char(i, "%s\r\n", spell_info[af->spell].wear_off_msg);
- affect_remove(i, af);
+ int spellnum = af->spell;
+ int should_message = spellnum > 0
+ && spellnum <= MAX_SPELLS
+ && (!af->next
+ || af->next->spell != af->spell
+ || af->next->duration > 0);
+ if (should_message && spell_info[spellnum].wear_off_msg)
+ send_to_char(i, "%s\r\n", spell_info[spellnum].wear_off_msg);
+
+ affect_remove(i, af);
+
+ /* do this after removing the affect, in case it was invisibility... */
+ if (should_message && IS_NPC(i) && spell_info[spellnum].wear_off_echo_msg)
+ act(spell_info[spellnum].wear_off_echo_msg, TRUE, i, NULL, i, TO_ROOM);
}
}
}
diff --git a/src/spell_parser.c b/src/spell_parser.c
index a443cc8..d620357 100644
--- a/src/spell_parser.c
+++ b/src/spell_parser.c
@@ -29,7 +29,9 @@ const char *unused_spellname = "!UNUSED!"; /* So we can get &unused_spellname */
/* Local (File Scope) Function Prototypes */
static void say_spell(struct char_data *ch, int spellnum, struct char_data *tch, struct obj_data *tobj);
-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);
+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,
+ const char *wear_off_echo_msg);
static int mag_manacost(struct char_data *ch, int spellnum);
/* Local (File Scope) Variables */
@@ -655,7 +657,8 @@ void spell_level(int spell, int chclass, int level)
/* Assign the spells on boot up */
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 mana_change, int minpos, int targets, int violent, int routines, const char *wearoff,
+ const char *wear_off_echo_msg)
{
int i;
@@ -670,6 +673,7 @@ static void spello(int spl, const char *name, int max_mana, int min_mana,
spell_info[spl].routines = routines;
spell_info[spl].name = name;
spell_info[spl].wear_off_msg = wearoff;
+ spell_info[spl].wear_off_echo_msg = wear_off_echo_msg;
}
void unused_spell(int spl)
@@ -688,7 +692,7 @@ void unused_spell(int spl)
spell_info[spl].name = unused_spellname;
}
-#define skillo(skill, name) spello(skill, name, 0, 0, 0, 0, 0, 0, 0, NULL);
+#define skillo(skill, name) spello(skill, name, 0, 0, 0, 0, 0, 0, 0, NULL, NULL);
/* Arguments for spello calls:
* spellnum, maxmana, minmana, manachng, minpos, targets, violent?, routines.
* spellnum: Number of the spell. Usually the symbolic name as defined in
@@ -724,224 +728,224 @@ void mag_assign_spells(void)
spello(SPELL_ANIMATE_DEAD, "animate dead", 35, 10, 3, POS_STANDING,
TAR_OBJ_ROOM, FALSE, MAG_SUMMONS,
- NULL);
+ NULL, NULL);
spello(SPELL_ARMOR, "armor", 30, 15, 3, POS_FIGHTING,
TAR_CHAR_ROOM, FALSE, MAG_AFFECTS,
- "You feel less protected.");
+ "You feel less protected.", "$Ns skin stops shimmering.");
spello(SPELL_BLESS, "bless", 35, 5, 3, POS_STANDING,
TAR_CHAR_ROOM | TAR_OBJ_INV, FALSE, MAG_AFFECTS | MAG_ALTER_OBJS,
- "You feel less righteous.");
+ "You feel less righteous.", "$N lost the blessing of $S deity.");
spello(SPELL_BLINDNESS, "blindness", 35, 25, 1, POS_STANDING,
TAR_CHAR_ROOM | TAR_NOT_SELF, FALSE, MAG_AFFECTS,
- "You feel a cloak of blindness dissolve.");
+ "You feel a cloak of blindness dissolve.", "The white cloak dissolves from $Ns eyes.");
spello(SPELL_BURNING_HANDS, "burning hands", 30, 10, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_CALL_LIGHTNING, "call lightning", 40, 25, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_CHARM, "charm person", 75, 50, 2, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_MANUAL,
- "You feel more self-confident.");
+ "You feel more self-confident.", "$N seems more self-confident.");
spello(SPELL_CHILL_TOUCH, "chill touch", 30, 10, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE | MAG_AFFECTS,
- "You feel your strength return.");
+ "You feel your strength return.", "$N no longer shivers with cold.");
spello(SPELL_CLONE, "clone", 80, 65, 5, POS_STANDING,
TAR_IGNORE, FALSE, MAG_SUMMONS,
- NULL);
+ NULL, NULL);
spello(SPELL_COLOR_SPRAY, "color spray", 30, 15, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_CONTROL_WEATHER, "control weather", 75, 25, 5, POS_STANDING,
TAR_IGNORE, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_CREATE_FOOD, "create food", 30, 5, 4, POS_STANDING,
TAR_IGNORE, FALSE, MAG_CREATIONS,
- NULL);
+ NULL, NULL);
spello(SPELL_CREATE_WATER, "create water", 30, 5, 4, POS_STANDING,
TAR_OBJ_INV | TAR_OBJ_EQUIP, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_CURE_BLIND, "cure blind", 30, 5, 2, POS_STANDING,
TAR_CHAR_ROOM, FALSE, MAG_UNAFFECTS,
- NULL);
+ NULL, NULL);
spello(SPELL_CURE_CRITIC, "cure critic", 30, 10, 2, POS_FIGHTING,
TAR_CHAR_ROOM, FALSE, MAG_POINTS,
- NULL);
+ NULL, NULL);
spello(SPELL_CURE_LIGHT, "cure light", 30, 10, 2, POS_FIGHTING,
TAR_CHAR_ROOM, FALSE, MAG_POINTS,
- NULL);
+ NULL, NULL);
spello(SPELL_CURSE, "curse", 80, 50, 2, POS_STANDING,
TAR_CHAR_ROOM | TAR_OBJ_INV, TRUE, MAG_AFFECTS | MAG_ALTER_OBJS,
- "You feel more optimistic.");
+ "You feel more optimistic.", "$N seems less burdened, somehow.");
spello(SPELL_DARKNESS, "darkness", 30, 5, 4, POS_STANDING,
TAR_IGNORE, FALSE, MAG_ROOMS,
- NULL);
+ NULL, NULL);
spello(SPELL_DETECT_ALIGN, "detect alignment", 20, 10, 2, POS_STANDING,
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
- "You feel less aware.");
+ "You feel less aware.", "$Ns eyes lose their yellow aura.");
spello(SPELL_DETECT_INVIS, "detect invisibility", 20, 10, 2, POS_STANDING,
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
- "Your eyes stop tingling.");
+ "Your eyes stop tingling.", "$Ns eyes lose their purple aura.");
spello(SPELL_DETECT_MAGIC, "detect magic", 20, 10, 2, POS_STANDING,
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
- "The detect magic wears off.");
+ "The detect magic wears off.", "$Ns eyes lose their blue aura.");
spello(SPELL_DETECT_POISON, "detect poison", 15, 5, 1, POS_STANDING,
TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL,
- "The detect poison wears off.");
+ "The detect poison wears off.", "$Ns eyes lose their green aura.");
spello(SPELL_DISPEL_EVIL, "dispel evil", 40, 25, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_DISPEL_GOOD, "dispel good", 40, 25, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_EARTHQUAKE, "earthquake", 40, 25, 3, POS_FIGHTING,
TAR_IGNORE, TRUE, MAG_AREAS,
- NULL);
+ NULL, NULL);
spello(SPELL_ENCHANT_WEAPON, "enchant weapon", 150, 100, 10, POS_STANDING,
TAR_OBJ_INV, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_ENERGY_DRAIN, "energy drain", 40, 25, 1, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE | MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_GROUP_ARMOR, "group armor", 50, 30, 2, POS_STANDING,
TAR_IGNORE, FALSE, MAG_GROUPS,
- NULL);
+ NULL, NULL);
spello(SPELL_FIREBALL, "fireball", 40, 30, 2, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_FLY, "fly", 40, 20, 2, POS_FIGHTING,
TAR_CHAR_ROOM, FALSE, MAG_AFFECTS,
- "You drift slowly to the ground.");
+ "You drift slowly to the ground.", "$N slowly drifts to the ground.");
spello(SPELL_GROUP_HEAL, "group heal", 80, 60, 5, POS_STANDING,
TAR_IGNORE, FALSE, MAG_GROUPS,
- NULL);
+ NULL, NULL);
spello(SPELL_HARM, "harm", 75, 45, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_HEAL, "heal", 60, 40, 3, POS_FIGHTING,
TAR_CHAR_ROOM, FALSE, MAG_POINTS | MAG_UNAFFECTS,
- NULL);
+ NULL, NULL);
spello(SPELL_INFRAVISION, "infravision", 25, 10, 1, POS_STANDING,
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
- "Your night vision seems to fade.");
+ "Your night vision seems to fade.", "$Ns eyes lose their red aura.");
spello(SPELL_INVISIBLE, "invisibility", 35, 25, 1, POS_STANDING,
TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_AFFECTS | MAG_ALTER_OBJS,
- "You feel yourself exposed.");
+ "You feel yourself exposed.", "$N fades into visiblity.");
spello(SPELL_LIGHTNING_BOLT, "lightning bolt", 30, 15, 1, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_LOCATE_OBJECT, "locate object", 25, 20, 1, POS_STANDING,
TAR_OBJ_WORLD, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_MAGIC_MISSILE, "magic missile", 25, 10, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_POISON, "poison", 50, 20, 3, POS_STANDING,
TAR_CHAR_ROOM | TAR_NOT_SELF | TAR_OBJ_INV, TRUE,
MAG_AFFECTS | MAG_ALTER_OBJS,
- "You feel less sick.");
+ "You feel less sick.", "$N looks noticable less ill.");
spello(SPELL_PROT_FROM_EVIL, "protection from evil", 40, 10, 3, POS_STANDING,
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
- "You feel less protected.");
+ "You feel less protected.", "$N looks less protected, somehow.");
spello(SPELL_REMOVE_CURSE, "remove curse", 45, 25, 5, POS_STANDING,
TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_EQUIP, FALSE,
MAG_UNAFFECTS | MAG_ALTER_OBJS,
- NULL);
+ NULL, NULL);
spello(SPELL_REMOVE_POISON, "remove poison", 40, 8, 4, POS_STANDING,
TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_UNAFFECTS | MAG_ALTER_OBJS,
- NULL);
+ NULL, NULL);
spello(SPELL_SANCTUARY, "sanctuary", 110, 85, 5, POS_STANDING,
TAR_CHAR_ROOM, FALSE, MAG_AFFECTS,
- "The white aura around your body fades.");
+ "The white aura around your body fades.", "The white aura around $Ns body fades");
spello(SPELL_SENSE_LIFE, "sense life", 20, 10, 2, POS_STANDING,
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
- "You feel less aware of your surroundings.");
+ "You feel less aware of your surroundings.", "The keen glint in $Ns eyes fades");
spello(SPELL_SHOCKING_GRASP, "shocking grasp", 30, 15, 3, POS_FIGHTING,
TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE,
- NULL);
+ NULL, NULL);
spello(SPELL_SLEEP, "sleep", 40, 25, 5, POS_STANDING,
TAR_CHAR_ROOM, TRUE, MAG_AFFECTS,
- "You feel less tired.");
+ "You feel less tired.", "$N looks less tired");
spello(SPELL_STRENGTH, "strength", 35, 30, 1, POS_STANDING,
TAR_CHAR_ROOM, FALSE, MAG_AFFECTS,
- "You feel weaker.");
+ "You feel weaker.", "$N looks weaker.");
spello(SPELL_SUMMON, "summon", 75, 50, 3, POS_STANDING,
TAR_CHAR_WORLD | TAR_NOT_SELF, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_TELEPORT, "teleport", 75, 50, 3, POS_STANDING,
TAR_CHAR_ROOM, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_WATERWALK, "waterwalk", 40, 20, 2, POS_STANDING,
TAR_CHAR_ROOM, FALSE, MAG_AFFECTS,
- "Your feet seem less buoyant.");
+ "Your feet seem less buoyant.", "$Ns feet return to normal.");
spello(SPELL_WORD_OF_RECALL, "word of recall", 20, 10, 2, POS_FIGHTING,
TAR_CHAR_ROOM, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
spello(SPELL_IDENTIFY, "identify", 50, 25, 5, POS_STANDING,
TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
/* NON-castable spells should appear below here. */
spello(SPELL_IDENTIFY, "identify", 0, 0, 0, 0,
TAR_CHAR_ROOM | TAR_OBJ_INV | TAR_OBJ_ROOM, FALSE, MAG_MANUAL,
- NULL);
+ NULL, NULL);
/* you might want to name this one something more fitting to your theme -Welcor*/
spello(SPELL_DG_AFFECT, "Script-inflicted", 0, 0, 0, POS_SITTING,
TAR_IGNORE, TRUE, 0,
- NULL);
+ NULL, NULL);
/* Declaration of skills - this actually doesn't do anything except set it up
* so that immortals can use these skills by default. The min level to use
diff --git a/src/spells.h b/src/spells.h
index 4bcb8ec..15610cb 100644
--- a/src/spells.h
+++ b/src/spells.h
@@ -193,6 +193,7 @@ struct spell_info_type {
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. */
+ const char *wear_off_echo_msg; /* Input size not limited. Originates from string constants. */
};
/* Possible Targets:
So, not so much work, after all.