From the NannyMUD documentation

LAST CHANGE

2005-02-22

RULES

NAME

        spells - Rules on magic and spells

DESCRIPTION

	Spells has the power to disrupt the game balance and must therefore
	be approved. All spells must check the following, and if true, they
	are not to work at all:

	+ Is the player currently a ghost, i.e. dead?
	+ Is the player currently busy?
	+ Does the player have the required SP?
	+ Does the environment have the property "no_magic"?


	TELEPORTATION

	One of the most desired spells in the game seems to be a teleport
	spell, at least judging from how many such have been coded. A
	teleport spell must cost 30 SP or more to use. Before teleporting,
	check the following properties:

	+ "no_teleport_in"
	+ "no_teleport_out"
	+ Does the start and end point of the teleport have the same
          "dimension" property?


	ATTACK SPELLS

	Attack spells are those spells that do damage to monsters and/or
	players. They must all take the following into account:

	+ Attack spells must check for the property "no_fight" in the
	  environment; if this property exists the spell must not function.
	+ All attack spells must have some pre-delay before going of, or the
	  players will in effect have free kills (by running in, using the
	  spell, running out, all in the same heartbeat).


	HEALING SPELLS

	Healing spells must cost at least 1 SP per HP healed, but preferably
	more. The spells are easy to carry around the game; consider them
	portable. Some spells convert the players HP into SP or vice
	verse. If the convesrion ratio should be less than 1.

EXAMPLE

	Here are pieces of code that show checks for various things, as it
	has been found that wizards have a hard time writing such checks


	CHECK FOR GHOST

	The player must not be able to use any abilites when ghost.

	if (this_player() -> query_ghost()) return 0;


	CHECK FOR PROPERTY "no_magic"

	If the room is no_magic, then the player must fail in casting the
	spell.

	if (!environment(this_player()))
	  return 0;
	if (environment(this_player()) -> query_property("no_magic"))
        {
          write("You cannot cast a spell here.\n");
          return 1;
        }


	CHECK FOR BUSY

	Busy is a thing that will keep players from casting two spells at
        one time. It is used in many other kinds of extra attacks and
	actions, too.

        if (this_player() -> check_busy(2))
        {
          write("You cannot do two things at one time.\n");
          return 1;
        }

        The function 'check_busy()' returns 1 if the player is busy and 0 if
	not. The argument is the number of heart beats the player will be
	busy by this action, if he wasn't busy before.



	CHECK FOR SPELL POINTS

	If the player hasn't got enough SP, he shouldnt be able to cast the
	spell. Do not forget to draw the SP from the player when he casts the
	spell.

	consume_sp(arg)
        {
          if (this_player() -> query_sp() add_sp(-arg);
          return 1;
        } // consume_sp


	CHECK FOR NO_FIGHT

	In places like churches, no aggressive actions are allowed, and
	therefore no attack spells.

        if (environment(this_player()) -> query_property("no_fight"))
        {
          write("Such actions are forbidden here.\n");
          return 1;
        }


	CHECK FOR TELEPORT PROPERTIES

	Teleportation is not allowed between every two locations. The
	property "no_teleport" automatically links to "no_teleport_in" and
	"no_teleport_out", so the checks below are sufficient.

        here = environment(this_player());
        there = destination;
        if (here -> query_property("no_teleport_out") ||
            there -> query_property("no_teleport_in") ||
	    here -> query_property("dimension") !=
            there -> query_property("dimension")) 
        {
          write("The spell fails.\n");
          return 1;
        }