CONCEPT
Caster, Cast Object
LAST UPDATE
Softbyte 19.08.1995
USAGE
inherit "obj/caster";
#include <magic.h>
#include <combat.h>
DESCRIPTION
This is a generic castobject for all magic use It can
be used for casting a spell or scroll as well as for singing
a bards song or invoking magic in any other way.
This object provides all necessary functions for invoking
magic as well as checking whther it is allowed to cast
magic. Repulse handling is also included.
The usual command for invoking magic is "cast", but it can
be changed if necessary.
The basic function of this object is to add one ore more
spells with individual cast and fail functions as well
as SP cost, failchance, failchecks, backfire chance and
spelltypes.
A spell has usually a short name used for casting (e.g. "fire")
and a long name for description ("e.g. arcanic fire"). Also
one can define a long description and a spell usage which
can be diplayed via the "describe" command or via the
QuerySpellMsg().
Whereever sensible the argument string spname is optional. If not
given it is replace by this_spell(), which is the last spell
accessed via, cast, describe or AddSpell.
Functions marked with a '*' are more important.
Remark: - Most functions have a name which says what they actually do.
- Use caster::init() and caster::create() if you inherit
the caster as second inheritance, e.g in an armour.
------------------------ Main Functions ---------------------------------
int IsSpell(string spname):
return int: 0: spname is NO known spell
1: spname is a valid spell
Test whether spname is a spell in the spelllist or not.
*int ModifyMagic(int effect)
return int: new strength of a spell
This function allows to increase or decrease the effect of magic.
When overwritten it should first call the original function to
calculate a possible modification via the room or player property
P_MODIFYMAGIC="ModifyMagic" (gives % of change, i.e. 100 is no change.
0 means no change, too.)
Setting this property in a player or a room will cause all
magic effects to be modified by this (percentage) value.
closure QuerySuccessFunction(string spname)
return closure successfunction
int SetSuccessFunction(closure fun,string spname)
return int 0: set function did not work
1: ok
Sets the function which will be called after the cast had been
performed. This function is only necessary if one has to perform
some kind of cleanup, like removing the cast object or setting a
scroll as used. The successfunction returns nothing and gets as
arguments an integer 0: spell not casted, 1: spell casted and
the spellname (string).
E.g.
void spelldone(int flag,string spname) {
if (flag) casted=1;
}
*a return of the type MESSAGE can be one of the following:
0 : Default message is used
string : The string is written to this_player()
({string}) : Is the same as string
({stringA,stringB}): The stringA is written to this_player() and
the stringB is said to its environment
({stringA,stringB, : Additionally string1,2.. are told to object 1,2,..
({object1,object2,..}), the objects1,2,.. are exclude from the
({string1,strings2,...)} say, though. If more objects then strings
}) the last string is told to all following
objects.
*void Message(mixed mesg)
This function gives out a MESSAGE as decribed above.
*int AddFailCheck(closure failfun,string spname)
*int SetFailChecks(closure *failfuns,string spname)
return int 0: set function did not work
int 1: ok
closure *QueryFailChecks(string spname)
return closure* functions: Array of all failcheck functions
Set, add or query the failcheck functions of a spell. These failchecks
will be performed to check whether a spell can be casted. One could
check e.g. the guild or the race or the presence of some magic items.
All default checks are already performed. A fail here will cost the
caster the full ampount of spellpoints. If this is not wanted use a
RestoreSP() or RestoreSP(amount) in these functions.
A failfunctions has to return a MESSAGE (see above) if the spell should
fail or 0 if the spell works. The MESSAGE is then printed to the player
(and its environment). The failcheck function gets as arguments the
spellname of the spell.
Using SetFailChecks will reset all former Added or Set Failchecks!
string QuerySpellDescription(string spname)
string QuerySpellDesc(string spname)
return string: Long description for the spell
int SetSpellDescription(string desc,string spname)
*int SetSpellDesc(string desc,string spname)
return int 0: set function did not work
int 1: ok
Queries or sets a description of a spell. This is optional. If set
a player can read it by typing "describe <spname>". One can also set
the ReadMsg of the object very easily to this (see QuerySpellDescMsg)
If no description is set or the description is 0 then nothing will
be printed out.
string QuerySpellUsage(string spname)
return string: Usage of the spell
*int SetSpellUsage(mixed usage,string spname)
return int 0: set function did not work
int 1: ok
Queries or sets the usage string of the spell. This is optional and
comes together with the Spelldescription. The description is printed
first followed by a
"Usage: usagesgtring
It will cost XXX spellpoints to cast this spell."
So the usagestring is usually one line, like "cast rcold <target>".
If no usage is set or the usage is 0 nothing of the above mentioned
text will be printed.
Another possibilty is to set the usage to a closure, which has to
return all (!) the above mentioned usage text.
The function gets as argument the spellname.
*int AddSpell(string spname,mixed spelltype,int|closure SPcost,closure castfun,
string longname,int|closure failchance,int|closure backfirechance)
return int 0: set function did not work
int 1: ok
This is the main function for creating a spell. It sets the minimum
arguments that are necessary for a spell.
spname is the castname and idendification for a spell. spelltype
is the class a spell belongs to (see magic.h, ST_XXX). The SPcost
is the cost in SP the caster needs to cast the spell. It can be
a function the calculates the cost (see SetCastCost).
The castfunction is the function which does the actual cast. It
has to perform no additional validy checks, except for a Repulse()
check (see Repulse) if it influences another living! See
SetCastFunction() for details. failchance determines the chance for
failing the spell (0..100) i.e. its difficulty. A caster needs
Wisdom to overcome the difficulty. Failchance can be a function, too.
See SetFailChance(). If failchance is ommited it is set to 0 (never fail).
Same as for failchance holds for backfirechance. This simply sets
the chance in percent that a repulsed spell will backfire!
longname is the real name of a spell. It is the a longer version of
spname (e.g. rcold and resist cold). If ommited it is set to spname.
string QuerySpellMsg(string spname)
return string: Description and usage of a spell
This function reads out the description and usage of a spell
and returns it. It is called by the describe command and can
be directly implemented into a ReadMsg of an object (scroll).
*mixed QueryCastDamage(int damage,object enemy,mixed damtype,string spname,object me)
return MESSAGE: Damage message for combat
This returns a MESSAGE object that can be output by
Message(). It contains the combat strings which depend on
the actual damage done by a spell (return value of Defend!).
The output is similar to:
"The orc is slightly hurt by your spell."
For the usage see the example in SetCastFunction.
The arguments damtype, spname and me are only needed when they
differ from the default values, i.e. damtype=QuerySpellType() and
spname=this_spell(). 'me' is this_object() unless you call this
function via another object, i.e. "/obj/caster"->QueryCastDamage(..),
where you have to set 'me' to this_object().
*int Repulse(object enemy,object caster,mixed sp_type,string spname,object me)
return 0: Spell is not repulsed
1: Spell is repulsed
Checks the magic resitances of the enemy versus the casters
abilities to cast the spell (spname) from the magic type sptype.
When a spell got repulsed a me->NotifySpellFail(enemy,caster,spname)
is called to allow some optional repulse action other than default.
The NotifySpellFails should return a message that can be printed
via Message(): Otherwise a default text is printed and no action
taken.
It can be called by an external object if me is set to it.
Defaults are me=this_obejct(), caster and enemy=this_player() and
spname=me->this_spell() and sptype=me->QuerySpellType(spname)||ST_ALL.
Attributs checked for the magic defence are ATT "MagicDefence"
and PROP "Resistance"
string DifficultyToString(int difficulty)
return string: descrition of difficulty
Converts the difficulty of a spell (QueryDifficulty) into
a string like "very easy" or "difficult".
mixed NotifySpellFail(object enemy,object caster,string spname)
return MESSAGE: text saying that caster failed this spell or 0
This function is called when a spell failed due to lack of ability
of the caster (fail) or if an enemy repulsed a spell (backfire).
One can overwrite this function to perform any own action there.
caster (object) will be the caster, i.e. this_player() and
enemy (object) will be the enemy who repulsed the spell or 0 if the
spell did fail.
Per default this function does write a default string when the spell
indicating that the caster faild to cast that spell. When the
spell got repulsed it will check the BackfireChance and when
appropriate the spell will be casted with its halfstrength at
the caster itself!
Easiest way to avoid it is to overwrite this function and
return 0;
int DisableCast()
int IndirectCast()
int DirectCast()
return 1
These Functions allow to change the use of the cast command.
In the cast of DisableCast() no casting at all is possible.
If the case of DirectCast() one can directly type the name
of the spell to activate it. In the case of IndirectCast()
one has to type "cast" before the spellname to activate it.
Default is IndirectCast().
------------------- Auxiliary Functions ---------------------------------
*void LogCast(object caster,object target)
Will write caster as aggressor in the logfile AGGRESSORS.
Time and date, name of the spell and the target are recorded as well.
Use this if an attack spell is casted against a player.
*int AllowDescribe()
*int ForbidDescribe()
Enable or disable the describe function of the spell.
Default is enabled, i.e. the user can read the long description
and usage about this spell via "describe <spname>".
string QueryCastVerb()
int SetCastVerb(string str)
string QuerySpellNoun()
int SetSpellNoun(string str)
Allow to change the standard cast action "cast" and all
occurences of the verb cast by some other verb. The second
function allow to replace all occurences of the noun spell
by another noun.
This is handy if you want to invoke magic by singing a song
or playing an instrument.
MESSAGE QueryCastActionMessage(string spname,string longname,object who)
The message returned here will be written when a spell is
casted. Per default it is e.g. "You cast a holy water spell" and
something similar to the environment.
This can be changed again if you want to sing a song. It might be
also used if you want to write something special to the environment,
e.g. non-magic user would not understand a spell, while mages would
int QueryNumberOfSpells()
return int: number of spells stored in the cast object.
-------------- Internal or not so important functions -------------------
string SetThisSpell(string str)
Sets str to be the actual spell returned by this_spell().
str should be a spell added to this object. str should be
its shortname.
string QueryLongName(string spname)
return string: longname of the spell
string SetLongName(string long,string spname)
return string: longname of the spell
Queries or sets the longname of a spell. The long name is the real
name of a spell that is used in any messages. The spname or shortname
is the name one types for casting.
e.g. longname=resist cold, spname=rcold
Setting the long name can be done better with AddSpell function.
int QueryCastCost(string spname)
return int: cast cost for this_player()
int SetCastCost(mixed cost,string spname)
return int 0: set cost did not work
1: ok
Queries or sets the cost for casting a spell. Cost can either be an
integer, which then will be the fixed cost for casting or a closure
(#'function) which calculates the cost for this_player() to cast the
current spell. This function has to return the cast cost as an integer
and it will get as argument the name of the spell.
E.g.:
int spellcostfunction(string spname) {
return 42;
}
Setting the cost(function) can be done better with the AddSpell function.
mixed QuerySpellType(string spname)
return mixed: ST_TYPE
mixed SetSpellType(mixed type,string spname)
return mixed: ST_TYPE
Queries or sets the type of a spell as defined in <magic.h> in ST_XXXX,
e.g. ST_FIRE.
Setting the spelltype can be done better with the AddSpell function.
closure QueryCastFunction(string spname)
return closure: castfunction
int SetCastFunction(closure fun,string spname)
return int 0: set function did not work
1: ok
Queries or sets the function which does the actual magic action.
When this is called all checks have been performed, so that this
function just has to do the basic magic, like for example
cloning an item, adjusting stats or damaging an opponent.
If the magic is applied to an enemy one has to
check the result of Repulse(..,..,..) whether
the enemy does resist that spell !!!
If a spell does any damage or depends on any quantity, it should
process this quantity or damage via
damage=ModifyMagic(damage) to allow for dynamical adjustment of
the strenght of magic.
The cast function gets as arguments the target (string) and the
name of the spell (string).
It has to return 1 if the spell had been performed or 0 if the spell
had not been performed, e.g. because the parameter target was illegal.
In the latter case the spellpoints for the caster will be restored!
E.g.:
int arcfire(string target, string spname)
{
object ob;
int dam;
if (!target) return 0; /* illegal use */
ob=present(target,environment(TP));
if (!ob) return 0;
if (Repulse(ob,TP)) return 1; /* cast was performed ! */
dam=ob->Defend(ModifyMagic(70HP),QuerySpellType(),1); /* do damage */
Message(QueryCastDamage(dam,ob)); /* write damage string */
return 1;
}
Setting the castfunction can be done better with the AddSPell function.
int QueryDifficulty(string spname)
int QueryFailChance(string spname)
return int failchance [0..100]
int SetFailChance(mixed fch,string spname)
int SetDifficulty(mixed fch,string spname)
return int 0: set function did not work
1: ok
Queries or sets the failchance, i.e. the difficulty of a spell in
percent, i.e. a range from
0: no fail at all (means really no fail, no very easy)
1: very easy spell
100: very hard spell
Difficulty and Failchance are the same!
The failchance can either be an integer in the above mentioned range
or a closure which calculates the failchance for this_player(). This
function has to return an integer 0..100 and will get as argument the
name of the spell.
E.g.:
int failchance(string spname) {
return 42;
}
Setting the failchance can be done better with the AddSPell function.
int QueryBackfireChance(string spname)
return int backfirechance [0..100]
int SetBackfireChance(mixed bch,string spname)
return int 0: set function did not work
1: ok
Queries or sets the backfirechance, i.e. the chance of a spell in
percent to backfire on the caster if it got repulsed.
0: no backfiring at all
100: Every repulse will lead to a backfiring of the spell
Backfiring of a spell is that the castfunction of the spell
is called with the caster(!) as argument and the thrid argument
set to 1 to indicate backfireing. ModifyMagic is set
so that the effect will only half as much as before. So if
not protected a player will be hurt by his/her own spell!
This is all done in NotifySpellFail.
Setting the backfirechance can be done better with the AddSPell function.
mixed CheckWisdom(string spname)
return MESSAGE: text saying that caster faild this spell
This function is an example for a FailCheckFunction. It is per default
added to any new spell and will check the Wisdom of a player verus the
difficulty of the spell. Depending on the outcome the spell can fail
and an appropriate message is written.
If you really don't want that (why) you can use SetFailCheck with an
empty array as argument.
spname is the name of the spell and will be passed to every failfunction.
Further properties of the spell can be queried with the appropriate
Query functions.
int QueryCastResult()
int SetCastResult(int result)
return int CAST_XXXXX (from magic.h)
Returns the last value of a cast function. Needed for the spellbook
to check whether the cast had been successful or not.
*int RestoreSP(int amount)
Restores the spepppoints of the caster to the value before the cast
or if amount is given adds amount to the current spellpoints.
This should be used in a failcheck function if it is not meant to
reduce the spellpoints or restore a part of the spellpoints.
int ReduceSP()
Compatibility only
-------------------------------------------------------------------------
EXAMPLE
Examples are mentioned in some function descriptions above.
/obj/scroll uses the caster and so do all scrolls in
MAGIC_SCROLL_DIR.
KNOWN BUGS
INHERITANCE TREE
std/thing
SEE ALSO
scroll, magic, spells, combat, [magic] resistance