Writting Scripts
This section talks about things to think about when writing scritps.
Scripts are ment as a flexible alternative to hard coding things in. It
allows area designers to add life and variety to an otherwise passive
area. Good scripts are short and sweet, don't feel you need to add scripts
to every mob and object in your area. A few well placed scripts can spice
up the place, but too many can lead to a noisy, unplesent area.
In this section we'll talk about some design considerations you should
remember when writing scripts.
Working with Mobs
Mobs are the lifeblood of the mud. And most mobs are pretty booring.
They just stand there and wait to get killed, or they might wander around
a little while waiting to get killed. Some mobs try to kill you right
away, and some don't. Without scripts, that's about as interactive as
mobs got.
Now we have a wide variety of script triggers like @rand, @action, @greet,
@entry, etc.That are triggered when certain actions happen in the mud.
If you want a mob to say hello to everyone who walks into the room the
mob is already in, you can use a @greet script that might look like this:
@greet 100~
{
say Hello $n.persname!
}
~
|
This script will fire 100% of the time a new person enters the room.
If you want a more interesting fight on a mob, you might add a @fight
script that looks like this:
@fight 30~
{
if (@rand(1,100) < 25) {
mpcast heal
} else if (@rand(1,100) < 33) {
mpcast acid
} else if (@rand(1,100) < 50) {
mpcast exorcise
} else {
disarm
}
}
~
|
PCs and NPCs
In the mud, NPCs and PCs are both based on the 'character' class. As
such most of their attributes are the same. However there are some exceptions,
and those are noted in the player
and mob attribute table. Be carefull when using an attribute that
is either npc or pc only. You should always test for the condition you
are looking for before attempting to use one of these attributes. For
example if you wanted a mob that only greeted members of a certain tribe,
you could use something like this:
@greet 100~
{
if (@ispc($n) and $n.tribe) {
if ($n.tribe == "illum") {
say Greetings fellow member of the Illuminati.
}
}
}
First we tested to make sure who ever entered the room ($n) was
a pc and if $n is in a tribe, then we went on with the rest of the script.
The same would be true if you wanted to test an attribute specific to
an npc.
Also, some attributes are available to both, but are used dierently.
Some of the attributes, namely short_descr
and long_descr are available on pcs,
but are always blank. Here is a greet script that takes into account the
diferences between pcs and npcs:
@greet 100~
{
if (@ispc($n)) {
say Greetings $n.name!
} else {
say Greetings $n.short_descr!
}
}
This script takes into account the fact that mobs typically have very
strange 'name' attributes. For example, the great red dragon's 'name'
is actually 'great dragon red'. So if you were to simply use $n.name
for both pcs and npcs, if the great red dragon entered the room this mob
would say "Greetings great dragon red!" and that would be kinda
silly. Similarly, since the short_descr on pcs is always blank, if you
used only the $n.short_descr for both, when a pc entered
the room the mob would say "Greeting !".
Altho we now have the attribute $n.persname,
which is smart and chooses the name of a player, and the short_descr of
an npc, so the use of $n.persname is prefered anytime printing or saying
of a mob's name is used:
@greet 100~
{
say Look! It's $n.persname!
}
You should also remember to take into account that many players will
walk around invisable or hiding. If your mob does not have detect invis
and detect hidden (most mobs shouldn't) you should take this into consideration
in your scripts as well. Let's say you had a script that you wanted to
have a mob attack only evil orcs. Because the aggressive flags on mobs
are an OR opperator, if you were to set the mob aggie to orcs and evil,
it would attack good orcs, as well as evil elves. So in order to test
for both, you would need to write a simple script. However if this mob
cannot see invisable or hidden things, then we should not attack:
@greet 50~
{
if (@cansee($i,$n)) {
if (($n.race == "orc") and ($n.alignment < -300))
{
mpkill $n
}
}
}
If the mob can't see $n, then the rest of the script is bypassed.
Attributes, Variables, and the dot (.) notation
Mob Scripts
You see $n and $i being used a lot in all these examples.
These refer to characters, either mobs or players, that relate to the
script somehow. The $i variable always relates to the mob that
the script is attached to. Therefor if we want to know anything about
the mob itself, the room the mob is in, etc, we start with $i.
| $i.short_descr |
returns the short description of the mob that this script is on
(Barliman Butterbur) |
| $i.long_descr |
returns the long description of the mob (Barliman Butterbur stands
here, a jovial greeting on his lips.) |
| $i.level |
the level of the mob |
| $i.room.vnum |
the vnum of the room this mob is in right now. |
| $i.room.area.name |
the name of the are the mob is in |
Similarly, the $n variable is probably the most used variable,
because it targets the actor that triggered the script. Scripts like @action,
@speach, @give, and @greet all generate an $n variable
that is associated with the mob or player that triggered it. So if Estranged
were to enter a room with a mob that had a @greet trigger on it,
then $n would point to Estranged, and any of Estranged's attributes
could then be referenced based on that.
One thing to keep in mind. The period character is sort of a reserved
character in scripts. Any period following a variable reference forces
the script parser to look for more attributes. For example:
if (@isafected($n,B) and @ispc($n)) {
say Oh, aren't we sneaky $n.persname...
}
If Estranged triggered this script and was invisable (the B is the AFF_INVISABLE
flag) you would expect the mob to say "Oh, aren't we sneaky Estranged...".
But in fact it will yield a parse error when we try and load the script,
because the period signals the parser that the next set of letters is
another attribute, and since the next letter is another period, the parser
will complain that it's not a valid attribute. This causes particular
problems where you may be using an echo to say something to a room. Unfortunately
right now, variables and attributes must have leading and trailing spaces
between it and other info.
IMPORTANT! One thing to remember is that the @death
trigger does NOT generate an actor. The mob just dies. This is because,
while player induced death is by far the most common way mobs die, a mob
could die from poison, plague, or via another script. So any references
to $n in a @death trigger will cause the script to crash
when it triggers.
@death does now generate an
actor, so $n will work.
Another frequently used variable is $r. This targets a random
player or mob in a room. Most of the time this is simply used to spice
stuff up. For example, Barliman has a random script on him that looks
like this:
@rand 3~
{
if (@rand(1,100) < 25) {
if ($r) {
smile $r
}
} else if (@rand(1,100) < 25) {
if ($r) {
hug $r
}
} else if (@rand(1,100) < 25) {
if ($r) {
noogie $r
}
} else if (@rand(1,100) < 25) {
if ($r) {
say $r! Good ta see ya, pal!
}
} else if (@rand(1,100) < 25) {
forehead
} else if ($r) {
tickle $r
}
}
~
All of the if ($r) statements are there
to make sure that the random character that was picked is actually still
around. This rarely is needed, but should always be there just in case.
One of the rarely used variables is $t. This refers to the 'victim',
and for the most part 'victims' are only generated in an @action trigger.
The victim is the reciever of the action. So if player A hit mob B with
an acid blast, the mob would be assigned to $t. This is really
only usefull if the mob with the script is observing two other characters
interacting. For example if you wanted a mob to say something when others
were fighting, you might use something like this:
@action p does UNSPEAKABLE things~
{
say Way to go $n.persname! Kick $t.persname in the butt for
me too!
}
~
More to Come!
|