Docs on making simple shadows for spells
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
	If you intend to code spells, you will probably at some point
need to know something about shadows.  If you want to know what they are
at the basic level, see 'man shadow'.  Once you understand that, you may
try to code one.
	It's not hard to figure out that shadows make it very easy to
temporarily modify just about anything (characters stats, weapons damage,
etc.)  However, the handling of cumulative shadows gets a little complex
so I have written a generic object that should handle all of the hard
work for you.

	The top of EVERY shadow file should have the line:

inherit "/std/spells/shadows/shadow";

	The main functions you'll need when coding a shadow are:

	create()
	remove()

	plus a function which starts the shadow.  The create function
only needs to stick initial values in your variables and may look
something like this:

void create() {
    strength_mod = 10;
    return;
}

When you start the shadow, you can include anything you want, but make
sure you have this line

begin_shadow(object shadowed)

where object shadowed is the object variable containg the thing you wish
to shadow.  Also, if the spell has a duration, include:

call_out("expire_me", int duration, this_object());

where int duration is the number of seconds to expiration.  The
this_object() arg is necessary for the shadow.c to handle location fo the
shadow.  Also, you will want to set any variables that you need to refer
back to the target of the spell.  You will need to define the function
expire_me(object me) later in the file.  We will discuss how to do that
later.  For instance, a start_shadow for a shadow which modifies a
player's strength might look like:

object who_shadowed;       <-- global variables at top of file
int strength_mod;

void start_shadow(object who, int duration) {
    if(!objectp(who)) return;
    who_shadowed = who;          <-- so we can get to him later to
    call_out("expire_me",duration,      send messages, etc.
	 this_object());
    begin_shadow(who);
    return;
}


	Now you must define the functions you want to shadow.  Very
important here is to MAKE SURE YOUR SHADOW IS CUMULATIVE with other
stacked shadows (if you want it to be).  If you want the effect of the
last spell cast to override the effects of all other spells, don't worry
about this.  The function

object next_shadow()

returns the next object in the shadow chain. Basically it would be used
like this.

query_stats(string what) {
    if(what == "strength")
	return strength_mod +
	    (int)next_shadow()->query_stats("strength");
    else return (int)next_shadow()->query_stats("strength");
}

This is an example of a shadow which would add strength_mod to a
character's strength.

Finally, the shadow must be removed if you want the effects to "wear
off."  This uses the remove function and is usually called by a call_out
(see above).  The remove function NEVER has any arguements, and can be
used to handle anything like sending a message to the player that the
spell has expired.  Here is the example remove function for out strength
modifying shadow:

void expire_me(object me) {
    if(me != this_object()) {     <-- This check is necessary.
      next_shadow()->expire_me(me);      ALWAYS include it.
      return;
    }
    message("info", "You don't feel so strong anymore.",
	who_shadowed);
    remove();         <-- Remember to remove(); at the end of the function.
    return;
}

If you want to be able to destroy a shadow with a call_other, i.e. from
an object outside the shadow, things can once again be complex.  Because
of the nature of shadows, if you try to call remove() in a shadowing
object, the call will "leap" down to the end of the shadow chain and
possibly destruct an object which is not the one you want to destroy.
In order to deal with this, you may call the function external_destruct.
BE SURE to supply an arguement which is an object variable pointing to
the shadow you wish to destruct.  The fuction in the external object
which destroys the shadow might look like this:

void destroy_shadow(object which) {
    which->external_destruct(which);
    return;
}

Hope this helps.  Mail me with any questions.

-Diewarzau 7/18/95
