This guideline is an attempt to give a better understanding of how the spells in CircleMUD work and a step-by-step method on how to create them. This is based on bpl15, with some reference to previous patchlevels or codebases.

Part 1: Categories of Spells
Part 2: Basic Steps to Create A Spell
Part 3: Damage Spells - Killing Enemy 101
Part 4: Area Spells - Make Thy Enemies Suffer!
Part 5: Affect Spells - Affect Them for Better or Worse…
Part 6: Unaffect Spells - "First You Have It, Now You Don't!"
Part 7: Alter Object Spells - Bend It to Your Will.
Part 8: Points Spells - Measuring the Beat of Our Life…
Part 9: Group-based Spells - Defend Thy Neighbors!
Part 10: Masses Spells - Let Them See Your Way…
Part 11: Summon Spells - "Come and Follow Me!"
Part 12: Creation Spells - Magical Sleight of Hand.
Part 13: Manual Spells - Making It Special…
Part 14: Giving NPCs Immunity.

A lot of people have benefited from the contributions made by the CircleMUD community. I, for one, have gained a lot and would like to contribute back. This, err… rather long guideline was supposed to be short at first. That is, until my housemates who also mud asked a simple question: "How to know what spell is under which category?" So, one thing led to another, after a while it became this long in my attempt to make it as comprehensive as possible, especially for those who just started to code.

Anyway, I hope someone will benefit from my first attempt…. :)

- Fizal (amustapa@hotmail.com)

Part 1: Categories of Spells

All the spells in Circle, whether it's a magical or clerical spell, or the more exotic druidic or elemental spell, they can be categorized into the following types:

Type 1: Damage spells

Type 2: Area spells Type 3: Affect spells Type 4: Unaffect spells Type 5: Alter Object spells Type 6: Points spells Type 7: Group-based spells Type 8: Masses spells Type 9: Summon spells Type 10: Creation Spells Type 11: Manual Spells As you can see, although most spells tend to be under a single category (Fireball - damage spell), some spells falls under several (Curse - affect spell and alter object spell) or make use of other spell types as its own (Group Heal - group-based spell that uses points spell). With this flexibility, think of various possibilities that can be added in to make a spell interesting. Something like Glitterdust spell, an affect spell that will attach AFF_GLITTERDUST to a person but at the same time, an unaffect spell that will remove AFF_HIDE and AFF_INVISIBLE. Every time someone affected by Glitterdust tries to hide or become invisible, you can do a check and make him unable to do so!

Part 2: Basic Steps to Create A Spell

Now, let's say you have loads of idea for a new spell, and you want to implement them. How? It's rather easy if you follow the basic steps below. As an example, we'll use the Glitterdust spell from before:

Step 1: Define your idea

Step 2: Define and name the spell
/* PLAYER SPELLS -- Numbered from 1 to MAX_SPELLS */

#define SPELL_ARMOR		 1 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_TELEPORT		 2 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_BLESS		 3 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_BLINDNESS		 4 /* Reserved Skill[] DO NOT CHANGE */
... [ snipped to make it shorter ]
#define SPELL_INFRAVISION	50 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_WATERWALK		51 /* Reserved Skill[] DO NOT CHANGE */
/* Insert new spells here, up to MAX_SPELLS */
#define MAX_SPELLS		130
#define SPELL_GLITTERDUST	52	ç Our spell is defined as 52
char *spells[] =
{
  "!RESERVED!",		/* 0 - reserved */

  /* SPELLS */

  "armor",		/* 1 */
  "teleport",
  "bless",
  "blindness",
... [ snipped again to make it shorter ]
  "infravision",	/* 50 */
  "waterwalk",
  "glitterdust",	ç The name for the new spell in slot 52.
  "!UNUSED!", 
Step 3: Code the spell in Step 4: Defining the spell characteristics Under codebases prior to bpl15
spello(SPELL_ARMOR, 30, 15, 3, POS_FIGHTING, 
	TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);
spello(SPELL_CURSE, 80, 50, 2, POS_STANDING,
	TAR_CHAR_ROOM | TAR_OBJ_INV, TRUE, MAG_AFFECTS | MAG_ALTER_OBJS);
spello(SPELL_GLITTERDUST, 80, 50, 2, POS_STANDING,  ç Our spell characteristic.
	TAR_CHAR_ROOM | TAR_NOT_SELF, FALSE, MAG_AFFECTS | MAG_UNAFFECTS);
Under codebase bpl15
spello(SPELL_ARMOR, "armor", 30, 15, 3, POS_FIGHTING,
	TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);
spello(SPELL_CURSE, "curse", 80, 50, 2, POS_STANDING,
	TAR_CHAR_ROOM | TAR_OBJ_INV, TRUE, MAG_AFFECTS | MAG_ALTER_OBJS);
spello(SPELL_GLITTERDUST, "glitterdust", 80, 50, 2, POS_STANDING,	ç
	TAR_CHAR_ROOM | TAR_NOT_SELF, FALSE, MAG_AFFECTS | MAG_UNAFFECTS);
Step 5: Create appropriate spell messages
const char *spell_wear_off_msg[] = {
  "RESERVED DB.C",				/* 0 */
  "You feel less protected.",			/* 1 */
  "!Teleport!",
  "You feel less righteous.",
  "You feel a cloak of blindness dissolve.",
... [ snipped to make it shorter ]
  "Your night vision seems to fade.",		/* 50 */
  "Your feet seem less buoyant.",
  "The wind finally blew away the glittering dust on you.",	ç added.
  "!UNUSED!"
};
* Burning Hands						ç A comment
M							ç Start message
 5							ç Spell number
You have burned $N to death!				----|
You have been burned to death by $n!			 Death messages (G1)
$n has burned $N to death!				----|
You miss $N with your burning hands.			----|
$n reaches for you with burning hands, but misses!	 Miss messages (G2)
$n tries to burn $N, but $E escapes!			----|
You burn $N with your hot little hands!			----|
You cry out in pain as $n grabs you with burning hands!  Hit messages (G3)
$N cries out as $n burns $M!				----|
Your attempt to burn $N nears BLASPHEMY!!!		----|
The pitiful creature before you tries to burn you.	 Attacking God (G4)
Unaware of the risks, $n tries to burn $N.		----|
Step 6: Setting class and level
   spell_level(SPELL_MAGIC_MISSILE, CLASS_MAGIC_USER, 1);
   spell_level(SPELL_DETECT_INVIS, CLASS_MAGIC_USER, 2);
   spell_level(SPELL_GLITTERDUST, CLASS_MAGIC_USER, 10); ç for Mages

   spell_level(SPELL_ARMOR, CLASS_CLERIC, 1);
   spell_level(SPELL_DETECT_INVIS, CLASS_CLERIC, 6);
   spell_level(SPELL_GLITTERDUST, CLASS_CLERIC, 15);	 ç for Clerics
After going through all these 6 basic steps, your spell will be complete and ready for the players to use. However, with all the changes done to the codes, you'll need to recompile the source code so that the changes will be incorporated and restart the mud so that it will be based on the newly compiled version. Now, the last thing you need to do is test the spell to see if it works, and do some modifications or adjustments so that the spell will do exactly as you planned it to.

But of course, I've oversimplified the whole process since I omitted the coding of the spell itself. That happens to be the backbone of the spell where the bulk of the codes will be. So now, let's slowly take a look at how to spells are actually coded in. So get your spell information and outline ready because if you plan and write down everything properly, they can be very helpful.

Part 3: Damage Spells - Killing Enemy 101

The first few spells that most people will think up are those for fighting purposes. Those spells will fall under this category. Now, let's try to code a clerical spell called "Flamestrike" where a column of holy flame will burst forth from the ground to engulf the victim. For details, let's make it a level 22 Cleric spell, obviously a violent one, can be cast while fighting and the target will be someone in the room or the person who the caster is fighting with. Beside that, since the holy fire needs to be "bursting forth" from the ground, let's limit it so that it can’t be cast on air, on watery surface and underwater. Let's make it cause quite a damage since it's high level: 12d8 + (caster's level) / 2

Functions or files involved in this spell:

Inside mag_damage(), a switch/case statement is use to determine which spell is being cast. So, let's add in a case for our spell:
case SPELL_HARM:
    dam = dice(8, 8) + 8;
    break;

case SPELL_FLAMESTRIKE:			ç Case statement for our spell.
    /* Is caster on air, on watery surface or underwater? */
    if (SECT(IN_ROOM(ch)) >= SECT_WATER_SWIM) {
      send_to_char("Your feet needs to be on firm ground!\r\n", ch);
      return (0);
    }
    dam = dice(12, 8) + level/2;
    break;
We don't need to worry neither the test for saving nor how it will inflict the damage to the victim. As mentioned, the function will do all those on our behalf. Now, all we need to do are define the characteristics of the spell, create some wonderful battle messages about how victim is being burned alive in the column of holy flames, and set the class and level for the spell.
spello(SPELL_FLAMESTRIKE, "flamestrike", 80, 50, 5, POS_FIGHTING,
	TAR_CHAR_ROOM | TAR_FIGHT_VICT, TRUE, MAG_DAMAGE);

Part 4: Area Spells - Make Thy Enemies Suffer!

Since there's only 1 area spell, let's make more and this time it's for the Mages. This time, let's code in a spell called "Reverse Gravity" which let the Mage temporarily reverse the gravitational pull around an area to go up, instead of down. Victims will be thrown up into the air for a while, before they come crashing back down. This will be a level 25 spell, violent and can be cast while fighting. Since this is an area spell, no target needs to be specified. For limitation, let's make it so that it can't be cast if the caster is on air, and only quarter damage when cast underwater. Let's take the victim's weight into consideration when calculating the damage. The heavier they are, the harder they fall: 3d8 + (victim's weight) / 2

Functions or files involved in this spell:

First, let's take a look inside mag_areas(). Again a switch/case statement is used to determine to find out which spell is being cast. Inside this function we only need to add in another case for our spell, and create a general message for when the spell is being cast, one for the caster and another for the rest in the room.
switch (spellnum) {
  case SPELL_EARTHQUAKE:
    to_char = "You gesture and the earth begins to shake all around you!";
    to_room ="$n gracefully gestures and the earth begins to shake violently!";
    break;

  case SPELL_REVERSE_GRAVITY:		ç Case statement for our spell
    /* Check if the caster is on air */
    if (SECT(IN_ROOM(ch)) == SECT_FLYING) {
      send_to_char("You are defying gravity yourself!\r\n", ch);
      return;
    }
    to_char = "You chant the spell softly, concentrating on reversing the gravitational pull."
    to_room = "$n softly chants. Suddenly, the gravitational pull begins to shift upwards!"
    break;
  }
That's it for mag_areas(). Remember, that function is only for the general message and to evaluate the list of characters in the room. The calculation of damage and inflicting it is being handled by mag_damage(). There's a heading for case statements for area spells. Let's put the damage formula under that heading:
  /* Area spells */
  case SPELL_EARTHQUAKE:
    dam = dice(2, 8) + level;
    break;

  case SPELL_REVERSE_GRAVITY:		ç Case statement for our spell
    dam = dice(3, 8) + GET_WEIGHT(victim)/2;
    /* Is the spell cast underwater? If so, quarter the damage */
    if (SECT(IN_ROOM(ch)) == SECT_UNDERWATER)
      dam /= 4;
    break;
And again, we just let those 2 functions evaluate the list of characters in the room for valid targets and inflict the damage to each of them. Next, define the characteristic of the spell, create some battle messages about how they were thrown high up in the air and come crashing down, and specify the class and level that can use this spell.
spello(SPELL_REVERSE_GRAVITY, "reverse gravity", 120, 100, 5,
	POS_FIGHTING, TAR_IGNORE, TRUE, MAG_AREAS);
Not everyone will be thrown up in the air by the reversal of the gravity. A tree monster that has strong roots deep inside the earth will definitely survive the ordeal. Part 14 is designed to explain on how to give some NPCs some form of immunity on certain spells (or skills).

Part 5: Affect Spells - Affect Them for Better or Worse…

We mention earlier on that affect spells can attach an affect flag or apply an affect on someone, or do both on that person. Let's do 2 spells here -- one to apply an affect, another to attach a flag. First, let's add in "Holy Purpose," a level 15 clerical affect application spell, which will increase the victim's hitroll and damroll temporarily. To make this as a "holy" spell, the caster must be good aligned, and if the victim is also good aligned then there's an added bonus. The duration of the spell is up to (caster's level) / 2 ticks. This spell is benign and can be cast on anybody, including the caster, but not during a fight.

Functions or files involved in this spell:

Again, a switch/case statement is used to identify the spell cast inside mag_affects(). However, there are other variables that we need to look at first. Once we are familiar with these variables, only then we can begin.
case SPELL_INFRAVISION:
  af[0].duration = 12 + level;
  af[0].bitvector = AFF_INFRAVISION;
  accum_duration = TRUE;
  to_vict = "Your eyes glow red.";
  to_room = "$n's eyes glow red.";
  break;

case SPELL_HOLY_PURPOSE:		ç Case statement for our spell
  /* First check for the caster's alignment */
  if (!IS_GOOD(ch)) {
    send_to_char("Your soul is not pure enough!\r\n", ch);
    return;
  }
  /* first set of affect to apply */
  af[0].duration = level/2;			/* Duration of affect   */
  af[0].location = APPLY_HITROLL;		/* Where it applies to  */
  af[0].modifier = 2 + (IS_GOOD(victim));	/* Amount being applied */
  af[0].bitvector = 0; 				/* Affect flag to use   */

  /* second set of affect to apply */
  af[1].duration = level/2;			/* If any of the values */
  af[2].location = APPLY_DAMROLL;		/* are 0, it is not     */
  af[3].modifier = 2 + (IS_GOOD(victim));	/* necessary to include */
  af[4].bitvector = 0; 				/* the field here       */

  accum_duration = FALSE;	/* Duration and affect doesn't accumulate */
  accum_affect = FALSE;		/* Not necessary to add if value is FALSE */

  to_vict = "You feel a deep sense of purpose in your heart.";
  to_room = "$n glows slightly and $s face is set with determination.";
  break;
For our second spell, let's do a Mage spell that uses an affect flag called "Silence." When cast, the victim will temporarily lose his voice. Therefore, he can no longer say something, shout or yell for everyone to hear, as well as do anything that requires the use of a voice, like casting spells and reciting scrolls! Offensive? Definitely… it's a spellcaster's nightmare! However, the affect is only temporary (duration: (caster's level) / 2), can't be cast while fighting and the victim has a chance to make his saves for not being affected.

Functions or files involved in this spell:

But before anything else, we need to create the affect flag for this spell first. First, we need to define the affect flag in STRUCTS.H under the heading Affect Bits. Place the new flag at the end of the list and increase the number by 1. The number is another form of a slot, which ranges from 0 to 31. Therefore we can only have a limited number of affect flags:
/* Affect bits: used in char_data.char_specials.saved.affected_by */
/* WARNING: In the world files, NEVER set the bits marked "R" ("Reserved") */
#define AFF_BLIND		(1 << 0)  /* (R) Char is blind          */
#define AFF_INVISIBLE		(1 << 1)  /* Char is invisible          */
#define AFF_DETECT_ALIGN	(1 << 2)  /* Char is sensitive to align */
#define AFF_DETECT_INVIS	(1 << 3)  /* Char can see invis chars   */
... [ snipped to make it shorter ]
#define AFF_UNUSED20		(1 << 20) /* Room for future expansion  */
#define AFF_CHARM		(1 << 21) /* Char is charmed            */
#define AFF_SILENCE		(1 << 22)  ç Our flag is defined as #22
And like the spell name, we also need to add in a name for our flag, but this time, it's inside CONSTANTS.C under affected_bits[]. Like before, we need to add the name at the end of the list, but before the termination ('\n') symbol:
/* AFF_x */
const char *affected_bits[] =
{
  "BLIND",		/*  0 */
  "INVIS",		/*  1 */
  "DET-ALIGN",
  "DET-INVIS",
... [ again, snipped to make it shorter ]
  "UNUSED",		/* 20 */
  "CHARM",
  "SILENCE",	ç The name of our affect flag
  "\n"
};
Only after this will we be able to make use of the affect flag. Now, let's add in another case statement inside mag_affects() for our new spell:
case SPELL_SILENCE:			ç Case statement for our spell
  /* Check if the victim managed to make his save */
  if (mag_savingthrow(victim, savetype, 0)) {
    send_to_char("You failed in your attempt!\r\n", ch);
    return;
  }
  /* Set up the affect flag */
  af[0].duration = level/2;			/* Duration of affect   */
  af[0].location = 0;				/* Where it applies to  */
  af[0].modifier = 0;				/* Amount being applied */
  af[0].bitvector = AFF_SILENCE; 		/* Affect flag to use   */

  accum_duration = FALSE;	/* Duration and affect doesn't accumulate */
  accum_affect = FALSE;		/* Not necessary to add if value is FALSE */

  to_vict = "An ethereal hand forces itself down your throat and steals your voice!";
  to_room = "An ethereal hand forces itself down $n's throat, leaving $m speechless!";
  break;
Now comes the most difficult part. We want those who are affected by this spell to lose his verbal ability. To do this, we have to go through all verbal communication functions, and do a check to see if that person is affected or not. If he is, then stop him from continuing. We also want to stop the affected person from casting spells and reciting scrolls, since both of them also require verbal ability. I will only include an example of a check in DO_SAY().
ACMD(do_say)
{
  /* Check if the person is affected by Silence spell */
  if (AFF_FLAGGED(ch, AFF_SILENCE)) { 	ç Our check for the flag
    send_to_char("But you have lost your voice!\r\n", ch);
    return;
  }

  skip_spaces(&;argument);

  if (!*argument)
    send_to_char("Yes, but WHAT do you want to say?\r\n", ch);
  else {
    sprintf(buf, "$n says, '%s'", argument);
    act(buf, FALSE, ch, 0, 0, TO_ROOM);

    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT))
      send_to_char(OK, ch);
    else {
      sprintf(buf, "You say, '%s'\r\n", argument);
      send_to_char(buf, ch);
    }
  }
}
That's it. The function will apply the affects on the victim when the spells are cast. Now, define the characteristic of the spells, and instead of battle messages, create some fancy wear off messages like how the player regrets that the feeling of determination is now gone, or how good it feels to get his voice back again. Don't forget to set the class and level of the spells.
spello(SPELL_HOLY_PURPOSE, "holy purpose", 80, 50, 5, POS_STANDING, 
	TAR_CHAR_ROOM, FALSE, MAG_AFFECTS);

spello(SPELL_SILENCE, "silence", 80, 50, 5, POS_STANDING, 
	TAR_CHAR_ROOM | TAR_NOT_SELF, TRUE, MAG_AFFECTS);
Note that even though an affect spell (like Silence spell) might be offensive, unlike damage spells the caster and victim will not automatically fight each other. They will only fight if the victim is an NPC and the caster loses his concentration while casting. Don't forget that some NPCs might be immune to this spell…. Check out Part 14 on how to do this.

Part 6: Unaffect Spells - "First You Have It, Now You Don't!"

If someone is affected by Silence spell, it will be a while before he can get his voice back. Let's code in something that will help him get his voice back faster. A different type of spell called "Vocalize" which will remove the Silence affect flag from someone. What's the different? This spell is only available in potions. There is a slight different when defining a non-castable spell.

First, let's define the spell. When defining a non-castable spell in SPELLS.H, we have to look further down list. There's a section for it:

/* NON-PLAYER AND OBJECT SPELLS AND SKILLS */

#define SPELL_IDENTIFY			201
#define SPELL_FIRE_BREATH		202
#define SPELL_GAS_BREATH		203
#define SPELL_FROST_BREATH		204
#define SPELL_ACID_BREATH		205
#define SPELL_LIGHTNING_BREATH		206
#define SPELL_VOCALIZE			207  ç Our spell is defined as #207
Now, let's create a potion that will use this new non-castable spell. I'm going to set the prototype of the potion as object number #3056, after the metal staff (#3055). After that, we can just set it so that the local Magic Shop in Midgaard or other places to sell it. Better yet, give it to an NPC somewhere so players will have to kill the NPC first before getting their hands on it!
#3056
potion blue glowing~
a blue, glowing potion~
A small vial filled with blue, glowing liquid has been left here.~
~
10 g 16385
12 207 -1 -1	ç This potion will use our spell, set at level 12
1 4000 100
E
potion blue glowing~
The vial is filled with some thick bluish liquid, and the liquid
seems to glow! Somehow, while examining the vial you feel a
strange urge to speak and speak and speak....
~
Functions or files involved: Now, let's code the spell in. Through the use of switch/case statement, it's easy to identify what spell has been cast:
case SPELL_REMOVE_POISON:
    spell = SPELL_POISON;
    to_vict = "A warm feeling runs through your body!";
    to_room = "$n looks better.";
    break;

case SPELL_VOCALIZE:			ç Case statement for out spell
    spell = SPELL_SILENCE;		ç This is the opposite affect spell
    to_vict = "Your throat feels cool and tingling suddenly...";
    to_room = "A look of surprise, then relieve appears on $n's face";
    break;
The function will check if the victim is affected by the opposite affect spell and will remove it. When defining the characteristic of the spell, the mana requirements and minimum position can be set as 0 since it's a non-castable spell. Besides that, since it's on a potion, neither target nor setting of the class and level for the spell is needed. This is not a violent spell and no fancy messages are needed.
/* 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);

spello(SPELL_VOCALIZE, "vocalize", 0, 0, 0, 0,	ç Our spell
	TAR_IGNORE, FALSE, MAG_UNAFFECTS); 

Part 7: Alter Object Spells - Bend It to Your Will.

We have done an affect and unaffect spells that can attach and remove an affect flag on someone. Now, let's do the same for object. This time, we'll do a spell called "Holy Weapon" that will make the weapon do more damage to evil characters. However, since it's supposed to be a holy and magical weapon, the weapon must not be magical in the first place. For the limitation of this spell, let's make it take only good aligned characters can use it, and it will only do quarter damage if used against good aligned characters. Let's make it a level 26 Cleric spell and can only be cast on a weapon in the caster's inventory.

Functions or files involved:

Like, affect flags in affect spells, we need to create the flag first. The place to add is in STRUCTS.H under the heading Extra Object Flags. Place the new flag at the end of the list and increase the number by 1. The number is another form of a slot, which ranges from 0 to 31. Therefore we can only have a limited number of object flags:
/* Extra object flags: used by obj_data.obj_flags.extra_flags */
#define ITEM_GLOW		(1 << 0)  /* Item is glowing            */
#define ITEM_HUM		(1 << 1)  /* Item is humming            */
#define ITEM_NORENT		(1 << 2)  /* Item cannot be rented      */
#define ITEM_NODONATE		(1 << 3)  /* Item cannot be donated     */
... [ snipped to make it shorter ]
#define ITEM_ANTI_WARRIOR	(1 << 15) /* Not usable by warriors     */
#define ITEM_NOSELL		(1 << 16) /* Shopkeepers won't touch it */
#define ITEM_HOLY_WEAPON	(1 << 17)   ç Our flag is defined as #17
And like the spell name, we also need to add in a name for our flag, but this time, it's inside CONSTANTS.C under extra_bits[]. Like before, we need to add the name at the end of the list, but before the termination ('\n') symbol:
/* ITEM_x (extra bits) */
const char *extra_bits[] = {
  "GLOW",		/*  0 */
  "HUM",		/*  1 */
  "!RENT",
  "!DONATE",
... [ snipped to make it shorter ]
  "!WARRIOR",		/* 15 */
  "!SELL",
  "HOLYWPN",	ç The name of our object flag
  "\n"
};
Now that that's done, let's start with the coding of the spell itself. To make it so that only good aligned characters can use the weapon, we'll use 3 ready-made flags -- ITEM_ANTI_EVIL and ITEM_ANTI_NEUTRAL, to make it into good aligned only, and ITEM_MAGIC to change it into a magical weapon. Let's add in our case statement inside mag_alter_objs():
case SPELL_REMOVE_POISON:
  if (((GET_OBJ_TYPE(obj) == ITEM_DRINKCON) || (GET_OBJ_TYPE(obj) == ITEM_FOUNTAIN) ||
       (GET_OBJ_TYPE(obj) == ITEM_FOOD)) && GET_OBJ_VAL(obj, 3)) {
    GET_OBJ_VAL(obj, 3) = 0;
    to_char = "$p steams briefly.";
  }
  break;

case SPELL_HOLY_WEAPON:			ç Case statement for out spell
  /* Let's make sure that the object is a weapon, and not magical */
  if ((GET_OBJ_TYPE(obj) == ITEM_WEAPON) && (!IS_OBJ_STAT(obj, ITEM_MAGIC))) {

    /* Let's make it so that it's a good-only weapon */
    if (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)) 
      REMOVE_BIT(GET_OBJ_EXTRA(obj), ITEM_ANTI_GOOD);
    if (!IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL)) 
      SET_BIT(GET_OBJ_EXTRA(obj), ITEM_ANTI_NEUTRAL);
    if (!IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)) 
      SET_BIT(GET_OBJ_EXTRA(obj), ITEM_ANTI_EVIL);

    /* Now, set the weapon to become a holy and magical one */
    SET_BIT(GET_OBJ_EXTRA(obj), ITEM_HOLY_WEAPON);
    SET_BIT(GET_OBJ_EXTRA(obj), ITEM_MAGIC)

    to_char = "$p starts to glow with a soft, white aura."
  }
  break;
We don't have to worry about doing a check for a character's alignment when he tries to wield it. With the setting of ITEM_ANTI_EVIL and ITEM_ANTI_NEUTRAL flags, the function equip_char() will do the check for us. Now, what we need to think of is how to do the check when the weapon is used for fighting. For that we need to take a look inside hit() which will calculate the damage being done by a weapon while fighting:
... [ snipped to make it shorter ]
  /* okay, we know the guy has been hit.  now calculate damage. */

  /* Start with the damage bonuses: the damroll and strength apply */
  dam = str_app[STRENGTH_APPLY_INDEX(ch)].todam;
  dam += GET_DAMROLL(ch);

  /* Maybe holding arrow? */
  if (wielded && GET_OBJ_TYPE(wielded) == ITEM_WEAPON) {
    /* Add weapon-based damage if a weapon is being wielded */
    dam += dice(GET_OBJ_VAL(wielded, 1), GET_OBJ_VAL(wielded, 2));

    /* Does it have Holy Weapon flag? */	ç Our check for the flag
    if (IS_OBJ_STAT(wielded, ITEM_HOLY_WEAPON)) {
      if (IS_GOOD(victim)) dam /= 4;
      if (IS_EVIL(victim)) dam *= 1.5;
    }

  } else {
    /* If no weapon, add bare hand damage instead */
... [ snipped to make it shorter ]
We're almost done. The only things left to do are to define the characteristic of the spell and set the class and level for the spell. This spell doesn't have any fancy wear off or battle messages.
spello(SPELL_HOLY_WEAPON, "holy weapon", 120, 100, 5, POS_STANDING, 
	TAR_OBJ_INV, FALSE, MAG_ALTER_OBJS);
Some people might wonder: if Enchant Weapon spell is supposed to alter an object, why does it fall under manual spell instead of this category? True, Enchant Weapon does alter an object. However, alter object spells are supposed to attach or remove object flags. Enchant Weapon not only attaches ITEM_MAGIC flag on a weapon, but also applies 2 affects (APPLY_HITROLL and APPLY_DAMROLL) to it. And we can't make it into an affect spell as well since affect spells are only for characters, and not object.

Part 8: Points Spells - Measuring the Beat of Our Life…

Points spells are those that will modify a person's hit, mana and movement points. So far, the implemented points spells are benign and curative. Let's make another one that will "cure" a person's movement point, instead of his hitpoint, and call it "Refresh." Since this is a not a violent spell, it can be cast on anyone in the room, including the caster, can't be cast while fighting and let's give this spell to a Cleric level 12. For the amount to be added in: (caster's level) x 3.

Functions or files involved:

There are 2 important variables inside mag_points() that we need to get familiar with: hit for the amount to add to the victim's hitpoint, and move for the victim's movement point. Again, we just add in a case statement in the switch/case for our spell.
case SPELL_HEAL:
    hit = 100 + dice(3, 8);
    send_to_char("A warm feeling floods your body.\r\n", victim);
    break;

case SPELL_REFRESH:		ç Case statement for our spell
    hit = 0			/* Add to hitpoint. Not necessary if 0 */
    move = level*3;		/* Add to movement point.              */
    send_to_char("A refresh feeling flows through you.\r\n", victim);
    break;
Again, the function will take care of everything and add the calculated amount to the victim's points. Now define the characteristics of the spell and set the class and level of spell before recompiling. You don't have to think up any fancy messages for this spell.
spello(SPELL_REFRESH, "refresh", 60, 30, 5, POS_STANDING, 
	TAR_CHAR_ROOM, FALSE, MAG_POINTS);

Part 9: Group-based Spells - Defend Thy Neighbors!

This is also one of the easiest spell to create. Since the targets of these spells are the caster's own group members, they are usually benign and beneficial in nature. We can actually make use of spells from other categories and call them from within. An example will be a Mage level 10 spell called "Group Invisibility." Anyone in the room who is grouped with the caster will become invisible. This spell doesn't have any target, and can't be cast while fighting.

Functions or files involved:

Since we are going to use an already implemented Invisibility spell, we don't need to code that in. However, if you want to do something new, then you will need to add in the appropriate spell. Another interesting to note is that we don't actually need to make any changes to mag_groups() since its function is to find the caster's group member who are in the same room. So, the only one we'll be changing is perform_mag_groups(), and maybe creating a new spell if you're not using a ready-made one. Just add in a case statement for our spell, and call the appropriate function:
case SPELL_GROUP_HEAL:
    mag_points(level, ch, tch, SPELL_HEAL, savetype);
    break;

case SPELL_GROUP_INVISIBILITY:	ç Case statement for our spell
    /* Invisibility spell is an affect spell */
    mag_affects(level, ch, tch, SPELL_INVISIBLE, savetype);
    break;
As simple as that. Mag_groups() will search for the group members, perform_mag_groups() will determine the spell being cast, and mag_affects() will place the affect of the spell on them. As before, no fancy battle or wear off messages is needed. Define the characteristic of the spell, set the class and level to use this spell, and you're done.
spello(SPELL_GROUP_INVISIBILITY, "group invisibility", 100, 80, 4, 
	POS_STANDING, TAR_IGNORE, FALSE, MAG_GROUPS);

Part 10: Masses Spells - Let Them See Your Way…

The word "mass" always reminds me of a preacher in a Sunday church. When the preacher starts preaching, everyone will listen (well, at least they were supposed to anyway). I guess that's why the description states that they are supposed to affect everyone the but the caster.

So far no spell has been implemented under this category. I guess it's a bit hard to figure out what is a suitable spell for this. If the spell should be offensive (damaging) then area spells is more appropriate since numerous checks are done. If the spell is beneficial, then why should a caster cast it since he won't benefit from it. Anyway, I have seen several MUDs that changed this so that it will include the caster as well, instead of excluding him.

Based on the description of the preacher above, let's make a spell called "Mass Bless" which let's a Cleric level 20 bless everyone in the room (except for himself that is…). Like the example for the group-based spell above, I'm going to use a ready-made Bless spell for this. No target is needed and it can only be cast while standing.

Functions or files involved:

Like the perform_mag_groups() above, just add in a case statement inside the switch/case in mag_masses(), and call the appropriate function that will cast the spell. The function will go through the list of characters in the room and will cause the spell to affect each of them.
switch (spellnum) {
case SPELL_MASS_BLESS:			ç Case statement for our spell
    /* Bless spell is an affect spell */
    mag_affects(level, ch, tch, SPELL_BLESS, savetype);
}
Again, no fancy battle and wear off messages are needed. All we need to do now is define the characteristics of the spell, and set the class and level for it.
spello(SPELL_MASS_BLESS, "mass bless", 80, 50, 4, POS_STANDING, 
	TAR_IGNORE, FALSE, MAG_MASSES);

Part 11: Summon Spells - "Come and Follow Me!"

So far we've been doing spells for Mages and Clerics. Let's do different one for this category. Let's base this one on nature, which a Druid or Ranger (even a Cleric actually) can make use off. This spell is called "Sticks to Snakes," which changes sticks in the room to become snakes, as the name said. Now, let's make it so that the number of snakes that will appear will depend on the sector type. The more nature-like the sector is, the more snakes will appear. This spell is not violent (at least I don't think so), but can be cast while fighting. There's no target for this spell, since the rooms aren't really littered with sticks to begin with. The snakes will be bound to the caster until one of them dies. By the way, this spell can't be cast on air, on watery surface and underwater.

Functions or files involved:

First, we have to get a prototype of a snake. I'm going to make one up and set it to use mobile number #3096, after the cryogenicist (#3095). The reason why I'm not using a ready-made prototype in the database is because I want the description to say that they are different:
#3096
snake brown stick~
the stick-like snake~
A brown stick-like snake is at your feet, hissing at you.
~
Unlike other snakes, this one is thin like a stick. Its coat is not
even glistening like the rest, but just dark brown. Even though the
snake puzzled you, looking at the poisoned saliva dripping from its
fangs does stop you from examining it even closer.
~
afnopr dks -200 S	ç 'a' indicates the use of special procedure
11 7 4 5d10+50 3d6+0
0 12000
8 8 0
Now, to make this more interesting, let's make the snake poisonous as well. The prototype is set to have a special procedure. To attach the procedure itself, we have to do that inside SPEC_ASSIGN.C file. Inside ASSIGN_MOBILES(), there is an entry for Midgaard. Just attach the snake procedure, which allows snakes to have a chance at poisoning the person who they are fighting with, using ASSIGNMOB() to our mobile prototype number:
  /* Midgaard */
  ASSIGNMOB(3005, receptionist);
  ASSIGNMOB(3010, postmaster);
  ASSIGNMOB(3020, guild);
  ASSIGNMOB(3021, guild);
... [ snipped to make it shorter ]
  ASSIGNMOB(3095, cryogenicist);
  ASSIGNMOB(3105, mayor);
  ASSIGNMOB(3096, snake);	ç Our prototype now has 'snake' procedure
Okay, now that the NPC that we want to use is ready, let's look inside mag_summons(). There are a few variables and structures that we need to get familiar first:
case SPELL_CLONE:
  msg = 10;
  fmsg = number(2, 6);	/* Random fail message. */
  mob_num = MOB_CLONE;	/* MOB_CLONE has been defined as 10 */
  pfail = 50;		/* 50% failure, should be based on something later. */
  break;

case SPELL_STICKS_TO_SNAKES:		ç Case statement for our spell
  /* Check where the caster is currently */
  if (SECT(IN_ROOM(ch)) >= SECT_WATER_SWIM) {
    send_to_char("You can't cast the spell here!\r\n", ch);
    return;
  }
  
  /* Set the possibility and amount to load base on sector type */
  mob_num = 3096;
  num = number(1, 1 + SECT(IN_ROOM(ch)));
  pfail = 100 - 10*SECT(IN_ROOM(ch));

  /* Set the appropriate values for the others */
  msg = 9;
  fmsg = number(2, 6);
  handle_corpse = FALSE;
  break;
Like normal, the function will take care of the loading of the NPC and set them to follow the caster. And like normal also, we need to set the characteristic, as well as the class and level of the spell. No fancy battle and wear off messages are needed for this spell.
spello(SPELL_STICKS_TO_SNAKES, "sticks to snakes", 80, 50, 4,
	POS_FIGHTING, TAR_IGNORE, FALSE, MAG_SUMMONS);

Part 12: Creation Spells - Magical Sleight of Hand.

Sleight of hand, a common trick that makes things seemed to appear from out of the thin air. However, with a creation spell like "Knowledge," we can make an identify scroll to appear in our hand for use. It is also simple to do actually, but first we need to know the prototype object number of the scroll which we'll be using (#3050). Only then we can continue. Let's make it a level 14 Mage spell, which can't be cast while fighting.

Functions or files involved:

Inside mag_creations(), we just add in a case statement for our spell in the switch/case combination:
  case SPELL_CREATE_FOOD:
    z = 10;
    break;
  case SPELL_KNOWLEDGE:		ç Case statement for our spell
    z = 3050;			ç The prototype number that will be used
    break;
If you want to create a different scroll or potion, you can either create a new one and place it inside the database or use one that is already in there. From here, we just need to define the characteristic of the spell, set the level and class of the spell and we are done since there is no need for fancy messages.
spello(SPELL_KNOWLEDGE, "knowledge", 60, 40, 4, POS_STANDING,
	TAR_IGNORE, FALSE, MAG_CREATIONS);

Part 13: Manual Spells - Making It Special…

Spells that can't fall into the other types will fall here. And since we don't have a ready-made function that will do everything for us, we have to code everything manually. For this, let's do a spell that will let Mages see into the rooms around him. A level 18 spell called "Farsight" which will show to the caster a list of who are in the rooms adjacent to the one he is in. This is not a violent spell, and can only be cast while standing.

Functions or files involved:

There is a slight different when defining the spell. After defining the unique spell number, we have to declare the function for the spell itself. This is done close to the end of SPELLS.H, together with the rest of manual spells function declaration:
ASPELL(spell_charm);
ASPELL(spell_identify);
ASPELL(spell_enchant_weapon);
ASPELL(spell_detect_poison);
ASPELL(spell_farsight);		ç Declaration of our spell function
The codes for the function is usually kept inside SPELLS.C:
ASPELL(spell_farsight)
{
  int door, found;
  struct char_data *person;

  /* Check for every exit, from north to west */
  for (door = NORTH; door <= WEST; door++)
    if (CAN_GO(ch, door)) {
      found = FALSE;
      sprintf(buf, "You look to the %s:", dir[door]);

      /* Is the room dark and can caster see in the dark? */
      if (IS_DARK(EXIT(ch, door)->to_room) && !CAN_SEE_IN_DARK(ch)) {
        strcat(buf, " Too dark to see anyone...");
        found = TRUE;
      } else {

        /* If there is someone in the room, can caster see him? */
        for (person = world[EXIT(ch, door)->to_room].people; person; 
             person = person->next_in_room)   
          if (CAN_SEE(ch, person)) {
            sprintf(buf + strlen(buf)," %s", GET_NAME(person));
            found = TRUE;
          }
      }      

      /* Tell the caster what he can see */
      if (found) send_to_char(strcat(buf, "\r\n"), ch);

    }    
}   
Okay, the last thing before we can finish this off like the rest, is that we need to add in a case statement for our new spell in SPELL_PARSER.C under call_magic() with the rest of the manual spells. Notice the difference in the way a manual spell function is called compared to the way other categories call theirs?:
if (IS_SET(SINFO.routines, MAG_MANUAL))
  switch (spellnum) {
  case SPELL_CHARM:          MANUAL_SPELL(spell_charm); break;
  case SPELL_CREATE_WATER:   MANUAL_SPELL(spell_create_water); break;
  case SPELL_DETECT_POISON:  MANUAL_SPELL(spell_detect_poison); break;
  case SPELL_ENCHANT_WEAPON: MANUAL_SPELL(spell_enchant_weapon); break;
  case SPELL_IDENTIFY:       MANUAL_SPELL(spell_identify); break;
  case SPELL_LOCATE_OBJECT:  MANUAL_SPELL(spell_locate_object); break;
  case SPELL_SUMMON:         MANUAL_SPELL(spell_summon); break;
  case SPELL_WORD_OF_RECALL: MANUAL_SPELL(spell_recall); break;
  case SPELL_TELEPORT:       MANUAL_SPELL(spell_teleport); break;
  case SPELL_FARSIGHT:       MANUAL_SPELL(spell_farsight); break; ç
  }
Like the rest, define the characteristic of the spell, and set the level and class for it. As to whether it needs a battle and/or wear off message, it depends on the nature of the spell. If you are placing an affect spell on someone, like Charm spell, then you'll require a wear off message. As for battle messages… I'm not sure. If the spell is too complex for damage and area type, then have a single set of battle messages might not be enough. Then again, I could be dead wrong!
spello(SPELL_FARSIGHT, "farsight", 100, 75, 5, POS_STANDING,
	TAR_IGNORE, FALSE, MAG_MANUAL);

I know some people wondered why Control Weather spell couldn't be cast. If you take a look at the arguments that are passed into ASPELL(), you'll notice that there is no way the word "worse" or "better" can be passed in. There are a few ways to go around this, and someone wrote to the mailing list suggesting a method he used sometime in 1998. Hopefully a copy of the mail is still in the archive.

Part 14: Giving NPCs Immunity.

Not everyone is susceptible to the spells and skills that we are using. For example, a tree is extremely hard to be bashed over with a small sword (even though it's a huge sword to the wielder). And a tree will definitely be immune to the Reverse Gravity spell that we just made, since they tend to have roots so deep that they can't be thrown around easily. Therefore, a check can be made in the coding for the Bash skill or the Reverse Gravity spell for these situations.

The question is, how are we to know? If you have implemented race in your MUD, which covers the NPCs as well, it's easy to check if the victim is of RACE_TREE for example. But until you add that in, you will have to make do with mobile flags for NPCs.

The existing flags are located in STRUCTS.H under Mobile Flags. Like affect and object flags, these flags are also limited, ranging from 0 to 31:

/* Mobile flags: used by char_data.char_specials.act */
#define MOB_SPEC        (1 << 0) /* Mob has a callable spec-proc    */
#define MOB_SENTINEL    (1 << 1) /* Mob should not move             */
#define MOB_SCAVENGER   (1 << 2) /* Mob picks up stuff on the ground*/
#define MOB_ISNPC       (1 << 3) /* (R)Automatically set on all Mobs*/
... [ snipped to make it shorter ]
#define MOB_NOSLEEP     (1 << 15)/* Mob can't be slept              */
#define MOB_NOBASH      (1 << 16)/* Mob can't be bashed (e.g. trees)*/
#define MOB_NOBLIND     (1 << 17)/* Mob can't be blinded            */
There is already a flag called MOB_NOBASH, to let NPCs who has it to be immune to bashing. However, not being able to bash someone only means that that person is either too heavy or too large to be bashed. So, let's make a flag that will protect NPCs from Reverse Gravity or other spells/skills that can throw them around. Let's call this flag MOB_NOTHROW. Again, like the affect and object flags, we put our new flag at the end of the list, incrementing it by 1:
#define MOB_NOTHROW     (1 << 18)/* Mob can't be thrown around      */
Next, we have to put the name of the flag, again inside CONSTANTS.C, but this time in under another heading. Just add the name at the end of the list, but before the termination ('\n') symbol:
/* MOB_x */
const char *action_bits[] = {
  "SPEC",		/*  0 */
  "SENTINEL",	/*  1 */
  "SCAVENGER",
  "ISNPC",
... [ snipped to make it shorter ]
  "!SLEEP",		/* 15 */
  "!BASH",
  "!BLIND",
  "!THROW",		ç The name of our mobile flag
  "\n"
};
With that, we can now make use of our new flag. For an example of how to use this flag, let's go back and look at our coding for Reverse Gravity spell again. We'll take a look at the one inside mag_damage() since that is where the damage is being calculated and inflicted from:
  /* Area spells */
  case SPELL_EARTHQUAKE:
    dam = dice(2, 8) + level;
    break;

  case SPELL_REVERSE_GRAVITY:		ç Case statement for our spell
 
    /* Can the victim be thrown around? */
    if (MOB_FLAGGED(victim, MOB_NOTHROW) { ç Our check for the flag
      send_to_char("You brace yourself, and survive the ordeal.\r\n", victim);
      act("$n braces $mself and survives the ordeal!", TRUE, victim, 0, 0, TO_ROOM);
      return (0);
    }
   
    dam = dice(3, 8) + GET_WEIGHT(victim)/2;
    /* Is the spell cast underwater? If so, quarter the damage */
    if (SECT(IN_ROOM(ch)) == SECT_UNDERWATER)
      dam /= 4;
    break;
Wait a minute! The code checks if the NPC has the MOB_NOTHROW flag. But what if the victim is a player and not an NPC? Simple…. If you follow the definition for MOB_FLAGGED(), you'll see that it actually checks to see if the victim is an NPC or not. If it's a player, the condition will automatically be false.

Checking a victim or an NPC for specific flags can be done anywhere in the codes, not just for spells and skills. The only think that you have to remember though is that affect flags (AFF_xxx) can be attached to both players and NPCs and uses AFF_FLAGGED() for checking, which mobile flags are only for NPCs and uses MOB_FLAGGED() for checking.