-=[ 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; }