/
lib/banish/
lib/d/
lib/doc/
lib/doc/domains/
lib/doc/efun/
lib/doc/examples/
lib/doc/examples/armour/
lib/doc/examples/contain/
lib/doc/examples/food/
lib/doc/examples/magic/
lib/doc/examples/monster/
lib/doc/examples/room/
lib/doc/examples/weapons/
lib/function/
lib/include/
lib/include/fn_specs/
lib/include/skills/
lib/info/
lib/inherit/base/
lib/log/
lib/manuals/312/
lib/news/
lib/obj/party/
lib/objects/components/
lib/open/
lib/open/library/
lib/open/party/
lib/players/
lib/players/zilanthius/
lib/room/
lib/room/city/arena/
lib/room/city/creator/
lib/room/city/garden/monst/
lib/room/city/obj/
lib/room/city/shop/
lib/room/death/
lib/room/registry/
lib/secure/
lib/secure/UDP_CMD_DIR/
lib/skills/
lib/skills/fighter/
lib/skills/thief/
lib/usr/
lib/usr/creators/
lib/usr/players/
              -=[ Making New Spells ]=-

Overview:

A new and extended spell front-end has been made to make simple spells
easier to create, but has the flexibility to make them quite complex.
The spell system works on the players heart beat. It has 3 main functions:
load_spell(), which loads the attributes of a spell into an array;
cast_spell_at_target() which finds the appropriate target; and 
spell_hit() which is called in the (living) target. Each heart beat the
the attack fn checks for a loaded spell, if there is a casting message it
writes the messages, otherwise it will call cast_spell_at_target(), and
cast the spell.

The spell system features easy to make area effect spells, casting times
with a message to caster and room once per heart beat, multiple spell
components, spell capture routine, use of alternative spell objects,
immunity checks, magic resistance checks, option for spell to start
fight or not (you dont want cure spells to start fights do you!),
saving throw, optional use of spell casting objects such as wands
and magic scrolls.

If you want more examples of spells there are about 140 files in
/skills/cleric, and /skills/mage that use this system.



Classifying Mage Spell Schools:

                 - Abjuration  - 

These magics are primarily concerned with prevention and exclusion of particular
magical and non-magical effects, situations, or individuals, and include most
spells of protection, avoidance, and repellence. EG - 'protection from evil',
'dispel magic', 'anti-magic shell'. 


                 - Alteration -

Spells which modify existing conditions or individuals through the infusion of
magical energy are alteration spells. Spells that give the recipient enhanced
strength, or the ability to fly, those that transmute substances ('polymorph
self', 'polymorph other') and spells that have general affects ('move earth' or
'lower water') are all alterations.


                 - Conjuration -

This school part brings additional matter from elsewhere or create a duct
between the caster and some greater magical power. Spells that summon existing
animals or monsters into the area, bring into being on this plane extra-
dimensional creatures (such as elementals) are conjurtation magics.


                  - Divination -

These are those that uncover information that is otherwise hidden under normal
circumstances and includes spells that detect magical effects, invisibility, and
the like,  those spells that predict hidden of future events, and those that
place the caster in contact with powerful extradimensional creatures but do not
involve direct action by those creatures.


                   - Charm -

Such spells place a dweomer on the target or item that radiates a magical aura.
On physical items it is normally used to invest an item with nagicak powers
(such as 'deep pockets' or 'bind'), but is more commonly used to induce
particular emotional or mental states in living targets (such as 'friends',
'forget', or 'Otto's irresistable dance').


                    - Evocation -

This channels magical energy, using that energy to create effects and types of
matter. These include permament features such as the 'wall of force', 'Bigby's
Crushing Hand', et al, and temoprary effects such as fireball and lightning
bolt.


                    - Illusion -

This creates a false reality. Illusions alone create the apparent existence of
items in the minds of the viewers, or creating a shadow reality that gives
illusions the power and reality to affect the viewer as if they were REAL.
Illusions are not simply two-dimensional holograms, but can touch the sound,
smell, optical, and thermal senses.


                     - Necromancy -

This involves the health, hp, or normal living (or once living) functions of
objects. Spells that increase or decrease hp, cause or cure wounds, or restore
lost souls to their bodies are all necromantic spells. Due to the nature of
handling the dead most users of this school are evil. Perhaps this is the nature
of the magic and its influence on the mortal soul, or the fact that only the
evil and twisted dare utilize this magic.


Classifying Cleric Prayer Spheres:

                 - healing_sphere -

These are prayers that will heal wounds, diseases, and physical
afflictions.


                 - stellar_sphere -

These are prayers that deal with the stars, planet, and the pure physical
characteristics of the universie.


                 - nature_sphere -

These are prayers that deal with nature and its infinite variety.


                 - protection_sphere -

These are prayers that will protect the cleric are prayers target from both
physical, and spiritual attacks.


                  - combat_sphere -

These are prayers that deal directly with the warlike nature of man.


                   - divination_sphere -

These prayers deal with the discernment of the unknown. Knowledge can be a
powerful tool.

                   - necromancy_sphere -

These are prayers which deal with the life essences. It can be both good or
evil.  Prayers from resurrecting the dead, to neutraliing poison.



Load_spell Attributes:

At the moment there are about 18 attributes one can set for a spell. These are
described below.


"target",  target,

The target attribute can be either a string or an object. It has a special
reference "room".  The target must be either the players environment,
in their environment, or in their inventory.


"name",   name,

The name attribute must be a string. It is the name of the spell.
Eg.  "name",  "Burning Hands",


"sphere" or "school",  type,

This attribute can be either an object or a string. If the type is a string
it must be one of the mage schools or cleric spheres. For example:
"school", "evocation", will check whether they have an appropriate
evocation level, enough evocation points, and will remove the appropriate
evocation points.  If the type is an object it will call in that object
query_cast_level() to see if it has the appropriate level, and will check 
for charges with query_charges(), and will remove the appropriate charges
with adj_charges(amt). This has been set up in "inherit/wand".

Notes: Current Mage schools are evocation, conjuration, abjuration,
                                charm, illusion, alteration, 
                                divination, and necromancy.

       Current Cleric Spheres are healing_sphere, stellar_sphere,
                                  nature_sphere, protection_sphere,
                                  combat_sphere, divination_sphere,
                                  and necromancy_sphere. 
  

"cost",  cost,

This attribute must be an int. This is the amount of 'school' or 'sphere'
points, or charges that are removed when the spell is cast.


"damage", dam,

This attribute must be an int. This is the maximum amount of damage a
spell will cause. Reduction in damage is made by the target if
they have magic resistance, are immune to the spell, make their saving throw,
or absorbed by their armour.


"immune", immune,

This attribute must be a string. This is the spells basic element type. 
An immunity to certain spells can be given to players, and monsters alike.
If the spell is offensive you must give an immune type. For example, 
fire ball has an immune of "fire".

Note: These are current immunity standards,
   light, darkness, death, draining, earth, air, fire, water, cold, acid,
   lightning, poison, disease, time, fear, charm, illusion, disintegrate.



"level",  level,

This attribute must be an int. This is the minimum level of a 'school', or
'sphere' of a player or monster, or 'query_cast_level()' of a wand to cast
the spell.


"casting time",  time,

This attribute must be an int. This is the number of heart beats that a
player or monster must spend casting a spell.  The caster will not be able
to attack in any other form whilst casting a spell.


"casting msg",  msg,

This attribute can be a string, or an array of strings. The casting msg
is written to the caster when they are casting the spell.


"casting msg room", room_msg,

This attribute can be a string or an array of strings. The room_msg is written
to those in the room of the caster, while the caster is casting the spell.

Note: The references, this_player(), and this_object() both designate
the caster at this stage. It is simpler not to reference the target
during casting messages, but it can be done.


"area",

This attribute sets the area effect flag, so that everyone in the room,
including the caster is hit by the spell.

Note: There are examples of how to make area effect spells that do not
hit the caster, and there are those which do not hit the caster's
party members.


"spell object", file,

This attribute must be a string. The file is cloned to the target of the
spell. Then the function,

status cast_spell(object caster,object target,object prev,int dmg) { }

is called in the object. cast_spell() is called with 4 arguments;
the caster; the target; the previous target if it was an area effect spell,
otherwise it is 0; and the damage. Of note is if damage is equal to
zero then the target has made its magic resistance, or is immune to the
spell, if the damage is half then it has made its saving throw. If cast spell
returns 0, then it will call hit_player() in the target for 'damage'. If
it returns 1, it will do no damage.


"passive",

This attribute will set a flag which by-passes magic resistance, 
immunity, and save checks. It is assumed that you will be using the
"spell object" attribute, with a cast spell that returns 1. Using the
"passive" flag for offensive spells is thought of as non-sporting, so
there must be a very good reason for doing so.


"component", component_string,

This attribute is must be a string. This attribute will accept a string
as the id of an object on the caster. The component will be necessary to
cast the spell. It will be destruct at the end of the spell. It will also 
accept multiple ids, and more then one component. The component parser
accepts two delimiters; the '#' which acts as an 'or', and the '+' which
acts as an 'and' (which has precedence).

Eg.  "component", "rock#stone#boulder+rope#cord#string",

Thus a rock, and a piece of string will be accepted as spell components.  


"msg target", msg,

This attribute must be a string. This message is written to the target.
Note if cast_spell() is called in a spell object returns 1 this message
will not be seen.

Note: at this stage this_player() references caster
                and this_object() references target for processed messages.
             

"msg room", msg, 

This attribute must be a string. This message is written to the room.
Note if cast_spell() is called in a spell object returns 1 this message
will not be seen.

Note: at this stage this_player() references caster
                and this_object() references target for processed messages.


"msg caster",

This attribute must be a string. This message is written to the caster.
Note if cast_spell() is called in a spell object returns 1 this message
will not be seen.

Note: at this stage this_player() references caster
                and this_object() references target for processed messages.


"argument",  arg,

arg is an optional argument that can by the "spell object", or in fact 
any object.  The value can be access by the function query_spell_argument().


Notes:

All messages are parsed through process_msg(str). This function uses 
process_string(str). Thus the name of the caster can be given by,
"@@query_name:$this_player()$@@", and the target name can be given by
"@@query_name:$this_object()$@@". Using string like this allows the target
to easily, absorb, reflect, or recast a spell. 

The example below is the spell burning hands. Notice how the fn will
accept a second argument wich will allow the spell to be used by
any school, sphere, or wand.

The file cloned by "spell obj" must exist, and must be error free. If
it isn't it will stop the players heart beat.



Related functions:

mixed *set_loaded_spell(mixed *arr)

This will load a spell in one shot, use this with care. An inappropriate
array size will cause problems stopping the players heart beat.  If a 
spell is loaded in this fashion, there are no checks for cast level, 
spell points, or components.


mixed *query_loaded_spell()

Will return the array holding the loaded spell. It returns an empty array 
if no spell is loaded.


void unload_spell() 

Will set the loaded spell to an empty array. THIS SHOULD NOT BE DONE BY
OUTSIDE OBJECTS. Let spell routines handle unloading.


int query_spell_dmg()

returns -1 if no spell loaded, otherwise will return the original spell
damage. 
Notes: This gives a reference to see if the target saved, or resisted
       the spell.


string query_spell_name()

This returns the name of the spell.


mixed query_spell_argument()

This returns the value of the optional "argument" attribute if it
has been set.

status load_spell(mixed *arr)

loads the spell attributes from the loading spell array arr, into the 
loaded_spell array. It is the spells front-end. If it fails to
load the spell it returns 0, otherwise 1.


void cast_spell_at_target()

This causes a loaded spell to be cast.
 



/**********************************************************************/
/* Example */

/** Burning Hands; by Serepion  **/

/* update - dec 93 */

#define NAME "@@query_name:$this_player()$@@"  /* gives greater flexibilty */
#define TARG "@@query_name:$this_object()$@@"

status bh(mixed targ, mixed alt_type) {
  int dam;

  if(!alt_type) alt_type = "alteration"; /* default school */
  dam = (objectp(alt_type))
      ? (int)alt_type->query_cast_level()  /* wands */
      : (int)call_other(this_player(),"query_"+alt_type);
  dam *= (random(4) + 1);
  if(dam > 20) dam = 20;  

  this_player()->load_spell(({
  "target",            targ,
  "name",              "Burning Hands",
  "sphere",            alt_type, 
  "cost",              2,
  "damage",            dam,
  "immune",            "fire",
  "level",             2,
  "cast time",         1,
  "msg target",       "Flames shoot from "+NAME+"'s fingers burning you.\n",
  "msg room",         "Flames shoot from "+NAME+"'s fingers burning "+
                      TARG +".\n",
  "msg caster",       "Flames shoot from your fingers burning "+ TARG +".\n",
/* other spell options...
  "area",
  "spell object",      0,
  "casting msg",       0,
  "casting msg room",  0,
  "passive",
  "component",        0,
 */
  }));
  return 1;
}